
Framework de emulação binária programável que integra IDA Pro/Radare2 com o motor Unicorn para análise automatizada de malware, descriptografia de strings e exploração de caminhos de código nas arquiteturas x86, ARM e ARM64.
flare-emu combina um framework suportado de análise binária, como IDA Pro ou Radare2, com o framework de emulação Unicorn para fornecer ao usuário uma interface fácil de usar e flexível para script de tarefas de emulação. Ele é projetado para lidar com toda a administração de configurar um emulador flexível e robusto para suas arquiteturas suportadas, para que você possa se concentrar em resolver seus problemas de análise de código. Atualmente, flare-emu suporta as arquiteturas x86, x86_64, ARM e ARM64.
Atualmente, ele fornece cinco interfaces diferentes para atender às suas necessidades de emulação, juntamente com uma série de funções auxiliares e utilitárias relacionadas.
emulateRange – Esta API é usada para emular um intervalo de instruções, ou uma função, dentro de um contexto especificado pelo usuário. Ela fornece opções para hooks definidos pelo usuário tanto para instruções individuais quanto para quando instruções de "call" são encontradas. O usuário pode decidir se o emulador irá pular ou chamar funções. Esta interface fornece uma maneira fácil para o usuário especificar valores para determinados registradores e argumentos de pilha. Se uma string de bytes for especificada, ela é escrita na memória do emulador e o ponteiro é escrito no registrador ou variável de pilha. Após a emulação, o usuário pode usar as funções utilitárias do flare-emu para ler dados da memória ou registradores emulados, ou usar o objeto de emulação Unicorn que é retornado para sondagem direta. Uma pequena função wrapper para emulateRange, chamada emulateSelection, pode ser usada para emular o intervalo de instruções atualmente destacado no IDA Pro.
iterate - Esta API é usada para forçar a emulação por caminhos específicos dentro de uma função para alcançar um determinado destino. O usuário pode especificar uma lista de endereços de destino, ou o endereço de uma função da qual uma lista de referências cruzadas para a função é usada como destinos, juntamente com um callback para quando um destino é alcançado. Os destinos serão alcançados, independentemente das condições durante a emulação que possam ter feito com que caminhos diferentes fossem tomados. Como a API emulateRange, são fornecidas opções para hooks definidos pelo usuário tanto para instruções individuais quanto para quando instruções de "call" são encontradas. Um exemplo de uso da API iterate é alcançar algo semelhante ao que nossa ferramenta argtracker faz.
iterateAllPaths - Esta API é muito parecida com iterate, exceto que, em vez de fornecer um endereço ou endereços de destino, você fornece uma função de destino para a qual ela tentará encontrar todos os caminhos e emulá-los. Isso é útil quando você está realizando análise de código que deseja alcançar todos os blocos básicos de uma função.
emulateBytes – Esta API fornece uma maneira de simplesmente emular um bloco de shellcode externo. Os bytes fornecidos não são adicionados ao IDB e são simplesmente emulados como estão. Isso pode ser útil para preparar o ambiente de emulação. Por exemplo, o próprio flare-emu usa esta API para manipular um Model Specific Register (MSR) para a CPU ARM64 que não é exposto pelo Unicorn, a fim de habilitar instruções Vector Floating Point (VFP) e acesso a registradores. O objeto de emulação Unicorn é retornado para posterior sondagem pelo usuário.
emulateFrom - Esta API é útil em casos onde os limites da função não são claramente definidos, como é frequentemente o caso com binários ofuscados ou shellcode. Você fornece um endereço inicial, e ela emulará até que não haja mais nada para emular ou você pare a emulação em um de seus hooks. Com o IDA Pro, isso pode ser chamado com o parâmetro strict definido como False para habilitar a descoberta dinâmica de código; flare-emu fará o IDA Pro criar instruções à medida que são encontradas durante a emulação.
Para instalar o flare-emu para o IDA Pro, basta colocar flare_emu.py, flare_emu_ida.py e flare_emu_hooks.py no diretório python do seu IDA Pro e importá-lo como um módulo em seus scripts IDAPython.
Para instalar o flare-emu para o Rizin, basta garantir que flare_emu.py, flare_emu_rizin.py e flare_emu_hooks.py estejam no caminho de pesquisa do Python para importação de módulos. Ao usar o Rizin como componente de análise binária para o flare-emu, o rzpipe é necessário.
Para instalar o flare-emu para o Radare2, basta garantir que flare_emu.py, flare_emu_radare.py e flare_emu_hooks.py estejam no caminho de pesquisa do Python para importação de módulos. Ao usar o Radare2 como componente de análise binária para o flare-emu, o r2pipe é necessário.
Em qualquer caso, o flare-emu depende do Unicorn e de suas ligações Python.
NOTA IMPORTANTE
flare-emu foi escrito usando a nova API do IDA Pro 7x, não é compatível com versões anteriores do IDA Pro.
Embora o flare-emu possa ser usado para resolver muitos problemas diferentes de análise de código, um de seus usos mais comuns é ajudar na descriptografia de strings em binários de malware. FLOSS é uma ótima ferramenta que muitas vezes pode fazer isso automaticamente por você, tentando identificar a(s) função(ões) de descriptografia de string e usando emulação para descriptografar as strings passadas em cada referência cruzada a ela. No entanto, nem sempre é possível para o FLOSS identificar essas funções e emulá-las corretamente usando suas abordagens genéricas. Às vezes, você precisa trabalhar um pouco mais, e é aí que o flare-emu pode economizar muito tempo depois que você se sentir confortável com ele. Vamos percorrer um cenário comum que um analista de malware encontra ao lidar com strings criptografadas.
Você identificou a função para descriptografar todas as strings em um binário x86_64. Essa função é chamada em vários lugares e descriptografa muitas strings diferentes. No IDA Pro, você nomeia essa função como decryptString. Aqui está seu script flare-emu para descriptografar todas essas strings e colocar comentários com as strings descriptografadas em cada chamada de função, além de registrar cada string descriptografada e o endereço em que é descriptografada.```
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)
Em `__main__`, começamos por criar uma instância da classe `EmuHelper` do `flare-emu`. Esta é a classe que usamos para fazer tudo com o `flare-emu`. Em seguida, usamos a API `iterate`, fornecendo o endereço da nossa função `decryptString` e o nome da nossa função de callback que o `EmuHelper` chamará para cada referência cruzada emulada até ela.