Analyse binaire parallèle avec IDA Pro, nommage de fonctions assisté par IA, graphe de connaissances Neo4j et moteur d'émulation/hooking/fuzzing phantomrt pour la rétro-ingénierie automatisée des formats PE, ELF et NSO.
Fantôme à travers les binaires.
Un assistant de rétro-ingénierie local, alimenté par l'IA : analyse parallèle d'IDA Pro, nommage de fonctions par IA, un terminal qui ne pue pas, un graphe de connaissances Neo4j de tout ce qu'il a jamais compris, et un serveur MCP pour que Claude puisse rechercher et enchaîner directement dans ce graphe.
Et maintenant — avec phantomrt — il ne se contente pas de lire les murs. Il les traverse : il émule, accroche et fuzze les fonctions qu'il a nommées, et écrit ce qui se passe réellement sur le graphe.
✓ 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
## Ce que c'est
L'analyse automatique d'IDA Pro est monothread. Sur une DLL il2cpp de 34 Mo, cela prend *des minutes*. spectrIDA divise le binaire en N fragments, les exécute en parallèle via idalib, les fusionne en un seul `.i64`, puis laisse un modèle 8B finement ajusté **nommer chaque fonction** — le tout depuis une interface terminal avec un thème cyberpunk et exactement la bonne dose de sarcasme.
Voilà le chapitre 1, et il se suffit à lui-même : pure vitesse, aucune IA nécessaire si on n'en veut pas.
Le chapitre 2 transforme la sortie en quelque chose qui survit à la session — un graphe Neo4j dans lequel un client MCP (Claude, [pi](https://pi.dev), ou tout ce qui parle MCP) peut réellement vivre, au lieu que vous copiiez-colliez la sortie du décompilateur dans une fenêtre de chat une fonction à la fois :```
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)
Chapitre 3 (phantomrt) ajoute la moitié que les outils statiques n'ont jamais : il exécute le code. Émule une fonction sans OS (fonctionne sur des binaires que vous ne pouvez même pas lancer, comme un .nso de Switch), ou accroche le processus en direct, ou le fuzz — et appose le verdict (crashes / needs live state / clean) sur le même nœud de graphe que le nom.
Le détail complet, y compris ce qui reste sur la liste des tâches, se trouve dans le Chapitre 2 et le Chapitre 3.
Ce n'est pas Ghidra. Il fait une chose ennuyeuse (analyse lente + nommage) rapidement, et c'est vraiment amusant à utiliser. 199 téléchargements parlent d'eux-mêmes.
Pas de cloud. Pas de télémétrie. S'exécute entièrement sur votre machine.
| tâche | temps |
|---|---|
| DLL Among Us — IDA mono-thread | ~4 heures |
| DLL Among Us — spectrIDA (16 workers) | 67 secondes |
| Binaire de 153 649 fonctions — passage de nommage complet | nuit |
| Aperçu du binaire (que fait cette chose ?) | ~30 secondes |
Matériel sur lequel ces mesures ont été prises : AMD Ryzen 7 5800X3D (8C/16T), 32 Go de RAM, RTX 4070 12 Go. Un matériel différent déplace les chiffres d'analyse parallèle (plus de cœurs, plus de shards, plus rapide) ; les chiffres de nommage sont principalement liés au GPU. Les chiffres 4 heures/67 secondes pour Among Us datent d'avant le Chapitre 2 et ne sont pas revérifiés indépendamment à chaque version — relancez spectrida analyze vous-même si vous voulez un chiffre pour votre propre machine et binaire, les résultats varient selon la densité des shards et la taille du binaire.
Chiffres effectivement revérifiés pendant le développement du Chapitre 2, même matériel :
| binaire | fonctions | tâche | temps / résultat |
|---|---|---|---|
| test_small.dll (PE) | 189 | analyse parallèle, 4 workers, CLI | 6,4 s |
| test_small.dll (PE) | 164 | pipeline MCP complet (analyse + démolage + écriture du graphe) | 9,8 s |
| main.nso — Mario Odyssey (NSO), 16 workers | 28 038 fonctions seed | phase de scan parallèle en shards | 54,5 s |
| main.nso — Mario Odyssey (NSO), 16 workers | 74 790 fonctions totales | + phase de fusion/analyse complète | 143,1 s |
| main.nso — Mario Odyssey (NSO), 16 workers | 74 790 fonctions totales | temps mur de bout en bout | 197,6 s |
| main.nso — Mario Odyssey (NSO) | 74 790 | résolu par démolage seul (ABI Itanium, gratuit, pas d'IA) | 67 300 (90,0 %) |
Cette ligne NSO est l'équivalent réel de l'ancienne affirmation « 4 heures → 67 secondes » pour Among Us, mesurée à nouveau dans cette version sur un binaire Switch de 74 790 fonctions, sans IA impliquée (démolage uniquement — populate=False). La phase parallèle (16 cœurs, ~55 s) effectue la découverte initiale en shards ; la phase de fusion (~143 s) est mono-thread par conception — une base de données IDA, un écrivain — donc si vous regardez le Gestionnaire des tâches pendant cette partie et voyez 15 cœurs somnoler, ce n'est pas un rapport de bug, c'est de la physique.
Obtenir un nombre honnête ici a été sa propre petite histoire d'horreur. La première version du support NSO s'est exécutée proprement, est sortie avec 0, et a fièrement renvoyé 727 fonctions pour un binaire qui en a environ 75 000 — pas un crash, juste spectaculairement, confiant dans l'erreur, ce qui est en quelque sorte pire. Il s'avère qu'IDA n'a pas de chargeur NSO natif, donc le fichier s'est silencieusement chargé en x86 brut (« metapc ») même si la Switch est en ARM64 depuis le lancement de la console. Chaque shard a exécuté un scan de prologue x86 sur des instructions AArch64 pures et a appelé tout ce qu'il avait accidentellement fait correspondre à une « fonction ». Réparer l'architecture n'a rien résolu en soi, car le binaire était aussi toujours compressé LZ4 en mémoire — donc la moitié de ce qui a été scanné était, généreusement, du bruit. Et même une fois correctement décompressé et signalé AArch64, chaque shard ne cherchait que les cibles d'appels à l'intérieur de sa propre petite tranche du binaire, manquant tous les appels traversant une limite de shard — ce qui, dans un binaire de cette taille, est la plupart d'entre eux. Trois bugs, un nombre, et pas un seul d'entre eux n'a eu la décence de lancer une exception. (Nous avons aussi essayé de réduire la phase de fusion en sautant l'analyse de pile d'IDA — nous avons obtenu une belle accélération et une base de données où Hex-Rays refusait poliment de décompiler la moitié. Cela a été annulé rapidement. À la place, on a gardé le saut de signature FLIRT, beaucoup plus petit et plus sûr, qui vaut un ~3 % haussement d'épaules et n'a rien cassé, ce qui, à ce stade, ressemblait à un trait de personnalité à conserver.)
Sur la précision du nommage : ce n'est pas une vérité de terrain de niveau Ghidra, c'est un modèle 8B qui devine à partir du pseudocode. Les helpers/getters génériques atterrissent bien ; la logique spécifique au jeu est davantage un pile ou face. Renommez tout ce qu'il se trompe — c'est pourquoi rename_function persiste directement dans le graphe.