How to Perform Cross-Version Binary Symbol Migration with the binary-diff Module

The binary-diff skill in zhaoxuya520/reverse-skill automates cross-version binary symbol migration by sending IDA Pro exports from a symbol-rich old binary and a stripped new binary to an LLM, then applying the returned YAML mappings to the new IDB with IDAPython.

Cross-version binary symbol migration recovers meaningful names in stripped binaries by referencing known symbols from older builds. The binary-diff module in the zhaoxuya520/reverse-skill repository implements a lightweight, LLM-assisted pipeline designed for this exact task. It combines deterministic prompt templates, structured YAML output, and IDA Pro automation to migrate symbols one function at a time.

Architecture of the binary-diff Migration Pipeline

The binary-diff pipeline consists of three tightly-coupled layers that move symbols from an old binary to a newer binary.

Data Preparation Layer

The first step exports disassembly and pseudo-code from both binaries using IDA Pro. The old binary must contain known symbols, while the new binary is typically stripped. These exported blocks are fed into a fixed prompt template. The required inputs are described in skills/binary-diff/SKILL.md at lines 48-55.

LLM Comparison Layer

A single LLM call compares the old and new function exports. By default, the skill uses DeepSeek V3; larger functions are automatically routed to bigger models. The LLM returns a YAML mapping of discovered symbol relationships. The exact prompt definition lives in skills/binary-diff/SKILL.md at lines 68-99.

Result Application Layer

The returned YAML is parsed with PyYAML and applied programmatically to the new IDB using IDAPython helpers such as idapro_rename or idapro_set_comments. The mapping of YAML keys to specific actions is documented in skills/binary-diff/SKILL.md at lines 14-22.

Cross-Version Symbol Migration Workflow

The overall workflow, from start to finish, is illustrated in skills/binary-diff/SKILL.md at lines 56-84. Follow these steps:

  1. Load both binaries into IDA Pro (the old binary with symbols and the new binary 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 the desired coverage is reached.

Model Selection and Cost Optimization

As documented in skills/binary-diff/SKILL.md at lines 58-66, the skill routes functions based on size to manage cost and context limits:

  • Small functions (< 200 lines) default to DeepSeek V3, costing approximately 1¢ per 200 functions.
  • Large functions are automatically routed to GPT-4o, Claude Sonnet, or Claude Opus.

This one-function-per-LLM-call design keeps token usage low and avoids context overflow.

Complete Python Example for binary-diff Automation

Below is a minimal, end-to-end Python snippet that drives the binary-diff workflow for a single function. It assumes four exported files exist: old_disasm.txt, old_pcode.txt, new_disasm.txt, and new_pcode.txt.

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

{procedure_for_reference}

This is the function you need to reverse-engineering:

Disassembly to reverse-engineering

{disasm_code}

Procedure code to reverse-engineering

{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 described in [`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md) at lines 70-98 and uses the same YAML schema defined at lines 4-12.

## Key Files in the reverse-skill Repository

Understanding where binary-diff lives in the larger project helps with integration and navigation:

- **[`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md)** — Full skill definition, prompt template, workflow, and YAML schema.
- **[`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json)** — Registers the binary-diff skill with the router (`"skill": "binary-diff/SKILL.md"`).
- **[`skills/INDEX.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/INDEX.md)** — Human-readable index that points to the binary-diff skill page (line 13).
- **[`docs/ARCHITECTURE.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/docs/ARCHITECTURE.md)** — Shows the overall system architecture where binary-diff appears as a sub-module of the BinDiff node (line 51).
- **[`skills/reverse-engineering/tools-advanced.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/reverse-engineering/tools-advanced.md)** — Lists binary-diff among other advanced reverse-engineering tools (line 14).

## Summary

- The **binary-diff** module provides an LLM-assisted pipeline for cross-version binary symbol migration within the zhaoxuya520/reverse-skill framework.
- The workflow is split into three layers: **data preparation**, **LLM comparison**, and **result application**.
- Each function is processed individually to control token usage, with small functions defaulting to **DeepSeek V3** and large functions routing to premium models.
- The LLM returns a structured **YAML** mapping that is parsed and applied via **IDAPython** to rename symbols and set comments in the new binary.
- Iteration using promoted anchor functions extends coverage across the new binary's entire surface area.

## Frequently Asked Questions

### What inputs are required to start a binary-diff migration?

You need two sets of IDA Pro exports: disassembly and pseudo-code from a known old binary that contains symbols, and the same exports from the new stripped binary. The specific input requirements are detailed in [`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md) at lines 48-55.

### Why does binary-diff use one LLM call per function?

Processing one function per call keeps token usage low, prevents context-window overflow, and yields deterministic, easy-to-parse YAML output for each individual comparison. This architecture is a core design decision documented in the skill's workflow.

### Which LLM models are supported for binary-diff?

The skill defaults to **DeepSeek V3** for small functions under 200 lines. For larger functions, it automatically routes to **GPT-4o**, **Claude Sonnet**, or **Claude Opus**. You can see the exact model-selection logic in [`skills/binary-diff/SKILL.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/binary-diff/SKILL.md) at lines 58-66.

### How are the YAML results applied to the new binary?

The YAML is parsed with **PyYAML** and applied programmatically to the new IDB using IDAPython helpers. The skill references actions such as `idapro_rename` and `idapro_set_comments`, while practical scripts typically use standard APIs like `idc.set_name` and `idc.set_cmt` to rename call targets and add virtual-call comments.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →