
Genera shellcode indipendente dalla posizione per x86, x64 o AMD64+x86 che carica assembly .NET, file PE e altri payload Windows dalla memoria e li esegue con parametri.

Versione corrente: v1.1
Donut è un codice indipendente dalla posizione che consente l'esecuzione in memoria di file VBScript, JScript, EXE, DLL e assembly .NET. Un modulo creato da Donut può essere ottenuto da un server HTTP oppure incorporato direttamente nel loader stesso. Il modulo è opzionalmente cifrato utilizzando il cifrario a blocchi Chaskey con una chiave a 128 bit generata casualmente. Dopo che il file viene caricato ed eseguito in memoria, il riferimento originale viene cancellato per scoraggiare gli scanner di memoria. Il generatore e il loader supportano le seguenti caratteristiche:
Sono disponibili librerie dinamiche e statiche sia per Linux che per Windows che possono essere integrate nei propri progetti. È disponibile anche un modulo Python di cui puoi saperne di più in Costruzione e utilizzo dell'estensione Python.
Donut contiene loader individuali per ogni tipo di file supportato. Per gli assembly .NET EXE/DLL, Donut utilizza l'API Unmanaged CLR Hosting API per caricare il Common Language Runtime. Una volta che il CLR è caricato nel processo host, viene creato un nuovo Application Domain per consentire l'esecuzione di Assembly in AppDomain usa e getta. Quando l'AppDomain è pronto, l'assembly .NET viene caricato tramite il metodo AppDomain.Load_3. Infine, il Punto di ingresso per gli EXE o il metodo pubblico per le DLL specificato dall'utente viene invocato con eventuali parametri aggiuntivi. Fare riferimento a MSDN per la documentazione sull'API Unmanaged CLR Hosting. Per un esempio autonomo di un host CLR, fare riferimento al codice qui.
I file VBScript e JScript vengono eseguiti utilizzando l'interfaccia IActiveScript. C'è anche un supporto minimo per alcuni dei metodi forniti da Windows Script Host (wscript/cscript). Per un esempio autonomo, fare riferimento al codice qui. Per una descrizione più dettagliata, leggere: Esecuzione in memoria di JavaScript, VBScript, JScript e XSL
I file EXE/DLL non gestiti o nativi vengono eseguiti utilizzando un loader PE personalizzato con supporto per Import ritardati, TLS e patch della riga di comando. Sono supportati solo i file con informazioni di rilocazione. Leggere Esecuzione in memoria di DLL per maggiori informazioni.
Il loader può disabilitare AMSI e WLDP per aiutare a eludere il rilevamento di file dannosi eseguiti in memoria. Per maggiori informazioni, leggere Come i Red Team bypassano AMSI e WLDP per il codice dinamico .NET. Supporta anche la decompressione dei file in memoria utilizzando aPLib o l'API RtlDecompressBuffer. Leggere Compressione dei dati per maggiori informazioni.
A partire dalla v1.0, anche ETW viene bypassato. Come con AMSI/WLDP, questo è un sistema modulare che ti permette di sostituire il bypass predefinito con il tuo. Il bypass predefinito è derivato dalla ricerca di XPN. Leggere Nascondere il tuo .NET - ETW per maggiori informazioni.
Per impostazione predefinita, il loader sovrascrive gli header PE dei PE non gestiti (dall'indirizzo di base a `IMAGE_OPTIONAL_HEADER.SizeOfHeaders`). Se non viene utilizzato un modulo fittizio (module overloading), gli header PE vengono azzerati. Se viene utilizzato un modulo fittizio, gli header PE del modulo fittizio vengono utilizzati per sovrascrivere quelli del modulo payload. Questo serve a scoraggiare il rilevamento confrontando gli header PE dei moduli in memoria con il file che li supporta su disco. L'utente può richiedere che tutti gli header PE siano conservati nel loro stato originale. Questo è utile in scenari in cui il modulo payload deve accedere ai propri header PE, ad esempio durante la ricerca di risorse PE incorporate.
Per una guida dettagliata all'uso del generatore e a come Donut influisce sulle tecniche operative, leggere Donut - Iniettare assembly .NET come shellcode. Per maggiori informazioni sul loader, leggere Caricare assembly .NET dalla memoria.
Chi desidera saperne di più sugli interni dovrebbe fare riferimento alle Note per sviluppatori.
Esistono due tipi di compilazione. Se desideri eseguire il debug di Donut, consulta la documentazione qui. In caso contrario, continua a leggere per la compilazione della release.
Da un prompt dei comandi di Windows o un terminale Linux, clona il repository.
git clone http://github.com/thewover/donut.git
Il passo successivo dipende dal sistema operativo e dal compilatore che decidi di utilizzare. Attualmente, il modello del generatore e del loader per Donut possono essere compilati con successo sia con Microsoft Visual Studio 2019 che con MingGW-64. Per utilizzare le librerie nel tuo progetto C/C++, fai riferimento agli esempi forniti qui.
Per generare il modello del loader, la libreria dinamica donut.dll, la libreria statica donut.lib e il generatore donut.exe. Avvia un prompt dei comandi per sviluppatori Microsoft Visual Studio x64, spostati nella directory in cui hai clonato il repository Donut e inserisci quanto segue:
nmake -f Makefile.msvc
Per fare lo stesso, ma usando MinGW-64 su Windows o Linux, spostati nella directory in cui hai clonato il repository Donut e inserisci quanto segue:
make -f Makefile.mingw
Per generare la libreria dinamica donut.so, la libreria statica donut.a e il generatore donut. Spostati nella directory in cui hai clonato il repository Donut e digita semplicemente make.
Donut può essere installato e utilizzato come modulo Python. Per installare dal sorgente è necessario pip per Python3. Per prima cosa, assicurati che le versioni precedenti di donut-shellcode non siano installate eseguendo il seguente comando sul terminale Linux o sul prompt dei comandi di Microsoft Visual Studio.
pip3 uninstall donut-shellcode
Dopo aver confermato che le versioni precedenti non sono più installate, esegui il seguente comando.
pip3 install .
Puoi anche installare Donut come modulo Python prelevandolo dal repository PyPi.
pip3 install donut-shellcode
Per maggiori informazioni, consulta Costruzione e utilizzo dell'estensione Python.
Costruzione del contenitore Docker.
docker build -t donut .
Esecuzione di Donut.
docker run -it --rm -v "${PWD}:/workdir" donut -h
Donut include molti altri eseguibili che possono essere compilati separatamente. Questi includono "hash.exe", "encrypt.exe","inject.exe" e "inject_local.exe". I primi due sono utilizzati nella generazione di shellcode. Gli ultimi due sono forniti per assistere nel test dello shellcode di Donut. "inject.exe" inietta un file binario grezzo (loader.bin) in un processo tramite il suo PID o nome del processo. "inject_local.exe" inietta un file binario grezzo nel proprio processo.
Per compilare questi eseguibili di supporto separatamente, puoi utilizzare il makefile MSVC. Ad esempio, per compilare "inject_local.exe" per testare il tuo shellcode Donut, puoi eseguire:
nmake inject_local -f Makefile.msvc
Sono stati forniti tag per ogni versione di rilascio di Donut che contengono gli eseguibili compilati.
Attualmente sono disponibili altri due generatori.
La seguente tabella elenca i parametri supportati dalla versione da riga di comando del generatore.
Ci sono alcuni requisiti specifici che il tuo payload deve soddisfare affinché Donut possa caricarlo con successo.
Gli eseguibili Cygwin utilizzano routine di inizializzazione che si aspettano che il processo host sia in esecuzione dal disco. Se eseguiti dalla memoria, il processo host probabilmente andrà in crash.
Ci sono quattro progetti compagni forniti con Donut:
Potresti voler aggiungere supporto per più tipi di payload, modificare il nostro set di funzionalità o integrare Donut nei tuoi strumenti esistenti. Abbiamo fornito una documentazione per sviluppatori. Ulteriori funzionalità sono lasciate come esercizio al lettore. I nostri suggerimenti:
Se hai domande o commenti su Donut, unisciti al canale #Donut nello Slack di BloodHound Gang
Non siamo responsabili per qualsiasi uso improprio di questo software o tecnica. Donut è fornito come dimostrazione dell'iniezione CLR e del caricamento in memoria tramite shellcode al fine di fornire ai red team un modo per emulare gli avversari e ai difensori un punto di riferimento per costruire analisi e mitigazioni. Ciò comporta inevitabilmente il rischio che autori di malware e attori malintenzionati ne facciano un uso improprio. Tuttavia, riteniamo che il beneficio netto superi il rischio. Speriamo che sia corretto. Nel caso in cui prodotti EDR o AV siano in grado di rilevare Donut tramite firme o pattern comportamentali, non aggiorneremo Donut per contrastare firme o metodi di rilevamento. Per non essere offesi, per favore non chiedete.
| Parametro | Argomento | Descrizione |
|---|---|---|
| -a | arch | Architettura di destinazione per il loader: 1=x86, 2=amd64, 3=x86+amd64 (predefinito). |
| -b | level | Comportamento per il bypass di AMSI/WLDP: 1=Nessuno, 2=Interrompi in caso di fallimento, 3=Continua in caso di fallimento (predefinito). |
| -k | headers | Conserva gli header PE: 1=Sovrascrivi (predefinito), 2=Conserva tutti |
| -j | decoy | Percorso opzionale del modulo fittizio per Module Overloading. |
| -c | class | Nome della classe opzionale (richiesto per DLL .NET). Può includere anche il namespace: es. namespace.classe |
| -d | name | Nome dell'AppDomain da creare per .NET. Se l'entropia è abilitata, ne verrà generato uno casualmente. |
| -e | level | Livello di entropia: 1=Nessuno, 2=Genera nomi casuali, 3=Genera nomi casuali + usa cifratura simmetrica (predefinito) |
| -f | format | Formato di output del loader salvato su file: 1=Binario (predefinito), 2=Base64, 3=C, 4=Ruby, 5=Python, 6=PowerShell, 7=C#, 8=Esadecimale |
| -m | name | Metodo o funzione opzionale per DLL (un metodo è richiesto per DLL .NET). |
| -n | name | Nome del modulo per lo staging HTTP. Se l'entropia è abilitata, ne viene generato uno casualmente. |
| -o | path | Specifica dove Donut deve salvare il loader. Predefinito: "loader.bin" nella directory corrente. |
| -p | parameters | Parametri/riga di comando opzionali tra virgolette per il metodo/funzione di DLL o EXE. |
| -r | version | Versione del runtime CLR. Utilizzato MetaHeader di default o v4.0.30319 se non disponibile. |
| -s | server | URL del server HTTP che ospiterà un modulo Donut. Le credenziali possono essere fornite nel seguente formato: https://username:[email protected]/ |
| -t | Esegue l'entrypoint di un EXE non gestito/nativo come thread e attende la fine del thread. | |
| -w | La riga di comando viene passata alla funzione DLL non gestita in formato UNICODE (l'ANSI è predefinito). | |
| -x | option | Determina come il loader deve uscire: 1=Esci dal thread (predefinito), 2=Esci dal processo, 3=Non uscire né pulire e blocca a tempo indeterminato |
| -y | addr | Crea un nuovo thread per il loader e continua l'esecuzione a un indirizzo che è un offset relativo all'eseguibile del processo host. Il valore fornito è l'offset. Questa opzione supporta loader che desiderano riprendere l'esecuzione del processo host dopo che Donut ha completato l'esecuzione. |
| -z | engine | Impacchetta/Comprimi il file di input: 1=Nessuno, 2=aPLib, 3=LZNT1, 4=Xpress, 5=Xpress Huffman. Attualmente, gli ultimi tre sono supportati solo su Windows. |
| Strumento | Descrizione |
|---|---|
| DemoCreateProcess | Un assembly .NET di esempio da utilizzare nei test. Accetta due parametri da riga di comando che specificano ciascuno un programma da eseguire. |
| DonutTest | Un semplice injector di shellcode in C# per testare Donut. Lo shellcode deve essere codificato in Base64 e copiato come stringa. |
| ModuleMonitor | Uno strumento proof-of-concept che rileva l'iniezione CLR così come viene eseguita da strumenti come Donut e execute-assembly di Cobalt Strike. |
| ProcessManager | Uno strumento di scoperta dei processi che gli operatori offensivi possono utilizzare per determinare in cosa iniettare e gli operatori difensivi per determinare cosa è in esecuzione, quali proprietà hanno quei processi e se hanno caricato o meno il CLR. |