# How to Use the binary-diff Module for Cross-Version Symbol Migration

> Learn to use the binary-diff module for cross-version symbol migration. Export IDA Pro disassembly, use an LLM for comparison, and apply YAML mappings to update new IDBs.

- Repository: [ZhaoXu/reverse-skill](https://github.com/zhaoxuya520/reverse-skill)
- Tags: how-to-guide
- Published: 2026-08-16

---

**Use the binary-diff skill to migrate symbols from an old binary with known symbols to a newer binary by exporting disassembly and pseudo-code from IDA Pro, feeding them through an LLM-powered comparison pipeline, and applying the resulting YAML mappings back to the new IDB.**

The `binary-diff` module in the [zhaoxuya520/reverse-skill](https://github.com/zhaoxuya520/reverse-skill) repository provides a lightweight, LLM-assisted workflow for **cross-version symbol migration**. This article walks through the complete pipeline—from data preparation to automated symbol renaming—based on the actual implementation in [`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md).

## Overview of the Three-Layer Architecture

The binary-diff skill is built on three tightly coupled layers that handle data preparation, LLM comparison, and result application.

### Data Preparation Layer

Export **disassembly** and **pseudo-code** from both binaries using IDA Pro:

- **Old binary**: Contains known symbols (the reference)
- **New binary**: Missing symbols (the target)

The exported blocks feed into a fixed prompt template defined in [`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md) [lines 48-55](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md#L48-L55). Only **one function per LLM call** is processed to keep token usage low and avoid context overflow.

### LLM Comparison Layer

A single LLM call (default **DeepSeek V3**) receives the filled prompt and returns a **YAML** mapping of discovered symbol relationships. The prompt template lives in [`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md) [lines 68-99](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md#L68-L99).

**Model selection logic** (lines 58-66):
- Small functions (< 200 lines): DeepSeek V3 (~1¢ per 200 functions)
- Large functions: GPT-4o, Claude Sonnet, or Claude Opus

### Result Application Layer

Parse the YAML output with **PyYAML**, then apply mappings to the new IDB using IDAPython helpers such as `idapro_rename` or `idapro_set_comments`. The YAML key-to-action mapping is documented in [`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md) [lines 14-22](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md#L4-L22).

## Step-by-Step Cross-Version Symbol Migration Workflow

The complete workflow from start to finish is illustrated in [`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md) [lines 56-84](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md#L56-L84):

| Step | Action |
|:---|:---|
| **1** | Load both binaries into IDA (old with symbols, new without) |
| **2** | Export a **single anchor function's** disassembly and pseudo-code from each binary |
| **3** | Fill the prompt template and invoke the LLM |
| **4** | Parse the returned YAML and programmatically rename symbols in the new IDB |
| **5** | **Iterate**: promoted functions become new anchors until desired coverage is reached |

## Complete Code Example: Driving the Pipeline

This Python snippet demonstrates the end-to-end workflow for one function. Assume these exported files exist:

- [`old_disasm.txt`](https://github.com/zhaoxuya520/reverse-skill/blob/main/old_disasm.txt) & [`old_pcode.txt`](https://github.com/zhaoxuya520/reverse-skill/blob/main/old_pcode.txt) — from the old binary (with symbols)
- [`new_disasm.txt`](https://github.com/zhaoxuya520/reverse-skill/blob/main/new_disasm.txt) & [`new_pcode.txt`](https://github.com/zhaoxuya520/reverse-skill/blob/main/new_pcode.txt) — from the new binary (without symbols)

```python
import json, yaml, requests

# -------------------------------------------------

# 1️⃣  Load exported data (normally produced by IDA)

# -------------------------------------------------

def load_file(path: str) -> str:
    with open(path, "r", encoding="utf-8") as f:
        return f.read()

old_disasm = load_file("old_disasm.txt")
old_pcode = load_file("old_pcode.txt")
new_disasm = load_file("new_disasm.txt")
new_pcode = load_file("new_pcode.txt")

# -------------------------------------------------

# 2️⃣  Build the prompt (see SKILL.md for the exact template)

# -------------------------------------------------

prompt_template = """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.
"""

symbol_list = "PsSetCreateProcessNotifyRoutine, PspSetCreateProcessNotifyRoutine"  # example

filled_prompt = prompt_template.format(
    disasm_for_reference=old_disasm,
    procedure_for_reference=old_pcode,
    disasm_code=new_disasm,
    procedure=new_pcode,
    symbol_name_list=symbol_list,
)

# -------------------------------------------------

# 3️⃣  Call the LLM (DeepSeek V3 shown; replace URL/key as needed)

# -------------------------------------------------

api_url = "https://api.deepseek.com/v1/chat/completions"
headers = {"Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json"}

payload = {
    "model": "deepseek-coder",
    "messages": [{"role": "user", "content": filled_prompt}],
    "temperature": 0.0,
}
response = requests.post(api_url, headers=headers, json=payload)
response.raise_for_status()
yaml_text = response.json()["choices"][0]["message"]["content"]

# -------------------------------------------------

# 4️⃣  Parse the YAML output

# -------------------------------------------------

mapping = yaml.safe_load(yaml_text)

# -------------------------------------------------

# 5️⃣  Apply results to the new IDB (IDAPython example)

# -------------------------------------------------

import idaapi, idc

def rename_call(addr: int, name: str):
    idc.set_name(addr, name, idc.SN_CHECK)

for entry in mapping.get("found_call", []):
    rename_call(int(entry["insn_va"], 16), entry["func_name"])

for entry in mapping.get("found_vcall", []):
    comment = f"vcall: {entry['func_name']} @ +{entry['vfunc_offset']}"
    idc.set_cmt(int(entry["insn_va"], 16), comment, 0)

```

This script follows the exact steps in [`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md) [lines 70-98](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md#L70-L98) and uses the **YAML schema** defined in [lines 4-12](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md#L4-L12).

## Key Architectural Decisions

- **One-function-per-LLM call**: Minimizes token usage and prevents context window overflow
- **Static prompt template**: Ensures deterministic input formatting for easy automation
- **YAML as interchange format**: Enables deterministic parsing and clear downstream contracts
- **Automatic model routing**: Cost-efficient for small functions, capable for large ones

## Essential Source Files

| File | Purpose | Link |
|:---|:---|:---|
| [`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md) | Full skill definition, prompt template, workflow, YAML schema | [View](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md) |
| [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) | Registers binary-diff with the router (`"skill": "binary-diff/SKILL.md"`) | [View](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) |
| [`skills/INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/INDEX.md) | Human-readable skill index | [Line 13](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/INDEX.md#L13) |
| [`docs/ARCHITECTURE.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/docs/ARCHITECTURE.md) | System architecture showing binary-diff as "BinDiff" sub-module | [Line 51](https://github.com/zhaoxuya520/reverse-skill/blob/main/docs/ARCHITECTURE.md#L51) |

## Summary

- The **binary-diff module** implements an LLM-assisted pipeline for cross-version symbol migration in three layers: data preparation, LLM comparison, and result application
- Each LLM call processes **one function at a time** using a **static prompt template** that consumes IDA-exported disassembly and pseudo-code
- The LLM returns **YAML mappings** that are parsed and applied via **IDAPython** to rename functions, set comments, and recover virtual calls
- **Model selection** automatically routes small functions to cost-efficient DeepSeek V3 and large functions to more capable models
- The workflow is **iterative**: successfully identified symbols become new anchor points for进一步扩大 coverage

## Frequently Asked Questions

### What input files does binary-diff require from IDA Pro?

Two pairs of text exports for each function: disassembly and pseudo-code from the **old binary** (with symbols), plus disassembly and pseudo-code from the **new binary** (without symbols). These four files populate the prompt template fields `disasm_for_reference`, `procedure_for_reference`, `disasm_code`, and `procedure`.

### Why does binary-diff use YAML instead of JSON for LLM output?

YAML was chosen as the **interchange format** because it allows deterministic parsing through PyYAML and establishes a clear, human-readable contract between the LLM response and downstream IDAPython scripts. The schema defines keys like `found_call` and `found_vcall` that map directly to IDA actions.

### How does binary-diff handle very large functions?

Functions exceeding **200 lines of pseudo-code** are automatically routed to larger models—GPT-4o, Claude Sonnet, or Claude Opus—while smaller functions default to **DeepSeek V3** for cost efficiency (~1¢ per 200 functions). This routing logic is embedded in the skill configuration.

### Can I automate binary-diff for an entire IDA database?

Yes, but **iteratively**. The recommended approach processes one anchor function at a time, applies the recovered symbols to the new IDB, then promotes those newly-named functions as anchors for the next iteration. This controlled expansion prevents error propagation and keeps API costs predictable.