Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
flare-emu — 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. | Kitploit
Ferramentas/GitHubGitHub/mandiant/flare-emu
Análise Dinâmica (Sandboxing)Engenharia ReversaAnálise de MalwareAnálise de Binários
GitHubmandiant/flare-emu

flare-emu

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.

Ver Repositório
95814341há 1 anoRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

flare-emu

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.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

Instalaçã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.

Uso

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.

Cenário Fácil de Descriptografia de Strings com IDA Pro

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)

root@kitploit:~
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.

A função `iterateCallback` recebe a instância do `EmuHelper`, chamada `eh` aqui, juntamente com o endereço da referência cruzada, os argumentos passados para esta chamada específica e um dicionário especial chamado `userData` aqui. `userData` não é usado neste exemplo simples, mas pense nele como um contexto persistente para o seu emulador, onde pode armazenar seus próprios dados personalizados. No entanto, tenha cuidado, porque o próprio `flare-emu` também usa este dicionário para armazenar informações críticas necessárias para executar suas tarefas. Um desses dados é a própria instância do `EmuHelper`, armazenada na chave `"EmuHelper"`. Se estiver interessado, procure no código-fonte para saber mais sobre este dicionário. Esta função de callback simplesmente chama a função `decrypt`, imprime a string decifrada e cria um comentário para ela no endereço daquela chamada para `decryptString`.

`decrypt` cria uma segunda instância de `EmuHelper` que é usada para emular a própria função `decryptString`, que irá decifrar a string para nós. O protótipo desta função `decryptString` é o seguinte: `char * decryptString(char *text, int textLength, char *key, int keyLength)`. Ela simplesmente decifra a string no local. A nossa função `decrypt` passa os argumentos recebidos pela função `iterateCallback` para a nossa chamada à API `emulateRange` do `EmuHelper`. Como este é um binário `x86_64`, a convenção de chamada usa registradores para passar argumentos, não a pilha. O `flare-emu` determina automaticamente quais registradores representam quais argumentos com base na arquitetura e formato de arquivo do binário, conforme determinado pelo IDA Pro, permitindo escrever código pelo menos um pouco independente de arquitetura. Se fosse `x86` de 32 bits, usaria o argumento `stack` para passar os argumentos, assim: `myEH.emulateRange(myEH.analysisHelper.getNameAddr("decryptString"), stack = [0, argv[0], argv[1], argv[2], argv[3]])`. O primeiro valor da pilha é o endereço de retorno em `x86`, então usamos `0` como valor de espaço reservado. Uma vez concluída a emulação, chamamos a API `getEmuString` para recuperar a string terminada em nulo armazenada no local de memória apontado pelo primeiro argumento passado à função.

### flare-emu e idalib
* instalar o IDA Pro
* instalar o idalib de acordo com o guia do utilizador da Hex-Rays
  * (ativar ambiente virtual)
  * pip install /path/to/IDA/installation/idalib/python
  * python /path/to/IDA/installation/idalib/python/py-activate-idalib.py [-d /path/to/active/IDA/installation]
* importar idapro e escrever o seu script
  * ver tests/test_flare_emu_idalib.py para um exemplo

### Cenário de Decifração Fácil de Strings com Rizin

Usando o mesmo exemplo acima, não muda muita coisa ao trabalhar com Rizin em vez
do IDA Pro. Uma diferença é que o `flare-emu` foi desenhado para ser executado
como um script de linha de comando ou dentro de um shell Python ao trabalhar com
Rizin. O shell Python é ótimo para resolução de problemas ad-hoc, enquanto o
script de linha de comando é ótimo para processamento em lote. A versão Rizin do
script acima se parece com isto (também pode omitir o caminho da amostra para
executá-lo dentro do rizin):```
from __future__ import print_function
import sys
import flare_emu


def decrypt(argv, eh):
  myEH = flare_emu.EmuHelper(samplePath=sys.argv[1], emuHelper=eh, isRizin=True)
  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, eh)
  print("%s: %s" % (eh.hexString(address), s))
  eh.analysisHelper.setComment(address, s, False)


if __name__ == "__main__":
  eh = flare_emu.EmuHelper(samplePath=sys.argv[1], isRizin=True)
  rz = eh.analysisHelper.r
  eh.analysisHelper.setName(0x100000D60, "decryptString")
  eh.iterate(eh.analysisHelper.getNameAddr("decryptString"), iterateCallback)

Cenário Simples de Descriptografia de String com Radare2

Usando o mesmo exemplo acima, não muda muita coisa ao trabalhar com Radare2 em vez de IDA Pro. Uma diferença é que o flare-emu atualmente é projetado para ser executado como um script de linha de comando ou dentro de um shell Python ao trabalhar com Radare2. O shell Python é ótimo para resolução de problemas ad-hoc, enquanto o script de linha de comando é ótimo para processamento em lote. A versão Radare2 do script acima se parece com isto:``` from future import print_function import flare_emu

def decrypt(argv, eh): myEH = flare_emu.EmuHelper(samplePath=sys.argv[1], emuHelper=eh) 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, eh) print("%s: %s" % (eh.hexString(address), s)) eh.analysisHelper.setComment(address, s, False)

if name == 'main':
eh = flare_emu.EmuHelper(samplePath=sys.argv[1]) eh.analysisHelper.setName(, "decryptString") eh.iterate(eh.analysisHelper.getNameAddr("decryptString"), iterateCallback)

root@kitploit:~
Há duas diferenças neste script. Primeiro, o construtor `EmuHelper` recebe um parâmetro aqui: `samplePath=sys.argv[1]`. Quando o parâmetro `samplePath` é fornecido, o `flare-emu` usará Radare2 com `r2pipe` como seu motor de análise binária. Você também pode ver que um segundo parâmetro é passado para a segunda instância `EmuHelper` criada na função `decrypt`. O parâmetro `emuHelper` recebe um objeto `EmuHelper` existente e clona sua memória ao criar o novo objeto. Além disso, se você estiver usando Radare2, a nova instância reutiliza a sessão existente do Radare2 em vez de criar uma nova, o que adicionaria mais sobrecarga. Segundo, `flare-emu` cria uma nova instância do Radare2 usando `r2pipe.open`, portanto, provavelmente não terá o nome `decryptString` para a função de interesse. Você pode definir o nome você mesmo usando o objeto `analysisHelper` do `EmuHelper` assim: `eh.analysisHelper.setName(<some address>, "decryptString")`, ou pode inserir diretamente o endereço para as chamadas a `iterate` e `emulateRange`.

## [Funções de Emulação](#emulationfuncs)
`emulateRange(startAddr, endAddr=None, registers=None, stack=None, instructionHook=None, callHook=None, memAccessHook=None, hookData=None, skipCalls=True, hookApis=True, strict=True, count=0)` - Emula o intervalo de instruções começando em `startAddress` e terminando em `endAddress`, não incluindo a instrução em `endAddress`. Se `endAddress` for `None`, a emulação para quando uma instrução do tipo "return" é encontrada dentro da mesma função em que a emulação começou.

* `registers` é um dicionário com chaves sendo nomes de registradores e valores sendo valores de registradores. Alguns nomes especiais de registradores são criados pelo `flare-emu` e podem ser usados aqui, como `arg1`, `arg2`, etc., `ret` e `pc`.

* `stack` é um array de valores a serem colocados na pilha em ordem inversa, assim como argumentos para uma função em `x86`. Em `x86`, lembre-se de considerar que o primeiro valor neste array é usado como endereço de retorno para uma chamada de função e não o primeiro argumento da função. `flare-emu` inicializará o contexto e a memória do thread emulado de acordo com os valores especificados nos argumentos `registers` e `stack`. Se uma string for especificada para qualquer um desses valores, ela será escrita em um local na memória e um ponteiro para essa memória será escrito no registrador ou localização de pilha especificada.

* `instructionHook` pode ser uma função que você define para ser chamada antes de cada instrução ser emulada. Ela tem o seguinte protótipo: `instructionHook(unicornObject, address, instructionSize, userData)`.

* `callHook` pode ser uma função que você define para ser chamada sempre que uma instrução do tipo "call" for encontrada durante a emulação. Ela tem o seguinte protótipo: `callHook(address, arguments, functionName, userData)`.

* `hookData` é um dicionário contendo dados definidos pelo usuário a serem disponibilizados para suas funções de hook. É uma forma de persistir dados durante toda a emulação. `flare-emu` também usa este dicionário para seus próprios fins, portanto, deve-se ter cuidado para não definir uma chave já definida. Esta variável é frequentemente chamada de `userData` em funções de hook definidas pelo usuário devido à sua nomenclatura no Unicorn.

