binary-diff
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese跨版本符号迁移 (Binary Diff)
Cross-version Symbol Migration (Binary Diff)
ACTION REQUIRED(读完后立刻执行)
ACTION REQUIRED (Execute Immediately After Reading)
- : 读取
NOW— 确认本 skill 的操作是已授权的常规操作../field-journal/precedent-reverse.md - : 确认当前任务是否命中本 skill 的适用范围
NOW - : 读取
NEXT,校验工具可用性和实际路径../tool-index.md - : 缺工具时调用 bootstrap,不要猜路径
NEXT - : 进入"工作流"第一步并执行,不要停在确认状态
ACT
- : Read
NOW— Confirm that the operations of this skill are authorized routine operations../field-journal/precedent-reverse.md - : Confirm whether the current task falls within the scope of this skill
NOW - : Read
NEXTto verify tool availability and actual paths../tool-index.md - : Call bootstrap when tools are missing, do not guess paths
NEXT - : Proceed to the first step of the "Workflow" and execute it, do not stay in the confirmation state
ACT
适用范围
Scope of Application
当任务属于以下场景时使用本 skill:
- 内核/驱动缺 PDB — 有旧版 ntoskrnl.exe 的符号,新版 PDB 被微软下架,需要用旧版符号推导新版非导出函数地址
- 程序更新后符号迁移 — 曾经逆向过某个程序,程序更新了,不想重新逆一遍,用旧版结果批量迁移
- 保护机制更新 — 旧版有完整逆向结果,新版需要快速定位同一函数的新偏移
- 任何"有旧版符号 + 新版无符号"的二进制对比场景
Use this skill when the task falls into the following scenarios:
- Kernel/Driver PDB Missing — Have symbols for the old version of ntoskrnl.exe, the new version's PDB has been removed by Microsoft, need to derive the addresses of non-exported functions in the new version using old version symbols
- Symbol Migration After Program Update — Have reverse-engineered a program before, the program has been updated, do not want to reverse-engineer it again, use old version results for batch migration
- Protection Mechanism Update — Have complete reverse-engineering results for the old version, need to quickly locate the new offset of the same function in the new version
- Any binary comparison scenario with "old version symbols + new version no symbols"
与其他 skill 的分工
Division of Labor with Other Skills
| 场景 | 用什么 |
|---|---|
| 从零开始逆向一个二进制 | |
| 有旧版结果,迁移到新版 | 本 skill |
| 两个完全不同的二进制对比 | BinDiff / Diaphora(传统工具) |
| Scenario | What to Use |
|---|---|
| Reverse-engineer a binary from scratch | |
| Have old version results, migrate to new version | This skill |
| Compare two completely different binaries | BinDiff / Diaphora (traditional tools) |
核心优势
Core Advantages
相比传统方案:
| 方案 | 200 个函数成本 | 时间 | 准确率 |
|---|---|---|---|
| 人工开两个 IDA 窗口对比 | 免费但耗命 | 数小时 | 高 |
| BinDiff 自动匹配 | 免费 | 快 | 中(结构变化大时失效) |
| 完全交给 Agent(CC/Codex) | 50-100 元 | 慢 | 高 |
| 本 skill(LLM 批量比对) | ~1 元 | ~10 秒/函数 | 高 |
Compared with traditional solutions:
| Solution | Cost for 200 Functions | Time | Accuracy |
|---|---|---|---|
| Manual comparison with two IDA windows | Free but time-consuming | Several hours | High |
| BinDiff automatic matching | Free | Fast | Medium (fails when structure changes greatly) |
| Fully entrusted to Agent (CC/Codex) | 50-100 yuan | Slow | High |
| This skill (LLM batch comparison) | ~1 yuan | ~10 seconds/function | High |
核心原理
Core Principles
text
旧版函数(有符号) 新版同一函数(无符号)
↓ ↓
导出反汇编 + 伪代码 导出反汇编 + 伪代码
↓ ↓
└──────── LLM 结构化比对 ────────┘
↓
输出 YAML(符号映射表)
↓
程序化解析 → 批量应用到新版 IDB关键点:
- prompt 是固定模板,程序化填充
- 输入输出格式确定,程序化解析
- LLM 只负责"看两段代码,找出对应关系"这一步
- 时间成本和 token 成本极低
text
旧版函数(有符号) 新版同一函数(无符号)
↓ ↓
导出反汇编 + 伪代码 导出反汇编 + 伪代码
↓ ↓
└──────── LLM 结构化比对 ────────┘
↓
输出 YAML(符号映射表)
↓
程序化解析 → 批量应用到新版 IDBKey points:
- The prompt is a fixed template, filled programmatically
- Input and output formats are fixed, parsed programmatically
- LLM only takes charge of the step of "looking at two code segments and finding the corresponding relationship"
- Time cost and token cost are extremely low
Prompt 模板
Prompt Template
标准比对 Prompt
Standard Comparison Prompt
text
I have disassembly outputs and procedure code of the same function.
This is the function for reference:
**Disassembly for Reference**
```c
{disasm_for_reference}Procedure code for Reference
c
{procedure_for_reference}This is the function you need to reverse-engineering:
Disassembly to reverse-engineering
c
{disasm_code}Procedure code to reverse-engineering
c
{procedure}What you need to do is to collect all references to "{symbol_name_list}" in the function you need to reverse-engineering and output those references as YAML.
Example:
yaml
found_vcall: # This is for indirect call to virtual function or virtual function pointer fetching.
- insn_va: '0x180777700' # Always be the instruction with displacement offset
insn_disasm: call [rax+68h] # Always be the instruction with displacement offset
vfunc_offset: '0x68'
func_name: ILoopMode_OnLoopActivate
- insn_va: '0x180777778' # Always be the instruction with displacement offset
insn_disasm: mov rax, [rax+80h] # Always be the instruction with displacement offset
vfunc_offset: '0x80'
func_name: INetworkMessages_GetNetworkGroupCount
found_call: # This is for direct call to non-virtual regular function.
- insn_va: '0x180888800'
insn_disasm: call sub_180999900
func_name: CLoopMode_RegisterEventMapInternal
- insn_va: '0x180888880'
insn_disasm: call sub_180555500
func_name: CLoopMode_SetSystemState
found_funcptr: # This is for non-virtual regular function pointer.
- insn_va: '0x180666600' # Must load/reference the function pointer target address
insn_disasm: lea rdx, sub_15BC910 # Must load/reference the function pointer target address
funcptr_name: CLoopMode_OnClientPollNetworking
found_gv: # This is for reference to global variable.
- insn_va: '0x180444400'
insn_disasm: mov rcx, cs:qword_180666600 # Must load/reference the global variable
gv_name: g_pNetworkMessages
- insn_va: '0x180333300'
insn_disasm: lea rax, unk_180222200 # Must load/reference the global variable
gv_name: s_EventManager
found_struct_offset: # This is for reference to struct offset. NOTE THAT virtual function pointer should not be here! virtual function pointer should ALWAYS be in found_vcall !
- insn_va: '0x1801BA12A' # Always be the instruction with displacement offset
insn_disasm: mov rcx, [r14+58h] # Always be the instruction with displacement offset
offset: '0x58'
size: 8
struct_name: CResourceService
member_name: m_pEntitySystemIf nothing found, output an empty YAML. DO NOT output anything other than the desired YAML. DO NOT collect unrelated symbols.
undefinedtext
I have disassembly outputs and procedure code of the same function.
This is the function for reference:
**Disassembly for Reference**
```c
{disasm_for_reference}Procedure code for Reference
c
{procedure_for_reference}This is the function you need to reverse-engineering:
Disassembly to reverse-engineering
c
{disasm_code}Procedure code to reverse-engineering
c
{procedure}What you need to do is to collect all references to "{symbol_name_list}" in the function you need to reverse-engineering and output those references as YAML.
Example:
yaml
found_vcall: # This is for indirect call to virtual function or virtual function pointer fetching.
- insn_va: '0x180777700' # Always be the instruction with displacement offset
insn_disasm: call [rax+68h] # Always be the instruction with displacement offset
vfunc_offset: '0x68'
func_name: ILoopMode_OnLoopActivate
- insn_va: '0x180777778' # Always be the instruction with displacement offset
insn_disasm: mov rax, [rax+80h] # Always be the instruction with displacement offset
vfunc_offset: '0x80'
func_name: INetworkMessages_GetNetworkGroupCount
found_call: # This is for direct call to non-virtual regular function.
- insn_va: '0x180888800'
insn_disasm: call sub_180999900
func_name: CLoopMode_RegisterEventMapInternal
- insn_va: '0x180888880'
insn_disasm: call sub_180555500
func_name: CLoopMode_SetSystemState
found_funcptr: # This is for non-virtual regular function pointer.
- insn_va: '0x180666600' # Must load/reference the function pointer target address
insn_disasm: lea rdx, sub_15BC910 # Must load/reference the function pointer target address
funcptr_name: CLoopMode_OnClientPollNetworking
found_gv: # This is for reference to global variable.
- insn_va: '0x180444400'
insn_disasm: mov rcx, cs:qword_180666600 # Must load/reference the global variable
gv_name: g_pNetworkMessages
- insn_va: '0x180333300'
insn_disasm: lea rax, unk_180222200 # Must load/reference the global variable
gv_name: s_EventManager
found_struct_offset: # This is for reference to struct offset. NOTE THAT virtual function pointer should not be here! virtual function pointer should ALWAYS be in found_vcall !
- insn_va: '0x1801BA12A' # Always be the instruction with displacement offset
insn_disasm: mov rcx, [r14+58h] # Always be the instruction with displacement offset
offset: '0x58'
size: 8
struct_name: CResourceService
member_name: m_pEntitySystemIf nothing found, output an empty YAML. DO NOT output anything other than the desired YAML. DO NOT collect unrelated symbols.
undefined变量说明
Variable Description
| 变量 | 来源 | 说明 |
|---|---|---|
| 旧版 IDA 导出 | 有符号的反汇编 |
| 旧版 IDA 导出 | 有符号的伪代码 |
| 新版 IDA 导出 | 无符号的反汇编 |
| 新版 IDA 导出 | 无符号的伪代码 |
| 从旧版提取 | 需要在新版中定位的符号列表 |
| Variable | Source | Description |
|---|---|---|
| Exported from old version IDA | Disassembly with symbols |
| Exported from old version IDA | Pseudocode with symbols |
| Exported from new version IDA | Disassembly without symbols |
| Exported from new version IDA | Pseudocode without symbols |
| Extracted from old version | List of symbols to locate in the new version |
工作流
Workflow
完整流程
Complete Process
text
Step 1: 准备数据
- 旧版二进制加载到 IDA(有 PDB/符号)
- 新版二进制加载到 IDA(无符号)
- 找到两个版本中相同的锚点函数(导出函数、字符串引用等)
Step 2: 批量导出
- 从旧版导出:锚点函数的反汇编 + 伪代码(含符号名)
- 从新版导出:同一锚点函数的反汇编 + 伪代码(无符号名)
Step 3: LLM 比对
- 用 prompt 模板填充数据
- 调用 LLM API(推荐:deepseek 量大便宜,超大函数切 gpt)
- 解析返回的 YAML
Step 4: 应用结果
- 将 YAML 中的符号映射批量应用到新版 IDB
- 用 idapro_rename 或 IDAPython 脚本批量重命名
Step 5: 迭代
- 第一轮迁移的函数成为新的锚点
- 进入这些函数,继续对比内部调用
- 重复直到覆盖所有目标函数text
Step 1: Prepare Data
- Load the old version binary into IDA (with PDB/symbols)
- Load the new version binary into IDA (without symbols)
- Find the same anchor functions in both versions (exported functions, string references, etc.)
Step 2: Batch Export
- Export from old version: Disassembly + pseudocode of anchor functions (including symbol names)
- Export from new version: Disassembly + pseudocode of the same anchor functions (without symbol names)
Step 3: LLM Comparison
- Fill data using the prompt template
- Call LLM API (Recommendation: DeepSeek for large volume and low cost, use GPT for extra-large functions)
- Parse the returned YAML
Step 4: Apply Results
- Batch apply the symbol mappings in YAML to the new version IDB
- Use idapro_rename or IDAPython script for batch renaming
Step 5: Iterate
- Functions migrated in the first round become new anchors
- Enter these functions and continue comparing internal calls
- Repeat until all target functions are covered锚点选择策略
Anchor Selection Strategy
| 锚点类型 | 可靠性 | 说明 |
|---|---|---|
| 导出函数 | 最高 | 名字不变,地址可能变 |
| 字符串引用 | 高 | 字符串内容不变,引用位置可能变 |
| 常量/魔数 | 中 | 特征值不变 |
| 代码模式 | 中 | 函数结构相似但地址全变 |
| Anchor Type | Reliability | Description |
|---|---|---|
| Exported Functions | Highest | Names remain unchanged, addresses may change |
| String References | High | String content remains unchanged, reference positions may change |
| Constants/Magic Numbers | Medium | Feature values remain unchanged |
| Code Patterns | Medium | Function structures are similar but addresses are completely changed |
批量处理建议
Batch Processing Suggestions
- 每次比对 1 个函数(避免 context 爆炸)
- 中等函数(<200 行)用 deepseek
- 超大函数(>500 行)切 gpt-4o 或 claude
- 并发调用提高速度(10-20 并发)
- 结果缓存,避免重复调用
- Compare 1 function each time (avoid context explosion)
- Use DeepSeek for medium-sized functions (<200 lines)
- Use GPT-4o or Claude for extra-large functions (>500 lines)
- Concurrent calls to improve speed (10-20 concurrency)
- Cache results to avoid repeated calls
输出格式
Output Format
YAML 输出的 5 种符号类型
5 Symbol Types in YAML Output
| 类型 | 含义 | 关键字段 |
|---|---|---|
| 虚函数调用(间接 call) | |
| 直接函数调用 | |
| 函数指针引用 | |
| 全局变量引用 | |
| 结构体偏移引用 | |
| Type | Meaning | Key Fields |
|---|---|---|
| Virtual function call (indirect call) | |
| Direct function call | |
| Function pointer reference | |
| Global variable reference | |
| Struct offset reference | |
解析后的应用动作
Application Actions After Parsing
text
found_call → idapro_rename(addr=call_target, name=func_name)
found_vcall → idapro_set_comments(addr=insn_va, comment="vcall: {func_name} @ +{offset}")
found_funcptr → idapro_rename(addr=funcptr_target, name=funcptr_name)
found_gv → idapro_rename(addr=gv_addr, name=gv_name)
found_struct_offset → idapro_set_comments(addr=insn_va, comment="{struct_name}.{member_name}")text
found_call → idapro_rename(addr=call_target, name=func_name)
found_vcall → idapro_set_comments(addr=insn_va, comment="vcall: {func_name} @ +{offset}")
found_funcptr → idapro_rename(addr=funcptr_target, name=funcptr_name)
found_gv → idapro_rename(addr=gv_addr, name=gv_name)
found_struct_offset → idapro_set_comments(addr=insn_va, comment="{struct_name}.{member_name}")典型场景示例
Typical Scenario Examples
场景 1:ntoskrnl.exe 缺 PDB
Scenario 1: ntoskrnl.exe PDB Missing
text
已有:ntoskrnl.exe 10.0.26100.2000 + 完整 PDB
目标:ntoskrnl.exe 10.0.26100.2605(PDB 被下架)
需求:定位 PspSetCreateProcessNotifyRoutine 的新地址
步骤:
1. 两个版本都加载到 IDA
2. 找到导出函数 PsSetCreateProcessNotifyRoutine(两个版本都有)
3. 旧版中它调用了 PspSetCreateProcessNotifyRoutine(有符号)
4. 新版中它调用了 sub_140822108(无符号)
5. LLM 一眼看出:sub_140822108 = PspSetCreateProcessNotifyRoutine
6. 批量应用text
Available: ntoskrnl.exe 10.0.26100.2000 + complete PDB
Target: ntoskrnl.exe 10.0.26100.2605 (PDB removed)
Requirement: Locate the new address of PspSetCreateProcessNotifyRoutine
Steps:
1. Load both versions into IDA
2. Find the exported function PsSetCreateProcessNotifyRoutine (available in both versions)
3. In the old version, it calls PspSetCreateProcessNotifyRoutine (with symbol)
4. In the new version, it calls sub_140822108 (without symbol)
5. LLM immediately identifies: sub_140822108 = PspSetCreateProcessNotifyRoutine
6. Batch apply场景 2:应用更新后迁移
Scenario 2: Migration After Application Update
text
已有:target.exe v1.0 的完整逆向结果(200+ 函数已命名)
目标:target.exe v1.1(所有符号丢失)
需求:批量迁移 200 个函数名
步骤:
1. 从旧版导出所有已命名函数的反汇编+伪代码
2. 在新版中通过导出函数/字符串找到对应锚点
3. 批量调用 LLM 比对
4. 解析 YAML,批量 rename
5. 迭代深入text
Available: Complete reverse-engineering results for target.exe v1.0 (200+ functions named)
Target: target.exe v1.1 (all symbols lost)
Requirement: Batch migrate 200 function names
Steps:
1. Export disassembly + pseudocode of all named functions from the old version
2. Find corresponding anchors in the new version via exported functions/strings
3. Call LLM for batch comparison
4. Parse YAML and perform batch renaming
5. Iterate and deepenLLM 选择建议
LLM Selection Recommendations
| 模型 | 适合场景 | 成本 | 速度 |
|---|---|---|---|
| DeepSeek V3 | 中小函数(<200 行),批量处理 | 极低 | 快 |
| GPT-4o | 超大函数,复杂控制流 | 中 | 快 |
| Claude Sonnet | 中大函数,需要推理 | 中 | 快 |
| Claude Opus | 极复杂函数,需要深度理解 | 高 | 慢 |
推荐策略:默认 DeepSeek,遇到 context 超限或结果不准时自动升级。
| Model | Suitable Scenario | Cost | Speed |
|---|---|---|---|
| DeepSeek V3 | Small and medium-sized functions (<200 lines), batch processing | Extremely low | Fast |
| GPT-4o | Extra-large functions, complex control flow | Medium | Fast |
| Claude Sonnet | Medium and large-sized functions, requires reasoning | Medium | Fast |
| Claude Opus | Extremely complex functions, requires deep understanding | High | Slow |
Recommendation Strategy: Use DeepSeek by default, automatically upgrade when context exceeds limit or results are inaccurate.
注意事项
Notes
- 不要把整个二进制丢给 LLM — 一次只比对一个函数
- 锚点必须可靠 — 如果锚点本身就对错了,后续全部白费
- 结果需要人工抽检 — LLM 不是 100% 准确,关键符号要验证
- 缓存中间结果 — 避免重复调用浪费 token
- 注意 context 限制 — 超大函数(>1000 行反汇编)需要拆分或用大 context 模型
- Do not feed the entire binary to LLM — Compare only one function at a time
- Anchors must be reliable — If the anchor is wrong, all subsequent work will be in vain
- Results require manual spot checks — LLM is not 100% accurate, key symbols need to be verified
- Cache intermediate results — Avoid wasting tokens on repeated calls
- Pay attention to context limits — Extra-large functions (>1000 lines of disassembly) need to be split or use large context models
按需自举(On-Demand Bootstrap)
On-Demand Bootstrap
工具依赖
Tool Dependencies
| 工具 | 用途 | 可自动安装 |
|---|---|---|
| IDA Pro | 导出反汇编/伪代码 | ✗(商业软件) |
| Python | 脚本执行、API 调用 | ✓ |
| PyYAML | 解析 LLM 返回的 YAML | ✓(pip install pyyaml) |
| LLM API | 执行比对 | 需要 API key |
| Tool | Purpose | Auto-installable |
|---|---|---|
| IDA Pro | Export disassembly/pseudocode | ✗ (commercial software) |
| Python | Script execution, API calls | ✓ |
| PyYAML | Parse YAML returned by LLM | ✓ (pip install pyyaml) |
| LLM API | Perform comparison | Requires API key |
说明
Description
本 skill 的核心不依赖重型工具安装,主要依赖:
- IDA Pro 已有(用 skill 管理)
ida-reverse/ - Python + requests/httpx(调 API)
- 一个 LLM API endpoint
The core of this skill does not rely on heavy tool installation, mainly depends on:
- IDA Pro is already available (managed by skill)
ida-reverse/ - Python + requests/httpx (call API)
- An LLM API endpoint
路由上下文
Routing Context
上游入口: (总控)、
触发条件: 有旧版符号/逆向结果,需要迁移到新版本
下游出口:
skills/SKILL.mdrouting.md- 需要先打开二进制 →
ida-reverse/ - 需要快速侦察确认版本差异 →
radare2/
同级关联模块: (数据导出和符号应用都通过 IDA)
ida-reverse/Upstream Entries: (master control),
Trigger Condition: Have old version symbols/reverse-engineering results, need to migrate to new version
Downstream Exits:
skills/SKILL.mdrouting.md- Need to open binary first →
ida-reverse/ - Need to quickly recon and confirm version differences →
radare2/
Peer Associated Modules: (data export and symbol application are both done via IDA)
ida-reverse/任务完成自检(声称完成前 MUST 通过)
Task Completion Self-Check (MUST Pass Before Claiming Completion)
- 我是否执行了工作流中的每一步(而不是只阅读)?
- 我是否基于 使用了真实工具路径?
tool-index - 我是否产出了可复现证据(命令/脚本/截图/报告)?
- 我是否完成并回写了 RULES 要求的 Checklist 项?
- Have I executed every step in the workflow (instead of just reading)?
- Have I used real tool paths based on ?
tool-index - Have I produced reproducible evidence (commands/scripts/screenshots/reports)?
- Have I completed and written back the Checklist items required by RULES?