La DLL Injection è una delle tecniche più utilizzate dai malware per iniettare codice malevolo in uno o più processi in esecuzione. Questa metodologia si basa su una serie di step ben definiti, sfruttando le Windows API per ottenere il controllo del processo target e caricare una DLL dannosa.

Differenza tra DLL Injection e DLL Hijacking

La differenza tra DLL Injection e DLL Hijacking risiede nei metodi e negli obiettivi per sfruttare le DLL, pur avendo entrambi come scopo il caricamento di codice malevolo in un processo legittimo.

La DLL Injection è una tecnica attiva in cui un codice malevolo viene iniettato direttamente in un processo in esecuzione. L’obiettivo è far eseguire una DLL malevola nel contesto del processo target, manipolando il suo comportamento o raccogliendo dati sensibili. Richiede un’interazione diretta con il processo target, ad esempio usando funzioni legittime delle Windows API per allocare memoria, scrivere il percorso della DLL e creare un thread per eseguire il codice malevolo.

La DLL Hijacking, invece, è una tecnica passiva che sfrutta la vulnerabilità di ricerca delle DLL in un’applicazione. Se un’applicazione cerca una DLL mancante o errata, un attaccante può fornire una DLL malevola con lo stesso nome, che verrà caricata dall’applicazione.

Differenze principali

CaratteristicaDLL InjectionDLL Hijacking
MetodoIniezione attiva sul processo targetManipolazione dell’ordine di ricerca delle DLL
Richiede il controllo del processo target?No
Obiettivo primarioModifica del comportamento di un processo attivoIngannare un’applicazione per caricare una DLL malevola
Contesto di utilizzoAttacchi runtimeAttacchi persistenti o su software vulnerabile

Di seguito illustreremo i vari step utilizzati per fare DLL injection:

STEP 1: Identificazione del Processo Target

Il malware deve identificare un processo nel quale iniettare la DLL dannosa. Per raggiungere tale scopo sfrutta alcune funzioni delle Windows API, generando uno snapshot del processo e raccogliere informazioni da esso.

Funzione utilizzata per la creazione dello Snapshot del processo target:

CreateToolhelp32Snapshot(): Esegue un’istantanea (snapshot) dei processi specificati, nonché degli heap, dei moduli e dei thread utilizzati da tali processi. L’accesso allo snapshot è di sola lettura.

Sintassi della funzione in C++:

