mcpField
D
decompiler

decompiler

github.com/allthingsida开发4970 次安装3 周前更新
代码仓库

关于 decompiler

用于在 Hex-Rays 中分析反编译函数的技能,涵盖伪代码、AST、局部变量和模式视图。它指导按函数范围查询,并将后续工作衔接到相关分析技能。

主要功能

  1. 01查看反编译伪代码
  2. 02查询 AST 和局部变量
  3. 03搜索调用、分支与循环
  4. 04编辑伪代码注释
  5. 05通过反汇编工作流恢复分析

适用场景

  1. 01理解函数行为
  2. 02查找调用或条件模式
  3. 03检查局部变量语义
  4. 04在汇编层面验证反编译结果

安装

复制下面的命令,在终端中运行。

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

安装后在 Claude Code 中输入/decompiler确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
references/
ctree-manipulation.md
decompiler-views.md
decompiler-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))。
  • 修改未显示:
    • 执行强制修改循环(读取 -> 编辑 -> 刷新 -> 验证)。

移交模式

  1. decompiler -> types,用于局部类型注入和更丰富的声明。
  2. decompiler -> annotations,用于持久化说明和命名。
  3. decompiler -> disassembly,用于操作码级验证。

反编译器表(需要 Hex-Rays)

重要: 始终按 func_addr 筛选。不加约束的话,这些表会反编译每个函数——速度极慢!

pseudocode

pseudocode 表是逐行的结构化伪代码,并支持写入注释。使用 decompile(addr) 查看伪代码;此表仅用于精细编辑(注释)或结构化查询。

列类型可写描述
func_addrINT否函数地址
line_numINT否行号
lineTEXT否伪代码文本
addrINT否对应的汇编地址(来自 COLOR_ADDR 锚点)
commentTEXT是此地址处的反编译器注释
comment_placementTEXT是注释位置:semi(行内,默认)、block1(行上方)

筛选行为:

  • WHERE func_addr = X:性能最佳;仅遍历一个函数的伪代码。
  • WHERE addr = X:仅反编译包含该地址的函数,并返回该 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_addrINT否函数地址
func_nameTEXT否用于分类处理的当前函数名称
addrINT否存储的孤立注释 EA
comment_placementTEXT否存储的 treeloc_t.itp 位置
orphan_commentTEXT仅可删除存储的孤立注释文本

规则:

  • UPDATE ... SET orphan_comment = NULL 或 '' 会删除该孤立注释。
  • 任何非空写入都会被拒绝。
pseudocode_v_orphan_comment_groups

分组的只读孤立注释分类处理界面。每个包含孤立注释的函数对应一行。

列:func_addr、func_name、orphan_count、orphan_comments_json

注释锚点解析(关键)

在编写标题样式的反编译器注释之前,请先使用此方法。

规则:

  • 不要假设 addr == func_addr。
  • 显示的第一行伪代码通常有 addr = 0,不是合适的写入目标。
  • 一个 addr 可能对应多行({、语句、});优先选择唯一的非大括号锚点。
  • 对于真正的函数注释,请更新 funcs.comment / funcs.rpt_comment,而不是 pseudocode。
-- 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

反编译代码的完整抽象语法树。

列类型描述
func_addrINT函数地址
item_idINT唯一节点 ID
is_exprINT1=表达式,0=语句
opINT原始数值操作码
op_nameTEXT节点类型(cot_call、cit_if 等)
addrINT二进制文件中的地址
parent_idINT父节点 ID
depthINT树深度
x_id, y_id, z_idINT子节点 ID
cond_idINT条件子节点 ID(if/while/for)
then_idINTthen 分支子节点 ID(if)
else_idINTelse 分支子节点 ID(if)
body_idINT主体子节点 ID(循环)
init_idINT初始化子节点 ID(for)
step_idINT步骤子节点 ID(for)
var_idxINT局部变量索引
obj_addrINT目标地址
num_valueINT数值字面量
str_valueTEXT字符串字面量
helper_nameTEXT辅助函数名称(cot_helper)
member_offsetINT成员偏移量(cot_memptr/cot_memref)
var_nameTEXT变量名称
var_is_stkINT1=变量是栈变量
var_is_regINT1=变量是寄存器变量
var_is_argINT1=变量是函数参数
obj_nameTEXT符号名称
label_numINT节点定义标签时的标签编号
goto_label_numINTcit_goto 节点的目标标签编号
ctree_lvars

