Home | Chi sono | Contattami
 

Progr. lineare

Delphi
 
Componenti
  Database
 
Miei articoli

Windows

Miei articoli 

 

Creare un processo e mappargli una dll nello spazio di memoria


Nell'articolo Dll Injection ho analizzato un pò come mappare una dll nello spazio di memoria di un processo; l'articolo è focalizzato sull'utilizzo dell'api win32 CreateRemoteThread che consente la creazione e l'esecuzione di un thread nel contesto di un processo remoto (nel caso specifico si tratta di un thread che che esegue fondamentalmente l'api win32 LoadLibrary per caricare la dll). Per creare un processo esiste la famosa api win32 CreateProcess (e le sue varianti CreateProcessAsUser, CreateProcessWithLogon, CreateProcessWithtoken) per cui l'accoppiata CreateProcess e CreateRemoteThread potrebbe già risolvere tutto; ed in effetti risolve a grandi linee la questione. Il problema però è il seguente: spesso si vuole che la dll sia mappata il prima possibile nello spazio di memoria del processo remoto; questo perchè magari la dll implementa api hooking su un determinato set di api win32 e si vuole iniziare a tracciare la chiamata di tali api il prima possibile: se eseguiamo semplicemente CreateProcess e poi CreateRemoteThread , nulla ci garantisce che all'atto della chiamata dell'entrypoint della dll non sia già stato chiamato l'entrypoint dell'exe lanciato dalla CreateProcess; ciò significherebbe ovviamente che ci siamo potenzialmente persi alcune delle chiamate (per non parlare poi del codice eseguito nell'entrypoint delle dll importate). Allora si è soliti chiamare la CreateProcess con la Flag CREATE_SUSPENDED (valore 0x00000004) nell'ambito del 6° parametro (dwCreationFlags). In questo modo si crea un processo sospeso: in questo stato nel suo spazio di memoria saranno mappati l'exe e le dll kernel32.dll e ntdll.dll. E qui si arriva al problema: usare CreateRemoteThread su un processo in questo stato comporta un'alta probabilità di crash del processo all'atto del resume tramite l'api win32 ResumeThread. Quindi bisogna ricorrere ad altre tecniche: ve ne sono diverse e quella che esporrò nel seguito è probabilmente la più classica; si basa essenzialmente sulle api win32 GetThreadContext e SetThreadContext. Ho utilizzato direttamente l'ottima implementazione ad oggetti di Max Artemev nell'ambito del suo applicativo FreeCap. Ho estrapolato la unit dal contesto dell'applicativo originale eliminando del codice non necessario. Il risultato finale è una funzione che ho nominato CreateProcessAndMapDllA che è equivalente alla CreateprocessA con l'aggiunta di un ulteriore parametro alla fine che specifica appunto il nome della dll da mappare. 

unit uCreateWith; interface uses Windows; function CreateProcessAndMapDllA( lpApplicationName: PAnsiChar; lpCommandLine: PAnsiChar; lpProcessAttributes: PSecurityAttributes; lpThreadAttributes: PSecurityAttributes; bInheritHandles: Boolean; dwCreationFlags: Cardinal; lpEnvironment: Pointer; lpCurrentDirectory: PAnsiChar; const lpStartupInfo: TStartupInfo; var lpProcessInformation: TProcessInformation; lpDllName: PAnsiChar ): Boolean; stdcall; implementation uses uInjector; function CreateProcessAndMapDllA( lpApplicationName: PAnsiChar; lpCommandLine: PAnsiChar; lpProcessAttributes: PSecurityAttributes; lpThreadAttributes: PSecurityAttributes; bInheritHandles: Boolean; dwCreationFlags: Cardinal; lpEnvironment: Pointer; lpCurrentDirectory: PAnsiChar; const lpStartupInfo: TStartupInfo; var lpProcessInformation: TProcessInformation; lpDllName: PAnsiChar ): Boolean; stdcall; var Injector: TSuspendInjector; bSuspended: Boolean; begin bSuspended := ((dwCreationFlags and CREATE_SUSPENDED) <> 0); if not bSuspended then dwCreationFlags := dwCreationFlags or CREATE_SUSPENDED; result := CreateProcessA( lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation ); if result then begin Injector := TSuspendInjector.Create; Injector.ProcessInformation := lpProcessInformation; Injector.SetDLLToInject(lpDllName); Injector.ShouldRunAfter := not bSuspended; Injector.Run(); end; end; end.

Di seguito i sorgenti di un semplice esempio

CreateProcessAndMapDll.7z

Altri modi per eseguire dll injection su un processo da creare sono i seguenti

1) Creare il processo in forma Suspended ed eseguire un runtime patching della tabella IAT del .exe aggiungendo nell'elenco delle dll da importare anche la nostra dll: al Resume il loader di windows si troverà con la IAT del .exe modificata ed eseguirà il suo consueto lavoro di caricamento delle dll ivi incluse coinvolgendo quindi anche la nostra dll. Questa tecnica viene usata dalla Detours Library

2) Utilizzare il Thread Local Storage (TLS): questa tecnica viene discussa ad esempio all'indirizzo

http://blog.dkbza.org/2007/03/pe-trick-thread-local-storage.html

3) Eseguire l'overwriting dell'entrypoint del .exe inserendo codice che carica la dll ed al termine esegue il codice originale. Questa tecnica viene usata dalla MadCodeHook di Madshi.

 

 

 

 
 
Your Ad Here