
Reconstruit des binaires Windows hérités en code source C en associant les exports du décompilateur Ghidra à des LLM locaux, produisant des candidats vérifiés par compilation et des rapports basés sur la similarité.
Ce dépôt est une reconstruction en cours du code source de RATS.EXE, la version Windows d'origine de Rats! (1994) de Sean O'Connor. Il compile un exécutable Win32 avec Microsoft Visual C++ 4.1 sous wibo et peut être testé dans DREAMM.
L'expérience explore jusqu'où les LLM locaux peuvent mener la reconstruction de code source sur une base de code petite mais réaliste, plutôt qu'un exemple jouet. La fidélité de correspondance reste inégale, ce qui est utile ici : l'objectif est de présenter une vision réaliste du processus et de ses limites actuelles, et non de masquer les fonctions difficiles.
La reconstruction des fonctions est réservée aux LLM locaux. Codex et Claude sont utilisés pour la configuration du dépôt et l'orchestration des benchmarks, mais ils ne sont pas autorisés à écrire ni à modifier le code source reconstruit.
Sauf mention contraire, toutes les expériences ont utilisé Qwen3.8 27B BF16 sur un MacBook Pro 2024 avec une puce Apple M4 Max (CPU 16 cœurs, GPU 40 cœurs) et 128 Go de mémoire. L'approche fonctionne — imparfaitement, mais utilement : les 36 fonctions conservées ont chacune pris en moyenne 2m 32.1s de temps journalisé pour être reconstruites.
Clonez avec les sous-modules, ou initialisez-les après le clonage :
git submodule update --init --recursive
L'exécutable d'origine n'est pas inclus. Téléchargez la version Windows gratuite depuis la page officielle de Rats! et placez son RATS.EXE à la racine du dépôt pour utiliser les cibles original-executable et binary-comparison.
make # build out/RATS_RE.EXE, .map, .obj, and .asm
make toolchain # download, extract, and verify Microsoft Visual C++ 4.1
make run # launch the rebuilt executable in DREAMM
make run-original # launch the preserved original RATS.EXE
make test # bounded DREAMM smoke test of the rebuilt executable
make test-original # bounded DREAMM smoke test of the original executable
make debug # start the rebuilt executable in DREAMM's debugger
make report # report similarity for every reconstructed function
make compare-func FUNC=SaveHighScores ADDR=00409092
L'archive MSVC 4.1 dont la somme de contrôle est épinglée, les bibliothèques MSVC 4.1 requises, la msvcrt40.dll compatible de wibo et DREAMM 4.0x21 sont téléchargés à la demande. Ils restent des dépendances de build locales ignorées et ne sont pas commités.
Le répertoire ghidra/ inclus dans le dépôt contient les exportations assembleur et décompilateur pour les 177 fonctions internes. L'assembleur fait autorité pour la comparaison ; le C décompilé n'est qu'une graine sémantique.
Installez binary-recons une fois, puis exécutez-le depuis la racine du dépôt :
python3 -m pip install -e /path/to/binary-recons
binary-recons --next-function # reconstruct the next safe missing target
binary-recons --address 0x409092 # reconstruct or improve a specific target
L'outil détecte Qwen automatiquement dans le cache Hugging Face standard ; BINARY_RECONS_MODEL_PATH peut le remplacer. binary-recons.toml maintient la sélection automatique dans les plages de code du jeu, démarre et arrête llama.cpp, et définit les fichiers transactionnels et la commande binary-comp. Chaque exécution bornée amorce une fonction depuis Ghidra, demande à Qwen des réparations ciblées de compilation ou de diff assembleur, et conserve le meilleur candidat compilable sûr. Utilisez --target-score 95 pour une passe plus approfondie, ou --dry-run-prompt pour inspecter le prompt sans charger Qwen.
Les exécutions mesurées des modèles locaux sont consignées dans docs/MODEL_RESULTS.md.
La plupart des candidats conservés ont été générés avec le Qwen3.8 27B GGUF d'Unsloth en BF16 (Qwen3.8-27B-BF16, servi sous qwen3.8-27b-bf16) via llama.cpp avec un contexte de 32 768 jetons et le préréglage de modèle qwen. Le workflow actuel utilise la décompilation de Ghidra comme graine mécanique, ne demande à Qwen qu'un contrat pertinent et des modifications de source bornées, suit les modifications valides comme trajectoire de réparation, et conserve le meilleur résultat mesuré par binary-comp. Gemma 4 31B IT BF16 a également été évalué, mais aucun de ses candidats n'a été conservé dans l'arborescence source.
Les scores ci-dessous ont été remesurés à partir de l'arborescence source actuelle avec MSVC 4.1 et binary-comp le 2026-08-16. Le temps journalisé inclut le démarrage du serveur géré, la génération ou la réparation, la compilation et la comparaison pour le candidat conservé. Il exclut les exécutions exploratoires infructueuses et les tours de réparation effectués après qu'un candidat reprenable a déjà été produit ; ceux-ci restent disponibles dans les journaux d'exécution.
Remerciements particuliers à :
| Adresse | Fonction | Similarité actuelle | Temps journalisé |
|---|
0x0040215C | IsLevelIndexInRange | 65.31% | 3m 06.4s |
0x00402205 | ShowLevelComplete | 93.96% | 5m 26.1s |
0x0040250C | SubmitHighScore | 97.37% | 1m 49.7s |
0x004026D0 | RenderScoreboard | 95.40% | 2m 30.9s |
0x00402BF3 | AddLevelToTable | 73.85% | 4m 04.6s |
0x00402DC6 | UpdateGameDisplay | 78.18% | 1m 36.4s |
0x00402EE7 | GetLevelDisplayInfo | 71.70% | 2m 15.9s |
0x00402FD5 | GetLevelIndex | 87.27% | 5m 48.3s |
0x00403430 | IsBombAtLevel | 80.62% | 27.3 s |
0x00403607 | PlaceLevel | 80.00% | 2m 32.6s |
0x00404764 | DrawLevelIndicator | 97.33% | 1m 35.6s |
0x0040499F | RenderCornerGlyph | 69.83% | 1m 50.9s |
0x00404D6E | DrawBitmapPair | 98.67% | 1m 04.6s |
0x00404E3B | RenderBitmapToWindow | 94.74% | 26.4 s |
0x00404ECE | DrawBitmapToWindow | 95.59% | 59.3 s |
0x00404F8B | DrawScore | 96.20% | 1m 32.4s |
0x0040507F | DrawScorePanel | 97.97% | 2m 45.0s |
0x0040525D | DrawScoreDigits | 94.20% | 2m 13.7s |
0x00405343 | RenderScoreOverlay | 77.78% | 1m 28.1s |
0x0040546B | DrawFrameBorder | 84.93% | 37.0 s |
0x0040552E | ExplodeBomb | 64.71% | 1m 50.9s |
0x0040560E | RenderExplosionWave | 85.07% | 5m 40.0s |
0x0040591A | DrawBombExplosion | 89.31% | 1m 45.8s |
0x00405AF5 | DrawPausedOverlay | 96.21% | 1m 05.1s |
0x00405C52 | HighScoreDialogProc | 79.82% | 41.5 s |
0x00405DB8 | ScorePanelDialogProc | 50.34% | 1m 53.1s |
0x00405F72 | DemoVersionDialogProc | 46.31% | 4m 18.5s |
0x004061D3 | OrderDialogProc | 53.16% | 10m 46.5s |
0x00408854 | DrawStartButton | 70.80% | 1m 35.6s |
0x00408A51 | UpdateMainMenuState | 97.56% | 28.9 s |
0x00408AD3 | InitializeGameLevel | 83.72% | 5m 35.7s |
0x00408E6A | LoadLevelData | 77.50% | 52.5 s |
0x00408F02 | LoadHighScores | 79.61% | 1m 15.0s |
0x00409092 | SaveHighScores | 94.12% | 1m 25.9s |
0x0040910C | LoadLevelBitmaps | 98.93% | 7m 08.4s |
0x00409DB6 | IsRatsHelpFile | 91.67% | 41.5 s |
Les tentatives de reconstruction des adresses suivantes ont été épuisées sans qu'une implémentation source ne soit conservée. Le temps passé est cumulatif sur toutes les tentatives journalisées.
| Adresse différée | Temps passé | Résultat |
|---|---|---|
0x00401000 | 10m 29.7s | Fonction trop volumineuse pour une première passe bornée ; échafaudage d'origine conservé (1.13 %) |
0x00403840 | 13m 10.0s | Aucun candidat compilable ; fonction trop volumineuse pour une passe bornée rapide |
0x00406674 | — | Ignorée : trop volumineuse pour une passe bornée rapide |