AAS 跨版本二进制符号迁移实战:binary-diff 技能如何用 LLM 批量恢复无 PDB 新版的函数符号
AI 技能AI 插件【免费下载链接】agentic-awesome-skillsAAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,445 agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.项目地址https://gitcode.com/gh_mirrors/an/agentic-awesome-skills点击查看免费下载导读当程序发布新版本、微软下架 PDB、或保护机制更新导致旧版逆向成果全部失效时binary-diff技能位于 plugins/agentic-awesome-skills-claude/skills/binary-diff/SKILL.md提供了一条旧版有符号 新版无符号的低成本迁移路径用固定 Prompt 模板把新旧两个版本同一函数的反汇编与伪代码交给 LLM 做结构化比对程序化解析返回的 YAML 符号映射表再批量应用到新版 IDB。读完本文你将掌握该技能的完整工作原理、可直接复制的 Prompt 模板与 5 种 YAML 符号输出格式、从锚点选择到迭代深入的五步工作流以及结合 ida-reverse 的idapro_rename/idapro_set_comments等工具落地符号的完整方案。一、这个技能解决什么问题binary-diff面向的是逆向工程中一个非常高频的痛点同一程序跨版本升级后旧版积累的符号与注释无法自动带进新版。其 frontmatter 中的描述将其定位为 Cross-version binary symbol migration: diff updated binaries, recover function names without PDBs, and propagate annotations after software updates在 data/catalog.json 的binary-diff条目中被标记为risk: safe、source_type: community标签为binary、diff。适用场景在文档中被归纳为四类内核/驱动缺 PDB—— 有旧版ntoskrnl.exe的符号新版 PDB 被微软下架需要用旧版符号推导新版非导出函数地址程序更新后符号迁移—— 曾经逆向过某个程序程序更新后不想重新逆一遍用旧版结果批量迁移保护机制更新—— 旧版有完整逆向结果新版需要快速定位同一函数的新偏移任何有旧版符号 新版无符号的二进制对比场景。与其他技能的分工场景用什么从零开始逆向一个二进制ida-reverse/或radare2/有旧版结果迁移到新版本技能两个完全不同的二进制对比BinDiff / Diaphora传统工具从仓库看与binary-diff同级且直接协作的模块是 ida-reverse数据导出和符号应用都通过 IDA而data/catalog.json中还登记了攻击侧的互补技能patch-diff-exploitLocate vulnerability fixes in vendor patches, diff binaries across versions, and build N-day PoCs标记为risk: offensive说明本技能定位在防御/分析侧的符号恢复而非漏洞利用。相比传统方案的成本优势文档给出了一个非常直观的对比以 200 个函数为例方案200 个函数成本时间准确率人工开两个 IDA 窗口对比免费但耗命数小时高BinDiff 自动匹配免费快中结构变化大时失效完全交给 AgentCC/Codex50-100 元慢高本技能LLM 批量比对~1 元~10 秒/函数高注意以上成本、耗时与准确率数据均来自原文档作者给出的经验估算属于方法论层面的参考实际效果会因模型、函数复杂度与反编译质量而异使用时宜以自身实测为准。二、核心原理LLM 只做看两段代码找对应关系这一件事整个技能的设计哲学是把 LLM 的职责压缩到最小其余全部程序化旧版函数有符号 新版同一函数无符号 ↓ ↓ 导出反汇编 伪代码 导出反汇编 伪代码 ↓ ↓ └──────── LLM 结构化比对 ────────┘ ↓ 输出 YAML符号映射表 ↓ 程序化解析 → 批量应用到新版 IDB三个关键点Prompt 是固定模板程序化填充—— 不依赖每次重新构思 prompt保证输出稳定性输入输出格式确定程序化解析—— LLM 只被允许输出纯 YAML脚本直接yaml.safe_loadLLM 唯一职责是看两段代码找出对应关系因此时间成本和 token 成本极低可大规模并发。这也是它与 BinDiff 的本质差异BinDiff 靠图同构等算法做结构匹配遇到重编译导致的结构变化容易失效而binary-diff让 LLM 结合语义理解去匹配对结构变了但逻辑没变的函数有更好的容错性。三、Prompt 模板可直接复制的标准比对 Prompt以下是技能文档与 references/prompt-template.md 中给出的标准模板占位符由程序填充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.Example: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 [rax68h] # 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, [rax80h] # 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, [r1458h] # 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.模板中值得注意的两条硬约束 - **末行约束**If nothing found, output an empty YAML. DO NOT output anything other than the desired YAML. DO NOT collect unrelated symbols. —— 既约束了输出纯净性便于程序化解析也约束了 LLM 不要发散收集无关符号 - **found_vcall 与 found_struct_offset 的边界**模板中特别注明虚函数指针永远归入 found_vcall不得混入 found_struct_offset这是保证后续应用动作正确性的关键设计。 ### 变量说明 | 变量 | 来源 | 说明 | |------|------|------| | {disasm_for_reference} | 旧版 IDA 导出 | 有符号的反汇编 | | {procedure_for_reference} | 旧版 IDA 导出 | 有符号的伪代码 | | {disasm_code} | 新版 IDA 导出 | 无符号的反汇编 | | {procedure} | 新版 IDA 导出 | 无符号的伪代码 | | {symbol_name_list} | 从旧版提取 | 需要在新版中定位的符号列表 | 在 [references/prompt-template.md](https://link.gitcode.com/i/c40078c9e29901db9827a40a5d0a5efd) 中变量获取方式被进一步对应到具体 IDA MCP 工具{disasm_for_reference} 通过 idapro_disasm(addr函数名) 取得{procedure_for_reference} 通过 idapro_decompile(addr函数名) 取得新版同理{symbol_name_list} 则是从 reference 代码中提取所有非 sub_/loc_ 的符号名。 --- ## 四、输出格式YAML 中的 5 种符号类型与应用动作 ### 5 种符号类型 | 类型 | 含义 | 关键字段 | |------|------|---------| | found_vcall | 虚函数调用间接 call | vfunc_offset, func_name | | found_call | 直接函数调用 | insn_va, func_name | | found_funcptr | 函数指针引用 | insn_va, funcptr_name | | found_gv | 全局变量引用 | insn_va, gv_name | | found_struct_offset | 结构体偏移引用 | offset, struct_name, member_name | ### 解析后的应用动作 text found_call → idapro_rename(addrcall_target, namefunc_name) found_vcall → idapro_set_comments(addrinsn_va, commentvcall: {func_name} {offset}) found_funcptr → idapro_rename(addrfuncptr_target, namefuncptr_name) found_gv → idapro_rename(addrgv_addr, namegv_name) found_struct_offset → idapro_set_comments(addrinsn_va, comment{struct_name}.{member_name})这套应用动作与 ida-reverse/SKILL.md 中登记的工具能力一一对应idapro_rename(batch)支持批量重命名函数/全局/局部/栈变量idapro_set_comments(items)支持添加注释反汇编反编译双向同步。也就是说binary-diff的 YAML 结果可以直接落入 IDA MCP 的修改操作工具形成解析 → 应用的闭环而不需要手工在 IDA GUI 里逐个改名。五、五步工作流从准备数据到迭代深入完整流程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: 迭代 - 第一轮迁移的函数成为新的锚点 - 进入这些函数继续对比内部调用 - 重复直到覆盖所有目标函数Step 5 是这套方法论能滚雪球的关键每一轮被成功迁移命名的函数都会变成下一轮比对的锚点从而逐步把整个符号图从旧版搬到新版。锚点选择策略锚点类型可靠性说明导出函数最高名字不变地址可能变字符串引用高字符串内容不变引用位置可能变常量/魔数中特征值不变代码模式中函数结构相似但地址全变锚点的可靠性直接决定整个迁移的成败 —— 原文档在注意事项中特别强调锚点必须可靠如果锚点本身就对错了后续全部白费。批量处理建议每次比对1 个函数避免 context 爆炸中等函数200 行用 DeepSeek超大函数500 行切 GPT-4o 或 Claude并发调用提高速度10-20 并发结果缓存避免重复调用。六、两个典型场景场景 1ntoskrnl.exe 缺 PDB已有ntoskrnl.exe 10.0.26100.2000 完整 PDB 目标ntoskrnl.exe 10.0.26100.2605PDB 被下架 需求定位 PspSetCreateProcessNotifyRoutine 的新地址 步骤 1. 两个版本都加载到 IDA 2. 找到导出函数 PsSetCreateProcessNotifyRoutine两个版本都有 3. 旧版中它调用了 PspSetCreateProcessNotifyRoutine有符号 4. 新版中它调用了 sub_140822108无符号 5. LLM 一眼看出sub_140822108 PspSetCreateProcessNotifyRoutine 6. 批量应用这个场景完美诠释了导出函数锚点 → 函数内部调用关系比对的核心循环PsSetCreateProcessNotifyRoutine是导出的名字不变它内部调用的PspSetCreateProcessNotifyRoutine是非导出的新版只剩sub_140822108LLM 通过比对两端反汇编与伪代码确认二者是同一个函数。场景 2应用更新后迁移已有target.exe v1.0 的完整逆向结果200 函数已命名 目标target.exe v1.1所有符号丢失 需求批量迁移 200 个函数名 步骤 1. 从旧版导出所有已命名函数的反汇编伪代码 2. 在新版中通过导出函数/字符串找到对应锚点 3. 批量调用 LLM 比对 4. 解析 YAML批量 rename 5. 迭代深入七、批量调用脚本骨架与 API 配置references/prompt-template.md 提供了可直接落地的 Python 脚本骨架核心是两个函数migrate_function构造 Prompt → 调 LLM → 抽取 YAML 块 → 解析与apply_results把解析结果转成 renames / comments 两类操作。import yaml import httpx import json from pathlib import Path PROMPT_TEMPLATE open(prompt-template.txt).read() def migrate_function(ref_disasm, ref_procedure, target_disasm, target_procedure, symbols, api_url, api_key, modeldeepseek-chat): prompt PROMPT_TEMPLATE.format( disasm_for_referenceref_disasm, procedure_for_referenceref_procedure, disasm_codetarget_disasm, proceduretarget_procedure, symbol_name_list, .join(symbols) ) resp httpx.post(api_url, json{ model: model, messages: [{role: user, content: prompt}], temperature: 0 }, headers{Authorization: fBearer {api_key}}, timeout60) content resp.json()[choices][0][message][content] # 提取 YAML 块 if yaml in content: yaml_str content.split(yaml)[1].split()[0] elif in content: yaml_str content.split()[1].split()[0] else: yaml_str content return yaml.safe_load(yaml_str) def apply_results(results, ida_session): 将解析后的 YAML 结果应用到 IDA if not results: return renames [] comments [] if found_call in results: for item in results[found_call]: # 从 insn_disasm 中提取 call target # call sub_XXXXXXX → 提取 sub_XXXXXXX 的地址 renames.append({addr: item[insn_va], name: item[func_name], type: call_target}) if found_funcptr in results: for item in results[found_funcptr]: renames.append({addr: item[insn_va], name: item[funcptr_name], type: funcptr_target}) if found_gv in results: for item in results[found_gv]: renames.append({addr: item[insn_va], name: item[gv_name], type: gv}) if found_vcall in results: for item in results[found_vcall]: comments.append({ addr: item[insn_va], comment: fvcall: {item[func_name]} {item[vfunc_offset]} }) if found_struct_offset in results: for item in results[found_struct_offset]: comments.append({ addr: item[insn_va], comment: f{item[struct_name]}.{item[member_name]} {item[offset]} }) return {renames: renames, comments: comments}脚本中的几个工程细节值得注意temperature: 0保证比对输出的确定性YAML 块抽取逻辑兼容了带yaml 围栏带普通围栏裸 YAML三种 LLM 返回形式提高了解析健壮性apply_results把结果归一化为renames与comments两个列表与 ida-reverse 中idapro_rename(batch)与idapro_set_comments(items)的入参结构保持一致。API 配置建议# 默认用 DeepSeek便宜 default: api_url: https://api.deepseek.com/v1/chat/completions model: deepseek-chat # 超大函数回退到 GPT fallback: api_url: https://api.openai.com/v1/chat/completions model: gpt-4o # 或者用 Claude alternative: api_url: https://api.anthropic.com/v1/messages model: claude-sonnet-4-20250514注意以上 API endpoint 与模型名取自仓库中技能文档给出的配置示例实际使用前请确认对应服务商的最新接口与模型可用性并妥善管理 API key。八、LLM 选择策略模型适合场景成本速度DeepSeek V3中小函数200 行批量处理极低快GPT-4o超大函数复杂控制流中快Claude Sonnet中大函数需要推理中快Claude Opus极复杂函数需要深度理解高慢推荐策略默认 DeepSeek遇到 context 超限或结果不准时自动升级。这套分档升级策略让绝大多数中小函数的批量比对成本保持在极低水平只有极少数超大/极复杂函数才动用高端模型。九、注意事项与任务完成自检注意事项实战红线不要把整个二进制丢给 LLM—— 一次只比对一个函数锚点必须可靠—— 锚点对错后续全部白费结果需要人工抽检—— LLM 不是 100% 准确关键符号要验证缓存中间结果—— 避免重复调用浪费 token注意 context 限制—— 超大函数1000 行反汇编需要拆分或用大 context 模型。工具依赖与按需自举工具用途可自动安装IDA Pro导出反汇编/伪代码✗商业软件Python脚本执行、API 调用✓PyYAML解析 LLM 返回的 YAML✓pip install pyyamlLLM API执行比对需要 API key核心不依赖重型工具安装主要依赖已有的 IDA Pro由ida-reverse技能管理、Python requests/httpx 调 API、以及一个 LLM API endpoint。路由上下文上游入口skills/SKILL.md总控、routing.md触发条件有旧版符号/逆向结果需要迁移到新版本下游出口需要先打开二进制 →ida-reverse/需要快速侦察确认版本差异 →radare2/同级关联模块ida-reverse/数据导出和符号应用都通过 IDA。任务完成自检声称完成前 MUST 通过我是否执行了工作流中的每一步而不是只阅读我是否基于tool-index使用了真实工具路径我是否产出了可复现证据命令/脚本/截图/报告我是否完成并回写了 RULES 要求的 Checklist 项十、局限性与适用边界原文档同时坦诚地列出了本技能的局限性Diff quality degrades with heavy recompilation or obfuscation between versions—— 若两个版本之间发生了大规模重编译或混淆处理比对质量会显著下降Requires local diff tooling (e.g., BinDiff, Diaphora, radiff2)—— 技能仍然依赖本地差异分析工具作为基础设施例如用于锚点确认与交叉验证。因此本技能适合改动可控、逻辑延续的常规版本升级场景而不适合结构被彻底改写或刻意混淆的目标此时需要回到 ida-reverse 重新建立分析基础。参考资源技能本体plugins/agentic-awesome-skills-claude/skills/binary-diff/SKILL.mdPrompt 模板与批量脚本plugins/agentic-awesome-skills-claude/skills/binary-diff/references/prompt-template.md配套逆向技能数据导出与符号应用plugins/agentic-awesome-skills-claude/skills/ida-reverse/SKILL.md技能登记信息data/catalog.jsonbinary-diff条目本技能改编自 zhaoxuya520/reverse-skill 开源项目遵循 MIT 许可。赞分享AI 技能AI 插件【免费下载链接】agentic-awesome-skillsAAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,445 agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.项目地址https://gitcode.com/gh_mirrors/an/agentic-awesome-skills点击查看免费下载相关推荐RetDec符号恢复从无符号二进制中重建函数名RetDec符号恢复从无符号二进制中重建函数名 引言无符号二进制的调试困境 在逆向工程和软件分析过程中我们经常会遇到没有符号信息的二进制文件。这些文件缺乏逆向工程静态分析pyo3-ffi 跨版本符号链接修复解析PyUnstable_Eval_RequestCodeExtraIndex 在 Python 3.12 前的私有符号兼容pyo3 ffi 跨版本符号链接修复解析PyUnstable_Eval_RequestCodeExtraIndex 在 Python 3.12 前的私有符号兼开发工具CardView性能优化解决Xamarin.Forms列表滑动卡顿问题CardView性能优化解决Xamarin.Forms列表滑动卡顿问题 CardView是Xamarin.Forms中一款功能强大的卡片视图控件支持Card创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考