
GhidraデコンパイラのエクスポートとローカルLLMを組み合わせて、レガシーWindowsバイナリをCソースコードに再構築し、コンパイル検証済みの候補と類似性ベースのレポートを生成します。
このリポジトリは、Sean O'ConnorによるRats!(1994年)のオリジナルWindows版であるRATS.EXEのソースコードを再構築する進行中のプロジェクトです。wibo上でMicrosoft Visual C++ 4.1を使ってWin32実行ファイルをビルドし、DREAMMでテストできます。
この実験は、おもちゃ的な例ではなく、小規模ながら現実的なコードベースにおいて、ローカルLLMがソースコードの再構築をどこまで進められるかを探るものです。一致精度はまだらなままですが、これはここでは有用です。目的は、難しい関数を隠すことではなく、プロセスとその現状の限界を現実的に示すことだからです。
関数の再構築はローカルLLMのみに限定されています。CodexとClaudeはリポジトリのセットアップとベンチマークのオーケストレーションに使用されていますが、再構築されたソースコードを書いたり編集したりすることは許可されていません。
特に記載がない限り、すべての実験は、Apple M4 Max(16コアCPU、40コアGPU)と128GBメモリを搭載した2024年製MacBook Pro上でQwen3.8 27B BF16を使用して行われました。このアプローチは機能します。不完全ではありますが、有用です。保持された36個の関数は、それぞれ平均記録時間2m 32.1sで再構築されました。
サブモジュール付きでクローンするか、クローン後にサブモジュールを初期化します:
git submodule update --init --recursive
オリジナルの実行ファイルは含まれていません。公式の*Rats!*ページから無料のWindows版をダウンロードし、そのRATS.EXEをリポジトリのルートに配置すると、original-executableターゲットと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
チェックサムで固定されたMSVC 4.1アーカイブ、必要なMSVC 4.1ライブラリ、wibo互換のmsvcrt40.dll、およびDREAMM 4.0x21はオンデマンドでダウンロードされます。これらは無視されるローカルのビルド依存関係として残り、コミットされません。
チェックインされているghidra/ディレクトリには、177個すべての内部関数のアセンブリとデコンパイラのエクスポートが含まれています。比較の基準となるのはアセンブリであり、逆コンパイルされたCはセマンティックなシードにすぎません。
binary-reconsを一度インストールし、リポジトリのルートから実行します:
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
このツールは、標準のHugging Faceキャッシュ内でQwenを自動的に検出します。BINARY_RECONS_MODEL_PATHで上書きできます。binary-recons.tomlは、自動選択をゲームコード範囲内に保ち、llama.cppの起動と停止を行い、トランザクションファイルとbinary-compコマンドを定義します。各制限付き実行は、Ghidraから1つの関数をシードし、Qwenに焦点を絞ったコンパイルまたはアセンブリ差分の修復を依頼し、最も安全なコンパイル可能な候補を保持します。より深いパスには--target-score 95を、Qwenをロードせずにプロンプトを検査するには--dry-run-promptを使用します。
測定されたローカルモデルの実行結果はdocs/MODEL_RESULTS.mdに記録されています。
保持された候補のほとんどは、UnslothのQwen3.8 27B GGUFをBF16(Qwen3.8-27B-BF16、qwen3.8-27b-bf16として提供)で使用し、32,768トークンのコンテキストとqwenモデルプリセットを備えたllama.cppを通じて生成されました。現在のワークフローは、Ghidraの逆コンパイルを機械的なシードとして使用し、Qwenには意味のある契約と制限付きのソース編集のみを依頼し、有効な編集を修復の軌跡として追跡し、binary-compで測定された最良の結果を保持します。Gemma 4 31B IT BF16もベンチマークされましたが、その候補はどれもソースツリーに保持されていません。
以下のスコアは、2026-08-16にMSVC 4.1とbinary-compを使用して現在のソースツリーから再測定されたものです。記録された時間には、管理サーバーの起動、生成または修復、ビルド、保持された候補の比較が含まれます。失敗した探索的実行や、再開可能な候補がすでに生成された後に行われた修復ターンは除外されます。これらは実行ログで引き続き確認できます。
| アドレス | 関数 | 現在の類似度 | 記録時間 |
|---|---|---|---|
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 |
以下のアドレスに対する再構築の試みは、ソース実装を保持しないまま尽きました。費やした時間は、記録されたすべての試行の累計です。
| 延期されたアドレス | 費やした時間 | 結果 |
|---|---|---|
0x00401000 | 10m 29.7s | 制限付きの最初のパスには関数が大きすぎる。元の1.13%のスキャフォールドを保持 |
0x00403840 | 13m 10.0s | コンパイル可能な候補なし。高速な制限付きパスには大きすぎる |
0x00406674 | — | スキップ: 高速な制限付きパスには大きすぎる |
特に感謝を捧げます: