
Crittografo polimorfico che trasforma file shellcode, PE e COFF in payload offuscati e indipendenti dalla posizione, con crittografia RC4 e cifrario a blocchi casuale, più generazione di istruzioni spazzatura utilizzando la libreria AsmJit.
Presentato a
Shoggoth è un progetto open-source basato su C++ e sulla libreria asmjit utilizzato per cifrare polymorphicamente shellcode, file PE e COFF forniti.
Shoggoth genera un file di output che memorizza il payload e il suo corrispondente loader in forma offuscata. Poiché il contenuto dell'output è indipendente dalla posizione, può essere eseguito direttamente come shellcode. Durante l'esecuzione del payload, si decifra autonomamente a runtime. Oltre alla routine di cifratura, Shoggoth aggiunge anche istruzioni spazzatura, che non cambiano nulla, tra le routine.
Ho iniziato a sviluppare questo progetto per studiare diversi approcci di generazione dinamica di istruzioni, pratiche di assembly e rilevamenti di firme. Prevedo di aggiornare regolarmente il repository con i miei nuovi apprendimenti.
Le funzionalità attuali sono elencate di seguito:
Il flusso di esecuzione generale di Shoggoth per un file di input può essere visto nell'immagine sottostante. Puoi osservare questo flusso con le configurazioni predefinite.
In pratica, Shoggoth unisce prima lo shellcode del loader precompilato in base alla modalità scelta (file COFF o PE) e al file di input. Quindi aggiunge a questo payload unito multiple istruzioni spazzatura che genera. Lo stub contenente il loader, l'istruzione spazzatura e il payload viene cifrato prima con la cifratura RC4 e poi con una cifratura a blocchi generata casualmente combinando i corrispondenti decifratori. Infine, aggiunge un'istruzione spazzatura al blocco risultante.
Mentre Shoggoth genera casualmente istruzioni per stub spazzatura o routine di cifratura, utilizza la libreria AsmJit.
AsmJit è una libreria leggera per la generazione di codice macchina scritta in C++. Può generare codice macchina per le architetture X86, X86_64 e AArch64 e supporta le istruzioni di base e tutte le estensioni recenti. AsmJit consente di specificare codici operativi, registri, operandi immediati, etichette di chiamata e di incorporare valori arbitrari in qualsiasi offset all'interno del codice. Durante la generazione di alcune istruzioni assembly usando AsmJit, è sufficiente chiamare la funzione API che corrisponde all'operazione assembly richiesta con i valori degli operandi assembly della classe Assembler. Per ogni chiamata API, AsmJit memorizza le informazioni sul codice e il riposizionamento nella sua struttura interna CodeHolder. Dopo aver chiamato le funzioni API di tutti i comandi assembly da generare, la sua classe JitRuntime può essere utilizzata per copiare il codice da CodeHolder in memoria con permesso di esecuzione e riposizionarlo.
Mentre cercavo una libreria di generazione di codice, mi sono imbattuto in AsmJit e ho visto che è ampiamente utilizzata da molti progetti popolari. Ecco perché ho deciso di usarla per le mie esigenze. Non so se Shoggoth sia il primo progetto a usarla nel contesto del red team, ma credo che possa essere un riferimento per implementazioni future.
Shoggoth può essere utilizzato per cifrare file PE e COFF dati in modo che entrambi possano essere eseguiti come shellcode grazie a loader precompilati indipendenti dalla posizione. Ho semplicemente usato il metodo C to Shellcode per ottenere la versione PIC di noti loader PE e COFF che ho modificato per i miei vecchi progetti. Per la compilazione, ho usato il Makefile del progetto HandleKatz che è un dump LSASS in forma PIC.
In pratica, per ottenere shellcode con la tecnica C to Shellcode, ho rimosso tutte le variabili globali nel codice sorgente del loader, ho memorizzato tutte le stringhe nello stack e ho risolto gli indirizzi delle funzioni API di Windows caricando e analizzando le DLL necessarie a runtime. Successivamente, ho determinato il punto di ingresso con un linker script e ho compilato il codice usando MinGW con vari flag di compilazione. Ho estratto la sezione .text del file eseguibile generato e ho ottenuto lo shellcode del loader. Poiché il file eseguibile ottenuto dopo la modifica del codice come sopra non contiene sezioni diverse dalla sezione .text, il codice in questa sezione può essere utilizzato come indipendente dalla posizione.
Il codice sorgente di questi può essere visualizzato e modificato dalle directory COFFLoader e PELoader. Inoltre, le versioni compilate di questi codici sorgente si trovano nella directory stub. Per ora, se vuoi modificare o cambiare questi loader, devi rispettare le firme e sostituire i binari precompilati dalla directory stub.
Per passare argomenti a un BOF, usa l'opzione '--coff-arg'. Shoggoth si aspetta una stringa esadecimale preformattata contenente gli argomenti impacchettati, che può essere creata usando lo script beacon_generate.py di TrustedSec. Una copia di questo script è stata inclusa come COFFArgGenerator/beacon_generate.py. (Molte grazie a @Octoberfest7)
Shoggoth utilizza prima uno dei cifrari a flusso, l'algoritmo RC4, per cifrare il payload che ottiene. Dopo aver generato casualmente la chiave utilizzata qui, cifra il payload con quella chiave. Lo stub decifratore, che decifra il payload durante il runtime, viene creato dinamicamente e assemblato usando AsmJit. I registri utilizzati nello stub vengono selezionati casualmente per ogni campione.
Ho fatto riferimento al codice di Nayuki per l'implementazione dell'algoritmo RC4 che ho usato in Shoggoth.
Dopo aver eseguito la prima cifratura, Shoggoth utilizza la seconda cifratura che è un cifrario a blocchi generato casualmente. Con la seconda cifratura, cifra sia il decifratore RC4 sia opzionalmente lo stub che contiene il payload, le istruzioni spazzatura e il loader cifrato con RC4. Divide il blocco da cifrare in blocchi da 8 byte e utilizza istruzioni generate casualmente per ogni blocco. Queste istruzioni includono ADD, SUB, XOR, NOT, NEG, INC, DEC, ROL e ROR. Anche gli operandi per queste istruzioni vengono selezionati casualmente.
La logica delle istruzioni spazzatura generate è fortemente ispirata dall'incredibile progetto SGN di Ege Balci. Shoggoth può selezionare istruzioni spazzatura basate sul salto sopra byte casuali, istruzioni senza effetti collaterali, chiamate di funzione false e istruzioni che hanno effetti collaterali ma mantengono i valori iniziali. Tutte queste istruzioni vengono selezionate casualmente e generate chiamando le corrispondenti funzioni API della libreria AsmJit. Inoltre, per aumentare sia la dimensione che le diverse combinazioni, queste funzioni di generazione vengono chiamate ricorsivamente.
Ci sono molti punti in cui le istruzioni spazzatura possono essere inserite nella prima versione di Shoggoth. Ad esempio, possiamo mettere istruzioni spazzatura tra le istruzioni del cifrario a blocchi o le istruzioni del cifrario RC4. Tuttavia, per scopi dimostrativi, le ho lasciate per le versioni successive per evitare la complessità aggiuntiva dei payload generati.
Non ho compilato il progetto principale. Ecco perché devi compilare tu stesso. Opzionalmente, se vuoi modificare il codice sorgente del loader PE o del loader COFF, devi avere MinGW sulla tua macchina per compilarli usando i Makefile forniti.
______ _ _
/ _____) | _ | |
( (____ | |__ ___ ____ ____ ___ _| |_| |__
\____ \| _ \ / _ \ / _ |/ _ |/ _ (_ _) _ \
_____) ) | | | |_| ( (_| ( (_| | |_| || |_| | | |
(______/|_| |_|\___/ \___ |\___ |\___/ \__)_| |_|
(_____(_____|
by @R0h1rr1m
"Tekeli-li! Tekeli-li!"
Usage of Shoggoth.exe:
-h | --help Show the help message.
-v | --verbose Enable more verbose output.
-i | --input <Input Path> Input path of payload to be encrypted. (Mandatory)
-o | --output <Output Path> Output path for encrypted input. (Mandatory)
-s | --seed <Value> Set seed value for randomization.
-m | --mode <Mode Value> Set payload encryption mode. Available mods are: (Mandatory)
[*] raw - Shoggoth doesn't append a loader stub. (Default mode)
[*] pe - Shoggoth appends a PE loader stub. The input should be valid x64 PE.
[*] coff - Shoggoth appends a COFF loader stub. The input should be valid x64 COFF.
--coff-arg <Argument> Set argument for COFF loader. Generate this string using COFFArgGenerator/beacon_generate.py.
example: --coff-arg 0a0000000600000068656c6c6f00
Only used in COFF loader mode. (Thanks to @Octoberfest7)
-k | --key <Encryption Key> Set first encryption key instead of random key.
--dont-do-first-encryption Don't do the first (stream cipher) encryption.
--dont-do-second-encryption Don't do the second (block cipher) encryption.
--encrypt-only-decryptor Encrypt only decryptor stub in the second encryption.
"Era una cosa terribile, indescrivibile, più vasta di qualsiasi treno della metropolitana: un informe ammasso di bolle protoplasmatiche, debolmente auto-luminescente, e con miriadi di occhi temporanei che si formavano e si deformavano come pustole di luce verdastra su tutta la parte anteriore che riempiva il tunnel, precipitandosi su di noi, schiacciando i frenetici pinguini e strisciando sul pavimento luccicante che essa e la sua specie avevano spazzato via così malvagiamente da ogni detrito." ~ H. P. Lovecraft, Alle montagne della follia
Uno Shoggoth è un mostro immaginario nel Mito di Cthulhu. Questi esseri furono menzionati di sfuggita nel ciclo di sonetti di H. P. Lovecraft Funghi da Yuggoth (1929–30) e successivamente descritti in dettaglio nel suo romanzo breve Alle montagne della follia (1931). Sono capaci di formare qualsiasi organo o appendice di cui abbiano bisogno per il compito da svolgere, sebbene il loro stato usuale sia una massa contorta di occhi, bocche e tentacoli guizzanti.
Poiché queste creature sono come una massa senziente di carne gelatinosa che si auto-modella e non hanno una forma fissa nelle descrizioni di Lovecraft, ho voluto dare quel nome a uno strumento di cifratura polimorfica. 🙂
Solo per test di sicurezza autorizzati. L'uso improprio di questo strumento contro sistemi senza autorizzazione esplicita è illegale.