Análise binária paralela com IDA Pro, nomeação de funções alimentada por IA, grafo de conhecimento Neo4j e motor de emulação/hooking/fuzzing phantomrt para engenharia reversa automatizada em formatos PE, ELF e NSO.
Fantasma através dos binários.
Um assistente de engenharia reversa local com inteligência artificial: análise paralela do IDA Pro, nomeação de funções por IA, um terminal que não é ruim, um grafo de conhecimento Neo4j de tudo que já descobriu e um servidor MCP para que Claude possa pesquisar e encadear diretamente nesse grafo.
E agora — com phantomrt — não apenas lê as paredes. Ele as atravessa: emula, faz hook e fuzza as funções que nomeou, e escreve de volta no grafo o que realmente acontece.
✓ 00 ✓ 01 ✓ 02 ✓ 03 ▸ 04 · 05 · 06 · 07 ✓ 08 ✓ 09 ✓ 10 ✓ 11 ✓ 12 ✓ 13 ▸ 14 · 15
14/16 shards │ 141,203 functions found ████████████████████████████░░░░ 89% ~4s remaining
## O que é
A análise automática do IDA Pro é single-threaded. Em uma DLL il2cpp de 34 MB, são *minutos*. spectrIDA divide o binário em N fragmentos, executa-os em paralelo via idalib, mescla em um único `.i64` e, em seguida, permite que um modelo 8B ajustado **nomeie cada função** — tudo a partir de uma única interface de terminal com tema cyberpunk e exatamente a quantidade certa de sarcasmo.
Esse é o Capítulo 1, e ele se sustenta por si só: pura velocidade, sem necessidade de IA se você não quiser.
O Capítulo 2 transforma a saída em algo que sobrevive à sessão — um grafo Neo4j no qual um cliente MCP (Claude, [pi](https://pi.dev), qualquer um que fale MCP) pode realmente viver, em vez de você copiar e colar a saída do descompilador em uma janela de chat, uma função de cada vez:```
Binary ─▶ Parallel IDA Analysis ─▶ Demangle ─▶ AI Naming ─▶ Neo4j Graph ─▶ MCP Server ─▶ Claude
(N idalib shards) (free, real) (stripped (persists, (search/chain/
leftovers forever, rename, live)
only) across sessions)
Capítulo 3 (phantomrt) adiciona a metade que ferramentas estáticas nunca têm: ele executa o código. Emula uma função sem SO (funciona em binários que você não consegue nem executar, como um .nso do Switch), ou hooks o processo ativo, ou faz fuzzing — e carimba o veredito (crashes / needs live state / clean) no mesmo nó do grafo que o nome.
A descrição completa, incluindo o que ainda está na lista de pendências, está nos Capítulo 2 e Capítulo 3.
Não é o Ghidra. Ele faz uma coisa irritante (análise lenta + nomeação) rapidamente, e é genuinamente divertido de usar. 199 downloads falam por si mesmos.
Sem nuvem. Sem telemetria. Executa totalmente na sua máquina.
| task | time |
|---|---|
| Among Us DLL — single-threaded IDA | ~4 hours |
| Among Us DLL — spectrIDA (16 workers) | 67 seconds |
| 153,649 function binary — full naming pass | overnight |
| Binary overview (what does this thing do?) | ~30 seconds |
Hardware usado nas medições: AMD Ryzen 7 5800X3D (8C/16T), 32 GB RAM, RTX 4070 12 GB. Hardware diferente altera os números de análise paralela (mais núcleos, mais shards, mais rápido); os números de nomeação são majoritariamente limitados pela GPU. Os números de 4 horas/67 segundos do Among Us são anteriores ao Capítulo 2 e não são re-verificados de forma independente em cada versão — execute spectrida analyze novamente se quiser um número para sua própria máquina e binário, os resultados variam com a densidade de shards e o tamanho do binário.
Números realmente re-verificados durante o desenvolvimento do Capítulo 2, mesmo hardware:
| binary | functions | task | time / result |
|---|---|---|---|
| test_small.dll (PE) | 189 | parallel analysis, 4 workers, CLI | 6.4s |
| test_small.dll (PE) | 164 | full MCP pipeline (analyze + demangle + graph write) | 9.8s |
| main.nso — Mario Odyssey (NSO), 16 workers | 28,038 seed functions | parallel sharded scan phase | 54.5s |
| main.nso — Mario Odyssey (NSO), 16 workers | 74,790 total functions | + merge/full-analysis phase | 143.1s |
| main.nso — Mario Odyssey (NSO), 16 workers | 74,790 total functions | end-to-end wall time | 197.6s |
| main.nso — Mario Odyssey (NSO) | 74,790 | resolved via demangling alone (Itanium ABI, free, no AI) | 67,300 (90.0%) |
Essa linha do NSO é o equivalente real da antiga alegação de "4 horas → 67 segundos" do Among Us, medida novamente nesta versão em um binário do Switch com 74.790 funções, sem envolvimento de IA na nomeação (apenas demangling — populate=False). A fase paralela (16 núcleos, ~55s) faz a descoberta inicial fragmentada; a fase de mesclagem (~143s) é single-threaded por design — um banco de dados IDA, um escritor — então se você olhar o Gerenciador de Tarefas durante essa parte e ver 15 núcleos dormindo, isso não é um relatório de bug, é física.
Conseguir um número honesto aqui foi sua própria pequena história de terror. A primeira versão do suporte a NSO rodou limpo, saiu com código 0, e orgulhosamente retornou 727 funções para um binário que tem aproximadamente 75.000 delas — não uma falha, apenas espetacularmente, confiantemente errado, o que é de alguma forma pior. Acontece que o IDA não tem um carregador nativo para NSO, então o arquivo foi carregado silenciosamente como x86 simples ("metapc") mesmo que o Switch seja ARM64 desde o lançamento. Cada shard executou um scanner de prólogo x86 contra instruções puramente AArch64 e chamou de "função" qualquer coisa que acidentalmente correspondesse. Corrigir a arquitetura não resolveu nada por si só, porque o binário também ainda estava comprimido em LZ4 na memória — então metade do que foi escaneado era, generosamente, ruído. E mesmo depois de devidamente descomprimido e marcado como AArch64, cada shard estava apenas caçando alvos de chamada dentro de sua própria fatia minúscula do binário, perdendo toda chamada que cruzava o limite do shard — o que em um binário deste tamanho é a maioria delas. Três bugs, um número, e nenhum deles teve a decência de lançar uma exceção. (Também tentamos reduzir a fase de mesclagem pulando a análise de stack frame do IDA — conseguimos uma bela aceleração e um banco de dados onde o Hex-Rays educadamente se recusou a descompilar metade dele. Isso foi revertido rapidamente. Mantivemos a omissão muito menor e muito mais segura da assinatura FLIRT, que vale uns ~3% dignos de um encolher de ombros e não quebrou nada, o que neste ponto parecia um traço de personalidade que valia a pena manter.)
Sobre a precisão da nomeação: não é verdade absoluta no nível do Ghidra, é um modelo de 8B adivinhando a partir de pseudocódigo. Helpers/getters genéricos tendem a acertar bem; lógica profundamente específica de jogos é mais um cara ou coroa. Renomeie qualquer coisa que ele errar — é por isso que rename_function persiste diretamente de volta no grafo.