mcpField
D
debugger

debugger

github.com/allthingsida開発4949 回インストール3 週間前に更新
リポジトリ

debugger について

debuggerは、IDAでのデバッグ作業向けスキルです。ブレークポイント、ウォッチポイント、バイトパッチを扱う分析者に、一覧確認や変更・復元の手順、分析結果に基づく設定例を示します。

主な機能

  1. 01ブレークポイントの作成・更新・削除
  2. 02条件付きブレークポイントとハードウェアウォッチポイントの管理
  3. 03マップ済みバイトの読み取りと変更
  4. 04パッチの一覧表示と元バイトへの復元
  5. 05呼び出し箇所への一括ブレークポイント設定

活用シーン

  1. 01セキュリティ上重要なAPI呼び出しへの設定
  2. 02構造体フィールドへの書き込み監視
  3. 03バイナリパッチの記録と確認
  4. 04パッチの取り消しや変更内容の検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/allthingsida/idasql-skills --skill debugger

インストール後、Claude Code で/debuggerを入力して読み込まれたか確認します。

同梱ファイルagents/openai.yaml

詳細


トリガーインテント

ユーザーが次のことを求めた場合に、このスキルを使用します。

  • ブレークポイントの追加/削除/変更
  • バイトのパッチ適用またはパッチの取り消し
  • パッチの一覧とデバッグアクションプランの作成
  • 分析に基づいたブレーク/ウォッチのワークフローの構築

次にルーティングします。

  • まず対象を選定するには、analysis/xrefs
  • オペコードレベルのパッチコンテキストを確認するには、disassembly
  • パッチの根拠と結果を記録するには、annotations

最初に行うこと(ウォームスタート手順)

-- 1) Current breakpoint inventory
SELECT printf('0x%X', addr) AS addr, type_name, enabled
FROM breakpoints
ORDER BY addr;

-- 2) Current patch inventory (fast: backed by IDA's patch list)
SELECT printf('0x%X', addr) AS addr, original_value, value AS patched_value
FROM bytes WHERE is_patched = 1
ORDER BY addr
LIMIT 50;

-- 3) Validate target bytes before patch
SELECT addr, value, original_value, is_patched
FROM bytes
WHERE addr = 0x401000;

解釈のガイダンス:

  • 追加する前に、既存の計装を確認します。
  • 変更を加える前に、必ず現在のバイト状態/元のバイト状態をスナップショットします。

失敗と復旧

  • ブレークポイントの挿入/更新に失敗した場合:
    • アドレスが存在すること、およびハードウェアのサイズ/タイプとの互換性を確認します。
  • パッチの検証で不一致が発生した場合:
    • bytes(および WHERE is_patched = 1)を再読み込みし、正確なアドレスを指定して再試行します。
  • 意図しないパッチの副作用が発生した場合:
    • DELETE FROM bytes WHERE addr = ... で元に戻し、対象命令のコンテキストを再評価します。

引き継ぎパターン

  1. debugger -> disassembly:パッチ箇所の周辺で命令の意味を検証します。
  2. debugger -> xrefs:パッチ適用/ブレークした呼び出し経路の影響範囲を評価します。
  3. debugger -> annotations:後から参照できる分析上の手がかりを残します。

breakpoints

デバッガーのブレークポイントです。完全な CRUD(SELECT、INSERT、UPDATE、DELETE)をサポートします。アクティブなデバッガーセッションがなくても、ブレークポイントは IDB に保持されます。folder_path は IDA のブレークポイント group のフォルダー形式の表記です。どちらを更新しても、同じブレークポイントグループが更新されます。

ColumnTypeRWDescription
addrINTRブレークポイントのアドレス
enabledINTRW1=有効、0=無効
typeINTRWブレークポイントのタイプ(1=hw_write、2=hw_read、3=hw_rdwr、4=software、8=hw_exec)
type_nameTEXTRタイプ名(software、hardware_write など)
sizeINTRWブレークポイントのサイズ(ハードウェアブレークポイント用)
flagsINTRWブレークポイントのフラグ
pass_countINTRWトリガーされるまでの通過回数
conditionTEXTRW条件式
loc_typeINTRロケーションタイプのコード
loc_type_nameTEXTRロケーションタイプ(absolute、relative、symbolic、source)
moduleTEXTRモジュールのパス(相対ブレークポイント)
symbolTEXTRシンボル名(シンボリックブレークポイント)
offsetINTRオフセット(相対/シンボリック)
source_fileTEXTRソースファイル(ソースブレークポイント)
source_lineINTRソース行番号
is_hardwareINTR1=ハードウェアブレークポイント
is_activeINTR1=現在アクティブ
groupTEXTRWブレークポイントグループ名
bptidINTRブレークポイント ID
folder_pathTEXTRWブレークポイントグループフォルダーの別名。NULL はルートを意味します
full_pathTEXTR利用可能な場合のブレークポイントの完全な dirtree パス
-- List all breakpoints
SELECT printf('0x%08X', addr) as addr, type_name, enabled, condition
FROM breakpoints;

