
32ビットDOSおよびWin32ゲーム(1993-2010)のリバースエンジニアリング向けHeadless-Ghidraツールキット:独自のLE/LXローダー、Watcom呼び出し規約、ライブラリシグネチャ、MCPサーバー

ヘッドレスGhidraを使って、およそ1993年から2010年頃の32ビットゲームを逆コンパイルするためのツールキット:
出力は、すべての関数を含む1つの大きな.cファイルと、インデックス
(関数、コールグラフ、文字列、フィックスアップ/ポインタテーブル、インポート)をまとめたワークスペースで、
grepしたり、人やAIエージェント間で分割したりできる。解析中に見つかった名前はGhidraに戻され、
エクスポートが再生成される。
前提条件:Ghidra 12.x
(展開済み)、JDK 21+(JAVA_HOME)、Python 3.10+。
pipx install git+https://github.com/nemo22/retrokit # or from a checkout: pip install . (or python -m retrokit)
retrokit doctor # checks Python, Ghidra, Java, loader, cspecs
retrokit install-loader # once per Ghidra install (DOS LE/LX only)
Ghidra は --ghidra DIR、$GHIDRA_INSTALL_DIR、またはゲームやキットの隣にある ghidra/ghidra_* ディレクトリから検出されます。install-loader はその Ghidra に対して javac でローダーをコンパイルし(Gradle は使用しません)、Ghidra/Extensions にインストールして Watcom コンパイラスペックを登録します。Ghidra を更新した後は再度実行してください(doctor がそのタイミングを教えてくれます)。
retrokit info GAME.EXE # format, DOS extender, compiler, calling convention
retrokit analyze GAME.EXE # full pipeline -> GAME_analysis/ (-o DIR to choose)
retrokit show GAME_analysis FUN_00012345 main
retrokit tables GAME_analysis # function-pointer and string tables (from fixups)
retrokit names GAME_analysis # apply notes/names_*.csv, re-export
retrokit reexport GAME_analysis # re-run the fix-up passes + export without re-importing
analyze はフォーマット、ローダー、そして Watcom の場合は呼び出し規約を検出し(--cspec watcom|watcomreg で上書き可能)、それらを GAME_analysis/retrokit.json に保存します。以降のコマンドはワークスペースのみを必要とします。ワークスペースは次のとおりです:
GAME_analysis/
retrokit.json how the binary was analysed
decomp/ <exe>_decompiled.c, functions.csv (addr,name,size,callers,callees,cc,signature),
calls.txt, strings.txt, data_symbols.txt, memory_blocks.txt,
fixups.txt (source -> target of every pointer: the key to pointer tables
and to which function uses which string), imports.txt (PE)
notes/ findings, names_<topic>.csv proposals
ghidra_project/ the Ghidra project (open it in the Ghidra GUI too)
logs/
AIエージェント: retrokit mcp GAME_analysis はワークスペース上で動作する MCP サーバー(stdio、追加パッケージ不要)であり、関数、逆コンパイルされたコード、コールグラフ、クロスリファレンス、文字列、ポインタテーブル、逆アセンブリとバイト列、ライブラリを扱います。名前の提案とメモを記録し、適用された名前で再エクスポートできます(リクエストに応じて、バックグラウンドで)。Claude Code:
claude mcp add retrokit -- retrokit mcp /path/to/GAME_analysis
他のクライアント向けのセットアップ、すべてのツールとエージェントの動作方法: docs/MCP.md; エージェント向けの短縮版は AGENTS.md。
名前: 提案は notes/names_<topic>.csv に書き出す(addr,name,confidence,comment、confidence は
V が検証済み、G が推測); retrokit names WS は関数/ラベルをリネームし(V が G に優先、
衝突には _<addr> を付与)、再エクスポートする。
パイプラインの動作:
retrokit libs(info と analyze の一部でもあり ->
notes/libraries.md)は当時の約20のライブラリ - Miles/AIL、HMI SOS、DIGPAK、
Smacker、Bink、FMOD、BASS、DirectX、zlib、libjpeg、libpng、PKWARE DCL、Lua、... - を
文字列、インポート、データファイルから認識し、バージョン、フォーマットに関する注記、移植のヒントを提供する。
ライブラリコードはシグネチャによって検出される(同梱: Watcom C/C++ ランタイム、Open Watcom の
数学および C++ ライブラリ、zlib 1.0.4-1.2.3、libjpeg 6b; retrokit sigs build は所有する
ライブラリから、sigs learn は特定した関数からそれらを作成する) - まず完全一致、次に
他のコンパイラバージョンの類似コード - 名前を付け、retrokit/knowledge/*.h から型を付ける。switch ジャンプテーブルは
その関数内に保持、誤った "no return" フラグは元に戻し、短い文字列は定義され文字列リテラルは
"text" として表示、パラメータ数は呼び出し箇所の ADD ESP,n クリーンアップから、プロトタイプは
被呼び出し側優先で復元し、エクスポートする。その他のコマンド: classes(RTTI からの MSVC C++ クラス)、libs(使用中のライブラリ)、convert(XMIDI/HMI/HMP -> MIDI、VOC -> WAV、
Smacker/Bink/FLIC -> MP4、内容による)、sigs match|build|learn(ライブラリシグネチャ、docs/WORKFLOW.md 参照)、
entries(PE: 関数のないコードアドレス)、modules --rules FILE
(PE: アサートパス経由で関数 → 元のソースファイル)、strings EXE OUT(Ghidra なしの PE 文字列インベントリ)、
match(関連する EXE へ名前を転送: 続編、アドオン、別バージョン)、
le EXE info|dump|rec|s16|s32(Ghidra アドレスで LE からテーブルを読み取る)、rnc(RNC ProPack)、
flic info|png|video(Autodesk FLI/FLC)。オプションは retrokit COMMAND --help を参照。
詳細な手順、予想されること、既知の落とし穴は docs/WORKFLOW.md に; MCP サーバーは docs/MCP.md に;
AI エージェント向けのタスクテンプレートは docs/AGENT_PROMPTS.md に; 計画中の作業は
docs/ROADMAP.md に; メンテナンスとリリースは docs/MAINTAINING.md に。
retrokit/ Python package (CLI: retrokit/cli.py)
ghidra_scripts/ headless Ghidra scripts used by the pipelines
tools/ standalone Python tools behind the CLI commands
le-loader/ LE/LX loader for Ghidra (Java) + Watcom compiler specs (data/languages/)
sigs/ library signatures (Open Watcom C run-time)
knowledge/ libraries.json (library catalog), library prototypes as C headers
scripts/ build_sigs.py: rebuilds the shipped signatures
tests/ synthetic test programs, scoring against the linker map, baseline
docs/ WORKFLOW, AGENT_PROMPTS, ROADMAP
| Ghidra スクリプト | 目的 |
|---|---|
CreateFunctionsFromFixups.java | LE: 32 ビット fixup のターゲットをコード内の関数に変換; コード内の switch テーブル |
CreateFunctionsAtEntries.java | 指定されたアドレス(リストまたは @file)の関数、オプションでコードギャップ内の fixup またはプロローグから |
FixTruncatedCallers.java | 呼び出し元を切り捨てる誤った「no return」をクリア |
FixAnalysis.java | 手動修正: noreturn:ADDR、func:ADDR |
MarkStringsConstant.java | 短い文字列を定義し、書き込み可能データ内の文字列を constant(逆コンパイル内のリテラル)としてマーク |
ApplyLibraryPrototypes.java | 名前付きライブラリ関数の文書化されたプロトタイプ(knowledge/*.h)、タグ LIBRARY |
ApplyStackConvention.java | 呼び出しサイトの ADD ESP,n からのパラメータ数 / __cdecl / 可変引数、RET n からの __stdcall |
RecoverPrototypes.java | 逆コンパイラからのプロトタイプ、コールグラフレベルによるボトムアップ |
ApplyNames.java | names_*.csv からの名前 |
ExportDecompiled.java | .c + functions.csv、calls.txt、strings.txt、… をエクスポート |
DumpFixups.java | LE fixup / PE ベースリロケーション → fixups.txt |
DumpImports.java | PE インポートと IAT スロット → imports.txt |
DumpFunctions.java | 関数リストのみ(PE エントリパス間) |
DumpDisasm.java | 関数の逆アセンブリを stdout へ |
EnableDeepAnalysis.java | 低速アナライザを有効化(非推奨、WORKFLOW 参照) |
tests/ は Open Watcom で小さな合成プログラムをビルドし(開発/CI 専用の依存: DOS/4GW、
DOS/32A、PMODE/W、DOS/4G bind、OS/2 LX、Win32; スタックおよびレジスタ規約)、
各イメージの独立した Python モデルに対してローダをチェックし、それらに対して retrokit analyze を実行し、
リンカマップ(関数アドレス、パラメータ数、呼び出し引数、文字列リテラル、切り捨てられた関数、
逆コンパイラノイズ)に対して結果をスコアリングする。tests/README.md を参照。
GitHub で Issue とプルリクエストを歓迎する。主要リポジトリは
他所で維持され GitHub にミラーリングされているため、プルリクエストはそこでマージされ、
ミラーが同期すると GitHub 上でマージ済みとして表示される(docs/MAINTAINING.md)。ゲームファイルや
逆コンパイルされたゲームコードを添付しないこと。代わりにバイナリを説明し(フォーマット、エクステンダ、
コンパイラ、何がうまくいかないか)、可能であれば tests/ にあるような Open Watcom でビルドした
小さなプログラムで再現すること。
retro-kit は Claude Code を通じて Claude(Anthropic)で開発されている: コードと
ドキュメントのほとんどはメンテナの指示の下で Claude によって書かれ、メンテナがスコープと
設計を設定し、Windows と Linux でテストし、各リリースに何を含めるかを決定する。コミットには
Claude が共同作者として記載される。品質は tests/ のテストコーパスによって追跡される:
合成プログラムをリンカマップに対してスコアリングし、ベースラインが Windows と Linux の CI でチェックされる。