反编译得到的局部变量。

列类型描述
func_addrINT函数地址
idxINT变量索引
nameTEXT变量名称
typeTEXT类型字符串
commentTEXT显示在声明旁的局部变量注释
sizeINT字节数
is_argINT1=函数参数
is_resultINT1=保存函数结果
is_stk_varINT1=栈变量
is_reg_varINT1=寄存器变量
stkoffINT栈偏移量
mregINT微码寄存器编号(寄存器变量)

修改指南:

  • 优先使用基于 idx 的更新,以确保写入具有确定性。
  • type 接受标量、指针和数组类型——例如,对于宽字符栈字符串/固定缓冲区,可设置为 SET type = 'WCHAR[6]' 或 '_BYTE[392]'(类型必须适合局部变量的栈槽)。
  • comment 更新会映射到 Hex-Rays 局部变量注释(lv.cmt),并显示在 decompile(...) 输出中。
ctree_labels

反编译器控制流标签。支持更新(name),并映射 cfunc_t 上的标签功能。

列类型RW描述
func_addrINTR函数地址
label_numINTR标签编号(LABEL_<n>)
nameTEXTRW当前标签名称
item_idINTR此标签对应的 ctree 项目 ID
item_addrINTR带标签的 ctree 项目的地址
is_user_definedINTR若名称不同于默认的 LABEL_<n>,则为 1
ctree_call_args

扁平化的调用参数,便于查询。

列类型描述
func_addrINT函数地址
call_item_idINT调用节点 ID
call_addrINT调用点 EA
call_obj_nameTEXT被调用对象名称
call_helper_nameTEXT被调用辅助函数名称
arg_idxINT参数索引(从 0 开始)
arg_item_idINT参数表达式项 ID
arg_opTEXT参数类型
arg_var_idxINT参数为变量时的局部变量索引
arg_var_nameTEXT适用时的变量名称
arg_var_is_stkINT1=参数变量是栈变量
arg_var_is_argINT1=参数变量本身是函数参数
arg_obj_addrINT参数为全局对象时的对象地址
arg_obj_nameTEXT参数为全局对象时的对象名称
arg_num_valueINT数值
arg_str_valueTEXT字符串值

反编译器视图

针对常见模式预构建的视图(始终按 func_addr 筛选):

视图用途
ctree_v_calls包含被调用方信息的函数调用
ctree_v_indirect_calls用于调用点类型判定的间接/动态调用点
ctree_v_loopsfor/while/do 循环
ctree_v_ifsif 语句
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_ifsif 分支内的调用(递归)
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]),因此重命名操作可以安全地以 WHERE func_addr = ... AND idx = N 为条件,执行 UPDATE ctree_lvars ...。
  • 编辑后需要获取最新输出 -> 使用 SELECT decompile(addr, 1) 强制重新反编译。
  • 需要按结构访问行或执行注释的增删改查 -> 查询/更新 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 item id 设置/清除 numform
get_numform_item(func_addr, item_id, opnum)通过显式的 ctree item 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

其他资源


另请参阅

  • data — 反编译代码引用的原始字节和字符串内容(用于逐字节读取和有界窗口读取的 bytes 表,通过 WHERE start_addr = X AND n = N 查询;使用 hex(blob_concat(value)) 输出十六进制内容)。
  • disassembly — 同一函数的指令级事实依据(disasm_func、instructions、disasm_calls)。
  • xrefs — 反编译函数的调用方和被调用方;从伪代码切换到调用图。
  • types — 已应用的原型决定 ctree 结构;通过 applied_types / funcs.prototype 重新指定类型,以清理类型转换和间接调用。

评论

支持 Markdown