-- Add software breakpoint
INSERT INTO breakpoints (addr) VALUES (0x401000);

-- Add hardware write watchpoint
INSERT INTO breakpoints (addr, type, size) VALUES (0x402000, 1, 4);

-- Add conditional breakpoint (at a different address than the plain one above)
INSERT INTO breakpoints (addr, condition) VALUES (0x401330, 'eax == 0');

-- Move breakpoint into/out of an IDA breakpoint folder
UPDATE breakpoints SET folder_path = 'idasql/breakpoints/network' WHERE addr = 0x401000;
UPDATE breakpoints SET folder_path = NULL WHERE addr = 0x401000;

-- Disable a breakpoint
UPDATE breakpoints SET enabled = 0 WHERE addr = 0x401000;

-- Delete a breakpoint
DELETE FROM breakpoints WHERE addr = 0x401000;

-- Find which functions have breakpoints
SELECT b.addr, f.name, b.type_name, b.enabled
FROM breakpoints b
JOIN funcs f ON b.addr >= f.addr AND b.addr < f.end_addr;

bytes(バイトパッチ適用)

パッチに対応した、マップ済みバイトのプログラムビューです。このテーブルはマップ済みのバイトアドレスごとに1行あります。サイズやタイプなどの IDA アイテムメタデータは heads に属します。

ColumnTypeRWDescription
addrINTRバイトアドレス
valueINTRW現在のバイト値(UPDATE は1バイトにパッチを適用)
wordINTRW2バイトのリトルエンディアン値(UPDATE は2バイトにパッチを適用)
dwordINTRW4バイトのリトルエンディアン値(UPDATE は4バイトにパッチを適用)
qwordINTRW8バイトのリトルエンディアン値(UPDATE は8バイトにパッチを適用)
original_valueINTRパッチ適用前の元のバイト値
is_patchedINTRバイトが元の値と異なる場合は1(WHERE is_patched = 1 でパッチをすばやく列挙できます)
fposINTR物理/入力ファイルのオフセット(利用できない場合は NULL)

パッチを元に戻すには、DELETE FROM bytes WHERE addr = ...(または WHERE is_patched = 1)を実行します。

-- Read one address
SELECT addr, value, original_value, is_patched
FROM bytes WHERE addr = 0x401000;

-- Read a byte range, including item-tail bytes
SELECT addr, value
FROM bytes
WHERE addr >= 0x401000 AND addr < 0x401010
ORDER BY addr;

-- Get item metadata separately
SELECT addr, size, type, flags, disasm
FROM heads
WHERE addr = 0x401000;

-- Patch via table update (single byte, or width columns word/dword/qword)
UPDATE bytes SET value = 0x90 WHERE addr = 0x401000;
UPDATE bytes SET dword = 0x90909090 WHERE addr = 0x401000;  -- little-endian

-- Inspect patch inventory (fast: backed by IDA's patch list)
SELECT printf('0x%X', addr) AS addr, original_value, value AS patched_value
FROM bytes WHERE is_patched = 1 ORDER BY addr LIMIT 20;

-- Persist once done
SELECT save_database();

bytes — パッチ適用(書き込み可能な領域)

すべてのバイトへのパッチ適用は、書き込み可能な bytes テーブルを通じて行います。

列RW意味
valueRW現在のバイト。UPDATE で 1 バイトにパッチを適用します
word / dword / qwordRWUPDATE で 2/4/8 バイトにリトルエンディアンでパッチを適用します
original_valueR元の(パッチ適用前の)バイト
is_patchedRパッチ適用済みの場合は 1。WHERE is_patched = 1 でパッチをすばやく列挙できます
SELECT printf('0x%X', addr) AS addr,
       printf('0x%02X', original_value) AS old,
       printf('0x%02X', value) AS new
FROM bytes WHERE is_patched = 1
ORDER BY addr;

bytes テーブルを使ったバイトアクセス

すべてのバイトの読み取りとパッチ適用は、bytes テーブルを通じて行います。範囲を指定した読み取りの形式は data に記載されています。このスキルでは、パッチ適用のワークフローに焦点を当てます。load_file_bytes(...) は、指定範囲の IDB にファイルのバイトを書き込みます。パッチの内容がすでにファイルにある場合に使用します。

関数/形式説明
SELECT hex(blob_concat(value)) FROM (SELECT value FROM bytes WHERE start_addr = X AND n = N ORDER BY addr)N バイトを大文字の 16 進数として読み取ります
SELECT blob_concat(value) FROM (SELECT value FROM bytes WHERE start_addr = X AND n = N ORDER BY addr)N バイトを BLOB として読み取ります
load_file_bytes(path, file_offset, addr, size[, patchable])対象範囲の IDB にファイルのバイトを書き込みます
-- Read 16 bytes as hex
SELECT hex(blob_concat(value))
FROM (SELECT value FROM bytes WHERE start_addr = 0x401000 AND n = 16 ORDER BY addr);

-- Patch one byte (example: NOP) and a 4-byte little-endian value
UPDATE bytes SET value = 0x90 WHERE addr = 0x401000;
UPDATE bytes SET dword = 0x90909090 WHERE addr = 0x401000;

-- Verify current vs original
SELECT value AS current, original_value AS original
FROM bytes WHERE addr = 0x401000;

-- Revert patch (one byte, or every patch)
DELETE FROM bytes WHERE addr = 0x401000;
DELETE FROM bytes WHERE is_patched = 1;

-- Persist patches explicitly
SELECT save_database();

分析に基づくブレークポイントのワークフロー

セキュリティ上重要な API のすべての呼び出し元にブレークポイントを設定する

disasm_calls を使用してすべての呼び出し箇所を見つけ、一括でブレークポイントを挿入します。

-- Breakpoint on every call to VirtualAlloc (or similar)
INSERT INTO breakpoints (addr)
SELECT addr FROM disasm_calls WHERE callee_name LIKE '%VirtualAlloc%';

-- Verify
SELECT printf('0x%08X', addr) AS addr, type_name, enabled
FROM breakpoints;
型分析で見つかった構造体フィールドにウォッチポイントを設定する

構造体を復元した後、特定のフィールドオフセットにハードウェアウォッチポイントを設定します。

-- Hardware write watchpoint on a 4-byte field (e.g., config.flags at base+0x10)
-- First, find where the struct base is stored (requires manual analysis)
INSERT INTO breakpoints (addr, type, size) VALUES (0x402010, 1, 4);
-- type=1 is hardware_write, size=4 for DWORD field
デコンパイラーの分析結果に基づく条件付きブレークポイント

特定の条件が満たされた場合にのみトリガーされるブレークポイントを設定します。

-- Break when first argument (rcx on x64 fastcall) equals a specific enum value
INSERT INTO breakpoints (addr, condition)
VALUES (0x401000, 'rcx == 3');

-- Break on error return
INSERT INTO breakpoints (addr, condition)
VALUES (0x401050, 'rax == 0xFFFFFFFF');

パッチ適用のワークフロー

アンチデバッグチェックを NOP 化する

IsDebuggerPresent チェックを見つけて無効化します。

-- Find calls to IsDebuggerPresent
SELECT dc.addr, (SELECT name FROM funcs WHERE dc.func_addr >= addr AND dc.func_addr < end_addr LIMIT 1) AS func_name,
       disasm_at(dc.addr, 2) AS context
FROM disasm_calls dc
WHERE dc.callee_name LIKE '%IsDebuggerPresent%';

-- Patch the conditional jump after the check (example: jnz → nop nop)
-- First inspect the instruction after the call
SELECT disasm_at(0x401030, 3);
-- Then patch (adjust addresses based on actual binary)
UPDATE bytes SET value = 0x90 WHERE addr = 0x401035;
UPDATE bytes SET value = 0x90 WHERE addr = 0x401036;
すべてのパッチを一覧化してレポートを生成する
-- Full patch report: what was changed and where
SELECT printf('0x%X', addr) AS addr,
       (SELECT name FROM funcs WHERE addr >= addr AND addr < end_addr LIMIT 1) AS func_name,
       printf('0x%02X', original_value) AS original,
       printf('0x%02X', value) AS patched,
       disasm_at(addr) AS context
FROM bytes WHERE is_patched = 1
ORDER BY addr;

パフォーマンスに関する注意事項

テーブルサイズ制約備考
breakpoints小規模(通常は 100 件未満)不要常に高速です
bytesマッピング済みの全バイトaddr重要 — 1 つのアドレスまたは狭い範囲に絞り込んでください
bytes WHERE is_patched = 1小規模(パッチ数分)is_patched = 1高速 — IDA のパッチリストを使って、パッチ適用済みの箇所のみを反復します
  • breakpoints テーブルは小規模なので、全件スキャンしても問題ありません。
  • bytes テーブルはマッピング済みのバイトごとに 1 行を出力します。WHERE addr = X または狭い addr 範囲を使用してください。
  • bytes WHERE is_patched = 1 はパッチ適用済みの箇所のみを反復するため、常に高速です。

関連項目

  • disassembly — パッチ箇所周辺の命令コンテキスト(disasm_at、オペランドの意味)。
  • annotations — 変更する前に、コメント/ブックマークでパッチの理由を記録します。
  • data — バイト読み取り形式の正式な定義(テーブルとスカラーの区別)。

コメント