decompiler について
Hex-Raysで関数を分析するスキルです。疑似コード、AST、ローカル変数、パターンビューを扱い、関数単位のクエリや関連スキルへの引き継ぎを案内します。
主な機能
- 01逆コンパイル済み疑似コードの確認
- 02ASTとローカル変数の検索
- 03呼び出し・分岐・ループの検索
- 04疑似コードコメントの編集
- 05逆アセンブルによる分析の補完
活用シーン
- 01関数の動作を理解
- 02呼び出しや条件のパターンを特定
- 03ローカル変数の意味を調査
- 04アセンブリレベルで結果を検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ allthingsida/ idasql-skills --skill decompilerインストール後、Claude Code で/decompilerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlreferences/ctree-manipulation.mddecompiler-views.mddecompiler-workflows.md詳細
トリガーとなるインテント
ユーザーが次のことを求めた場合に、このスキルを使用します。
- 「この関数を逆コンパイルして」
- 疑似コードの理解、または AST レベルの分析
- 逆コンパイル結果におけるローカル変数の意味の解釈
- デコンパイラー中心のパターン抽出(戻り値/呼び出し/条件)
次にルーティングします。
- 解釈後のコメントや名前の永続化には
annotations - 構造体/列挙型/型の構築と適用には
types - デコンパイラーが利用できない、または不十分な場合は
disassembly
最初に実行すること(ウォームスタートの手順)
-- 1) Capability/profile probe
SELECT * FROM pragma_table_list WHERE name IN ('pseudocode', 'ctree', 'ctree_lvars');
-- 2) Pick one concrete function target
SELECT name, printf('0x%X', addr) AS addr, size
FROM funcs
ORDER BY size DESC
LIMIT 10;
-- 3) View decompiled text via primary read surface
SELECT decompile(0x401000);
解釈のガイダンス:
decompile(addr)は主要な表示サーフェスです。pseudocode/ctree*は構造化されたクエリー/編集用サーフェスです。
グローバル制約に関する注意(重要)
デコンパイラーのテーブルには、必ず関数で制約をかけてください。
WHERE func_addr = 0x...
これを行わないと、デコンパイラーのテーブルがすべての関数を逆コンパイルし、非常に遅くなる場合があります。
失敗時の復旧
- Hex-Rays がない/デコンパイラーのテーブルを利用できない:
disassemblyとxrefsのワークフローにフォールバックします。
- 行が空/不完全:
- 対象の
func_addrが存在することを確認し、逆コンパイルキャッシュを更新します(サポートされている場合はdecompile(addr, 1))。
- 対象の
- 変更が反映されない:
- 必須の変更ループ(読み取り → 編集 → 更新 → 検証)を実行します。
引き継ぎパターン
decompiler→ ローカル型の設定と、より詳細な宣言にはtypes。decompiler→ 永続的な説明や命名にはannotations。decompiler→ オペコードレベルでの検証にはdisassembly。
デコンパイラーのテーブル(Hex-Rays が必要)
重要: 必ず func_addr でフィルターしてください。制約を指定しない場合、これらのテーブルはすべての関数を逆コンパイルするため、非常に遅くなります!
pseudocode
pseudocode テーブルは、書き込み可能なコメントを備えた、行単位の構造化された疑似コードです。疑似コードの表示には decompile(addr) を使用してください。このテーブルは、ピンポイントの編集(コメント)または構造化クエリーにのみ使用してください。
| 列 | 型 | 書き込み可能 | 説明 |
|---|---|---|---|
func_addr | INT | いいえ | 関数アドレス |
line_num | INT | いいえ | 行番号 |
line | TEXT | いいえ | 疑似コードテキスト |
addr | INT | いいえ | 対応するアセンブリアドレス(COLOR_ADDR アンカーから取得) |
comment | TEXT | はい | このアドレスにおけるデコンパイラーコメント |
comment_placement | TEXT | はい | コメントの配置:semi(行内、デフォルト)、block1(行の上) |
フィルターの動作:
WHERE func_addr = X:最高のパフォーマンスです。1つの関数の疑似コードだけを反復処理します。WHERE addr = X:対象 EA を含む関数だけを逆コンパイルし、その EA に一致する行を返します。WHERE line_num = N:関数を走査し、その行インデックスに該当する行を返します。関数間で行を対応付ける必要がある場合にのみ使用してください。
コメントの配置: semi(; の後)、block1(独立した行の上)、block2、curly1、curly2、brace1、brace2、colon、case、else、do、asm、try。認識されない配置文字列は、警告なしで semi に変換されます。
-- VIEWING: Use decompile() function, NOT the pseudocode table
SELECT decompile(0x401000);
-- COMMENTING: Use pseudocode table to add/edit/delete comments
UPDATE pseudocode SET comment_placement = 'semi',
comment = 'buffer overflow here'
WHERE func_addr = 0x401000 AND addr = 0x401020;
-- Add block comment (appears on own line above the statement)
UPDATE pseudocode SET comment_placement = 'block1', comment = 'vulnerable call'
WHERE func_addr = 0x401000 AND addr = 0x401020;
-- Delete comments at a resolved unique anchor
UPDATE pseudocode SET comment = NULL
WHERE func_addr = 0x401000 AND addr = 0x401020;
関数コメントそのものは pseudocode に含まれません。
- 通常の関数コメントには
UPDATE funcs SET comment = ... WHERE addr = ...を使用します。 - 繰り返し表示される関数コメントには
UPDATE funcs SET rpt_comment = ... WHERE addr = ...を使用します。
pseudocode_orphan_comments
現在の関数の逆コンパイル結果に紐付かなくなった、永続化済みの Hex-Rays コメントです。古いコメントの確認や削除に使用します。
| 列 | 型 | 書き込み可能 | 説明 |
|---|---|---|---|
func_addr | INT | いいえ | 関数アドレス |
func_name | TEXT | いいえ | トリアージ用の現在の関数名 |
addr | INT | いいえ | 保存された孤立コメントの EA |
comment_placement | TEXT | いいえ | 保存された treeloc_t.itp の配置 |
orphan_comment | TEXT | 削除のみ | 保存された孤立コメントのテキスト |
ルール:
UPDATE ... SET orphan_comment = NULLまたは''を指定すると、その孤立コメントが削除されます。- 空でない値の書き込みは拒否されます。
pseudocode_v_orphan_comment_groups
グループ化された読み取り専用の孤立コメント用トリアージサーフェスです。孤立コメントを含む関数ごとに1行あります。
列:func_addr、func_name、orphan_count、orphan_comments_json
コメントアンカーの解決(重要)
見出し形式の逆コンパイラ注釈を書く前に、この手順に従ってください。
ルール:
addr == func_addrと決めつけないでください。- 最初に表示される擬似コードの行は
addr = 0であることが多く、書き込み先として適切ではありません。 - 1 つの
addrが複数の行({、文、})に対応することがあります。ブレース以外の一意なアンカーを優先してください。 - 関数に対するコメントを付ける場合は、
pseudocodeではなくfuncs.comment/funcs.rpt_commentを更新してください。
-- Resolve the first attachable non-brace row near function start
SELECT line_num, addr, line
FROM pseudocode
WHERE func_addr = 0x401000
AND addr != 0
AND TRIM(line) NOT IN ('{', '}')
AND addr IN (
SELECT addr
FROM pseudocode
WHERE func_addr = 0x401000 AND addr != 0
GROUP BY addr
HAVING COUNT(*) = 1
)
ORDER BY line_num
LIMIT 1;
-- Write a heading-style summary using the resolved addr
UPDATE pseudocode
SET comment_placement = 'block1',
comment = 'One-paragraph summary of the function.'
WHERE func_addr = 0x401000
AND addr = (
SELECT addr
FROM pseudocode
WHERE func_addr = 0x401000
AND addr != 0
AND TRIM(line) NOT IN ('{', '}')
AND addr IN (
SELECT addr
FROM pseudocode
WHERE func_addr = 0x401000 AND addr != 0
GROUP BY addr
HAVING COUNT(*) = 1
)
ORDER BY line_num
LIMIT 1
);
ctree
逆コンパイルされたコードの完全な抽象構文木です。
| Column | Type | Description |
|---|---|---|
func_addr | INT | 関数アドレス |
item_id | INT | 一意なノード ID |
is_expr | INT | 1=式、0=文 |
op | INT | 生の数値オペコード |
op_name | TEXT | ノードの型(cot_call、cit_if など) |
addr | INT | バイナリ内のアドレス |
parent_id | INT | 親ノード ID |
depth | INT | 木の深さ |
x_id, y_id, z_id | INT | 子ノード ID |
cond_id | INT | 条件の子ノード ID(if/while/for) |
then_id | INT | then 分岐の子ノード ID(if) |
else_id | INT | else 分岐の子ノード ID(if) |
body_id | INT | 本体の子ノード ID(ループ) |
init_id | INT | 初期化の子ノード ID(for) |
step_id | INT | ステップの子ノード ID(for) |
var_idx | INT | ローカル変数のインデックス |
obj_addr | INT | 対象のアドレス |
num_value | INT | 数値リテラル |
str_value | TEXT | 文字列リテラル |
helper_name | TEXT | ヘルパー関数名(cot_helper) |
member_offset | INT | メンバーのオフセット(cot_memptr/cot_memref) |
var_name | TEXT | 変数名 |
var_is_stk | INT | 1=変数はスタック変数 |
var_is_reg | INT | 1=変数はレジスター変数 |
var_is_arg | INT | 1=変数は関数の引数 |
obj_name | TEXT | シンボル名 |
label_num | INT | ノードがラベルを定義する場合のラベル番号 |
goto_label_num | INT | cit_goto ノードの対象ラベル番号 |
ctree_lvars
逆コンパイルで取得したローカル変数です。
| Column | Type | Description |
|---|---|---|
func_addr | INT | 関数アドレス |
idx | INT | 変数のインデックス |
name | TEXT | 変数名 |
type | TEXT | 型文字列 |
comment | TEXT | 宣言の横に表示されるローカル変数のコメント |
size | INT | サイズ(バイト単位) |
is_arg | INT | 1=関数の引数 |
is_result | INT | 1=関数の戻り値を保持 |
is_stk_var | INT | 1=スタック変数 |
is_reg_var | INT | 1=レジスター変数 |
stkoff | INT | スタックオフセット |
mreg | INT | マイクロコードのレジスター番号(レジスター変数) |
変更時の指針:
- 決定的に書き込むには、
idxベースの更新を優先してください。 typeにはスカラー、ポインター、配列型を指定できます。たとえば、スタック上のワイド文字列や固定バッファにはSET type = 'WCHAR[6]'または'_BYTE[392]'を使用します(型はローカル変数のスタックスロットに収まる必要があります)。commentの更新は Hex-Rays のローカル変数コメント(lv.cmt)に反映され、decompile(...)の出力に表示されます。
ctree_labels
逆コンパイラの制御フローラベルです。UPDATE(name)をサポートし、cfunc_t のラベル機能を反映します。
| Column | Type | RW | Description |
|---|---|---|---|
func_addr | INT | R | 関数アドレス |
label_num | INT | R | ラベル番号(LABEL_<n>) |
name | TEXT | RW | 現在のラベル名 |
item_id | INT | R | このラベルの基になる ctree 項目 ID |
item_addr | INT | R | ラベルを持つ ctree 項目のアドレス |
is_user_defined | INT | R | 1=名前が既定の LABEL_<n> と異なる |
ctree_call_args
簡単にクエリできるように、呼び出し引数をフラット化したものです。
| Column | Type | Description |
|---|---|---|
func_addr | INT | 関数アドレス |
call_item_id | INT | 呼び出しノード ID |
call_addr | INT | 呼び出しサイト EA |
call_obj_name | TEXT | 呼び出し先オブジェクト名 |
call_helper_name | TEXT | 呼び出し先ヘルパー名 |
arg_idx | INT | 引数インデックス(0 始まり) |
arg_item_id | INT | 引数式アイテム ID |
arg_op | TEXT | 引数の型 |
arg_var_idx | INT | 引数が変数の場合のローカル変数インデックス |
arg_var_name | TEXT | 該当する場合の変数名 |
arg_var_is_stk | INT | 1=引数の変数がスタック変数 |
arg_var_is_arg | INT | 1=引数の変数自体が関数引数 |
arg_obj_addr | INT | 引数がグローバルオブジェクトの場合のオブジェクトアドレス |
arg_obj_name | TEXT | 引数がグローバルオブジェクトの場合のオブジェクト名 |
arg_num_value | INT | 数値 |
arg_str_value | TEXT | 文字列 |
デコンパイラビュー
よくあるパターン向けの事前定義済みビューです(常に func_addr でフィルターしてください)。
| View | Purpose |
|---|---|
ctree_v_calls | 呼び出し先情報を含む関数呼び出し |
ctree_v_indirect_calls | 呼び出しサイトの型付けに使う間接/動的呼び出しサイト |
ctree_v_loops | for/while/do ループ |
ctree_v_ifs | if 文 |
ctree_v_comparisons | オペランドを含む比較 |
ctree_v_signed_ops | 符号付き比較/算術演算 |
ctree_v_assignments | オペランドを含む代入 |
ctree_v_derefs | ポインターの間接参照 |
ctree_v_returns | 値の詳細を含む return 文 |
ctree_v_calls_in_loops | ループ内の呼び出し(再帰的) |
ctree_v_calls_in_ifs | if 分岐内の呼び出し(再帰的) |
ctree_v_leaf_funcs | 外部への呼び出しがない関数 |
ctree_v_call_chains | 深さ 10 までの呼び出しチェーンのパス |
型テーブルとビュー
types、types_members、types_enum_values、types_func_args のスキーマ、型ビュー、型 CRUD の例については、types スキルを参照してください。
SQL 関数 — デコンパイル
decompile() と pseudocode テーブルの使い分け:
- 擬似コードを読む/表示する -> 常に
SELECT decompile(addr)から始めます。行ごとのプレフィックス付きで、関数全体をひとつのテキストブロックとして返します。 - ローカル変数の宣言ヒント -> 宣言行にはコンパクトなローカル変数インデックスのヒント(
[lv:N])が含まれるため、名前変更操作ではUPDATE ctree_lvars ... WHERE func_addr = ... AND idx = Nを安全に対象指定できます。 - 編集後に最新の出力が必要 ->
SELECT decompile(addr, 1)を使って再デコンパイルを強制します。 - 構造化された行へのアクセス、またはコメントの CRUD が必要 ->
pseudocodeテーブルをクエリ/更新します。
| 関数 | 説明 |
|---|---|
decompile(addr) | 推奨 -- 行プレフィックス付きの完全な擬似コード |
decompile(addr, 1) | 同じ出力ですが、再デコンパイルを強制します |
call_arg_addrs(call_addr) | 永続化された引数ローダーのアドレスを JSON として読み取ります |
set_union_selection(func_addr, addr, path) | EA におけるユニオン選択パスを設定/解除します |
set_union_selection_item(func_addr, item_id, path) | ctree.item_id によってユニオン選択パスを設定/解除します |
set_union_selection_addr_arg(func_addr, addr, arg_idx, path[, callee]) | 推奨 呼び出し引数の対象指定ヘルパー |
call_arg_item(func_addr, addr, arg_idx[, callee]) | 呼び出し引数の座標を明示的な arg_item_id に解決します |
ctree_item_at(func_addr, addr[, op_name[, nth]]) | 一般的な式の座標を明示的な ctree.item_id に解決します |
set_union_selection_addr_expr(func_addr, addr, path[, op_name[, nth]]) | 一般的な式の座標を使ってユニオン選択を設定/解除します |
get_union_selection(func_addr, addr) | EA におけるユニオン選択パスの JSON を読み取ります |
get_union_selection_item(func_addr, item_id) | ctree.item_id によってユニオン選択パスの JSON を読み取ります |
get_union_selection_addr_arg(func_addr, addr, arg_idx[, callee]) | 呼び出し引数の座標を使ってユニオン選択の JSON を読み取ります |
get_union_selection_addr_expr(func_addr, addr[, op_name[, nth]]) | 一般的な式の座標を使ってユニオン選択の JSON を読み取ります |
set_numform(func_addr, addr, opnum, spec) | EA とオペランドインデックスを直接指定して numform を設定/解除します |
get_numform(func_addr, addr, opnum) | EA とオペランドインデックスを直接指定して numform の JSON を読み取ります |
set_numform_item(func_addr, item_id, opnum, spec) | 明示的な ctree アイテム ID を指定して numform を設定/解除します |
get_numform_item(func_addr, item_id, opnum) | 明示的な ctree アイテム ID を指定して numform の JSON を読み取ります |
set_numform_addr_arg(func_addr, addr, arg_idx, opnum, spec[, callee]) | 呼び出し引数の座標を使って numform を設定/解除します |
get_numform_addr_arg(func_addr, addr, arg_idx, opnum[, callee]) | 呼び出し引数の座標を使って numform の JSON を読み取ります |
set_numform_addr_expr(func_addr, addr, opnum, spec[, op_name[, nth]]) | 一般的な式の座標を使って numform を設定/解除します |
get_numform_addr_expr(func_addr, addr, opnum[, op_name[, nth]]) | 一般的な式の座標を使って numform の JSON を読み取ります |
対象指定のガイダンス:
- 繰り返し呼び出される関数や呼び出し箇所の引数には、
*_addr_argヘルパーを使用します。 - 呼び出し式以外の式や、代入側での構造体/ユニオンへの格納には、
ctree_item_at(..., op_name, nth)と*_addr_exprヘルパーを使用します。
SQL 関数 — 変更
applied_types、parse_decls()、および names/funcs 経由での名前の書き込みについては、types スキルを参照してください。
関数メタデータの SQL 書き込みには、次の方法を推奨します。
UPDATE funcs SET name = '...', prototype = '...', comment = '...', rpt_comment = '...' WHERE addr = ...prototypeはapplied_typesの動作に対応し、デコンパイラーのキャッシュを無効化します。comment/rpt_commentはget_func_cmt()/set_func_cmt()に対応します。
パフォーマンスルール
| テーブル | アーキテクチャ | 主な制約 | 備考 |
|---|---|---|---|
pseudocode | キャッシュ | func_addr | 関数ごとに遅延キャッシュされ、クエリ後に解放されます |
pseudocode_orphan_comments | キャッシュ | func_addr | 孤立行はクエリのスコープ内に限定されます。書き込みは削除のみ可能です |
pseudocode_v_orphan_comment_groups | キャッシュ | func_addr | グループ化された孤立行のトリアージはクエリのスコープ内に限定されます。まずは広い範囲を LIMIT で絞り込んでください |
ctree | ジェネレーター | func_addr | 遅延ストリーミングで、結果全体をメモリ上に展開せず、LIMIT を尊重します |
ctree_lvars | キャッシュ | func_addr | 関数ごとに遅延キャッシュされ、クエリ後に解放されます |
ctree_call_args | ジェネレーター | func_addr | 遅延ストリーミングで、LIMIT を尊重します |
重要なルール:
- すべてのデコンパイラーテーブルで
func_addr制約が必要です。 指定しないと、すべての関数がデコンパイルされます。 - ジェネレーターテーブル(
ctree、ctree_call_args)は行を遅延ストリーミングし、LIMIT に達すると停止します。 - デコンパイラービュー(
ctree_v_calls、ctree_v_indirect_calls、ctree_v_loopsなど)はfunc_addr制約を引き継ぎます。常にフィルターを指定してください。 - Hex-Rays cfunc キャッシュ:
decompile(addr)は内部でキャッシュされます。decompile(addr, 1)は完全な再デコンパイルを強制します。ミューテーションの効果を確認する必要がある場合にのみ使用してください。
コストモデル:
decompile(addr) -> ~50-200ms first call, ~0ms cached
decompile(addr, 1) -> ~50-200ms always (forces re-decompile)
ctree WHERE func_addr=X -> one decompilation + streaming rows
ctree (no constraint) -> one decompilation per row in funcs
追加リソース
- 詳細なワークフロー(機能の確認、ミューテーションループ、呼び出しサイトの型付け、ローカル型のシード設定、フォールバックパターン、完全な実例)については、references/decompiler-workflows.md を参照してください。
- 詳細なビューのスキーマ(ctree_v_indirect_calls、ctree_v_returns)については、references/decompiler-views.md を参照してください。
- ctree ノードの種類、操作パターン、高度な CTE については、references/ctree-manipulation.md を参照してください。
関連項目
data— デコンパイルされたコードが参照する生バイト列と文字列の内容(バイト単位の読み取りおよびWHERE start_addr = X AND n = Nによる範囲を限定したウィンドウ読み取り用のbytesテーブル、16 進数出力用のhex(blob_concat(value)))。disassembly— 同じ関数の命令レベルの正解情報(disasm_func、instructions、disasm_calls)。xrefs— デコンパイルされた関数の呼び出し元と呼び出し先。擬似コードからコールグラフへ移動できます。types— 適用されたプロトタイプが ctree の形状を決定します。applied_types/funcs.prototypeを使って型を付け直し、キャストや間接呼び出しを整理してください。