mcpField
D
diffing-binary-patches

diffing-binary-patches

github.com/trilwu安全17746 次安装12 周前更新
代码仓库

关于 diffing-binary-patches

面向逆向工程师和漏洞分析人员的二进制补丁差异分析技能。它帮助比较修补前后的构建版本、定位逻辑变化,并追踪不可信输入是否能到达相关代码。

主要功能

  1. 01比较不同版本的二进制文件
  2. 02重建 Microsoft 补丁二进制文件
  3. 03定位变更函数
  4. 04解读差异中的安全检查
  5. 05追踪输入可达性
  6. 06以 Markdown 获取公开公告

适用场景

  1. 01分析厂商安全更新
  2. 02根据编译文件调查 CVE
  3. 03评估疑似未公开说明的修复
  4. 04查找通往变更代码的可达路径

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/trilwu/secskills --skill diffing-binary-patches

安装后在 Claude Code 中输入/diffing-binary-patches确认已加载。

详细介绍

二进制补丁差分分析

安全补丁是供应商用自己的代码写下的漏洞修复说明。对比修复前后的二进制文件,可以把只有一行的安全公告转化为具体函数、添加的具体检查,以及通过反向推理得出的漏洞触发前输入。1-day 分析的核心就在于此:修复告诉你该看哪里,差分告诉你改了什么,而修复前的可达路径告诉你如何触发。

适用场景

  • 对比同一二进制文件(DLL、ELF、驱动程序)的两个版本,找出安全更新改动了什么
  • 将 CVE 公告或 Patch Tuesday 公告定位到具体的易受攻击代码
  • 从 Microsoft 补丁(MSU/MSP/cab,采用增量压缩)中提取完整二进制文件,以便进行差分分析
  • 评估新版本中“未公开说明”的修复是否修复了安全漏洞

不适用场景

  • 分析单个二进制文件,没有对应的修补版本 — 请使用 analyzing-binaries。
  • 在已了解漏洞和触发方式后构建可用漏洞利用程序 — 原生代码漏洞请使用 exploiting-memory-corruption,Web 漏洞请使用相关技能。
  • 源码级差分(GitHub 提交、变更日志)— 使用 reviewing-code-changes 阅读源码;二进制差分适用于只有编译产物的情况。
  • 解包受保护的二进制文件,使其可以进行差分分析 — 请先使用 unpacking-protected-binaries。

获取两个可比较的二进制文件

差分质量取决于输入文件。你需要同一二进制文件的两个版本,架构相同,最好由同一编译器编译,这样噪声才足够少,安全改动才能显现出来。

对于 Microsoft 补丁,这本身就是一个步骤。从 Windows 10 开始,更新以正向/反向增量补丁的形式发布,而非完整文件 — MSU 中包含的是压缩增量,而不是最终 DLL。提取更新(展开 MSU/cab),并将增量应用到基线二进制文件,以重建完整的修补后文件(使用 PatchExtract / delta_patch.py 方法,调用 msdelta API)。对原始增量进行差分,或使用不匹配的基线,都会得到无用结果。对于大多数其他软件,两个发行版本或两个软件包版本可直接进行比较。

查找改动过的函数

运行二进制差分工具,并按相似度查看结果,而不是从头到尾逐项查看:

  • BinDiff(开源,通过 IDA 或 Ghidra 中的 BinExport 使用)可匹配两个二进制文件中的函数并评估相似度;值得关注的是只有轻微改动的函数 — 相似度略低于 1.0 的函数,而不是全新出现或已删除的函数。
  • Diaphora(IDA)也能完成同样的工作,使用强大的启发式方法,并提供出色的伪代码差分视图。这一点很重要,因为你需要阅读反编译器的输出才能理解改动。
  • ghidriff 提供基于 Ghidra、可脚本化的差分分析,适用于无界面运行或 CI 风格的任务。

要预料到噪声。编译器变更、函数重排或无关功能都会扩大差分范围;ASLR 和地址偏移不是真正的改动。筛选出逻辑发生变化的函数,忽略纯粹的地址变化。

