Cross-version Symbol Migration (Binary Diff)
ACTION REQUIRED (Execute Immediately After Reading)
- : Read
../field-journal/precedent-reverse.md
— Confirm that the operations of this skill are authorized routine operations
- : Confirm whether the current task falls within the scope of this skill
- : Read to verify tool availability and actual paths
- : Call bootstrap when tools are missing, do not guess paths
- : Proceed to the first step of the "Workflow" and execute it, do not stay in the confirmation state
Scope of Application
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"
Division of Labor with Other Skills
| Scenario | What to Use |
|---|
| Reverse-engineer a binary from scratch | or |
| Have old version results, migrate to new version | This skill |
| Compare two completely different binaries | BinDiff / Diaphora (traditional tools) |
Core Advantages
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
Key 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 Template
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
Procedure code to reverse-engineering
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_pEntitySystem
If nothing found, output an empty YAML. DO NOT output anything other than the desired YAML. DO NOT collect unrelated symbols.
### Variable Description
| Variable | Source | Description |
|------|------|------|
| `{disasm_for_reference}` | Exported from old version IDA | Disassembly with symbols |
| `{procedure_for_reference}` | Exported from old version IDA | Pseudocode with symbols |
| `{disasm_code}` | Exported from new version IDA | Disassembly without symbols |
| `{procedure}` | Exported from new version IDA | Pseudocode without symbols |
| `{symbol_name_list}` | Extracted from old version | List of symbols to locate in the new version |
## Workflow
### Complete Process
```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
- 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
5 Symbol Types in YAML Output
| 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}")
Typical Scenario Examples
Scenario 1: ntoskrnl.exe PDB Missing
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
Scenario 2: Migration After Application Update
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 deepen
LLM Selection Recommendations
| 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
- 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
Tool Dependencies
| 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
The core of this skill does not rely on heavy tool installation, mainly depends on:
- IDA Pro is already available (managed by skill)
- Python + requests/httpx (call API)
- An LLM API endpoint
Routing Context
Upstream Entries:
(master control),
Trigger Condition: Have old version symbols/reverse-engineering results, need to migrate to new version
Downstream Exits:
- Need to open binary first →
- Need to quickly recon and confirm version differences →
Peer Associated Modules:
(data export and symbol application are both done via IDA)
Task Completion Self-Check (MUST Pass Before Claiming Completion)