
Framework di emulazione binaria scriptabile che integra IDA Pro/Radare2 con il motore Unicorn per l'analisi automatizzata di malware, la decifrazione di stringhe e l'esplorazione di percorsi di codice su architetture x86, ARM e ARM64.
flare-emu unisce un framework di analisi binaria supportato, come IDA Pro o Radare2, con il framework di emulazione Unicorn per fornire all'utente un'interfaccia facile da usare e flessibile per scrivere script di emulazione. È progettato per gestire tutte le attività di manutenzione necessarie per impostare un emulatore flessibile e robusto per le architetture supportate, in modo che tu possa concentrarti sulla risoluzione dei problemi di analisi del codice. Attualmente, flare-emu supporta le architetture x86, x86_64, ARM e ARM64.
Attualmente fornisce cinque diverse interfacce per soddisfare le tue esigenze di emulazione, insieme a una serie di funzioni helper e utility correlate.
emulateRange – Questa API viene utilizzata per emulare un intervallo di istruzioni, o una funzione, all'interno di un contesto specificato dall'utente. Fornisce opzioni per hook definiti dall'utente sia per singole istruzioni che per quando vengono incontrate istruzioni "call". L'utente può decidere se l'emulatore salterà o chiamerà le funzioni. Questa interfaccia fornisce un modo semplice per l'utente di specificare valori per registri e argomenti dello stack. Se viene specificata una stringa di byte, viene scritta nella memoria dell'emulatore e il puntatore viene scritto nel registro o nella variabile dello stack. Dopo l'emulazione, l'utente può utilizzare le funzioni utility di flare-emu per leggere dati dalla memoria emulata o dai registri, oppure utilizzare l'oggetto di emulazione Unicorn restituito per un'analisi diretta. Una piccola funzione wrapper per emulateRange, chiamata emulateSelection, può essere utilizzata per emulare l'intervallo di istruzioni attualmente evidenziato in IDA Pro.
iterate - Questa API viene utilizzata per forzare l'emulazione lungo rami specifici all'interno di una funzione per raggiungere un determinato target. L'utente può specificare un elenco di indirizzi target, o l'indirizzo di una funzione da cui viene utilizzato un elenco di cross-reference alla funzione come target, insieme a un callback per quando un target viene raggiunto. I target verranno raggiunti, indipendentemente dalle condizioni durante l'emulazione che potrebbero aver causato l'assunzione di rami diversi. Come l'API emulateRange, vengono fornite opzioni per hook definiti dall'utente sia per singole istruzioni che per quando vengono incontrate istruzioni "call". Un esempio di utilizzo dell'API iterate è ottenere qualcosa di simile a ciò che fa il nostro strumento argtracker.
iterateAllPaths - Questa API è molto simile a iterate, tranne per il fatto che invece di fornire un indirizzo target o indirizzi, fornisci una funzione target di cui cercherà di trovare tutti i percorsi ed emularli. Questo è utile quando si esegue un'analisi del codice che vuole raggiungere ogni blocco base di una funzione.
emulateBytes – Questa API fornisce un modo per emulare semplicemente un blob di shellcode estraneo. I byte forniti non vengono aggiunti all'IDB e vengono semplicemente emulati così come sono. Questo può essere utile per preparare l'ambiente di emulazione. Ad esempio, flare-emu stesso utilizza questa API per manipolare un Model Specific Register (MSR) per la CPU ARM64 che non è esposto da Unicorn per abilitare le istruzioni Vector Floating Point (VFP) e l'accesso ai registri. L'oggetto di emulazione Unicorn viene restituito per ulteriori analisi da parte dell'utente.
emulateFrom - Questa API è utile nei casi in cui i confini delle funzioni non sono chiaramente definiti, come spesso accade con binari offuscati o shellcode. Fornisci un indirizzo di partenza ed emulerà fino a quando non rimane nulla da emulare o interrompi l'emulazione in uno dei tuoi hook. Con IDA Pro, questo può essere chiamato con il parametro strict impostato su False per abilitare la scoperta dinamica del codice; flare-emu farà sì che IDA Pro crei le istruzioni man mano che vengono incontrate durante l'emulazione.
Per installare flare-emu per IDA Pro, basta copiare flare_emu.py, flare_emu_ida.py e flare_emu_hooks.py nella directory python di IDA Pro e importarlo come modulo nei tuoi script IDAPython.
Per installare flare-emu per Rizin, assicurati semplicemente che flare_emu.py, flare_emu_rizin.py e flare_emu_hooks.py siano nel percorso di ricerca di Python per importare moduli. Quando si utilizza Rizin come componente di analisi binaria per flare-emu, è richiesto rzpipe.
Per installare flare-emu per Radare2, assicurati semplicemente che flare_emu.py, flare_emu_radare.py e flare_emu_hooks.py siano nel percorso di ricerca di Python per importare moduli. Quando si utilizza Radare2 come componente di analisi binaria per flare-emu, è richiesto r2pipe.
In ogni caso, flare-emu dipende da Unicorn e dai suoi binding Python.
NOTA IMPORTANTE
flare-emu è stato scritto utilizzando la nuova API di IDA Pro 7x, non è compatibile con le versioni precedenti di IDA Pro.
Sebbene flare-emu possa essere utilizzato per risolvere molti diversi problemi di analisi del codice, uno dei suoi usi più comuni è quello di aiutare a decifrare le stringhe nei binari malware. FLOSS è un ottimo strumento che spesso può farlo automaticamente per te cercando di identificare le funzioni di decifratura delle stringhe e utilizzando l'emulazione per decifrare le stringhe passate in ogni cross-reference ad essa. Tuttavia, non è possibile per FLOSS essere sempre in grado di identificare queste funzioni ed emularle correttamente utilizzando i suoi approcci generici. A volte devi fare un piccolo lavoro extra, ed è qui che flare-emu può farti risparmiare molto tempo una volta che ti senti a tuo agio con esso. Esaminiamo uno scenario comune che un analista malware incontra quando ha a che fare con stringhe crittografate.
Hai identificato la funzione per decifrare tutte le stringhe in un binario x86_64. Questa funzione viene chiamata ovunque e decifra molte stringhe diverse. In IDA Pro, dai un nome a questa funzione decryptString. Ecco il tuo script flare-emu per decifrare tutte queste stringhe e inserire commenti con le stringhe decifrate in ogni chiamata di funzione, oltre a registrare ogni stringa decifrata e l'indirizzo in cui è stata decifrata.```
from future import print_function
import flare_emu
def decrypt(argv): myEH = flare_emu.EmuHelper() myEH.emulateRange(myEH.analysisHelper.getNameAddr("decryptString"), registers = {"arg1":argv[0], "arg2":argv[1], "arg3":argv[2], "arg4":argv[3]}) return myEH.getEmuString(argv[0])
def iterateCallback(eh, address, argv, userData): s = decrypt(argv) print("%s: %s" % (eh.hexString(address), s)) eh.analysisHelper.setComment(address, s, False)
if name == 'main':
eh = flare_emu.EmuHelper()
eh.iterate(eh.analysisHelper.getNameAddr("decryptString"), iterateCallback)
In `__main__`, iniziamo creando un'istanza della classe `EmuHelper` da `flare-emu`. Questa è la classe che usiamo per fare tutto con `flare-emu`. Successivamente, utilizziamo l'API `iterate`, fornendole l'indirizzo della nostra funzione `decryptString` e il nome della nostra funzione di callback che `EmuHelper` chiamerà per ogni riferimento incrociato emulato.