* `skipCalls` fará com que o emulador pule instruções do tipo "call" e ajuste a pilha adequadamente, padrão é `True`.

* `hookApis` faz com que `flare-emu` execute uma implementação ingênua de algumas das funções mais comuns de runtime e bibliotecas do sistema operacional que encontra durante a emulação. Isso o liberta de ter que se preocupar com chamadas para funções como `memcpy`, `strcat`, `malloc`, etc., e o padrão é `True`.

* `memAccessHook` pode ser uma função que você define para ser chamada sempre que a memória for acessada para leitura ou escrita. Ela tem o seguinte protótipo: `memAccessHook(unicornObject, accessType, memAccessAddress, memAccessSize, memValue, userData)`.

* `strict`, quando definido como `True` (padrão), verifica os destinos dos branches para garantir que o desmontador espera instruções. Caso contrário, ele pula a instrução de branch. Se definido como `False` ao usar IDA Pro, o `flare-emu` criará instruções no IDA Pro à medida que as emula **(DESATIVE COM CUIDADO)**.

* `count` é o número máximo de instruções a emular, o padrão é `0`, o que significa sem limite.

`iterate(target, targetCallback, preEmuCallback=None, callHook=None, instructionHook=None, hookData=None, resetEmuMem=False, hookApis=True, memAccessHook=None)` - Para cada destino especificado por `target`, uma emulação separada é realizada desde o início da função que o contém até o endereço de destino. A emulação será forçada pelos branches necessários para alcançar cada destino. `target` pode ser o endereço de uma função, caso em que a lista de destinos é preenchida com todas as referências cruzadas para a função especificada. Ou, `target` pode ser uma lista explícita de destinos.

* `targetCallback` é uma função que você cria que será chamada pelo `flare-emu` para cada destino alcançado durante a emulação. Ela tem o seguinte protótipo: `targetHook(emuHelper, address, arguments, userData)`.

* `preEmuCallback` é uma função que você cria que será chamada antes da emulação para cada destino começar. Você pode implementar algum código de configuração aqui, se necessário.

* `resetEmuMem` fará com que `flare-emu` redefina a memória de emulação antes que a emulação de cada destino comece, o padrão é `False`.

`iterateAllPaths(target, targetCallback, preEmuCallback=None, callHook=None, instructionHook=None, hookData=None, resetEmuMem=False, hookApis=True, memAccessHook=None, maxPaths=MAXCODEPATHS, maxNodes=MAXNODESEARCH)` - Para a função que contém o endereço `target`, uma emulação separada é realizada para cada caminho descoberto através dela, até `maxPaths`.

* `maxPaths` - o número máximo de caminhos pela função que serão pesquisados e emulados. Algumas funções mais complexas podem fazer com que a função de busca em grafo demore muito ou nunca termine; ajuste este parâmetro para atender às suas necessidades em um tempo razoável.

* `maxNodes` - o número máximo de blocos básicos que serão pesquisados ao encontrar caminhos através da função alvo. Esta é uma medida de segurança para evitar tempos de pesquisa irracionais e travamentos e provavelmente não precisa ser alterada.

`emulateBytes(bytes, registers=None, stack=None, baseAddress=0x400000, instructionHook=None, hookData=None)` - Escreve o código contido em `bytes` na memória de emulação em `baseAddress` se possível e emula as instruções do início ao fim de `bytes`.

`emulateFrom(startAddr, registers=None, stack=None, instructionHook=None, callHook=None, memAccessHook=None, hookData=None, skipCalls=True, hookApis=True, strict=True, count=0)` - Esta API é útil em casos onde os limites da função não estão claramente definidos, como é frequentemente o caso com binários ofuscados ou shellcode. Você fornece um endereço inicial como `startAddr`, e ela emulará até que não haja mais nada para emular ou você pare a emulação em um de seus hooks. Isto pode ser chamado com o parâmetro `strict` definido como `False` para habilitar a descoberta dinâmica de código; o `flare-emu` fará com que o IDA Pro crie instruções à medida que elas são encontradas durante a emulação.

