
Analisi di Triage ad Alto Ottano
__ __ High Octane Triage Analysis __
|| _||______ __ __________ _____ ||
|| \||___ \__| ____/ ______/___ / ____\ ||
==||=====|| | __/ |/ \ /==| / __ \ __\===]|
'======|| | \ | | \_ _| \ ___/| | ||
||____ /__|___|__/ / | \____]| | ||
=========''====\/=========/ /==|__|=====|__|======'
\ /
\/
Il Binary Refinery™ è una raccolta di script Python che implementano trasformazioni di dati binari come compressione e cifratura.
Spesso ci riferiremo ad esso semplicemente come refinery, che è anche il nome del pacchetto corrispondente.
Gli script sono progettati per leggere l'input esclusivamente da stdin e scrivere l'output su stdout.
La filosofia principale è che ogni script dovrebbe essere un'unità nel senso che svolge un solo compito,
e le singole unità possono essere combinate in pipeline con l'operatore di pipe | sulla riga di comando per eseguire attività più complesse.
L'obiettivo principale del progetto è il triage di malware,
ed è un tentativo di implementare qualcosa come CyberChef sulla riga di comando.
Crea un ambiente virtuale Python. Serve Python 3.11 o successivo. Installa refinery così:
python -m pip install -U pip
python -m pip install -U binary-refinery[extended]
Esegui le unità con -h per imparare come funzionano, cerca nella documentazione o usa il comando binref per trovarle.
Guarda un video recente se vuoi vederlo in azione.
Ma leggi anche il resto di questo readme.
Non esiste un calendario delle release, ma le release avvengono molto frequentemente ed è consigliato aggiornare periodicamente. Le correzioni di bug non sono documentate al di fuori di GIT, ma tutte le altre modifiche (cioè le nuove funzionalità) sono documentate nel changelog. Seguimi su Mastodon per aggiornamenti sulle release particolarmente impattanti.
Il testo di aiuto che viene visualizzato quando si esegue un'unità con lo switch -h o --help è la sua documentazione principale.
La documentazione generata automaticamente contiene una raccolta di quell'output per ogni unità di primo livello,
ma contiene anche la specifica dei tre concetti fondamentali del toolkit:
framing, argomenti multibin e meta variabili.
La ricerca full-text della descrizione e del testo di aiuto per ogni unità è disponibile anche sulla riga di comando,
tramite il comando binref fornito. Riconoscendo il fatto che la documentazione di riferimento può essere alquanto arida,
c'è uno sforzo continuo per produrre una serie di tutorial; consiglio vivamente di darci un'occhiata.
Inoltre, raccolgo risorse aggiuntive (incluse alcune prodotte da terze parti) qui sotto.
[!NOTE]
Refinery è ancora in alpha e l'interfaccia può talvolta cambiare, cioè le unità e i parametri possono essere rimossi o rinominati. Quindi può capitare che specifiche righe di comando da video e post di blog più vecchi non funzionino più.
2021/08] OALabs è stato così gentile da lasciarmi mostrare il toolkit in un video dedicato.
Nel video, in sostanza, seguo il contenuto del
primo tutorial.2021/11] Johannes Bader ha scritto un fantastico post sul blog sull'analisi di malspam con binary refinery.2024/03] Malware Analysis For Hedgehogs ha realizzato un video sull'unpacking di un campione XWorm usando refinery.2024/11] the CyberYeti mi ha invitato in streaming per presentare refinery.2025/06] Sono stato di nuovo in streaming con the CyberYeti, questo è un po' più grezzo.
Tutti i bug che potete vedere qui sono stati corretti. 😉Le dimostrazioni includono ancora campioni dalla sezione degli esempi qui sotto e i tutorial.
The Binary Refinery è (c) 2019 Jesko Hüttenhain, e pubblicato sotto una 3-Clause BSD License. Questo repository contiene anche una copia del testo completo della licenza. Se vuoi fare qualcosa con esso che non è coperto da questa licenza, sentiti libero di contattare l'autore.
Refinery richiede almeno Python 3.11. Si consiglia di installarlo in un proprio ambiente virtuale: Il pacchetto può tirare dentro molte dipendenze, e installarlo nel tuo Python globale è alquanto soggetto a conflitti di versione. Inoltre, poiché il toolkit introduce un gran numero di nuovi comandi, c'è una buona probabilità che alcuni di questi entrino in conflitto su alcuni sistemi, e tenerli in un proprio ambiente virtuale separato è un modo per prevenirlo.
Se vuoi avere tutti i comandi di refinery disponibili nella tua shell in ogni momento (cioè senza dover passare a un ambiente virtuale personalizzato),
hai anche l'opzione di scegliere un prefisso per l'installazione,
che verrà anteposto a ogni shim di comando installato.
Ad esempio, se scegli r. come prefisso, allora l'unità emit verrà installata come comando r.emit.
Un vantaggio aggiuntivo è che puoi digitare r. e premere Tab due volte per ottenere un elenco di tutti i comandi refinery disponibili.
Nota però che nessun prefisso è assunto nella documentazione ed è un obiettivo di sviluppo di refinery non entrare in conflitto sulla maggior parte dei sistemi.
L'autore non usa un prefisso e fornisce questa opzione come rete di sicurezza.
Il modo più semplice per installare e aggiornare refinery è tramite pip. Assicurati di eseguire prima la versione più recente:
python -m pip install -U pip
Poi installa semplicemente il pacchetto refinery:
pip install -U binary-refinery
Se vuoi scegliere un prefisso per tutte le unità, puoi specificarlo tramite la variabile d'ambiente REFINERY_PREFIX.
Ad esempio, il seguente comando installerà refinery nell'ambiente Python corrente con prefisso r. su Linux:
REFINERY_PREFIX=r. pip install -U binary-refinery
Su Windows, dovresti eseguire i seguenti comandi:
set REFINERY_PREFIX=r.
pip install -U binary-refinery
Specificare il prefisso speciale ! avrà l'effetto che non verranno creati affatto comandi shell,
e binary refinery sarà installato solo come libreria.
Se vuoi installare l'attuale HEAD di refinery, puoi ripetere tutti i passaggi precedenti, specificando questo repository invece del pacchetto pip.
Ad esempio, il seguente comando installerà il commit più recente di refinery:
pip install -U git+git://github.com/binref/refinery.git
Infine, se stai usando REMnux, puoi usare il loro container docker refinery.
Se vuoi insegnare alla tua claude locale per l'analisi di malware a usare binary refinery, dai un'occhiata alla Binary Refinery Skill.
Quanto segue è un riepilogo di quanto bene sono attualmente supportati i vari ambienti shell:
Se stai usando una shell diversa e hai qualche feedback da condividere, fammelo sapere!
Ci sono alcune unità molto situazionali con dipendenze esterne (a volte grandi).
Ad esempio, stego è un'unità che richiede la libreria di parsing delle immagini Pillow.
Alcune librerie non sono installate di default per mantenere il tempo di installazione di refinery a un livello ragionevole per gli utenti alle prime armi.
Le unità corrispondenti ti diranno cosa fare quando la loro dipendenza è mancante:
$ emit config.png | stego RG
(13:37:00) failure in stego: dependency Pillow is missing; run pip install Pillow
Puoi quindi installare manualmente queste dipendenze mancanti. Se non vuoi essere infastidito dalle dipendenze mancanti e non ti dispiace una lunga installazione di refinery, puoi installare il pacchetto come segue:
pip install -U binary-refinery[all]
che installerà tutte le dipendenze oltre a quelle richieste. Più precisamente, sono disponibili le seguenti categorie extra:
| Nome | Dipendenze Incluse |
|---|---|
default | selezione raccomandata di dipendenze ragionevoli, scelta dell'autore |
extended | una selezione estesa, escludendo solo le più oscure |
all | tutte le dipendenze per tutte le unità di refinery |
Queste sono elencate qui in ordine crescente, cioè extended installerà tutto ciò che installerebbe default.
In alternativa, puoi clonare questo repository e usare gli script update.sh (su Linux) o update.ps1 (su Windows) per installare il pacchetto refinery in un ambiente virtuale locale. Il processo di installazione e aggiornamento per questo metodo consiste semplicemente nell'eseguire lo script:
binary-refinery,binary-refinery[all].Puoi anche generare tutta la documentazione localmente.
Per farlo, esegui lo script run-pdoc3.py.
Questo fallirà a meno che tu non lo esegua da un ambiente in cui binary refinery è stato installato come pacchetto Python.
Per eseguirlo, devi specificare il percorso di un ambiente virtuale come primo argomento della riga di comando di run-pdoc3.py,
il che farà sì che lo script si esegua di nuovo usando l'interprete di quell'ambiente.
Se sei certo di voler eseguire run-pdoc3.py,
c'è uno switch da riga di comando per forzare lo script a essere eseguito con l'interprete Python predefinito corrente.
Lo script installa il pacchetto pdoc3 e lo usa per generare una documentazione HTML per il pacchetto refinery.
La documentazione può quindi essere trovata nella sottodirectory html direttamente accanto a questo file readme.
I tutorial sono notebook Jupyter che puoi semplicemente eseguire ed eseguire se il tuo ambiente virtuale ha Jupyter installato. Vale la pena sottolineare che Visual Studio Code ha un supporto molto comodo per Jupyter.
Le unità emit e dump svolgono un ruolo speciale: la prima serve per emettere dati mentre la seconda serve per scaricare dati negli appunti o su disco. Come esempio, considera la seguente pipeline:
emit M7EwMzVzBkI3IwNTczM3cyMg2wQA | b64 | zl | hex
Qui, emettiamo la stringa M7EwMzVzBkI3IwNTczM3cyMg2wQA,
la decodifichiamo da base64 usando b64,
decomprimiamo il risultato con zlib usando zl,
e infine decodifichiamo da hex i dati decompressi.
Ogni unità esegue di default l'operazione di "decodifica" di una certa trasformazione, ma alcune di esse implementano anche l'operazione inversa.
Se lo fanno, questo avviene sempre fornendo lo switch da riga di comando -R, o --reverse.
Puoi produrre la stringa base64 di cui sopra usando il seguente comando perché hex, zl, e b64 forniscono tutti l'operazione inversa:
emit "Hello World" | hex -R | zl -R | b64 -R
Dato un file packed.bin contenente un buffer di payload codificato in base64, la seguente pipeline estrae detto payload in payload.bin:
emit packed.bin | carve -l -t1 b64 | b64 | dump payload.bin
L'unità carve può essere usata per ritagliare blocchi di dati dal buffer di input,
in questo caso cerca dati codificati in base64, li ordina per lunghezza (-l) e restituisce il primo di questi (-t1),
il che ritaglia il più grande blocco di dati che sembra base64 da packed.bin.
I dati vengono poi decodificati da base64 e scaricati nel file payload.bin.
L'unità pack, selezionerà tutte le espressioni numeriche da un buffer di testo e le trasformerà nella loro rappresentazione binaria. Un semplice esempio è la pipeline
emit "0xBA 0xAD 0xC0 0xFF 0xEE" | pack | hex -R
che produrrà la stringa BAADC0FFEE.
Estrai il più grande pezzo di dati codificati in base64 da un BLOB e decodificalo:
emit file.exe | carve -ds b64
Ritaglia un file ZIP da un buffer, scegli una DLL da esso e mostra informazioni su di essa:
emit file.bin | carve-zip | xtzip file.dll | pemeta
Elenca le sezioni di un file PE con il loro hash SHA-256 corrispondente:
emit file.exe | vsect [| sha256 -t | pf {} {path} ]]
Elenca ricorsivamente tutti i file nella directory corrente con il loro rispettivo hash SHA-256:
ef "**" [| sha256 -t | pf {} {path} ]]
Estrai indicatori da tutti i file enumerati ricorsivamente nella directory corrente:
ef "**" [| xtp -n6 ipv4 socket url email | dedup ]]
Converti l'indirizzo IP hard-coded 0xC0A80C2A in ordine di byte di rete in un formato leggibile:
emit 0xC0A80C2A | pack -EB4 | pack -R [| sep . ]
Esegui un brute force XOR a singolo byte e tenta di estrarre un payload di file PE in ogni iterazione:
emit file.bin | rep 0x100 [| xor v:index | carve-pe -R | peek | dump {name} ]
Estrai un server C2 RemCos:
emit c0019718c4d4538452affb97c70d16b7af3e4816d059010c277c4e579075c944 \
| perc SETTINGS [| put keylen cut::1 | rc4 cut::keylen | xtp socket ]
Estrai una configurazione AgentTesla:
emit fb47a566911905d37bdb464a08ca66b9078f18f10411ce019e9d5ab747571b40 \
| dnfields [| aes x::32 --iv x::16 -T ]] \
| rex -M "((??email))\n(.*)\n(.*)\n:Zone" addr={1} pass={2} host={3}
Estrai il payload PowerShell da un dropper macro XLS malevolo:
emit 81a1fca7a1fb97fe021a1f2cf0bf9011dd2e72a5864aad674f8fea4ef009417b [ \
| xlxtr 9.5:11.5 15.15 12.5:14.5 [ \
| scope -n 3 | chop -t 5 [| sorted -a | snip 2: | sep ] \
| pack 10 | alu --dec -sN B-S ]] \
| dump payload.cmd
E ottieni i domini per lo stadio successivo:
emit payload.cmd | cmdarg | ps1 | xtp -f domain
Estrai la configurazione di campioni HawkEye non impacchettati:
emit ee790d6f09c2292d457cbe92729937e06b3e21eb6b212bf2e32386ba7c2ff22c \
| put cfg perc[RCDATA]:c:: [\
| xtp guid | pbkdf2 48 rep[8]:h:00 | cca eat:cfg | aes -Q x::32 --iv x::16 ] \
| dnds
Warzone RAT:
emit 4537fab9de768a668ab4e72ae2cce3169b7af2dd36a1723ddab09c04d31d61a5 \
| vsect .bss | struct I{key:{}}{} [\
| rc4 eat:key | struct I{host:{}}{port:H} {host:u16}:{port} ]
Estrai il payload da un loader di shellcode e ritaglia il suo c2:
emit 58ba30052d249805caae0107a0e2a5a3cb85f3000ba5479fafb7767e2a5a78f3 \
| rex yara:50607080.* [| struct LL{s:L}{} | xor -B2 rand[s]:msvc | xtp url ]
Ottieni le macro VBA malevole da un tempo dimenticato in cui si faceva così:
emit ee103f8d64cd8fa884ff6a041db2f7aa403c502f54e26337c606044c2f205394 \
| vbamc
E poi estrai il payload del downloader malevolo:
emit ee103f8d64cd8fa884ff6a041db2f7aa403c502f54e26337c606044c2f205394 \
| doctxt | repl drp:c: | carve -s b64 | rev | b64 | rev | ppjscript
Estrai gli URL dei payload da un documento PDF malevolo:
emit 066aec7b106f669e587b10b3e3c6745f11f1c116f7728002f30c072bd42d6253 \
| xt JS | csd string | csd string | url | xtp url [| urlfix ]]
Estrai l'URL del payload da un documento exploit di equation editor:
emit e850f3849ea82980cf23844ad3caadf73856b2d5b0c4179847d82ce4016e80ee \
| officecrypt | xt oleObject | xt native | rex Y:E9[] | vstack -a=x32 -w=200 | xtp
Supponi che data sia un file che è stato cifrato con AES a 256 bit in modalità CBC.
La chiave è stata derivata dalla passphrase segreta swordfish usando la routine di derivazione chiave PBKDF2 con il salt s4lty.
L'IV è anteposto al buffer come primi 16 byte.
Può essere decifrato con la seguente pipeline:
emit data | aes --mode cbc --iv cut::16 pbkdf2[32,s4lty]:swordfish
Qui, sia cut:0:16 che pbkdf2[32,s4lty]:swordfish sono argomenti multibin che usano un handler speciale.
In questo caso, cut:0:16 estrae la slice 0:16 (cioè i primi 16 byte) dai dati di input - dopo l'applicazione di questo handler multibin,
i dati di input hanno i primi 16 byte rimossi e l'argomento iv è impostato esattamente su questi 16 byte.
L'argomento finale specifica la chiave di cifratura di 32 byte:
L'handler pbkdf2[32,s4lty] invece istruisce refinery a creare un'istanza dell'unità pbkdf2 come se le fossero stati dati i parametri da riga di comando 32 e s4lty in questo ordine e a processare la stringa di byte swordfish con questa unità.
Come semplice test, la seguente pipeline cifrerà e decifrerà un pezzo di testo di esempio:
emit "Once upon a time, at the foot of a great mountain ..." ^
| aes pbkdf2[32,s4lty]:swordfish --iv md5:X -R | ccp md5:X ^
| aes pbkdf2[32,s4lty]:swordfish --iv cut:0:16
| Shell | Piattaforma | Stato | Commento |
|---|
| Bash | Posix | 🔵 Buono | Usato occasionalmente dall'autore. |
| CMD | Windows | 🔵 Buono | Usato estensivamente dall'autore. |
| PowerShell | Windows | 🟡 Ragionevole | Funziona semplicemente se la versione di PowerShell è almeno 7.4. |
| Zsh | Posix | 🟠 Problemi Minori | In seguito a una discussione, c'è una correzione. |
| Fish | Posix | 🟠 Problemi Minori | Vedi issue #55 e discussione #22. |