关于 disassembly
disassembly 是一项通过 IDASQL 检查二进制代码的技能,涵盖指令、函数和控制流。它支持基于 SQL 的分析与编辑,并将语义解读、关系分析和调试交由其他技能处理。
主要功能
- 01检查函数、段、指令和操作数
- 02分析基本块和控制流边
- 03查询已解析的调用目标和调用点类型
- 04编辑名称、函数元数据和操作数格式
适用场景
- 01检查函数中的指令序列
- 02追踪调用点并查看目标
- 03调查二进制行为时审查控制流
- 04设置操作数格式或更新函数与符号名称
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ allthingsida/ idasql-skills --skill disassembly安装后在 Claude Code 中输入/disassembly确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/disassembly-examples.mddisassembly-tables.md详细介绍
触发意图
用户提出以下请求时使用此技能:
- 检查函数/代码段/指令
- 基于反汇编分析调用点或控制流
- 操作数格式化和底层代码结构
- 原始字节/指令级证据
转交给:
decompiler,用于 AST/伪代码语义分析xrefs,用于涉及大量关系的调用者/被调用者工作流debugger,用于修补/断点操作
首先执行(热启动序列)
-- 1) Orientation
SELECT * FROM binary;
-- 2) Segment map
SELECT name, printf('0x%X', start_addr) AS start_addr, printf('0x%X', end_addr) AS end_addr, perm
FROM segments
ORDER BY start_addr;
-- 3) Largest functions (triage anchors)
SELECT name, printf('0x%X', addr) AS addr, size
FROM funcs
ORDER BY size DESC
LIMIT 20;
解读指南:
- 从可执行段以及规模最大/连接最密集的函数入手。
- 查询指令密集型数据时,尽早使用
func_addr约束。
故障与恢复
- 查询
instructions/heads较慢:- 添加
WHERE func_addr = X或使用紧密的 EA 范围。
- 添加
- 缺少预期的符号名称:
- 转而采用基于地址的工作流,之后再通过
names更新补充信息。
- 转而采用基于地址的工作流,之后再通过
- 控制流行为不明确:
- 使用
disasm_calls交叉核对,然后升级到decompiler。
- 使用
交接模式
disassembly->xrefs,用于扩展关系。disassembly->decompiler,用于语义解释。disassembly->debugger,用于执行修补/断点操作。
实体表
funcs
二进制文件中检测到的所有函数及其原型信息。
| 列 | 类型 | 描述 |
|---|---|---|
addr | INT | 函数起始地址 |
name | TEXT | 函数名称 |
size | INT | 函数大小(字节) |
end_addr | INT | 函数结束地址 |
flags | INT | 函数标志 |
folder_path | TEXT | 相对于 Function 窗口根目录的可读写函数文件夹路径;NULL/'' 表示根目录 |
full_path | TEXT | 只读的完整 dirtree 路径,包含函数名称 |
原型列(有类型信息时填充):
| 列 | 类型 | 描述 |
|---|---|---|
return_type | TEXT | 返回类型字符串(例如,“int”、“void *”) |
return_is_ptr | INT | 返回类型为指针时为 1 |
return_is_int | INT | 返回类型恰为 int 时为 1 |
return_is_integral | INT | 返回类型为类 int 类型(int、long、DWORD、BOOL)时为 1 |
return_is_void | INT | 返回类型为 void 时为 1 |
arg_count | INT | 函数参数数量 |
calling_conv | TEXT | 调用约定(cdecl、stdcall、fastcall 等) |
-- 10 largest functions
SELECT name, size FROM funcs ORDER BY size DESC LIMIT 10;
-- Functions starting with "sub_" (auto-named, not analyzed)
SELECT name, printf('0x%X', addr) as addr FROM funcs WHERE name LIKE 'sub_%';
-- Functions returning integers with 3+ arguments
SELECT name, return_type, arg_count FROM funcs
WHERE return_is_integral = 1 AND arg_count >= 3;
-- Functions organized by IDASQL annotation folders
SELECT addr, name, folder_path
FROM funcs
WHERE folder_path LIKE 'idasql/%'
ORDER BY folder_path, name;
写入操作:
-- Create a function
INSERT INTO funcs (addr) VALUES (0x401000);
-- Rename a function
UPDATE funcs SET name = 'my_func' WHERE addr = 0x401000;
-- Move a function into an IDA Function window folder
INSERT INTO dirtree_folders(tree, path) VALUES ('funcs', 'idasql/triage/network');
UPDATE funcs SET folder_path = 'idasql/triage/network' WHERE addr = 0x401000;
-- Move it back to root
UPDATE funcs SET folder_path = NULL WHERE addr = 0x401000;
-- Delete a function
DELETE FROM funcs WHERE addr = 0x401000;
文件夹路径使用相对 / 路径。IDASQL 会拒绝 ./..、重复分隔符、反斜杠、非空文件夹删除,以及目标已存在的文件夹重命名。
segments
内存段。支持完整的 CRUD:INSERT 一个区域、DELETE 一个区域,以及 UPDATE start_addr(重定位/移动)、end_addr(调整大小)、name、class、perm。
| 列 | 类型 | RW | 描述 |
|---|---|---|---|
start_addr | INT | RW | 段起始地址;UPDATE 会重定位(移动)该段 |
end_addr | INT | RW | 段结束地址;UPDATE 会调整该段大小 |
name | TEXT | RW | 段名称(.text、.data 等) |
class | TEXT | RW | 段类别(CODE、DATA) |
perm | INT | RW | 权限(R=4、W=2、X=1) |
-- Find executable segments
SELECT name, printf('0x%X', start_addr) as start FROM segments WHERE perm & 1 = 1;
-- Rename a segment
UPDATE segments SET name = '.mytext' WHERE start_addr = 0x401000;
-- Add a region (e.g. SRAM for a raw firmware image), then rebase it
INSERT INTO segments(start_addr, end_addr, name, class, perm)
VALUES (0x20000000, 0x20005000, 'SRAM', 'DATA', 6);
UPDATE segments SET start_addr = 0x08000000 WHERE name = '.text'; -- rebase
names
所有已命名位置(函数、标签、数据)。支持 INSERT、UPDATE 和 DELETE。
| 列 | 类型 | RW | 描述 |
|---|---|---|---|
addr | INT | R | 地址 |
name | TEXT | RW | 名称 |
folder_path | TEXT | RW | 名称文件夹路径;NULL 表示根目录 |
full_path | TEXT | R | 完整的名称 dirtree 路径 |
-- Create/set a name
INSERT INTO names (addr, name) VALUES (0x401000, 'my_symbol');
-- Rename
UPDATE names SET name = 'my_symbol_renamed' WHERE addr = 0x401000;
-- Organize globals/labels into IDA name folders
UPDATE names SET folder_path = 'idasql/names/globals' WHERE name LIKE 'g_%';
UPDATE names SET folder_path = NULL WHERE addr = 0x401000;
entries
入口点(导出项、程序入口、tls 回调等)。
| 列 | 类型 | 描述 |
|---|---|---|
ordinal | INT | 导出序号 |
addr | INT | 入口地址 |
name | TEXT | 入口名称 |
指令表
instructions
instructions 是反汇编表。要获取特定 EA 处的标量反汇编文本,请使用 disasm_at(addr[, context])。
只有明确需要函数或范围列表时,才使用 disasm_func() 或 disasm_range()。
已解码的指令支持 DELETE(将指令转换为未探索的字节)以及通过 operand*_format_spec 更新操作数表示形式。
WHERE func_addr = X 是快速路径(函数项迭代器)。如果没有此条件,该表会扫描所有代码头。
| Column | Type | Description |
|---|---|---|
addr | INT | 指令地址 |
func_addr | INT | 所属函数 |
itype | INT | 指令类型(特定于架构) |
mnemonic | TEXT | 指令助记符 |
size | INT | 指令大小 |
operand0..operand7 | TEXT | 操作数文本(0..7) |
disasm | TEXT | 完整反汇编行 |
operand0_class..operand7_class | TEXT | 操作数类别:reg、imm、displ、mem 等 |
operand0_repr_kind..operand7_repr_kind | TEXT | 当前表示形式:plain、hex、dec、oct、bin、char、float、enum、offset、stroff、sizeof、segment、stkvar、forced |
operand0_repr_type_name..operand7_repr_type_name | TEXT | 枚举、stroff 或 sizeof 类型、偏移基址(十六进制)或强制文本 |
operand0_format_spec..operand7_format_spec | TEXT (RW) | 为特定操作数应用或清除表示形式(参见下方词汇表) |
-- Instruction profile of a function (FAST)
SELECT mnemonic, COUNT(*) as count
FROM instructions WHERE func_addr = 0x401330
GROUP BY mnemonic ORDER BY count DESC;
-- Find all call instructions in a function
SELECT addr, disasm FROM instructions
WHERE func_addr = 0x401000 AND mnemonic = 'call';
-- Apply enum representation to operand 1
UPDATE instructions
SET operand1_format_spec = 'enum:MY_ENUM'
WHERE addr = 0x401020;
-- Apply struct-offset representation to operand 0
-- e.g. makes `[rax+10h]` display as `[rax+command_t.field_name]`
UPDATE instructions
SET operand0_format_spec = 'stroff:command_t'
WHERE addr = 0x140001BE8;
-- Struct-offset with a base delta (subtracted before member resolution)
UPDATE instructions
SET operand0_format_spec = 'stroff:command_t,delta=16'
WHERE addr = 0x140001BE8;
-- Nested member path: separate type names with '/'
UPDATE instructions
SET operand0_format_spec = 'stroff:outer_t/inner_t'
WHERE addr = 0x140001BE8;
-- Clear representation back to plain
UPDATE instructions
SET operand1_format_spec = 'clear'
WHERE addr = 0x401020;
应用后会验证格式规范:UPDATE 会重新读取操作数;如果结果的 repr_kind、类型路径或 delta 与请求不匹配,则会失败(并产生 SQL 错误)。读取 operandN_repr_kind /
operandN_repr_type_name 以确认。
完整的 operandN_format_spec 词汇表(均为反汇编级操作,无需 IDAPython):
| Spec | Effect |
|---|---|
hex dec oct bin | 数字基数 |
char | 字符常量 |
float | 浮点数 |
offset | 普通偏移,基址为 0 |
offset:<base> | 使用用户定义基址的偏移(<base> = 符号名称或地址) |
enum:<NAME>[,serial=N] / enum:<NAME>::<MEMBER> | 枚举常量 |
stroff:<Type[/Nested...]>[,delta=N] | 结构体成员偏移 |
sizeof:<STRUCT> | 结构体大小常量——呈现为 size STRUCT |
segment | 段选择器 |
stkvar | 栈变量(操作数必须是栈引用) |
forced:<text> | 强制(手动)操作数文本,例如 forced:5 shl 3 |
clear / plain / none | 恢复默认表示形式 |
可组合修饰符(作为后缀添加到任意基项,或单独使用以修改当前表示形式):,signed / ,unsigned(切换负数显示)以及 ,bnot / ,nobnot(切换按位取反显示)。例如:dec,signed、
hex,bnot,或仅使用 signed。
-- Number base, character, and sign/bitwise-not modifiers
UPDATE instructions SET operand1_format_spec = 'hex' WHERE addr = 0x401020;
UPDATE instructions SET operand1_format_spec = 'dec,signed' WHERE addr = 0x401020;
UPDATE instructions SET operand1_format_spec = 'char' WHERE addr = 0x401020;
-- Offsets (plain and user-defined base)
UPDATE instructions SET operand1_format_spec = 'offset' WHERE addr = 0x401020;
UPDATE instructions SET operand1_format_spec = 'offset:tbl_start' WHERE addr = 0x401020;
-- sizeof: an immediate equal to sizeof(STRUCT) renders as `size STRUCT`
UPDATE instructions SET operand1_format_spec = 'sizeof:FILEDEF' WHERE addr = 0x4015EB;
-- Forced operand text
UPDATE instructions SET operand1_format_spec = 'forced:5 shl 3' WHERE addr = 0x401020;
instruction_operands
每行对应一个已解码的非空操作数。使用此表查询操作数类型和值详情,并联结替代旧操作数/解码辅助函数。
| 列 | 类型 | 描述 |
|---|---|---|
addr | INT | 指令地址 |
func_addr | INT | 所属函数 |
opnum | INT | 操作数索引 |
text | TEXT | 操作数文本 |
type_code | INT | IDA 操作数类型代码 |
type_name | TEXT | 操作数类型名称(reg、imm、near……) |
dtype | INT | 操作数 dtype |
reg | INT | 适用时的寄存器编号 |
op_addr | INT | 适用时的引用地址/位移 |
raw_value | INT | 原始操作数值 |
value | INT | 尽可能解析出的标量操作数值 |
注意(addr 与 op_addr):
addr是指令地址;操作数的引用地址是op_addr。若要获取操作数指向的目标(例如跳转/调用/数据引用),请选择op_addr——addr标识操作数所属的指令,而不是它引用的内容。
SELECT opnum, text, type_name, value
FROM instruction_operands
WHERE addr = 0x401000
ORDER BY opnum;
SELECT i.addr, i.itype, i.mnemonic, o.opnum, o.text, o.type_name, o.value
FROM instructions i
LEFT JOIN instruction_operands o
ON o.addr = i.addr AND o.func_addr = 0x401000
WHERE i.func_addr = 0x401000
ORDER BY i.addr, o.opnum;
性能:WHERE addr = X 会解码一条指令;WHERE func_addr = X 会进行 O(function_size) 次迭代。若不指定其中一个约束,则会扫描整个数据库。
disasm_calls
所有已解析目标且可选带有调用点原型覆盖的调用指令。
| 列 | 类型 | 描述 |
|---|---|---|
func_addr | INT | 包含该调用的函数 |
addr | INT | 调用指令地址 |
callee_addr | INT | 目标地址(未知时为 0) |
callee_name | TEXT | 目标名称 |
callee_type | TEXT | 可读写、可空的调用点原型;UPDATE 会应用/替换,NULL 或空值会清除 |
-- Functions that call malloc
SELECT DISTINCT (SELECT name FROM funcs WHERE func_addr >= addr AND func_addr < end_addr LIMIT 1) as caller
FROM disasm_calls WHERE callee_name LIKE '%malloc%';
-- Apply/replace a call-site prototype, then clear it
UPDATE disasm_calls
SET callee_type = 'int (__fastcall *)(const char *path)'
WHERE addr = 0x401234;
UPDATE disasm_calls SET callee_type = NULL WHERE addr = 0x401234;
在直接调用上应用 callee_type 会保留真实的被调用方符号,因此之后重新反编译调用方是安全的(不会出现 microcode INTERR);在间接调用上,它会为该调用点指定类型。空值/NULL 会清除覆盖。
blocks
函数内的基本块。为提升性能,请使用 func_addr 约束。
| 列 | 类型 | 描述 |
|---|---|---|
func_addr | INT | 所属函数 |
start_addr | INT | 块起始地址 |
end_addr | INT | 块结束地址 |
size | INT | 块大小 |
-- Blocks in a specific function (FAST - uses constraint pushdown)
SELECT * FROM blocks WHERE func_addr = 0x401000;
-- Functions with most basic blocks
SELECT (SELECT name FROM funcs WHERE func_addr >= addr AND func_addr < end_addr LIMIT 1) as name, COUNT(*) as blocks
FROM blocks GROUP BY func_addr ORDER BY blocks DESC LIMIT 10;
cfg_edges
基本块之间的控制流图边。始终使用 WHERE func_addr = X(filter_eq 下推,复杂度为 O(函数内块数))。
| 列 | 类型 | 描述 |
|---|---|---|
func_addr | INT | 所属函数 |
from_block | INT | 源块地址 |
to_block | INT | 目标块地址 |
edge_type | TEXT | normal(单后继或回退标签)、true/false(双向分支的通用第一/第二分支;标签遵循后继顺序,而非跳转成立/顺序执行语义) |
-- Get CFG structure
SELECT * FROM cfg_edges WHERE func_addr = 0x401000;
-- Find branch points (conditional blocks)
SELECT from_block, COUNT(*) as succ_count
FROM cfg_edges WHERE func_addr = 0x401000
GROUP BY from_block HAVING succ_count > 1;
-- Find merge points (blocks with multiple predecessors)
SELECT to_block, COUNT(*) as pred_count
FROM cfg_edges WHERE func_addr = 0x401000
GROUP BY to_block HAVING pred_count > 1;
-- Function complexity ranking: combine CFG, loops, and call metrics
SELECT f.name, f.size,
(SELECT COUNT(*)
FROM (
SELECT ce.from_block
FROM cfg_edges ce
WHERE ce.func_addr = f.addr
GROUP BY ce.from_block
HAVING COUNT(*) > 1
) branch_blocks) as branch_sites,
(SELECT COUNT(*) FROM disasm_loops dl WHERE dl.func_addr = f.addr) as loops,
(SELECT COUNT(*) FROM disasm_calls dc WHERE dc.func_addr = f.addr) as calls_made
FROM funcs f
WHERE f.size > 32
ORDER BY branch_sites DESC
LIMIT 20;
function_chunks
缓存表,每个函数块对应一行。若需计算函数级跨度或密度指标,请按 func_addr 聚合。
| 列 | 类型 | 描述 |
|---|---|---|
func_addr | INT | 函数地址 |
chunk_start | INT | 块起始地址 |
chunk_end | INT | 块结束地址 |
block_count | INT | 块中的块数 |
total_size | INT | 块的总大小 |
SELECT * FROM function_chunks WHERE func_addr = 0x401000;
SQL 函数——反汇编
| 函数 | 描述 |
|---|---|
disasm_at(addr) | 所属 head 的规范列表行(适用于代码/数据) |
disasm_at(addr, n) | 所属 head 及前后 n 个相邻 head 的规范列表行 |
disasm(addr) | 地址处的单条反汇编行 |
disasm(addr, n) | 从地址开始的后续 N 条指令(按数量计) |
disasm_range(start, end) | 地址范围 [start, end) 内的所有反汇编行 |
disasm_func(addr) | 包含该地址的函数的完整反汇编 |
make_code(addr) | 在地址处创建指令(返回 1/0) |
make_code_range(start, end) | 在范围内创建指令,返回创建数量 |
反汇编示例
-- Canonical single-EA disassembly (safe for code or data)
SELECT disasm_at(0x401000);
-- Canonical context window (+/- 2 heads)
SELECT disasm_at(0x401000, 2);
-- Full function disassembly (resolves boundaries via get_func)
SELECT disasm_func(addr) FROM funcs WHERE name = '_main';
-- Disassemble a specific address range
SELECT disasm_range(0x401000, 0x401100);
-- Sliding window: next 5 instructions from an address
SELECT disasm(0x401000, 5);
SQL 函数——名称与函数
使用表查询地址及其所属函数的元数据。使用以下模式前,先将符号名称解析为整数 EA。
| 模式 | 描述 |
|---|---|
SELECT name FROM names WHERE addr = :addr LIMIT 1 | 地址处的名称 |
SELECT name FROM funcs WHERE :addr >= addr AND :addr < end_addr LIMIT 1 | 包含该地址的函数 |
SELECT addr FROM funcs WHERE :addr >= addr AND :addr < end_addr LIMIT 1 | 所属函数的起始地址 |
SELECT end_addr FROM funcs WHERE :addr >= addr AND :addr < end_addr LIMIT 1 | 所属函数的结束地址 |
函数计数和索引查询由表驱动:
SELECT COUNT(*) AS function_count FROM funcs;
SELECT addr FROM funcs WHERE rowid = 0;
SQL 函数——导航
使用 heads 排序浏览已定义项,并使用 SQLite 格式化函数生成显示字符串。地址相等/范围筛选经过优化;对于查找下一个/上一个项的操作,会使用 ORDER BY addr 或 ORDER BY addr DESC。
SELECT addr
FROM heads
WHERE addr > 0x401000
ORDER BY addr
LIMIT 1;
SELECT addr
FROM heads
WHERE addr < 0x401000
ORDER BY addr DESC
LIMIT 1;
SELECT printf('0x%llx', addr) AS address_hex
FROM heads
LIMIT 10;
段查询由表驱动:
SELECT name
FROM segments
WHERE 0x401000 >= start_addr
AND 0x401000 < end_addr
LIMIT 1;
SQL 函数——项分析
使用 heads 获取项分类、大小和原始标志:
SELECT addr, size, type, flags, disasm
FROM heads
WHERE addr = 0x401000;
SQL 函数——指令详情
使用 instructions 和 instruction_operands 获取已解码的指令信息:
SELECT addr, itype, mnemonic
FROM instructions
WHERE func_addr = 0x401000
LIMIT 10;
SELECT opnum, text, type_code, type_name, value
FROM instruction_operands
WHERE addr = 0x401000
ORDER BY opnum;
SELECT i.addr, i.itype, i.mnemonic, i.size, o.opnum, o.text, o.type_name, o.value
FROM instructions i
LEFT JOIN instruction_operands o
ON o.addr = i.addr AND o.addr = 0x401000
WHERE i.addr = 0x401000
ORDER BY o.opnum;
SQL 函数——文件生成
| 函数 | 描述 |
|---|---|
gen_listing(path) | 生成完整数据库的列表输出(LST) |
SQL 函数——图生成
| 函数 | 描述 |
|---|---|
gen_cfg_dot(addr) | 将 CFG 生成为 DOT 图字符串 |
gen_cfg_dot_file(addr, path) | 将 CFG DOT 写入文件 |
gen_schema_dot() | 将数据库架构生成为 DOT |
-- Get CFG for a function as DOT format
SELECT gen_cfg_dot(0x401000);
性能规则
| 表 | 架构 | 关键约束 | 备注 |
|---|---|---|---|
funcs | 基于索引 | 无需约束 | 通过 getn_func(i) 每行 O(1)——始终快速 |
instructions | 迭代器 | func_addr | 函数项迭代器(快速),而非扫描所有代码头(慢速) |
blocks | 迭代器 | func_addr | 约束下推:迭代单个函数的代码块 |
cfg_edges | 迭代器 | func_addr | filter_eq 下推:复杂度为 O(函数中的代码块数) |
disasm_calls | 生成器 | 写入时使用 func_addr、addr | 延迟流式处理,遵循 LIMIT;callee_type 可写 |
heads | 生成器 | addr =、地址范围 | 导航上一个/下一个项时使用 ORDER BY addr;范围较大的扫描仍可能耗时 |
instruction_operands | 迭代器 | addr、func_addr | 地址查询会解码一条指令;函数查询会迭代一个函数 |
segments | 基于索引 | 无需约束 | 表较小,始终快速 |
names | 迭代器 | 无需约束 | 迭代 IDA 的名称列表 |
关键规则:
funcs始终快速——无需约束。instructions不带func_addr时会扫描每个代码头——按函数查询时使用func_addr。blocks不带func_addr时会迭代所有函数的流程图——务必添加约束。heads通常较大。获取项信息时使用addr = X;导航时使用地址范围,并结合ORDER BY addr [DESC] LIMIT 1。
成本模型:
funcs (full scan) -> O(number of functions), typically ~1000s, fast
instructions WHERE func_addr -> O(function_size / avg_insn_size)
instructions (no constraint) -> O(total_code_heads), potentially 100K+
blocks WHERE func_addr -> O(block_count_in_func), fast
cfg_edges WHERE func_addr -> O(block_count_in_func), fast
disasm_calls WHERE func_addr -> O(instructions_in_func), streaming
disasm_calls UPDATE callee_type WHERE addr -> O(1) call-site lookup
heads WHERE addr -> O(1) IDA head check
heads next/prev LIMIT 1 -> O(distance to next/previous defined head)
instruction_operands addr -> O(operands in one instruction)
instruction_operands func -> O(operands in one function)
更多资源
- 高级 CTE 模式和指令生命周期操作指南:references/disassembly-examples.md
- 其他表架构(fchunks、heads、bytes、signatures、problems、fixups 等):references/disassembly-tables.md
另请参阅
decompiler— 同一函数的伪代码和 ctree;反汇编过于杂乱时可切换使用。xrefs— 以函数或调用点为中心的调用图和数据引用。data— 面向操作数目标的字节/字符串;bytes表可用于逐字节读取,也可通过WHERE start_addr = X AND n = N限定窗口,再结合hex(blob_concat(value))批量获取十六进制数据。