## [Funções Utilitárias](#utility)
A seguir está uma lista incompleta de algumas das funções utilitárias úteis fornecidas pela classe `EmuHelper`.

* `hexString(value)` - Retorna uma string formatada em hexadecimal para o valor. Útil para logging e instruções de impressão.

* `skipInstruction(userData, useAnalysisHelper=False)` - Chame isso de um hook de emulação para pular a instrução atual, movendo o contador de programa para a próxima instrução. A opção `useAnalysisHelper` foi adicionada para lidar com casos em que o framework de análise binária combina múltiplas instruções em uma pseudo-instrução e você deseja pular todas elas. Esta função não pode ser chamada várias vezes de um único hook de instrução para pular múltiplas instruções. Para pular múltiplas instruções, é recomendado não escrever diretamente no contador de programa se você estiver emulando código ARM, pois isso pode causar problemas com o modo thumb. Em vez disso, tente a API `changeProgramCounter` do `EmuHelper` (descrita abaixo).

* `changeProgramCounter(userData, newAddress)` - Chame isso de um hook de emulação para alterar o valor do registrador contador de programa. Esta API cuida do rastreamento do modo thumb para a arquitetura ARM.

* `getRegVal(registerName)` - Recupera o valor do registrador especificado, sendo sensível ao endereçamento de sub-registradores. Por exemplo, "ax" retornará os 16 bits inferiores do registrador EAX/RAX em `x86`.

* `stopEmulation(userData)` - Chame isso de um hook de emulação para parar a emulação. Use isso em vez de chamar a API `emu_stop` do Unicorn para que o objeto `EmuHelper` possa lidar com a contabilidade relacionada ao recurso `iterate`.

* `getEmuString(address)` - Retorna a string de caracteres localizada em um endereço na memória emulada, até um terminador nulo. Os caracteres não são necessariamente imprimíveis.

* `getEmuWideString(address)` - Retorna a string de "caracteres largos" localizada em um endereço na memória emulada, até um terminador nulo. "Caracteres largos" é usado de forma ampla aqui para se referir a qualquer série de bytes contendo um byte nulo a cada dois bytes, como seria o caso de uma string ASCII codificada em UTF-16 LE. Os caracteres não são necessariamente imprimíveis.

* `getEmuBytes(address, length)` - Retorna uma string de bytes localizada em um endereço na memória emulada.

* `getEmuPtr(address)` - Retorna o valor do ponteiro localizado no endereço dado.

* `writeEmuPtr(address, value)` - Escreve o valor do ponteiro no endereço dado na memória emulada.

* `loadBytes(bytes, address=None)` - Aloca memória no emulador e escreve os bytes nela.

* `isValidEmuPtr(address)` - Retorna `True` se o endereço fornecido aponta para memória emulada válida.

* `getEmuMemRegion(address)` - Retorna uma tupla contendo o endereço inicial e final da região de memória que contém o endereço fornecido, ou `None` se o endereço não for válido.

* `getArgv()` - Chame isso de um hook de emulação em uma instrução do tipo "call" para receber um array dos argumentos da função.

* `addApiHook(apiName, hook)` - Adiciona um novo hook de API para esta instância de `EmuHelper`. Sempre que uma instrução de chamada para `apiName` for encontrada durante a emulação, `EmuHelper` chamará a função especificada por `hook`. Se `hook` for uma string, espera-se que seja o nome de uma API já com hook registrado pelo `EmuHelper`, caso em que ele chamará sua função de hook existente. Se `hook` for uma função, ele chamará essa função.

* `allocEmuMem(size, addr=None)` - Aloca memória do emulador suficiente para conter `size` bytes. Ele tenta honrar o `address` solicitado, mas se sobrepor a uma região de memória existente, alocará em uma região de memória não utilizada e retornará o novo endereço. Se `address` não estiver alinhado a página, ele retornará um endereço que mantenha o mesmo offset de alinhamento de página dentro da nova região. Por exemplo, solicitar o endereço `0x1234` quando `0x1000` já está alocado, pode fazer com que ele aloque em `0x2000` e retorne `0x2234`.

# [Saiba Mais](#learn)
Para saber mais sobre **flare-emu**, leia nosso blog introdutório em https://www.fireeye.com/blog/threat-research/2018/12/automating-objective-c-code-analysis-with-emulation.html.
Baixar ferramenta