Parametri:

  • dwFlags specifica i tipi di informazioni da includere nello snapshot (ad esempio processi, thread, heap, moduli.
  • th32ProcessID corrisponde all’ID del processo su cui si desidera avere lo snapshot, per ottenere informazioni su tutti i processi, questo valore può essere impostato su 0.

Se la funzione va a buon fine, restituisce un handle allo snapshot.

Per estrapolare le informazioni dallo snapshot, utili ad individuare il processo adatto per il DLL Injection, si usano le seguenti funzioni Windows API:

Process32First(): Recupera informazioni sul primo processo riscontrato in uno snapshot.

Sintassi della funzione in C++:

Parametri:

  • hSnapshot rappresenta l’handle per lo snapshot restituito dalla precedente chiamata alla funzione CreateToolhelp32Snapshot.
  • lppe rappresenta un puntatore a alla struttura PROCESSENTRY32, la quale contiene informazioni sul processo come: il nome del file eseguibile, l’identificativo del processo e l’identificativo del processo padre. Di seguito riportiamo le informazioni raccolte da PROCESSENTRY32:

Per recuperare informazioni su altri processi registrati nello stesso snapshot, utilizzare la funzione Process32Next.

Process32Next(): Recupera informazioni sul processo successivo registrato in uno snapshot del sistema.

Sintassi della funzione in C++:

Parametri:

  • hSnapshot rappresenta l’handle per lo snapshot restituito dalla precedente chiamata alla funzione CreateToolhelp32Snapshot.
  • lppe rappresenta un puntatore a alla struttura PROCESSENTRY32

Queste due funzioni (Process32First e Process32Next ) vengono utilizzate in un ciclo per esplorare tutti i processi nello snapshot, confrontando i dati con i criteri di selezione del malware (ad esempio, il nome del processo o il PID).

Step 2: Accesso del Processo Target

Una volta identificato il processo target, il malware deve aprirlo per effettuare operazioni su di esso.

Di seguito riportiamo le funzioni utilizzate per tale scopo:

OpenProcess(): usata per ottenere un handle su un processo specifico, permettendo operazioni come la lettura/scrittura di memoria.

Sintassi della funzione in C++:

Parametri:

  • dwDesiredAccess: Specifica i permessi desiderati (ad esempio PROCESS_ALL_ACCESS).
  • bInheritHandle: Indica se l’handle è ereditabile.
  • dwProcessId: ID del processo da aprire.

GetModuleHandle(): Recupera un handle a un modulo (DLL o EXE) già caricato nello spazio di memoria del processo chiamante.

Sintassi della funzione in C++:

GetProcAddress(): Recupera l’indirizzo di una funzione esportata da un modulo.

Sintassi della funzione in C++:

STEP 3: Allocazione della Memoria nel Processo Target


Dopo aver ottenuto l’accesso, il malware deve individuare un’area di memoria all’interno del processo target dove scrivere il percorso della DLL malevola.

Per tale scopo utilizza la seguente funzione:

VirtualAllocEx(): Tale funzione alloca memoria nello spazio di un processo specifico.

Sintassi della funzione in C++:

Parametri:

  • hProcess: rappresenta l’handle del processo target.
  • dwSize: dimensione della memoria da allocare (sufficiente per contenere il percorso della DLL).dwProcessId: ID del processo da aprire.
  • flAllocationType: Tipo di allocazione (ad esempio MEM_COMMIT).
  • flProtect: Protezione della memoria (ad esempio PAGE_READWRITE).

STEP 4: Scrittura del Percorso della DLL

Il malware scrive il percorso della DLL malevola nell’area di memoria precedentemente allocata nel processo target.

Per tale scopo utilizza la seguente funzione:

WriteProcessMemory(): Scrive dati in un’area di memoria di un processo specifico.

STEP 5: Esecuzione della DLL Malevola

Per completare il processo di iniezione, il malware avvia un thread remoto nel processo target, caricando la DLL. Per tale scopo esistono varie funzioni alcune dei quali non sono documentate:

Funzioni Documentate:

CreateRemoteThread(): crea un nuovo thread remoto che esegue il codice in un modulo specifico.

Parametri:

  • lpStartAddress: Indirizzo della funzione da eseguire (ad esempio LoadLibrary).
  • lpParameter: Parametro passato alla funzione (percorso della DLL).

LoadLibrary(): Carica una DLL in un processo.

È importante sottolineare che la funzione delle Windows API CreateRemoteThread() non è l’unica che può essere utilizzata per iniettare codice. Esistono anche altre funzioni che possono essere sfruttate per scopi simili, aumentando le possibilità per il malware di bypassare i controlli di sicurezza.

Funzioni Non Documentate:

NtCreateThreadEx(): Alternativa avanzata a CreateRemoteThread, caricata manualmente da Ntdll.dll.

RtlCreateUserThread(): Utilizzata da strumenti avanzati per il controllo dei processi, come Mimikatz e Metasploit.

L’uso di queste funzioni non documentate consente al malware di aggirare le tecniche di rilevamento basate su comportamenti noti delle API documentate.

Per far funzionare questa tecnica, il percorso della DLL malevola deve risiedere sul disco. Tuttavia, esiste una tecnica più discreta: la Reflective DLL Injection, che carica la DLL direttamente in memoria senza scriverla sul disco.

Conclusioni

Ogni step della DLL Injection sfrutta funzionalità legittime delle Windows API, rendendo questa tecnica particolarmente difficile da rilevare. La comprensione di queste procedure è fondamentale per lo sviluppo di contromisure efficaci, come l’analisi comportamentale e il monitoraggio delle chiamate API.
Speriamo che questo cyber tuffo ti abbia aiutato a comprendere un pochino meglio il funzionamento dei tuoi malware preferiti!

Ti è piaciuto l’articolo? Seguici su Linkedin per sostenerci!

consigliati