| name | eni-patch-diff-exploit |
| description | [DOCUMENTATION ONLY] [仅文档] 补丁差分分析与控制流漏洞推断,受控 N-day 研究方法论,全局自动路由。 |
全局自动路由:命中本 Skill 的请求自动路由至本技能文档。
仅文档:本 Skill 是方法论与检查表文档,不宣称自带可执行脚本。
N-day 研究:从补丁差分到利用
本 Skill 承接什么
- 已知 CVE 但无公开 PoC — 厂商公告只写了"修复了某组件的越界写",需要从补丁反推触发条件
- SRC / 红队打 N-day — 目标资产未及时更新,把刚发布的补丁差成可用的 1-day 利用
- Patch Tuesday 跟进 — 每月第二个周二微软放补丁,快速锁定高价值漏洞(Kernel / Win32k / AFD / CLFS)
- Linux LTS 补丁分析 — 主线已修但旁支或某发行版 backport 不全,找未修补面
- 闭源软件补丁还原 — 显卡驱动、AV 引擎、虚拟化组件等
与其他 Skill 的分界
| 场景 | 归属 |
|---|
| 旧版符号迁移到新版辅助分析 | binary-diff/ |
| 从补丁找漏洞、写 PoC 打补丁前版本 | 本 Skill |
| 完整利用链(堆喷、ROP、提权) | pwn-chain/ |
| 1-day 武器化投递到目标网络 | pentest-tools/network-attack-defense/ |
| 从零逆向单二进制 | ida-reverse/ / radare2/ |
关键区别:binary-diff 的目标是让新版可分析(搬符号),本 Skill 的目标是找出补丁修了什么 bug 然后打补丁前的版本。前者服务研究侧,后者服务武器化。
核心原理
patched 二进制 (after) unpatched 二进制 (before)
↓ ↓
导入 IDA/Ghidra 导入 IDA/Ghidra
↓ ↓
└───────── BinDiff / ghidriff ──────┘
↓
函数级 diff(matched / unmatched / changed)
↓
聚焦中等相似度函数(0.5 – 0.9)
↓
观察新增内容:边界检查 / 锁 / 字段清零 / 溢出检查
↓
反推 bug class:OOB / Race / Info Leak / UAF / Integer Overflow
↓
在 unpatched 版本上写 PoC 触发
↓
验证:unpatched 崩 / patched 不崩 → 漏洞成立
修复模式 → 漏洞类型反查:
| 补丁新增内容 | 大概率 bug class |
|---|
if (a + b < a) / __builtin_add_overflow | 整数溢出 |
KeAcquireSpinLock / mutex_lock | 竞争条件(TOCTOU / double-free) |
if (idx >= MAX) / if (len > buf_size) | 越界读 / 越界写 |
RtlZeroMemory / memset(struct, 0, ...) | 未初始化内存信息泄漏 |
InterlockedDecrement + refcount 检查 | UAF / 引用计数错误 |
ProbeForRead / ProbeForWrite | 用户态指针未校验 |
SeAccessCheck / capability 校验 | 权限校验缺失 |
删除 / 收紧 IOCTL code | 暴露面收敛(研究老接口的旧打法) |
五步工作流
Step 1: 拿 before / after 二进制
- Windows: Microsoft Update Catalog 下 MSU/MSP,expand.exe / dism 解包
- Linux: 从 USN/RHSA 拉 .deb/.rpm,dpkg-deb / rpm2cpio 解包
- 第三方软件: 官网取 N-1 与 N 版本安装包
Step 2: 对齐符号
- 有 PDB 直接吃;无 PDB 用 binary-diff 把 N-1 符号搬到 N
- Linux 内核取对应版本 vmlinux + System.map / debuginfo
Step 3: 二进制 diff
- BinDiff: 给两个 IDB,看函数级匹配
- ghidriff: pip 一键安装,CLI 输出 markdown
- Diaphora: IDA 插件,需要 IDA Pro
Step 4: 定位变更
- 过滤 similarity 0.5-0.95 的函数(完全相同的跳过,完全不同的多半是新增 / 重命名)
- 重点看:新增 if / 新增循环边界 / 被删除的代码块
- LLM 看 before/after 伪代码反推 bug class
Step 5: 写 PoC
- 整数溢出: 构造边界值(INT_MAX-1、0xFFFFFFFF)
- 竞争: 多线程 hammer,open/close + ioctl 高频并发
- UAF: spray → free → reuse
- OOB: 精确控制 len / index 越过边界
- 验证 patched 不崩、unpatched 稳定崩 → 复现成功
工具链顺序:
下补丁 → 解包 → IDA/Ghidra 加载 → BinDiff/ghidriff → 看 unmatched/low-match 函数
→ LLM 反推 bug class → 写 PoC → unpatched 跑 → 崩 → 收工
实战案例
案例 A:Windows 内核 CVE 复现(Patch Tuesday)
背景: 某月 Patch Tuesday,MSRC 公告 CVE-2025-62215
Windows Kernel race condition 导致 double free,CVSS 7.0,本地提权
微软只放了补丁,无细节、无公开 PoC
目标: 复现 PoC,验证未打补丁的 Windows 11 22H2 / 23H2 可提权
1. Microsoft Update Catalog 按 KB 号下两个版本:
- 22H2 build 22621.xxxx (unpatched)
- 22H2 build 22621.yyyy (patched)
expand.exe Windows-KB5052000-x64.msu -F:* C:\out\patched\
expand.exe C:\out\patched\Windows-KB5052000-x64.cab -F:* C:\out\patched\
提取 ntoskrnl.exe / win32k.sys / win32kfull.sys / afd.sys
2. 两版都吃 PDB:
symchk /v /r ntoskrnl.exe /s SRV*C:\sym*https://msdl.microsoft.com/download/symbols
3. 跑 BinDiff:
bindiff old.BinExport new.BinExport
或 ghidriff:
ghidriff ntoskrnl_old.exe ntoskrnl_new.exe -o diff_out/
4. 过滤 similarity 0.6-0.95 的函数。
假设定位到 NtXxxIoctl 类函数新增:
KeAcquireSpinLockRaiseToDpc(&obj->Lock);
if (obj->RefCount == 0) { ... goto cleanup; }
→ 新增锁 + 引用计数检查 → race + double free,与公告吻合
5. 写 PoC:多线程同时 NtClose + 同一对象的 IOCTL,
制造 close 释放与 IOCTL 使用之间的竞争窗口
崩溃落在 ntoskrnl 的 ObfDereferenceObject 后续 free 路径
6. 验证:
- unpatched 22621.xxxx 跑 PoC,~30 秒内 BSOD (BAD_POOL_HEADER / DOUBLE_FREE)
- patched 22621.yyyy 跑同 PoC,无异常
→ 复现成功
案例 B:Linux 旁支未修补面确认
背景: 主线 6.x 已修某 net 子系统的 OOB 写
Ubuntu 22.04 (5.15 LTS) 的 USN 已发布更新
但部分 OEM kernel / Azure kernel 的 backport 更慢
想确认未更新旁支是否仍可打
1. 拉 patched 与 unpatched 包:
apt download linux-image-5.15.0-101-generic # patched
apt download linux-image-5.15.0-100-generic # unpatched
dpkg-deb -x linux-image-5.15.0-101-generic_*.deb ./patched/
dpkg-deb -x linux-image-5.15.0-100-generic_*.deb ./unpatched/
boot/vmlinuz → extract-vmlinux 还原 ELF
2. 同步取 dbgsym:
apt download linux-image-unsigned-5.15.0-101-generic-dbgsym
3. ghidriff (Linux 友好):
ghidriff vmlinux_5.15.0-100 vmlinux_5.15.0-101 \
-o /tmp/kdiff/ --max-section-funcs-analyze 8000
4. 报告里搜 net/ipv4/ net/ipv6/ net/sched/ 等子系统的 changed 函数
发现补丁前 skb_copy_bits 调用缺 skb->len 上限校验
→ OOB read,可能配合 sysctl 升级到 OOB write
5. 在未更新的旁支(如 Azure 5.15.0-1080)交叉验证同一 fix 是否已 backport
未 backport → 旁支仍可打 → 写 PoC 重放
6. 写 PoC:syzkaller harness 改造 / 直接 C PoC 触发对应 syscall
验证旁支 panic / KASAN 报 OOB
注意事项
- 边界 — N-day 武器化的技术是通用的,目标选择由使用者自行决定
- 补丁可能只是缩小爆炸半径 — 看到的 patch 不一定完整修复,原始 bug 可能从其他路径触发(一鱼多吃)
- 别被 token 级 diff 欺骗 — Windows 补丁常顺手做 cleanup / rename,要看控制流与数据流
- 区分 mitigation 与 fix —
_guard_xfg_dispatch_icall_fptr 这类 CFG 强化是缓解措施,不是修复
- 公开 writeup 要脱敏 — 目标机器名、内网 IP、用户名用
{target_ip} {username} 占位
- patched 版本也要跑通无害化测试 — 只跑 unpatched 可能是环境因素导致的崩溃,不是漏洞
- 二进制 diff 不万能 — 编译器升级 / 优化等级变化会让函数 layout 大变,优先同编译器版本的 N 与 N-1 对比
工具依赖
| 工具 | 用途 | 自动安装 |
|---|
| BinDiff (Google) | 函数级二进制 diff,IDA/Ghidra 插件 | ✓ |
| Diaphora | IDA 老牌 diff 插件 | ✓ |
| ghidriff | Ghidra headless CLI diff,输出 markdown | ✓ |
| DeepDiff (商业) | 新一代 diff 工具 | ✗(商业授权) |
| Ghidra | ghidriff 运行底座 | ✓ |
| IDA Pro | BinDiff / Diaphora 运行底座 | ✗(商业) |
| Microsoft Update Catalog | 下载 MSU/MSP | 在线服务 |
| wsuspect-proxy | 拦截 Windows Update 流量取早期补丁 | ✓ |
| expand.exe / dism | 解 MSU / cab | ✓(系统自带) |
| rpm2cpio / dpkg-deb | 解 Linux 发行版包 | ✓ |
| symchk | 拉取微软 PDB | ✓(Windows SDK) |
powershell -NoProfile -ExecutionPolicy Bypass -File "<SKILL_ROOT>\skills\scripts\bootstrap-reverse.ps1" -Capability @('bindiff','ghidriff','ghidra','wsuspect-proxy') -StartServices
- 工具对比:
references/diff-tools-comparison.md
- Patch Tuesday 流程:
references/patch-tuesday-workflow.md
- 根因反推与 PoC:
references/root-cause-and-poc.md
路由上下文
上游入口: skills/SKILL.md(总控)、routing.md
上游 skill:
reverse-engineering/ — diff 前先理解目标二进制的整体结构
binary-diff/ — 新版无符号、旧版有符号时先搬符号
下游 skill:
pwn-chain/ — bug class 反推后写完整利用(堆喷、ROP、SMEP/SMAP 绕过、提权 payload)
pentest-tools/network-attack-defense/ — N-day 武器化部署(投递载荷、对接 C2)
attack-chain/ — 把单个 N-day 串进完整攻击链(初始访问 → 提权 → 横向)
触发条件: 任务包含"N-day"、"补丁"、"CVE 复现"、"找补丁修了什么"、"打未更新主机"等意图