关于 annotations
通过 idasql 编辑 IDA 数据库的技能,适用于需要注释和整理反编译代码的分析人员。它强调先读取再修改,并涵盖注释、命名、类型、书签及审查分类工作流。
主要功能
- 01编辑反编译与反汇编注释
- 02重命名并重设局部变量类型
- 03更新函数摘要与原型
- 04用文件夹整理函数和书签
- 05编辑后核验修改结果
适用场景
- 01为人工审查注释函数
- 02重命名符号以理清反编译代码
- 03为调查目标添加书签并分类
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ allthingsida/ idasql-skills --skill annotations安装后在 Claude Code 中输入/annotations确认已加载。
附带文件agents/openai.yamlreferences/annotation-workflows.md
详细介绍
此技能是通过 idasql 编辑 IDA 数据库的指南。当你需要为反编译输出、反汇编或类型信息添加注释、重命名、重新指定类型或进行其他修改时,请使用此技能。
触发意图
用户要求执行以下操作时使用此技能:
- 添加/编辑注释(伪代码、反汇编、函数摘要)
- 重命名符号或局部变量
- 应用类型/枚举/结构体表示
- 创建/更新调查工作流的书签
- 让伪代码更像源代码
- 准备反编译代码,以便与源代码并排审查
- 端到端地注释函数,而非只添加一条注释
转交给:
decompiler,用于编辑前的分析types,用于构建声明或结构体模型re-source,用于递归叙述/源代码恢复流程
首先执行(预热流程)
-- 1) Confirm target row/function before editing
SELECT * FROM funcs WHERE addr = 0x401000;
-- 2) Inspect current comment state
SELECT addr, line, comment
FROM pseudocode
WHERE func_addr = 0x401000
LIMIT 30;
-- 3) Inspect existing disassembly comments
SELECT * FROM comments WHERE addr BETWEEN 0x401000 AND 0x401100;
解读指南:
- 切勿盲目编辑:修改前先验证目标行的准确标识。
- 优先使用确定性键(
func_addr + addr、idx、slot),而非模糊的名称匹配。
失败与恢复
- 更新看似“没有任何效果”:
- 重新读取目标行,刷新反编译视图,并核实位置字段。
- 修改了错误的目标:
- 收紧筛选条件,并在重试前重新执行先读后写步骤。
- 枚举/结构体的显示未改变:
- 确认类型/numform/联合体选择支持情况以及目标上下文。
转交模式
annotations->decompiler,当语义含义不明确时。annotations->types,当编辑意味着缺少声明时。annotations->re-source,当函数级注释需要扩展为递归的分析记录时。
注释函数契约
将 annotate this function 视为完整的函数工作流,而非单条注释操作。
默认行为:
- 检查当前反编译结果以及局部变量/标签状态
- 应用类型/原型,让函数更像源代码
- 在能显著提升可读性时重命名局部变量、全局变量和标签
- 在有助于理解的地方添加有针对性的行注释
- 当工作流会创建持久化分类时,将函数放入审查/分流文件夹
- 最后始终在
funcs.rpt_comment上添加且仅添加一条可重复使用的函数摘要 - 使用
decompile(addr, 1)刷新并验证结果
仅在用户明确提出狭义请求时使用更有限的意图:
add a comment-> 仅添加注释func-summary/function summary-> 仅添加摘要annotate this function-> 完整清理并添加摘要
摘要必须添加的原因:
- 它能立即帮助人工审查者了解情况
- 它能创建语义化且可搜索的程序知识,便于后续理解整个程序
基于文件夹的注释工作流
注释时使用对象表中的 folder_path 列来整理工作。函数级工作优先使用 funcs.folder_path,全局变量/标签使用 names.folder_path,审查线索使用 bookmarks.folder_path。dirtree_entries 是原始浏览器,dirtree_folders 用于管理所有标准 IDA 目录树中的空文件夹。
常用文件夹:
idasql/review/needs-typesidasql/review/annotatedidasql/review/verifiedidasql/triage/networkidasql/triage/crypto
-- Create a review bucket and move selected functions into it
INSERT INTO dirtree_folders(tree, path)
VALUES ('funcs', 'idasql/review/needs-types');
UPDATE funcs
SET folder_path = 'idasql/review/needs-types'
WHERE addr = 0x401000;
-- Mark a function as annotated while adding the required repeatable summary
UPDATE funcs
SET folder_path = 'idasql/review/annotated',
rpt_comment = 'Parses command records, validates the opcode, and dispatches to command handlers.'
WHERE addr = 0x401000;
UPDATE names
SET folder_path = 'idasql/names/globals'
WHERE name LIKE 'g_%';
UPDATE bookmarks
SET folder_path = 'idasql/bookmarks/review'
WHERE description LIKE '%review%';
-- Review progress
SELECT folder_path, COUNT(*) AS functions
FROM funcs
WHERE folder_path LIKE 'idasql/%'
GROUP BY folder_path
ORDER BY folder_path;
使用 UPDATE ... SET folder_path = NULL WHERE ... 将对象移回根目录。DELETE FROM dirtree_folders 仅删除空文件夹。文件夹写入使用相对 / 路径,并拒绝 ./..、重复分隔符、反斜杠,以及重命名为已存在的目标位置。
编辑函数注释
真正的 IDA 函数注释位于 funcs 中,而不在 pseudocode 或地址级别的 comments 表中。
使用:
funcs.comment表示常规函数注释funcs.rpt_comment表示可重复函数注释
函数摘要的默认行为:
- 将单数形式的
add function comment视为UPDATE funcs SET rpt_comment = ... - 仅当用户明确要求非可重复函数注释时,才使用
funcs.comment - 仅当用户明确要求反编译器备注/摘要,而非真正的函数注释时,才使用标题样式的
pseudocode块注释
规范 SQL 模式:
SELECT addr, name, comment, rpt_comment
FROM funcs
WHERE addr = 0x401000;
UPDATE funcs
SET rpt_comment = 'One-paragraph summary of what the function does, inputs/outputs, and key behavior.'
WHERE addr = 0x401000;
编辑反编译器注释(伪代码)
pseudocode 表是编辑反编译器注释的操作界面。使用 decompile(addr) 查看;使用该表进行编辑。完整表结构请参阅 decompiler 技能。
重要区分:
pseudocode.comment仅编辑 Hex-Rays 反编译器注释。- 写入
pseudocode不会调用set_func_cmt()。 - 真正的函数注释请使用
funcs.comment/funcs.rpt_comment。
可写列:comment、comment_placement。位置:semi(在 ; 后)、block1(上方独占一行)、block2、curly1、curly2、brace1、brace2、colon、case、else、do、asm、try。无法识别的位置字符串会被静默转换为 semi。
锚点指南:
- 优先选择具体的伪代码语句行,而不是猜测的函数入口行。
- 如果一个
addr对应多行伪代码({、语句、}),请先解析出唯一的非括号锚点。 - 仅使用
line_num检查候选行。注释写入会按addr + comment_placement持久化;多个行共享同一addr时需要格外谨慎,因此不要假设每个显示出来的共享addr行都可单独写入。
写入前检查锚点:
SELECT line_num, addr, line, comment
FROM pseudocode
WHERE func_addr = 0x401000
ORDER BY line_num;
-- The example UPDATEs below assume 0x401020 is an already resolved writable
-- non-brace anchor from the inspection query above; do not substitute func_addr.
-- Edit: Add inline comment to decompiled code
UPDATE pseudocode SET comment_placement = 'semi',
comment = 'buffer overflow here'
WHERE func_addr = 0x401000 AND addr = 0x401020;
-- Edit: Add block comment (own line above statement)
UPDATE pseudocode SET comment_placement = 'block1', comment = 'vulnerable call'
WHERE func_addr = 0x401000 AND addr = 0x401020;
-- Edit: Delete comments at a resolved unique anchor
-- Warning: comment = NULL currently clears all placements at that addr.
UPDATE pseudocode SET comment = NULL
WHERE func_addr = 0x401000 AND addr = 0x401020;
-- Read edited pseudocode with comments
SELECT addr, line, comment FROM pseudocode WHERE func_addr = 0x401000;
清理孤立的反编译器注释
如果数据库中包含已过时、无法再附加到当前伪代码的反编译器注释,请使用孤立注释操作界面,而不要尝试通过 pseudocode 清除它们。
先读取的模式:
SELECT func_addr, func_name, orphan_count
FROM pseudocode_v_orphan_comment_groups
ORDER BY orphan_count DESC
LIMIT 20;
SELECT addr, comment_placement, orphan_comment
FROM pseudocode_orphan_comments
WHERE func_addr = 0x401000
ORDER BY addr, comment_placement;
仅删除的变更模式:
UPDATE pseudocode_orphan_comments
SET orphan_comment = NULL
WHERE func_addr = 0x401000
AND addr = 0x401020
AND comment_placement = 'semi';
注意:
pseudocode_orphan_comments仅支持删除。- 非空写入会被拒绝。
- 使用分组操作界面进行分诊,再使用精确表进行清理。
- 分诊后,在两个操作界面中都切换为
WHERE func_addr = ...,以使用快捷方式。
函数摘要(func-summary)
将 function summary 和 func-summary 视为等效意图。
触发约定:
- 如果用户说
function summary或func-summary,就在funcs.rpt_comment中添加或更新恰好一条可重复函数注释。 - 如果用户单数形式说
add function comment,且未指定具体行目标,则将其视为更新可重复函数注释。 - 如果用户明确要求反编译器标题备注或伪代码块注释,则改用
pseudocode.comment,并选择已解析且可写的锚点。 - 仅当用户明确要求逐行/深入注释时,才添加多条行注释。
默认行为:
- 将摘要写入
funcs.rpt_comment。 - 仅当用户明确要求非可重复函数注释时,才使用
funcs.comment。 - 除非用户明确要求深入注释,否则不要扩展为逐行注释。
- 对函数进行完整注释时,始终将此摘要作为最后一个语义步骤添加/更新。
长度指南:
- 适用时至少写一段。
- 对于简单的包装函数/跳板函数,可以使用更简短的摘要。
- 相关时,说明函数作用、关键输入/输出、重要状态变化和显著副作用。
规范 SQL 模式:
SELECT addr, name, comment, rpt_comment
FROM funcs
WHERE addr = 0x401000;
UPDATE funcs
SET rpt_comment = 'One-paragraph summary of what the function does, inputs/outputs, and key behavior.'
WHERE addr = 0x401000;
提示示例:
function summary 0x401000func-summary DriverEntryfunc-summary this function
编辑反汇编注释
从 comments 表读取反汇编级注释:
SELECT COALESCE(NULLIF(comment, ''), NULLIF(rpt_comment, '')) AS comment
FROM comments
WHERE addr = 0x401000
LIMIT 1;
Upsert 语义:对于 names 和 comments 表,在已有值的地址执行 INSERT 会替换现有条目(IDA 对每个 EA 只允许一个名称和一个注释槽位)。就地修改时,UPDATE 的效果相同。对于 names,IDA 的 SN_CHECK 标志还会自动消解全局名称冲突(例如,如果 foo 已在其他 EA 使用,它可能会变为 foo_0)——写入后请重新读取该行,以确认实际存储的内容。
comments 表支持 INSERT、UPDATE 和 DELETE:
| 表 | INSERT | UPDATE 列 | DELETE |
|---|---|---|---|
comments | 是 | comment、rpt_comment | 是 |
INSERT INTO comments(addr, comment) VALUES (0x401000, 'regular comment');
INSERT INTO comments(addr, rpt_comment) VALUES (0x401000, 'repeatable comment');
UPDATE comments SET comment = 'updated comment' WHERE addr = 0x401000;
DELETE FROM comments WHERE addr = 0x401000;
说明:
comments通过set_cmt()编辑地址注释。funcs.comment/funcs.rpt_comment通过set_func_cmt()编辑真正的函数注释。
书签
bookmarks 表支持完整的 CRUD 操作,可用于编辑标记位置和文件夹组织:
| 列 | 类型 | 说明 |
|---|---|---|
slot | INT | 书签槽位索引 |
addr | INT | 书签地址 |
description | TEXT | 书签说明 |
inode | INT | 只读 dirtree inode |
folder_path | TEXT | 可写的书签文件夹;NULL 表示根目录 |
full_path | TEXT | 只读的完整 dirtree 路径 |
-- List all bookmarks
SELECT printf('0x%X', addr) as addr, description, folder_path FROM bookmarks;
-- Edit: Add bookmark
INSERT INTO bookmarks (addr, description) VALUES (0x401000, 'interesting branch');
-- Edit: Update bookmark description
UPDATE bookmarks SET description = 'confirmed branch' WHERE slot = 0;
-- Edit: Move bookmark into a review folder
UPDATE bookmarks SET folder_path = 'idasql/bookmarks/confirmed' WHERE slot = 0;
-- Edit: Delete bookmark
DELETE FROM bookmarks WHERE slot = 0;
有关规范架构和所有者映射,请参阅 ../connect/references/schema-catalog.md(bookmarks)。
编辑局部变量(重命名、重新设置类型、添加注释)
ctree_lvars 表是编辑反编译器局部变量的操作接口。可写列:name、type、comment。完整表架构请参阅 decompiler 技能。
局部变量编辑指南:
- 检查并选定一个确定的
idx,然后按func_addr + idx更新。 - 使用
UPDATE ctree_lvars SET name = ...、type = ...或comment = ...进行局部编辑。 - 对于旧的按名称工作流,请先按
func_addr + name查询候选行,选定一个idx,然后按idx更新。
-- Inspect current locals before renaming
SELECT idx, name, type, comment
FROM ctree_lvars
WHERE func_addr = 0x401000
ORDER BY idx;
-- Edit: Rename a local variable by index (canonical, deterministic)
UPDATE ctree_lvars SET name = 'buffer_size' WHERE func_addr = 0x401000 AND idx = 2;
-- Edit: Rename by current name after selecting one deterministic idx
UPDATE ctree_lvars SET name = 'buffer_size'
WHERE func_addr = 0x401000
AND idx = (
SELECT idx FROM ctree_lvars
WHERE func_addr = 0x401000 AND name = 'v2'
ORDER BY idx LIMIT 1
);
-- Edit: Set local-variable comment by index
UPDATE ctree_lvars SET comment = 'points to decrypted buffer' WHERE func_addr = 0x401000 AND idx = 2;
-- Edit: Change variable type
UPDATE ctree_lvars SET type = 'char *'
WHERE func_addr = 0x401000 AND idx = 2;
编辑反编译器标签
先读取当前标签,再重命名你所观察到的确切标签。优先使用 label_num 标识,而不是根据行文本猜测。
-- Inspect labels before renaming
SELECT label_num, name, printf('0x%X', item_addr) AS item_addr
FROM ctree_labels
WHERE func_addr = 0x401000
ORDER BY label_num;
-- Rename deterministically by label number
UPDATE ctree_labels SET name = 'fail' WHERE func_addr = 0x401000 AND label_num = 12;
-- Equivalent UPDATE path
UPDATE ctree_labels
SET name = 'fail'
WHERE func_addr = 0x401000 AND label_num = 12;
编辑类型(创建、修改、应用)
有关类型创建、成员 CRUD、枚举值、parse_decls()、applied_types 以及通过 names/funcs 写入名称,请参阅 types 技能。
注释工作流中使用的快速应用模式:
-- Apply type to a function
UPDATE funcs SET prototype = 'void __fastcall exec_command(command_t *cmd);'
WHERE addr = 0x140001BD0;
-- Apply/replace the type at any mapped address
INSERT INTO applied_types(addr, decl)
VALUES (0x140001BD0, 'void __fastcall exec_command(command_t *cmd);');
编辑操作数表示形式(反汇编中的枚举/结构体)
instructions 表的 operand*_format_spec 列允许编辑操作数显示形式:
-- Edit: Apply enum representation to operand 1
UPDATE instructions
SET operand1_format_spec = 'enum:MY_ENUM'
WHERE addr = 0x401020;
-- Edit: Apply struct-offset representation
UPDATE instructions
SET operand0_format_spec = 'stroff:MY_STRUCT,delta=0'
WHERE addr = 0x401030;
-- Edit: Nested member path uses '/' to separate type names
UPDATE instructions
SET operand0_format_spec = 'stroff:OUTER_T/INNER_T'
WHERE addr = 0x401030;
-- Edit: Clear representation back to plain
UPDATE instructions
SET operand1_format_spec = 'clear'
WHERE addr = 0x401020;
这些操作都可在反汇编级别完成——无需 IDAPython。应用后会验证 UPDATE;如果未能应用该表示形式,则会显示 SQL 错误。
完整的 operand*_format_spec 词汇还涵盖数字进制和其他显示形式:
-- Number base / character
UPDATE instructions SET operand1_format_spec = 'hex' WHERE addr = 0x401020; -- also dec/oct/bin
UPDATE instructions SET operand1_format_spec = 'char' WHERE addr = 0x401020;
-- Offsets, sizeof, forced operand text
UPDATE instructions SET operand1_format_spec = 'offset:tbl_start' WHERE addr = 0x401020;
UPDATE instructions SET operand1_format_spec = 'sizeof:MY_STRUCT' WHERE addr = 0x401020;
UPDATE instructions SET operand1_format_spec = 'forced:5 shl 3' WHERE addr = 0x401020;
-- Sign / bitwise-not modifiers (combine with a base, or use alone)
UPDATE instructions SET operand1_format_spec = 'dec,signed' WHERE addr = 0x401020;
其他类型:float、segment、stkvar,以及 ,unsigned / ,bnot / ,nobnot 修饰符。完整列表请参阅 disassembly 技能。
在反编译代码中编辑联合体选择
有关联合体选择辅助函数(set_union_selection*、get_union_selection*),请参阅 decompiler 技能。
编辑数字格式(反编译代码中的枚举显示)
**建议:**将变量重新设置为枚举类型——IDA 的反编译器随后会自动使用枚举名称显示所有常量:
-- 1. Define the enum type (skip if it already exists)
SELECT parse_decls('typedef enum { DLL_PROCESS_DETACH=0, DLL_PROCESS_ATTACH=1 } fdw_reason_t;');
-- 2. Retype the parameter/variable
UPDATE ctree_lvars SET type = 'fdw_reason_t'
WHERE func_addr = 0x180001050 AND idx = 1;
-- 3. Verify
SELECT decompile(0x180001050, 1);
有关逐操作数的 numform 控制(set_numform*、get_numform*),请参阅 decompiler 技能。
强制变更循环(适用于所有编辑)
遵循
connect全局 Agent 合约中定义的读取 -> 编辑 -> 刷新 -> 验证循环。
批量编辑的性能提示
编辑多个函数或注释时,请注意以下开销:
decompile(addr, 1)会触发完整的重新反编译(每个函数约需 50–200ms)。在同一个函数中编辑多项内容时,请先批量完成所有编辑,再刷新:-- Good: structural typing first, then refresh, then naming cleanup UPDATE ctree_lvars SET type = 'MY_CTX *' WHERE func_addr = 0x401000 AND idx = 0; SELECT decompile(0x401000, 1); UPDATE ctree_lvars SET name = 'ctx' WHERE func_addr = 0x401000 AND idx = 0; UPDATE ctree_lvars SET name = 'size' WHERE func_addr = 0x401000 AND idx = 1; SELECT decompile(0x401000, 1); -- final refresh after cleanuppseudocode注释写入会(重新)反编译目标函数——每次写入都会反编译包含该注释的函数,以解析注释锚点;将注释保存到 IDA 的用户注释存储中;随后使该函数的反编译器缓存失效,以便下次调用decompile(addr)时重新渲染。你无需在每次写入注释之间自行调用decompile(addr, 1),但写入并非零成本——每次都会对该函数进行一次反编译。ctree_lvars类型更改会使反编译器缓存失效——更改变量类型后,请先刷新,再依赖基于idx/名称的清理结果。反编译器可能会拆分局部变量或重新渲染表达式。- 大型数据库上的
save_database()可能耗时较长。批量完成所有写入,并在一轮注释工作结束时保存一次,而不是每次编辑后都保存。
其他资源
- 有关完整的清理工作流、批量注释模式和完整的示例:references/annotation-workflows.md
另请参阅
types— 定义和修改类型字典条目;通过applied_types或funcs.prototype应用这些条目。decompiler— 伪代码注释(UPDATE pseudocode SET comment = ...);ctree 局部变量的重命名/重新设定类型。disassembly— 重命名代码标签(names),应用指令级操作数格式。