mcpField
A
annotations

annotations

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

关于 annotations

通过 idasql 编辑 IDA 数据库的技能,适用于需要注释和整理反编译代码的分析人员。它强调先读取再修改,并涵盖注释、命名、类型、书签及审查分类工作流。

主要功能

  1. 01编辑反编译与反汇编注释
  2. 02重命名并重设局部变量类型
  3. 03更新函数摘要与原型
  4. 04用文件夹整理函数和书签
  5. 05编辑后核验修改结果

适用场景

  1. 01为人工审查注释函数
  2. 02重命名符号以理清反编译代码
  3. 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/联合体选择支持情况以及目标上下文。

转交模式

  1. annotations -> decompiler,当语义含义不明确时。
  2. annotations -> types,当编辑意味着缺少声明时。
  3. 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-types
  • idasql/review/annotated
  • idasql/review/verified
  • idasql/triage/network
  • idasql/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 0x401000
  • func-summary DriverEntry
  • func-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:

表INSERTUPDATE 列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 操作,可用于编辑标记位置和文件夹组织:

列类型说明
slotINT书签槽位索引
addrINT书签地址
descriptionTEXT书签说明
inodeINT只读 dirtree inode
folder_pathTEXT可写的书签文件夹;NULL 表示根目录
full_pathTEXT只读的完整 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 cleanup
    
  • pseudocode 注释写入会(重新)反编译目标函数——每次写入都会反编译包含该注释的函数,以解析注释锚点;将注释保存到 IDA 的用户注释存储中;随后使该函数的反编译器缓存失效,以便下次调用 decompile(addr) 时重新渲染。你无需在每次写入注释之间自行调用 decompile(addr, 1),但写入并非零成本——每次都会对该函数进行一次反编译。
  • ctree_lvars 类型更改会使反编译器缓存失效——更改变量类型后,请先刷新,再依赖基于 idx/名称的清理结果。反编译器可能会拆分局部变量或重新渲染表达式。
  • 大型数据库上的 save_database() 可能耗时较长。批量完成所有写入,并在一轮注释工作结束时保存一次,而不是每次编辑后都保存。

其他资源


另请参阅

  • types — 定义和修改类型字典条目;通过 applied_types 或 funcs.prototype 应用这些条目。
  • decompiler — 伪代码注释(UPDATE pseudocode SET comment = ...);ctree 局部变量的重命名/重新设定类型。
  • disassembly — 重命名代码标签(names),应用指令级操作数格式。

评论

支持 Markdown