Ghidra BizHawk MCP について
Ghidra BizHawk MCPは、Ghidraによるバイナリ解析とBizHawkのライブエミュレーションを1つのMCPサーバーにまとめ、レトロゲーム機のROMやバイナリを扱うリバースエンジニアを対象としています。ROMの判別、逆コンパイル、P-codeエミュレーション、解析機能を共通のセッションで利用できます。
主な機能
- 01レトロROMの判別と読み込み
- 02Ghidraによる逆コンパイルとクロスリファレンス
- 03テイント追跡付きP-codeエミュレーション
- 04ブレークポイントによるエミュレーション
- 05複数バイナリの並行解析セッション
- 06バイナリ比較とバイト検索
活用シーン
- 01未知のレトロROMの判別と読み込み
- 02ゲーム機バイナリ内の関数の逆コンパイル
- 03エミュレーション中のループでのレジスタ変化の追跡
- 042つのバイナリ間での関数比較
MCP 対応
stdin/stdout経由で、バイナリ解析、Ghidra、エミュレーションのツールをMCPクライアントに提供します。BizHawkのライブエミュレーション機能は任意で、ループバック限定の接続を使用します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
uvx ghidra-bizhawk-mcpGHIDRA_INSTALL_DIRAbsolute path to the Ghidra installation directoryBIZHAWK_EXE_PATHOptional path to EmuHawk.exe for live emulation featuresMOCK_MODESet to 1 for zero-dependency CI simulationローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Ghidra BizHawk MCP
Ghidra のヘッドレス静的解析と BizHawk のライブエミュレーションを橋渡しする、統合型の MCP(Model Context Protocol)サーバーです。同じセッション内で、ROM の逆コンパイルと実機での実行を切り替えられます。
GBA ROM:Game Boy Advance ROM を解析する場合は、適切な ROM ヘッダー解析、ミラーリングされたメモリ領域、I/O レジスターマップを利用するため、Ghidra のインストール先に pudii/gba-ghidra-loader をインストールしてください。ローダーのリポジトリには、Ghidra 11.x 用のビルド済み
.gpaファイルがあります。
前提条件
| 依存関係 | バージョン | 必須 | 備考 |
|---|---|---|---|
| Python | >= 3.10 | はい | MCP サーバーのランタイム |
| Ghidra | 11.x または 12.x | はい | ヘッドレスまたは GUI でインストールします。GHIDRA_INSTALL_DIR はこの場所を指定する必要があります |
| Java(JDK) | >= 17 | はい | Ghidra に同梱されています。JVM ブリッジに必要です |
| pyghidra | >= 3.0 | はい | Python と Ghidra のブリッジです。自動的にインストールされます |
| BizHawk(EmuHawk) | 最新の安定版 | いいえ | ライブエミュレーションツールにのみ必要です。BIZHAWK_EXE_PATH の指定は任意です |
| Docker | 最新 | いいえ | コンテナー化したデプロイにのみ必要です |
アーキテクチャ
┌─────────────────────────────────────────────────────────────────┐
│ MCP Client (Claude / Cursor) │
│ sends JSON-RPC over stdin/stdout │
└─────────────────────────────┬───────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ ghidra-bizhawk-mcp │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ MCP Server (server.py) — tool registry, stdio dispatch ││
│ └──────────────────────────┬──────────────────────────────────┘│
│ │ │
│ ┌──────────────┴──────────────┐ │
│ ▼ ▼ │
│ ┌────────────────────┐ ┌──────────────────────────────┐ │
│ │ GhidraSession │ │ BizhawkBridge │ │
│ │ pyghidra → JVM │ │ TCP client → localhost:8766│ │
│ │ decompile, etc. │ └──────────────┬───────────────┘ │
│ └────────────────────┘ │ │
└───────────────────────────────────────────┼─────────────────────┘
│ TCP (newline-delimited JSON)
▼
┌──────────────────────────────┐
│ BizHawk (EmuHawk.exe) │
│ built-in socket server │
│ ┌────────────────────────┐ │
│ │ bridge.lua │ │
│ │ memory read/write │ │
│ │ joypad, savestate │ │
│ │ frame advance │ │
│ └────────────────────────┘ │
└──────────────────────────────┘
セキュリティモデル
MCP サーバーは、MCP クライアントとの通信に stdin/stdout のみを使用し、HTTP リスナーやネットワークリスナーは使用しません。唯一のローカル TCP ソケットは、サーバーと BizHawk 内蔵の Lua ソケットサーバー間の ループバック専用接続(127.0.0.1:8766)です。これはライブエミュレーション機能のみに使用され、ネットワークには公開されません。
ハードウェアおよびレトロゲームエコシステムとの連携
ghidra-bizhawk-mcp は、Ghidra の静的解析によるレトロゲームのリバースエンジニアリング自動化パイプラインと、マルチシステムエミュレーター BizHawk によるライブエミュレーションを、標準でネイティブにサポートしています。サーバーには次の機能が含まれています。
- Nintendo Entertainment System(NES):
GhidraNes - Super Nintendo Entertainment System(SNES):ネイティブの 65816 メモリーマップ
- Game Boy Advance(GBA):
gba-ghidra-loader - Nintendo DS(NDS):
NTRGhidra - Nintendo Switch:
ghidra-switch-loader - PlayStation 1(PSX):
ghidra_psx_ldr - Sega Genesis / Mega Drive:ネイティブの 68000 メモリーマップ
- Sega Master System / Game Gear:
Ghidra-SegaMasterSystem-Loader - Sega Dreamcast:ネイティブの SuperH4 メモリーマップ
入力不要のトリアージ — 実例(GBA)
主なエントリーポイントは triage_and_load_retro_rom です。任意の ROM パスを指定すると、サーバーが残りの処理を実行します。
# Auto-detect platform, map language, provision session
triage_and_load_retro_rom(rom_path="/data/game.gba")
# → platform: "Game Boy Advance (GBA)"
# → loader: "GBA ROM Loader"
# → arch: "ARM:LE:32:v4t"
# Decompile the main entry point on the same session
decompile_function(address="0x00001c2c")
# → decompiled C code for the GBA ROM entry routine
# Search for a known pattern (e.g. 32-bit ARM store-multiple)
search_bytes(pattern="09 08 00 01")
# → matching addresses labelled "gba_ram_start"
実行の連鎖フロー
AI エージェントにアーキテクチャーマップ、レジスターレイアウト、メモリーセグメントを手動で特定させて処理時間を費やす代わりに、自動取り込みパイプラインを連鎖させます。
- 対象ファイルのパスを指定して
triage_and_load_retro_romを呼び出します。 - サーバーがバイナリーファイル構造(
NES\x1a、NTR、NSO0、GBA、SNES タイトルベクター、PS-X EXE、SEGA、TMR SEGA、SEGA ENTERPRISES)をヘッドレスで解析し、一致する Ghidra 言語モジュール(6502:LE:16、ARM:LE:32:v4t、AARCH64:LE:64、65816:LE:24、MIPS:LE:32、68000:BE:32、Z80:16、SuperH4:LE:32)をバインドして、標準アドレスのメモリーブロックを読み込み、自動シグネチャーキャッシュ配列をリンクします。 - 統合された
emulate_sliceまたはemulate_slice_with_taintツールを使用して、コンソール上の特定のループを解析します。実機のコンソールや、外部公開された GDB ネットワークポートは不要です。
トリアージツール
| ツール | 説明 |
|---|---|
triage_and_load_retro_rom | ファイルのマジックバイトを読み取り、NES、SNES、GBA、NDS、Switch、PSX、Genesis、SMS、Dreamcast の ROM を検出します。正しい言語マッピングを適用した Ghidra セッションを用意し、キャッシュ済みの関数シグネチャーを自動で復元します。プラットフォーム、ローダー、アーキテクチャータグ、マッピングされたメモリーブロックを返します。 |
クイックスタート
1. インストール
pip install ghidra-bizhawk-mcp
または、ソースからインストールします。
git clone https://github.com/getanirao/ghidra-bizhawk-mcp.git
cd ghidra-bizhawk-mcp
pip install -e .
2. 環境を設定
# Required: point to your Ghidra installation
export GHIDRA_INSTALL_DIR=/opt/ghidra_11.2 # Linux / macOS
set GHIDRA_INSTALL_DIR=C:\Program Files\ghidra_11.2 # Windows
# Optional: enable live BizHawk emulation
export BIZHAWK_EXE_PATH=/path/to/EmuHawk.exe
# Optional: run in mock mode (no Ghidra/BizHawk needed)
export MOCK_MODE=1
3. 実行
ghidra-bizhawk-mcp
サーバーは stdin/stdout で待ち受けます。MCP 互換クライアントにパイプで接続できます。
Docker
docker build -t ghidra-bizhawk-mcp .
docker run -i --rm -v /path/to/binaries:/data ghidra-bizhawk-mcp
コンテナーには JDK 17、Ghidra 11.2、サーバーが同梱されているため、Docker 以外のホスト依存関係はありません。
設定
環境変数
| 変数 | 必須 | デフォルト | 説明 |
|---|---|---|---|
GHIDRA_INSTALL_DIR | はい | — | Ghidra のインストール先のパス(例:/opt/ghidra_11.2) |
BIZHAWK_EXE_PATH | いいえ | — | ライブエミュレーション機能用の EmuHawk.exe のパス |
MOCK_MODE | いいえ | 0 | Ghidra/BizHawk を使わずに実行する場合(テスト/CI 用)は 1 に設定します |
Claude Desktop
claude_desktop_config.json に追加します。
{
"mcpServers": {
"ghidra-bizhawk": {
"command": "ghidra-bizhawk-mcp",
"env": {
"GHIDRA_INSTALL_DIR": "/opt/ghidra_11.2"
}
}
}
}
Cursor
Cursor の MCP 設定に追加します。
{
"mcpServers": {
"ghidra-bizhawk": {
"command": "ghidra-bizhawk-mcp",
"env": {
"GHIDRA_INSTALL_DIR": "/opt/ghidra_11.2"
}
}
}
}
ツール
セッション管理
| ツール | 説明 |
|---|---|
analyze_binary | バイナリをインポートして解析し、session_id を返します。指定されている場合はその ID を再利用し、指定されていない場合は自動生成します。 |
list_sessions | アクティブなすべてのワークスペースについて、セッション ID、バイナリのパス、読み込み時刻を一覧表示します。 |
close_session | セッションを閉じ、Ghidra プロジェクトのリソースを解放します。 |
ほとんどのツールでは session_id パラメーターを省略できます。省略すると、最後に読み込まれたセッションが使用されます。
読み取り/解析
| ツール | 説明 |
|---|---|
decompile_function | 名前またはアドレスを指定して関数を逆コンパイルします。 |
decompile_function_paginated | line_start、line_end、max_tokens(トークン予算に基づく切り詰め)、summarize(定型的なローカル変数を除去し、空行をまとめる)を指定して逆コンパイルします。コンテキストウィンドウの枯渇を防ぎます。 |
get_data_types | プログラムで定義されているすべてのデータ型を一覧表示します。 |
get_cross_references | アドレスへの/アドレスからのクロスリファレンスを取得します。 |
get_call_graph | 関数の再帰的な呼び出しグラフと呼び出し元を取得します。 |
analyze_and_decompile_entrypoints | 複合ツール — プログラムのエントリーポイント、エクスポート、main、_start など、すべてのエントリーポイントを一度の呼び出しで一括して逆コンパイルします。 |
generate_workspace_report | アクティブなワークスペースの概要を Markdown 形式で生成します。エントリーポイント、関数数、カスタムシンボル、復元された構造体、名前を変更した関数、コメントが含まれます。GUI の CodeBrowser ウィンドウに代わるものです。 |
書き込み/変更
| ツール | 説明 |
|---|---|
rename_symbol | 関数またはラベルの名前を変更します。変更内容は Ghidra プロジェクト DB に保存されます。 |
add_comment | コメント(plate、pre、post、eol、repeatable)を追加します。 |
create_struct | JSON 形式のメンバー配置 [{offset, name, type}, ...] からカスタム構造化データ型を作成します。オフセットは省略可能です。 |
retype_variable | ローカル変数または関数パラメーターの型を変更します(例:undefined4* → MyStruct*)。 |
アセンブリレベル
| ツール | 説明 |
|---|---|
disassemble_range | アドレスから N 個の未加工命令を逆アセンブルします。より低レベルで正確に調査できるよう、ニーモニック、オペランド、16 進バイト列、長さを返します。 |
get_listing_range | バイト範囲の未加工の 16 進数と ASCII のダンプを取得します。Ghidra の Listing パネルに相当します。データ領域では disassemble_range を補完します。 |
バイト列検索
| ツール | 説明 |
|---|---|
search_bytes | バイナリ全体から 16 進バイトパターン(例:09 08 00 01 または F86D0003)を検索します。一致したアドレス、周辺のバイト、および該当位置に文字列ラベルがあればそれを返します。 |
バイナリ差分
| ツール | 説明 |
|---|---|
diff_binaries | 読み込み済みの 2 つのセッションを、関数名と本体サイズで比較します。それぞれに固有の関数と、変更された関数を返します。 |
ワークスペースセッション
analyze_binary を呼び出すたびに名前付きセッションが作成されます。各セッションはそれぞれ独立して Ghidra プロジェクトを開いたままにするため、複数のバイナリを同時に読み込めます。
# Load two binaries into separate sessions
s1 = analyze_binary(binary_path="/bin/a.out") # auto session_id
s2 = analyze_binary(binary_path="/bin/b.out", session_id="my_session")
# Operate on a specific session
decompile_function(function_name="main", session_id=s1.session_id)
# Diff them
diff_binaries(session_a=s1.session_id, session_b="my_session")
デプロイ
Docker(複数ユーザー/CI)
docker build -t ghidra-bizhawk-mcp .
# Run as an MCP subprocess
docker run -i --rm \
-v /data/binaries:/data \
ghidra-bizhawk-mcp \
--ghidra-dir /opt/ghidra
Dockerfile には Ghidra 11.2 と JDK 17 が、軽量な Python 3.11 イメージにバンドルされています。実行時にバインドマウントでバイナリのディレクトリを割り当ててください。
MCP バンドル(MCPB — Claude Desktop / Smithery)
ポータブルな .mcpb バンドルとしてパッケージ化し、Claude Desktop にワンクリックでインストールするか、Smithery で公開します。
前提条件: MCPB CLI をインストールします。
npm install -g @anthropic-ai/mcpb
バンドルをビルドします:
# From the repo root — also builds the Smithery publish variant
scripts/build-mcpb.ps1
または、mcpb を使って手動で実行します。
mcpb pack
出力される ghidra-bizhawk-mcp.mcpb は、インストール時に GHIDRA_INSTALL_DIR(必須)と、任意で BIZHAWK_EXE_PATH の入力を求める manifest.json とともにサーバーをパッケージ化します。JSON を手動で編集する必要はありません。
Smithery への公開:
Smithery の公開 API では、MCP 形式のツールスキーマ(inputSchema)とオブジェクト形式のプロンプト引数が必要ですが、MCPB スキーマでは manifest.json でこれらが禁止されています。
そのため、ビルドスクリプトは mcpb/tool-schemas.json からパッチを適用したマニフェストを含む、2つ目のバンドルを生成します。
python scripts/build_smithery_bundle.py
smithery mcp publish ./dist/ghidra-bizhawk-mcp.smithery.mcpb -n getanirao/ghidra-bizhawk-mcp
P-code のマイクロエミュレーション
| ツール | 説明 |
|---|---|
emulate_slice | N 個の命令をヘッドレスで実行します。レジスターの状態を初期設定し、レジスターの変化をステップごとにトレースします。 |
emulate_slice_with_taint | emulate_slice と同じですが、自動テイント追跡機能を備えています。テイント対象のレジスター(例:r0)を指定すると、その値が変更されたときや、ほかのレジスターに伝播したときを正確に通知します。 |
emulate_slice_with_breakpoints | 条件が満たされるか、指定した命令数に達するまで実行します。条件の構文:R0==0、R1>0xFF、R2!=R3、PC==0x1234。条件に一致する命令の前後で停止します。 |
すべて Ghidra の EmulatorHelper を介して pyhidra プロセス内で実行されます。GDB/LLDB、ネットワークポート、デバッガースタブは不要です。ARM、x86、MIPS、および Ghidra がサポートするすべてのアーキテクチャで動作します。
実例 — レジスター条件でブレークする
GBA ROM をリバースエンジニアリングしていて、0x08000100 のループ内で r0 が初めてゼロになる箇所を見つけたいとします。
# Step until r0 == 0, stop before the matching instruction
result = emulate_slice_with_breakpoints(
session_id="gba_v1",
start_address="0x08000100",
max_instructions=5000,
stop_condition="R0==0",
stop_mode="before"
)
# result.exit_reason → "R0==0"
# result.instructions_executed → 312
# result.trace → [step 311: r0 goes 4→2, step 312: r0 goes 2→0]
# Check if a specific address was reached after a branch
result = emulate_slice_with_breakpoints(
session_id="gba_v1",
start_address="0x08000100",
max_instructions=5000,
stop_condition="PC==0x08001234"
)
# result.exit_reason → "PC==0x08001234"
# Use inequalities to catch bounds checks
result = emulate_slice_with_breakpoints(
session_id="gba_v1",
start_address="0x08000100",
max_instructions=5000,
stop_condition="R1>0xFF"
)
# result.exit_reason → "R1>0xFF"
# result.last_step["r1"] → 0x100
これは、コピー処理のループ境界(R3 >= R4)、ヌルポインターのパス(R0==0)、スイッチテーブルのターゲット(PC==0x)を特定する際に特に有効です。
関数のフィンガープリント/シグネチャの転送
| ツール | 説明 |
|---|---|
calculate_function_fingerprint | 関数の構造ハッシュを生成します(変数、パラメーター、本文サイズ、分岐、呼び出し先の関数、埋め込み文字列、数値定数)。コンパイラーによる並べ替えにも影響されません。 |
export_signature_map | 現在のバイナリ内のすべての関数について、完全な {hash → name} マップを作成します。この JSON を保存して、バージョン間で再利用します。 |
apply_signature_map | 以前にエクスポートしたシグネチャマップを渡すと、サーバーがバイナリを走査し、一致したすべての関数の名前を自動で変更します。 |
永続的なシグネチャ保存領域(サーバー側キャッシュ)
| ツール | 説明 |
|---|---|
save_active_binary_signature | すべての関数のフィンガープリントを作成し、マップを lineage_group_id(例:"my_firmware_v1")に関連付けて保存します。~/.ghidra_bizhawk_mcp/signatures/ に保存されるため、JSON ファイルを管理する必要はありません。 |
auto_restore_signatures_from_stash | lineage_group_id で保存済みマップを読み込み、一致したすべての関数の名前を自動で変更します。 |
auto_stash_current_binary | 入力不要の自動保存 — バイナリの先頭 4 KB をハッシュ化し、そのハッシュに関連付けてマップを保存します。解析して呼び出すだけです。 |
auto_restore_current_binary | 入力不要の自動復元 — バイナリをハッシュ化し、以前に保存したデータを検索して、一致した関数の名前を変更します。グループ ID は不要です。 |
list_stashed_signature_groups | 現在ローカルキャッシュに保存されているすべてのグループを一覧表示します。 |
ワークフロー — 完全自動の永続化:
# Analyze v1 — stashes automatically under binary content hash
s1 = analyze_binary(binary_path="/bin/v1.bin")
auto_stash_current_binary(session_id=s1.session_id)
# Later, analyze v2 — restores automatically
s2 = analyze_binary(binary_path="/bin/v2.bin")
auto_restore_current_binary(session_id=s2.session_id)
# → 142 functions renamed, zero manual JSON handling
これらのプロンプトを試す
MCP クライアントを設定した後(設定を参照)、AI エージェントに次のように尋ねます。
- 「この GBA ROM を読み込んで、エントリーポイントを逆コンパイルして。」
- 「この NDS バイナリ内で 0x8001234 を呼び出している関数は?」
- 「この PSX EXE をトリアージして、最初の 20 命令で r0 を追跡して。」
- 「開いている2つのセッションを比較して、変更された関数を表示して。」
プロジェクト構成
ghidra-bizhawk-mcp/
├── Dockerfile
├── pyproject.toml
├── README.md
└── src/ghidra_bizhawk_mcp/
├── __init__.py
├── server.py # MCP server, tool registry, stdio transport
├── ghidra_bridge.py # GhidraSession — pyghidra wrapper, all Ghidra logic
├── lua/
│ └── bridge.lua # BizHawk-side Lua bridge for live emulation
└── tools/
├── __init__.py
├── bizhawk_bridge.py # TCP client connecting MCP ↔ BizHawk
└── ...
仕組み
pyhidra.start()は、サーバーの起動時に Ghidra の JVM を 1 回起動しますanalyze_binaryを呼び出すたびに、専用の名前付きセッションで新しい Ghidra プロジェクトを開きます- 読み取り/書き込みツールは、
session_id(またはアクティブなデフォルト)を介して指定されたセッションに振り分けられます - 書き込みツールは、変更を Ghidra のプログラムデータベースに直接適用します
- セッションは明示的に閉じられるまで維持されます。これにより、複数のバイナリを扱うワークフローや差分比較が可能になります
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。