
BOF di CobaltStrike per generare Beacon utilizzando il dirottamento della directory dell'applicazione tramite DLL
DropSpawn è un BOF di CobaltStrike utilizzato per generare ulteriori Beacon tramite un metodo relativamente sconosciuto di DLL hijacking. Funziona x86-x86, x64-x64 e x86-x64/viceversa. Utilizzalo come alternativa all'iniezione di processi.
Gli eseguibili Windows seguono l'ordine di ricerca delle DLL quando tentano di caricare DLL il cui percorso assoluto non è stato specificato:

Il DLL hijacking tipicamente richiede che:
A. Un utente abbia permessi di scrittura in una cartella con un ordine di precedenza di ricerca più alto rispetto a dove risiede la DLL originale
oppure
B. Che la DLL in questione non esista da nessuna parte nel sistema, nel qual caso può essere posizionata in una cartella scrivibile dall'utente nella variabile %PATH% dell'utente (come %USERPROFILE%\appdata\local\microsoft\windowsapps).
Questi requisiti escludono il DLL hijacking per gli eseguibili che risiedono in C:\Windows\System32 perché quasi tutte le DLL caricate da questi eseguibili risiedono anch'esse in System32. Copiare un eseguibile di System32 in una posizione scrivibile dall'utente ed eseguirlo lì è un'opzione, ma non è molto sicura dal punto di vista OPSEC perché i binari di System32 in esecuzione da posizioni alternative sono facili da identificare.
DropSpawn abilita il DLL hijacking utilizzando eseguibili di System32 (e altri presenti in cartelle aggiuntive non scrivibili dall'utente) falsificando la "Directory da cui viene caricata l'applicazione" con una arbitraria specificata dall'utente.
La versione pubblica di DropSpawn differisce leggermente da quella non pubblica. La versione non pubblica sfrutta un generatore di payload proprietario, rendendo l'esperienza molto più fluida per l'operatore. La versione pubblica è stata leggermente modificata per tenere conto del fatto che gli utenti avranno i propri modi per generare payload compatibili con il DLL hijack. Sono stati inclusi uno script Python3 e il codice sorgente per una DLL dimostrativa per aiutare gli utenti a integrare e rendere operativo dropspawn.
Identifica alcuni eseguibili target che tentano di caricare DLL senza specificarne il percorso assoluto. Puoi farlo copiando l'exe in una directory scrivibile dall'utente ed eseguendolo monitorandolo con Procmon. In questo esempio useremo WerFault.exe che normalmente risiede in C:\Windows\System32\WerFault.exe

Nell'esempio sopra, cryptsp.dll, wer.dll, dbghelp.dll e bcrypt.dll sono tutti candidati validi perché i loro percorsi assoluti non sono stati specificati all'interno di WerFault; di conseguenza, WerFault tenterà di caricarli prima dalla sua directory dell'applicazione prima di ricorrere al resto dell'ordine di ricerca delle DLL. Nota che questo di solito non è un problema perché la directory dell'applicazione di WerFault è System32.
Scarica una delle DLL hijackabili dal sistema target.
Questo è necessario per poter estrarre i suoi export e includerli nella nostra DLL payload. È importante prendere la DLL hijackabile dalla stessa macchina su cui desideri utilizzare DropSpawn, poiché le DLL cambiano tra le versioni di Windows. Inoltre, se stai eseguendo un beacon x86 e vuoi generare un beacon x64 usando DropSpawn, assicurati di scaricare la versione x64 della DLL reale specificando 'C:\windows\sysnative...' invece di 'C:\windows\system32...'.
Esegui generate_dll.py, passando la DLL scaricata e l'architettura del payload desiderata. Generate_dll.py è una versione modificata di questo script. Analizzerà la DLL fornita, creerà un file .def contenente gli export della DLL, e chiamerà MingW per compilare la nostra DLL payload dimostrativa. Quando il processo generato tenta di chiamare una funzione reale all'interno della DLL falsificata, la nostra DLL payload inoltrerà la chiamata alla DLL reale situata in System32 in modo che il processo host non si blocchi.

Chiama dropspawn utilizzando la DLL payload generata.
dropspawn <payload DLL> <x86|x64> <program to spawn> [writable target folder] [parent]
payload DLL - il percorso completo della DLL payload generata.
architecture - l'architettura del processo che desideri generare
program to spawn - il nome/percorso del processo che desideri generare. Se questo processo risiede in System32 (o syswow64), puoi specificare solo il nome. Altrimenti, specifica il percorso completo. Puoi anche fornire argomenti da riga di comando al processo. Se ci sono spazi nel percorso/se usi argomenti, racchiudi tutto tra virgolette.
writable target folder - Opzionale. Se lasciato vuoto, dropspawn proverà a utilizzare la directory corrente del Beacon. Usa le virgolette se ci sono spazi nel percorso.
parent - Opzionale. Il nome del processo da utilizzare per lo spoofing del PPID con il processo appena generato. Se viene specificato un processo che ha più istanze in esecuzione con diversi livelli di privilegio (ad esempio svchost.exe), dropspawn proverà a identificare una che può essere utilizzata per lo spoofing del PPID.
Esempio: dropspawn /root/gitlab/DropSpawn_BOF/dist/dbgcore.dll x64 "WerFault.exe -u -p 4352 -s 160" C:\users\user\appdata\local\temp explorer.exe
Questo depositerà la DLL payload 'dbgcore.dll' su disco in 'c:\users\user\appdata\local\temp\dbgcore.dll' e genererà un processo WerFault.exe x64 con gli argomenti da riga di comando '-u -p 4352 -s 160' e explorer.exe come processo padre.


La pulizia è facile. Includendo la funzione Self-Deletion nella DLL payload depositata su disco, verrà cancellata non appena il nostro nuovo processo viene generato e la carica. Questo è un punto di svolta, poiché tipicamente la DLL rimarrebbe bloccata su disco finché il nostro processo che l'ha caricata continua a funzionare. Se la tecnica di Self-Deletion fallisce per qualche motivo (o il processo non riesce a generarsi), DropSpawn tenterà di cancellare la DLL payload dal disco e informerà l'utente del risultato dell'operazione in ogni caso.
L'iniezione di processi segue tipicamente la catena: apri processo remoto -> alloca memoria remota -> scrivi memoria remota -> esegui memoria remota, con l'opzione di generare un nuovo processo all'inizio invece di utilizzarne uno esistente. DropSpawn crea solo un nuovo processo; il processo appena generato è responsabile dell'allocazione, scrittura ed esecuzione dello shellcode, così possiamo evitare molti degli IOC tipicamente associati all'iniezione di processi remoti.
Questa tecnica è ovviamente alla mercé di quanto siano buone le tue DLL payload. Ma possiamo dare un'occhiata a cosa vede Windows (questa prossima sezione utilizza la versione privata di DropSpawn e la generazione di Beacon).
Per quanto riguarda il Visualizzatore eventi, tutto sembra normale:

In MDE c'è molto poco da vedere.
Eseguendo dropspawn:

Log MDE:
Con spoofing del PPID:

Senza spoofing del PPID:

In entrambi i casi vediamo il nostro processo beacon originale (anche esso un werfault) depositare dbgcore.dll su disco, creare un nuovo processo WerFault.exe, il processo appena generato caricare dbgcore.dll, e poi rinominarlo (cancellarlo). Fondamentalmente non c'è un controllo extra su dbgcore.dll che spesso accompagna i DLL hijack perché non lo stiamo scrivendo in una posizione spesso hijackata, e WerFault.exe (o qualsiasi processo tu scelga di utilizzare) non è realmente associato ai DLL hijack nel modo in cui lo sono cose come WmiPrvSE.exe.
È interessante notare che è quasi più visibile farlo con lo spoofing del PPID che senza. Tuttavia, questo può variare a seconda del prodotto di sicurezza.
Come accennato, è essenziale che gli utenti scarichino le DLL reali dalla macchina target su cui intendono utilizzare DropSpawn. Utilizzare la versione sbagliata di una DLL può causare il crash del processo generato se tenta di chiamare una funzione che non esiste.
DropSpawn può essere utilizzato con eseguibili al di fuori di System32; tuttavia, si avverte che possono sorgere problemi se il processo tenta di caricare DLL aggiuntive dalla directory dell'applicazione reale del processo. Poiché abbiamo falsificato la directory dell'applicazione altrove, se la directory dell'applicazione reale non è comunque raggiungibile tramite l'ordine di ricerca delle DLL, il processo si bloccherà/non riuscirà ad avviarsi perché non può individuare DLL essenziali. Testare sempre i potenziali hijack su macchine di sviluppo prima di utilizzarli in produzione!
Questa ricerca è nata mentre esploravo come i processi assemblano il loro ordine finale di ricerca delle DLL (poiché deve essere determinato in fase di esecuzione a causa degli eseguibili che risiedono in directory diverse, la directory corrente che fa parte del percorso di ricerca, ecc.). La mia ricerca mi ha portato a questo post del forum, che è servito come origine delle due API critiche non documentate che sono centrali per questa tecnica.
Sono già stati linkati in precedenza, ma questo post riguardante l'evitare il loader lock, questo script per generare un file .def per il proxy DLL, e questa ricerca sull'abilitare l'auto-cancellazione degli eseguibili in esecuzione sono essenziali per produrre payload DLL efficaci e weaponizzati adatti a DropSpawn.
Quando ho pubblicato per la prima volta questa tecnica su Twitter, diverse altre persone si sono unite alla conversazione e hanno prodotto POC. SecurityAndStuff ha prodotto questo, mentre Snovvcrash ha il suo qui