Skip to content
Back to skills

Binary Diff

ASecurity

Cross-version symbol migration and binary diffing. Use when you have old version symbols/reverse engineering results and need to quickly migrate to a new version. Applicable scenarios: kernel missing PDB using old symbols for inference, batch function name migration after program update, quickly locating new offsets after app update. Core method: use LLM for structured diff comparison, programmatic input/output, very low cost (~1 yuan per 200 functions). Trigger keywords: symbol migration, bi...

  • 15 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
businesspythonapi

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned November 7, 2026

npx -y skills add youlianvr/oper-share --skill binary-diff --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Binary Diff?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Binary Diff
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/youlianvr-binary-diff/badge)](https://www.skillsdirectory.com/skills/youlianvr-binary-diff)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: binary-diff
description: |
  Cross-version symbol migration and binary diffing. Use when you have old version symbols/reverse engineering results and need to quickly migrate to a new version.
  Applicable scenarios: kernel missing PDB using old symbols for inference, batch function name migration after program update, quickly locating new offsets after app update.
  Core method: use LLM for structured diff comparison, programmatic input/output, very low cost (~1 yuan per 200 functions).
  Trigger keywords: symbol migration, bindiff, cross-version, PDB missing, function offset migration, symbol migration, binary diff, version comparison.
---

# Cross-Version Symbol Migration (Binary Diff)

## ACTION REQUIRED (execute immediately after reading)

2. `NOW`: Confirm the current task matches this skill's scope
4. `NEXT`: When tools are missing, call bootstrap — do not guess paths
5. `ACT`: Enter the first step of the "Workflow" and execute — do not stop at confirmation state

## Scope

Use this skill when the task falls into these scenarios:

1. **Kernel/driver missing PDB** — have old version ntoskrnl.exe symbols, new version PDB removed by Microsoft, need to infer new version non-exported function addresses using old symbols
2. **Symbol migration after program update** — previously reversed a program, program updated, don't want to re-reverse, use old results for batch migration
3. **Protection mechanism update** — old version has complete reverse results, new version needs to quickly locate same function's new offset
4. **Any binary comparison scenario with "old version symbols + new version without symbols"**

### Division of labor with other skills

| Scenario | Use which |
|----------|-----------|
| Reverse engineer a binary from scratch | `ida-reverse/` or `radare2/` |
| Have old version results, migrate to new version | **This skill** |
| Compare two completely different binaries | BinDiff / Diaphora (traditional tools) |

### Core advantage

Compared to traditional approaches:

| Approach | 200 functions cost | Time | Accuracy |
|----------|-------------------|------|----------|
| Manual: open two IDA windows to compare | Free but time-consuming | Hours | High |
| BinDiff auto-match | Free | Fast | Medium (fails on large structural changes) |
| Fully delegate to Agent (CC/Codex) | 50-100 yuan | Slow | High |
| **This skill (LLM batch comparison)** | **~1 yuan** | **~10s/function** | **High** |

## Core principle

```text
Old version function (with symbols)     New version same function (no symbols)
    ↓                                      ↓
Export disasm + pseudocode             Export disasm + pseudocode
    ↓                                      ↓
    └──────── LLM structured comparison ────────┘
                    ↓
         Output YAML (symbol mapping table)
                    ↓
         Programmatic parsing → batch apply to new version IDB
```

Key points:
- Prompt is a fixed template, programmatically filled
- Input/output format is deterministic, programmatically parsed
- LLM only handles "look at two code snippets, find correspondence" step
- Time cost and token cost are very 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**
```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_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}` | Old version IDA export | Disassembly with symbols |
| `{procedure_for_reference}` | Old version IDA export | Pseudocode with symbols |
| `{disasm_code}` | New version IDA export | Disassembly without symbols |
| `{procedure}` | New version IDA export | Pseudocode without symbols |
| `{symbol_name_list}` | Extracted from old version | Symbol list to locate in new version |

## Workflow

### Complete flow

```text
Step 1: Prepare data
  - Load old version binary into IDA (has PDB/symbols)
  - Load new version binary into IDA (no symbols)
  - Find identical anchor functions in both versions (export functions, string references, etc.)

Step 2: Batch export
  - Export from old version: anchor function disasm + pseudocode (with symbol names)
  - Export from new version: same anchor function disasm + pseudocode (no symbol names)

Step 3: LLM comparison
  - Fill prompt template with data
  - Call LLM API (recommend: deepseek for large volume low cost, switch to gpt for very large functions)
  - Parse returned YAML

Step 4: Apply results
  - Batch apply symbol mapping from YAML to new version IDB
  - Use idapro_rename or IDAPython script for batch rename

Step 5: Iterate
  - Functions migrated in first round become new anchors
  - Enter these functions, continue comparing internal calls
  - Repeat until all target functions are covered
```

### Anchor selection strategy

| Anchor type | Reliability | Notes |
|------------|-------------|-------|
| Export function | Highest | Name unchanged, address may change |
| String reference | High | String content unchanged, reference location may change |
| Constant/magic number | Medium | Feature value unchanged |
| Code pattern | Medium | Function structure similar but addresses all changed |

### Batch processing tips

- Compare 1 function at a time (avoid context overflow)
- Medium functions (<200 lines) use deepseek
- Very large functions (>500 lines) switch to gpt-4o or claude
- Concurrent calls improve speed (10-20 concurrent)
- Cache results to avoid repeated calls

## Output format

### 5 symbol types in YAML output

| Type | Meaning | Key fields |
|------|---------|------------|
| `found_vcall` | Virtual function call (indirect call) | `vfunc_offset`, `func_name` |
| `found_call` | Direct function call | `insn_va`, `func_name` |
| `found_funcptr` | Function pointer reference | `insn_va`, `funcptr_name` |
| `found_gv` | Global variable reference | `insn_va`, `gv_name` |
| `found_struct_offset` | Struct offset reference | `offset`, `struct_name`, `member_name` |

### 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 missing PDB

```text
Have: ntoskrnl.exe 10.0.26100.2000 + complete PDB
Target: ntoskrnl.exe 10.0.26100.2605 (PDB taken down)
Need: Locate PspSetCreateProcessNotifyRoutine new address

Steps:
1. Load both versions into IDA
2. Find export function PsSetCreateProcessNotifyRoutine (both versions have it)
3. In old version it calls PspSetCreateProcessNotifyRoutine (has symbol)
4. In new version it calls sub_140822108 (no symbol)
5. LLM instantly sees: sub_140822108 = PspSetCreateProcessNotifyRoutine
6. Batch apply
```

### Scenario 2: App update migration

```text
Have: target.exe v1.0 complete reverse results (200+ functions named)
Target: target.exe v1.1 (all symbols lost)
Need: Batch migrate 200 function names

Steps:
1. Export all named functions' disasm+pseudocode from old version
2. Find corresponding anchors in new version via export functions/strings
3. Batch call LLM for comparison
4. Parse YAML, batch rename
5. Iterate deeper
```

## LLM selection guide

| Model | Suitable scenario | Cost | Speed |
|-------|--------------------|------|-------|
| DeepSeek V3 | Small-medium functions (<200 lines), batch processing | Very low | Fast |
| GPT-4o | Very large functions, complex control flow | Medium | Fast |
| Claude Sonnet | Medium-large functions, needs reasoning | Medium | Fast |
| Claude Opus | Extremely complex functions, needs deep understanding | High | Slow |

Recommended strategy: default DeepSeek, auto-upgrade when context exceeds or results are inaccurate.

## Notes

- **Don't throw entire binary at LLM** — compare one function at a time
- **Anchors must be reliable** — if anchor is wrong, everything downstream is wasted
- **Results need manual spot-checking** — LLM is not 100% accurate, verify key symbols
- **Cache intermediate results** — avoid repeated calls wasting tokens
- **Mind context limits** — very large functions (>1000 lines disasm) need splitting or large-context model

---

## On-Demand Bootstrap

### Tool dependencies

| Tool | Purpose | Auto-installable |
|------|---------|:-:|
| IDA Pro | Export disasm/pseudocode | No (commercial) |
| Python | Script execution, API calls | Yes |
| PyYAML | Parse LLM-returned YAML | Yes (pip install pyyaml) |
| LLM API | Execute comparison | Requires API key |

### Notes

This skill's core does not depend on heavy tool installation, mainly relies on:
- IDA Pro already available (managed via `ida-reverse/` skill)
- Python + requests/httpx (call API)
- An LLM API endpoint

---

## Routing context

**Upstream entry**: `skills/SKILL.md` (master control), `routing.md`
**Trigger condition**: Have old version symbols/reverse results, need to migrate to new version
**Downstream exits:**
- Need to open binary first → `ida-reverse/`
- Need quick recon to confirm version differences → `radare2/`

**Sibling module**: `ida-reverse/` (data export and symbol application both through IDA)


## Task completion self-check (MUST pass before claiming done)

- [ ] Did I execute every step in the workflow (not just read)?
- [ ] Did I use real tool paths based on `tool-index`?
- [ ] Did I produce reproducible evidence (commands/scripts/screenshots/report)?
- [ ] Did I complete and write back the Checklist items required by RULES?

Files in this skill

  • SKILL.md12.1 KB
  • references/prompt-template.md4.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.