阅读修复,找回漏洞

新增代码是关键线索。大多数安全修复都属于少数几种模式,每种模式都指向一种漏洞类别:

  • 新增边界或长度检查,位于复制或索引操作之前 → 修复前的代码在该路径上存在溢出或越界访问。
  • 有符号性或整数类型变更(将 int 改为 size_t、新增溢出检查)→ 整数漏洞影响了内存分配或复制操作。
  • 新增空值或状态检查 → 检查用于防止释放后使用、竞态条件或未初始化数据的使用。
  • 对解析输入中的字段、类型标记或长度进行验证 → 解析器信任了攻击者可控的数据。
  • 调整释放顺序 / 释放后将指针设为空 → 释放后使用或重复释放。

阅读修复后的函数,了解现在强制执行了什么,再阅读修复前的函数,确认当时缺少这些检查。这两个版本就是理解漏洞的关键。

追溯到触发条件

已更改的函数只是线索,不是结论;只有确认能够触达它,才能下结论。追踪攻击者控制的输入如何到达修补前的代码:哪个 API、消息、文件字段或数据包会进入未受保护的路径?在什么状态下会进入?如果无法构造从不可信输入到已更改代码的路径,那么这项更改可能只是加固,而非可触达的漏洞——应如实说明,不要夸大其词。确认路径确实存在后,这个可触达的触发条件便是漏洞利用开发的起点。

阅读外部来源

以 Markdown 格式获取公开公告、规范和供应商报告:

curl -sL "https://defuddle.md/<url>"      # scheme in the path is optional

这会剥离页面的冗余内容——对于以文字为主的页面,令令牌数减少约 78%——并返回全文而非摘要,方便你搜索,也让你可以相信未找到相关内容的结果。

以下三种情况不适用。获取 JSON 和 API 响应时应直接读取原始内容,因为可读性提取会破坏结构化数据。获取需要身份验证或通过 JavaScript 渲染的页面时,应直接访问,因为该工具会以匿名身份获取内容。切勿通过它访问对手基础设施(钓鱼链接、C2、恶意软件托管)、客户端所有的主机或参与测试的网址——请求会离开你的计算机并发送给第三方;如果访问的是活跃的对手基础设施,还会向其运营者发出警告。

有些网站会拦截提取器,并返回错误信息而非页面内容——例如 freedesktop.org 返回的 {"error":"Failed to fetch: 418 I'm a teapot"}。这表示获取请求被拒绝,并不表示来源称相关内容不存在。得出任何结论之前,请直接重新获取该 URL。

应当摒弃的牵强说法

  • “有 200 个函数发生了更改,这个补丁无法比较。” 大部分差异只是编译器和布局产生的噪声。按相似度排序,并筛选出逻辑变更;安全修复通常只涉及少数几个函数。
  • “我直接对比了 MSU,结果一团糟。” Windows 发布的是差异包,而非完整文件。比较之前,先根据差异包和基线版本重建完整的修补后二进制文件。
  • “函数变了,所以它就是漏洞所在。” 更改只是线索。如果无法从不可信输入找到通往修补前代码的可达路径,你看到的可能只是加固。声称存在漏洞前,先证明其可达性。
  • “公告说是 RCE,所以这就是 RCE。” 公告刻意使用模糊措辞。应根据新增的检查确认漏洞类别,而不是根据公告中的宣传用语。
  • “漏洞相同,所以旧的漏洞利用也能用。” 修复可能会改变相邻代码、偏移量和对象布局。针对你实际拥有的修补前构建版本,重新确认利用原语。

参考

  • analyzing-binaries — 单独理解任一二进制文件
  • exploiting-memory-corruption — 根据还原出的漏洞构建漏洞利用
  • reviewing-code-changes — 手头有源代码差异,而非二进制文件时使用
  • unpacking-protected-binaries — 比较之前必须先解包二进制文件时使用

评论

支持 Markdown