ida-cli について
ida-cli を使ったリバースエンジニアリング向けスキルです。ローカルサービスの起動と、IDA データベースやバイナリのコマンドライン分析を案内し、逆コンパイル、逆アセンブル、構造体の復元も扱います。
主な機能
- 01自動インストールとランタイム検出
- 02関数、文字列、クロスリファレンスの確認
- 03逆コンパイルと逆アセンブルによる分析
- 04JSON-RPC によるリクエスト送信
- 05体系的なリバースエンジニアリング手順
活用シーン
- 01バイナリ内の関数やセグメントの調査
- 02呼び出しとクロスリファレンスの追跡
- 03コード上のアクセスから構造体を復元
- 04算術処理とデコンパイラ出力の検証
MCP 対応
ida-cli は stdio または Streamable HTTP 経由の MCP サービスとして動作します。このスキルでは主にクライアントモードからローカル管理サービスを呼び出します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ cpkt9762/ ida-cli --skill ida-cliインストール後、Claude Code で/ida-cliを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/binary-analysis-patterns.mdcli-tool-reference.mdcounterfactual-patch.mdheadless-api.mdida-domain-api.mdidalib-headless.mdidapython-cheatsheet.mdobfuscation-triage.mdplugin-development.mdvm-devirt.mdscripts/ida-cli.shvm_devirt_requirements.txtvm_devirt.py詳細
ida-cli によるリバースエンジニアリング
一般的なリバースエンジニアリングの手法と、実践的な ida-cli のセットアップおよびワークフローです。CLI は、自動管理されるローカルサーバー上のシンクライアントで、データベースごとにワーカーを介して IDA と通信します。
パート 0:ゼロ設定でのセットアップ
スキルを一度インストールします:
npx -y skills add https://github.com/cpkt9762/ida-cli --skill ida-cli --agent codex --yes --global
インストール後、ユーザーの PATH に ida-cli がすでにある、またはサーバーが起動中であると想定しないでください。
起動ルール
- 新しい環境で初めて使用する際は、
scripts/ida-cli.sh --helpを実行します。 - ラッパーは、
ida-cliが PATH 上、または~/.local/bin/ida-cliにあるかどうかを検出します。 - バイナリが見つからない場合、ラッパーはリポジトリのインストーラーをダウンロードして実行し、その後、スモークテストを再実行します。
実行時ルール
- 実際の解析の前に、
scripts/ida-cli.sh probe-runtimeを実行します。 - ホストが
native-linkedとidat-compatのどちらを選択するか、推測しないでください。 - IDA のインストールが複数ある場合は、
IDADIRを明示的にエクスポートします:export IDADIR="/Applications/IDA Professional 9.5.app/Contents/MacOS"export IDADIR=/opt/ida-pro-9.5
native-linkedが選択されるのは、実行環境がバイナリのビルドに使用された SDK と一致する IDA 9.3 / 9.5 の場合のみです。それ以外の場合、プローブは、対応するメソッドの範囲がより狭いidat-compatを報告します。
使用ルール
- スキル内では、単一のエントリーポイントとして
scripts/ida-cli.shを優先して使用します。 - 通常の作業で、ユーザーに
serveやserve-httpの実行を求めないでください。クライアントのサブコマンドは、ランダムなポートにバインドされたローカル HTTP サーバーを自動起動し、検出用に/tmp/ida-cli.socketを書き込みます。 - 長時間稼働するアドレス指定可能な HTTP コントロールプレーンが実際に必要な場合に限り、
serve-http --bind ...を明示的に実行します。
ゼロ設定コマンド
# 1. install ida-cli or confirm it is available
scripts/ida-cli.sh --help
# 2. probe the selected runtime backend
scripts/ida-cli.sh probe-runtime
# 3. routine analysis (client mode, auto-starts a server)
scripts/ida-cli.sh --path /path/to/sample.bin list-functions --limit 20
scripts/ida-cli.sh --path /path/to/sample.bin decompile --addr 0x140001000
# 4. only when a shared HTTP endpoint is actually needed
scripts/ida-cli.sh serve-http --bind 127.0.0.1:8765
環境設定項目
- インストーラーの配置先:
~/.local/bin/ida-cli - ソースリポジトリ/リファレンスを指定:
IDA_CLI_REPO=cpkt9762/ida-cliIDA_CLI_INSTALL_REF=master
- インストーラーに追加の引数を渡す:
IDA_CLI_INSTALL_ARGS="--add-path"
- 特定の IDA インストール先を指定:
export IDADIR=/path/to/ida/Contents/MacOS
このスキルでは、インストール、ダウンロード、実行、検証のエントリーポイントとして scripts/ida-cli.sh を使用します。
パート 1:CLI の概要
ida-cli には 2 つの機能があります:
- フラットクライアント — スキルが使用する機能です。呼び出しごとに 1 件のリクエストを送信します。
- サービス —
serve(stdio MCP)、serve-http(Streamable HTTP MCP)、serve-worker(内部サブプロセス)、probe-runtime(内部用)です。
バイナリ名が ida-cli で、最初の引数がサービスのサブコマンドではない場合、CLI は引数をクライアント呼び出しとして解析し、ローカルソケット経由でリクエストをルーティングします。
直接サブコマンド(クライアントモード)
ida-cli --path <file> list-functions [--filter NAME] [--limit 100] [--offset 0]
ida-cli --path <file> decompile --addr 0x1000
ida-cli --path <file> disasm --addr 0x1000 [--count 20]
ida-cli --path <file> disasm --name main [--count 20]
ida-cli --path <file> xrefs-to --addr 0x1000
ida-cli --path <file> list-strings [--query X] [--limit 100]
ida-cli --path <file> list-segments
サービス/キューヘルパー:
ida-cli --path <file> prewarm [--keep-warm] [--queue]
ida-cli prewarm-many samples.txt [--jobs 4]
ida-cli --path <file> enqueue <method> [--priority 0] [--dedupe-key K] [--params '{...}']
ida-cli task-status <id>
ida-cli list-tasks
ida-cli cancel-task <id>
ida-cli status
ida-cli --path <file> close
ida-cli shutdown
それ以外:raw/pipe
フラットサブコマンドでは、最も一般的な読み取り操作に対応しています。それ以外の操作には、単一のリクエストに raw、stdin の一括処理に pipe を使用します。どちらも JSON-RPC ペイロードを受け取り、その method フィールドには MCP メソッド名を指定する必要があります(cli-tool-reference.md を参照)。
ida-cli --path <file> raw '{"method":"get_function_by_name","params":{"name":"main"}}'
ida-cli --path <file> raw '{"method":"rename_symbol","params":{"address":"0x1000","new_name":"parse_header"}}'
ida-cli --path <file> raw '{"method":"batch_decompile","params":{"addresses":["0x1000","0x2000"]}}'
ida-cli --json --path <file> pipe <<'EOF'
{"method":"list_functions","params":{"limit":5}}
{"method":"get_xrefs_from","params":{"address":"0x1000"}}
EOF
出力モード
ida-cli --json --path <file> list-functions --limit 5 # pretty JSON
ida-cli --compact --path <file> list-functions --limit 5 # single-line JSON
ファイルタイプ
| タイプ | 動作 |
|---|---|
.i64/.idb | 既存の IDA データベースを直接再オープンします |
| raw PE/ELF/Mach-O | 解析され、入力ファイルと同じ場所に .i64 としてキャッシュされます |
ローカル実行環境のパス
- データベースキャッシュ:
~/.ida/idb/ - ログ:
~/.ida/logs/server.log - サーバーの Unix ソケット:
~/.ida/server.sock - PID ファイル:
~/.ida/server.pid - 検出ファイル(フラット CLI とソケットの対応付け):
/tmp/ida-cli.socket - 大容量レスポンスのキャッシュ:
/tmp/ida-cli-out/
障害からの復旧
ローカルサーバーが応答しなくなった場合:
ida-cli shutdown
pkill -9 -f "ida-cli"
rm -f ~/.ida/server.sock ~/.ida/server.pid ~/.ida/.startup.lock /tmp/ida-cli.socket
その後、元のクライアントサブコマンドを再実行し、サーバーを再起動させます。
パート 2:一般的なリバースエンジニアリングの手法
重要な原則
- まずF5、次に逆アセンブル(厳守) — 逆アセンブルに移る前に、必ず一度はデコンパイルを試みます。
- F5の10秒ゲート(厳守) — デコンパイルが明らかに失敗した場合、または
decompile_functionが10秒を超えて停止した場合は、対象は現時点でデコンパイル不能と判断し、逆アセンブルに移ります。 - 解析しながらリネーム(厳守) — 関数の目的が分かったら、すぐにリネームします。
sub_XXXXXという名前を溜め込まないでください。 - 積極的に反復する — F5 → 型を適用 → リネーム → 再度F5 → 新しいオフセットを検証 → 繰り返します。
- 定数を文字どおりに扱う — IDAに
0x6Eと表示されている場合、より高次の意味を示す根拠が得られるまでは110と記述します。 - 小さな差異には逆アセンブルを使う — 1〜10程度の値の不一致は、通常、オフバイワン、飽和、またはビット幅の問題を示しています。
- 解析ログを残す(厳守) — 関数を解析するたびに、アドレス、リネーム後の名前、目的を記録します。
デコンパイル戦略
次の場合は逆アセンブルに移ります。
decompile_functionがエラーを返すdecompile_functionに10秒以上かかる- 擬似コードに明らかなアーティファクトが見られる
ゲートが発動したら、ループして再試行し続けないでください。1段階下に進みます。
- デコンパイルの繰り返しを停止する
- 逆アセンブルと基本ブロックを使って作業する
- xrefとコールグラフを使って制御フローを復元する
- 逆アセンブルの根拠に基づいて、リネーム、コメントの追加、型の適用を行う
- 明確な理由がある場合に限り、パッチを適用するか簡略化する
- 障害要因を解消した後、デコンパイルを再試行する
「F5を止めて逆アセンブルに切り替える」一般的な兆候:
- 1つのディスパッチャーブロックが関数の大部分を占める
- 間接分岐や計算ジャンプが多い
- 明らかなフラット化状態変数がある
- VMのようなデコード・ディスパッチ・実行ループがある
- 定数のような結果を返す不透明な述語がある
- 例外駆動、またはCFGを破壊する制御フローがある
専用の手順書:obfuscation-triage.md。
デコンパイラーがよく誤る例:
| 症状 | 擬似コード | 実際の命令パターン |
|---|---|---|
| 定数の畳み込み | result = x * 1718750 / 1000000 | リテラル定数を使った MUL + UDIV |
隠れた +1/-1 | discount = bias * 110 / 64 | 除算後にも ADD #1 がある |
| 型の混同 | int v10 = *(int *)(ctx + 0x1DC) | 実際のロードは LDR W8 で、u32 として動作する |
| 隠れた飽和処理 | result = a - b | SUBS + 0への条件付き選択 |
命名戦略
関数の内容が分かったら、すぐにリネームします。
| 接頭辞 | 意味 |
|---|---|
check_ / validate_ | 検証 |
parse_ / deserialize_ | 解析/デシリアライズ |
compute_ / calc_ | 計算 |
dispatch_ | ディスパッチのエントリーポイント |
init_ / setup_ | 初期化 |
呼び出し先をリネームした後は、すぐに呼び出し元を再デコンパイルします。可読性はすぐに向上します。
解析ログ
判明したことはリアルタイムで記録します。最低限、次の項目を記録してください。
- 関数アドレス
- 旧名 → 新名
- 目的を1文で説明
- 新たに復元した構造体
- 復元した算術式
- エラーコードの対応関係
- 未解決の疑問
推奨フォーマット:
## Analysis Log: <binary_name>
### Functions Reversed
| # | Address | Old Name | New Name | Purpose |
|---|---------|----------|----------|---------|
| 1 | 0x1234 | sub_1234 | parse_header | Parse the message header from the input buffer |
### Structs Identified
| Struct | Size | Key Fields | Used By |
|--------|------|-----------|---------|
| MsgHeader | 0x40 | +0x00 magic, +0x04 msg_type, +0x08 payload_len | parse_header |
### Open Questions
- sub_9ABC: likely initializes a lookup table, not yet proven
構造体の復元
*(ptr + 0xNNN) というパターンの繰り返しから構造体を復元します。
ARM64の一般的なロード幅の対応:
LDR X8, [X0, #0x130] -> u64
LDR W8, [X0, #0x144] -> u32
LDRH W8, [X0, #0x168] -> u16
LDRB W8, [X0, #0x178] -> u8
推奨される手順:
- デコンパイルし、ポインターとオフセットへのアクセスを収集する
- 逆アセンブルで幅を確認する
- 必要に応じて実行時の値を読み取る
- 構造体を宣言する
- 型を適用する
- 再デコンパイルし、フィールドが生のオフセットに置き換わっていることを確認する
- 構造体フィールドのxrefを使って、理解を広げる
コールグラフのナビゲーション
巨大なディスパッチャーを先頭から順に読まないでください。リーフ優先の方法を使います。
- エントリーポイントからコールグラフを構築する
- リーフ関数をデコンパイルする
- 各リーフをすぐにリネームする
- 呼び出し元を再デコンパイルする
- 上位へ向かって繰り返す
検索戦略
x86とARM64ではリトルエンディアンのバイト順であることを忘れないでください。
ida-cli --path <file> raw '{"method":"search_bytes","params":{"pattern":"6E 00 00 00"}}'
ida-cli --path <file> raw '{"method":"search_text","params":{"targets":["110","10000"],"kind":"imm"}}'
ida-cli --path <file> raw '{"method":"search_pseudocode","params":{"pattern":"amount"}}'
ida-cli --path <file> raw '{"method":"search_instructions","params":{"patterns":["MUL","UDIV"]}}'
式の抽出
ルール:
- 定数をそのまま翻訳します
- IDA に表示される演算順序を正確に保ちます
- 64 ビットの乗算が複数段階にわたる場合は
u128を使用します - 飽和動作に注意します
- 不審な算術演算は逆アセンブル結果で確認します
差分のトリアージ:
| 差分の範囲 | よくある原因 | 修正方法 |
|---|---|---|
> 100 | 式またはスケールが誤っている | 定数をもとに再構築する |
10-100 | 演算子またはオペランドが誤っている | MUL / DIV / ADD / SUB を確認する |
1-10 | 1 つずれている、または飽和している | 命令ごとに比較する |
0 | 完全一致 | 完了 |
構造化デコンパイル
算術演算の連鎖が複雑で手動比較が難しい場合は、decompile_structured を使用します。
次の項目を探します。
mul、div、add、subノード__umulh、__multi3、__udivti3などのヘルパー関数呼び出し- 数値リーフ
- 変数参照
AST から式を生成し、逆アセンブル結果と照合します。
パート 3:一般的なワークフロー
ワークフロー 1:バイナリの把握
ida-cli --path <file> raw '{"method":"get_database_info"}'
ida-cli --path <file> list-segments
ida-cli --path <file> raw '{"method":"list_exports"}'
ida-cli --path <file> raw '{"method":"list_imports"}'
ida-cli --path <file> list-functions --limit 50
ida-cli --path <file> raw '{"method":"build_callgraph","params":{"roots":["0x1000"],"max_depth":3}}'
ワークフロー 2:構造体の再構築
- デコンパイルしてオフセットを収集する
- 逆アセンブル結果で幅を確認する
- 必要に応じて値を読み取る
- 構造体を宣言する
- 型を適用する
- 再度デコンパイルする
- フィールドの xref をたどる
ワークフロー 3:算術演算の検証
ida-cli --path <file> decompile --addr 0x1000
ida-cli --path <file> raw '{"method":"get_pseudocode_at","params":{"address":"0x1024"}}'
ida-cli --path <file> disasm --addr 0x1000 --count 200
ida-cli --path <file> raw '{"method":"search_instructions","params":{"patterns":["MUL","UDIV"]}}'
ida-cli --path <file> raw '{"method":"search_instruction_operands","params":{"patterns":["#0x6E"]}}'
ワークフロー 3b:F5 失敗後の難読化トリアージ
デコンパイルがすぐに失敗する場合、または 10 秒のゲートを超える場合は、次の手順に従います。
- デコンパイルの再試行をやめる
disasm --addr 0x... --count Nを使って関数全体を表示する- 基本ブロック、xref、呼び出しグラフから制御フローを把握する
- ディスパッチャーの分岐、不透明述語、フラット化の状態変数を特定する
- 逆アセンブル結果から直接シンボル名を変更し、意図を注釈する
- 十分な進展があった後でのみ、デコンパイルを再試行する
ワークフロー 3c:強い難読化の兆候
次のいずれかに該当する場合は、ただちに逆アセンブル優先モードに切り替えます。
- 中央の 1 つのブロックが状態変数に基づいてディスパッチする
- ほとんどのエッジが同じ制御ブロックに戻る
- 分岐先が間接的に計算される
- 関数がバイトコードインタープリターまたはハンドラー VM のように見える
- 擬似コードで簡約されない不透明な算術演算に分岐が依存している
- 例外フローまたは解析妨害ロジックによってデコンパイラーが不安定になる
専用のリファレンスページ:obfuscation-triage.md。
ワークフロー 3d:商用 VM 保護(Themida / VMProtect / Code Virtualizer / WinLicense)
対象が Windows x86-64 PE で、次のいずれかに該当する場合は、通常の難読化ではなく商用 VM プロテクターが使用されています。
- 関数本体が単一の
jmp/push+ret/callで、その転送先が.themida、.vlizer、.vmp0/vmp1/vmp2、.winlice、.pelock、.svmp、.xxx、またはその他の標準外 RX セクションにある - IAT が削除され、API が暗号化された
.rdataポインターテーブルを介して解決される - 擬似コードが数千ものディスパッチされたハンドラーに退化する
- IDA がセグメンテーション違反を起こす、停止する、またはバイトコード形式のデコードループを表示する
この場合、ハンドラーのリバースを試みないでください。同梱のエミュレーションベースのデバーチャライザーを実行し、パッチ適用済み PE を IDA で開いて、通常どおりデコンパイルします。
pip install -r scripts/vm_devirt_requirements.txt
python3 scripts/vm_devirt.py protected.bin --auto -o protected-devirt.bin
ida-cli --path protected-devirt.bin list-functions --limit 20
ida-cli --path protected-devirt.bin decompile --addr 0x140001000
詳細な手法、機能マトリックス、デバーチャライズ後の IDA ワークフローについては、vm-devirt.md を参照してください。
ワークフロー 4:エラーコードのマッピング
- 即値を検索する
- 含まれる関数を特定する
- 擬似コードのコンテキストを確認する
- コメントを追加する
- 同様の戻り箇所を検索する
ワークフロー 5:テーブルとディスパッチの解析
factoryやregistryなどの文字列を検索する- xref をたどる
- テーブルの構築処理を特定する
- テーブルを走査する
- 各関数ポインターを解決してデコンパイルする
ワークフロー 6:複数データベースの分析
- 複数のデータベースを開きます(リクエストごとに
--pathは 1 つです。サーバーがデータベースごとにワーカーを自動的に起動します) open_idbが返すハンドルを、並行して動作する複数のエージェント間で共有します- 読み取り中心の処理は並列化します
- 書き込み中心の処理は直列化します
close_idbで適切に閉じます(HTTP/SSE では、open_idbが返すclose_tokenが必要です)
ワークフロー 7:一括アノテーション
必要に応じて raw 経由で実行します。
batch_renameset_function_prototypeset_function_commentrename_stack_variableset_stack_variable_typecreate_enumbatch_decompile
ワークフロー 8:動的デバッグ
dbg_* メソッド群は、デバッガーの読み込み、プロセスの開始/アタッチ、ブレークポイント、ステップ実行、レジスターの調査、メモリーの読み書き、スレッドの調査に対応します。デバッガーを公開するランタイムでのみ利用でき、ヘッドレスの idat-compat 経路では利用できません。
ASLR が有効な場合、デバッグ操作では、メソッドが IDB アドレスを明示的に受け付ける場合を除き、リベース後の実行時アドレスを使用する必要があります。
パート 4:エラーからの復旧
デコンパイルの失敗
- 失敗が明示的な場合、またはデコンパイラーが 10 秒を超えて停止した場合は、その関数を強い難読化が施されているものとして分類します
- F5 の試行を繰り返すのはやめます
get_pseudocode_atは、範囲を絞った、すでに有望な箇所にのみ使用します- 逆アセンブリ、基本ブロック、クロスリファレンス、コールグラフの分析に移ります
- 関数を部分的に解きほぐした後にのみ、デコンパイルを再試行します
自動解析の未完了
get_analysis_status が auto_is_ok=false を返す場合:
run_auto_analysisを実行します- または解析が完了するまでポーリングします
解析が完了する前に、クロスリファレンスやデコンパイルの品質を信頼しないでください。
タイムアウトへの対処
run_scriptのデフォルトは 120 秒で、最大 600 秒まで設定できます- 非常に大規模な
batch_decompile呼び出しは、小さなバッチに分割します - CLI の
--timeoutフラグは、クライアント側のリクエストごとのタイムアウトを制御します
よくある間違い
- リーフ関数ではなく、最も大きなエントリーポイントから始める
- 呼び出し先の名前を変更しても、呼び出し元を再デコンパイルしない
- 逆アセンブリを確認せずに算術演算を信頼する
- 検索時にリトルエンディアンのバイト順を忘れる
- クロスリファレンスのファンアウト数を無視する
- 読み込み幅を確認せずに、符号付きの疑似コード型を信頼する
- キャッシュ済みの
.i64ではなく、生のバイナリを再度開く - 自動解析が完了する前にクエリを実行する
パート 5:参考資料
現在のタスクに合った参考資料だけを読み込んでください。デフォルトではすべて読まないでください。
| 参考資料 | 使用する場面 |
|---|---|
| cli-tool-reference.md | CLI コマンドのパターンと機能の検索 |
| obfuscation-triage.md | F5 の失敗、フラット化、VM ハンドラー、不透明述語、逆アセンブリ優先の作業 |
| vm-devirt.md | 商用 VM プロテクター(Themida / VMProtect / Code Virtualizer / WinLicense)— scripts/vm_devirt.py を使ったエミュレーションベースの仮想化解除 |
| counterfactual-patch.md | 反実仮想パッチのワークフロー |
| headless-api.md | ヘッドレス IDA の実行と API の選択 |
| idapython-cheatsheet.md | IDAPython スクリプトの作成 |
| ida-domain-api.md | IDA Domain API の完全なリファレンス |
| idalib-headless.md | idalib/idapro のヘッドレスでの使用方法 |
| binary-analysis-patterns.md | マルウェア、脆弱性調査、ファームウェア分析のパターン |
| plugin-development.md | IDA プラグインの開発 |