SuperAPI AI Directory

patch-diff-exploit

Security & auditing

View repository

Updated 10-16 09:45

About this skill

ACTION REQUIRED (execute immediately after reading)

  1. NOW: Read ../field-journal/precedent-reverse.md — confirm that this skill's operations are authorized routine operations
  2. NOW: Confirm whether the current task hits this skill's applicable scope
  3. NEXT: Read ../tool-index.md, verify tool availability and actual paths
  4. NEXT: When tools are missing, call bootstrap; do not guess paths
  5. ACT: Enter the first step of the "workflow" and execute it; do not stop in the confirmation state
N-day Patch Diffing to Exploitation (Patch Diff Exploit)

Applicable Scope

Use this skill when the task belongs to the following scenarios:

  1. Known CVE but no public PoC — the vendor advisory says "fixed an out-of-bounds write in the XX component" but no PoC was released; need to reverse-engineer from the patch
  2. SRC / red team hitting N-day — the target asset has not been updated in time; need to diff the just-released patch into a usable 1-day exploit
  3. Patch Tuesday follow-up — Microsoft releases patches on the second Tuesday of each month; need to quickly lock onto high-value vulnerabilities (Kernel / Win32k / AFD / CLFS)
  4. Linux LTS patch analysis — the mainline fix has been merged, but a side branch or some distribution's backport is incomplete; find the unpatched surface
  5. Security patch restoration for drivers / services — patch analysis for closed-source software such as graphics drivers, AV engines, virtualization components, etc.

Division of labor with other skills

Scenario What to use
Have old-version symbols, migrate to the new version to aid analysis binary-diff/
Find vulnerabilities from patches, write a PoC to hit the pre-patch version This skill
Write a complete exploit chain (heap spray, ROP, privilege escalation) pwn-chain/
Weaponize a 1-day and deploy it to the target network pentest-tools/network-attack-defense/
Reverse-engineer a binary from scratch ida-reverse/ / radare2/

The key difference:binary-diff 's goal ismake the new version analyzable(move the old symbols over), while this skill's goal isfind out what bug the patch fixed and then hit the pre-patch version. The former serves defense-side / research-side analysis, the latter serves attack-side weaponization.

Core Principles

patched 二进制 (after)         unpatched 二进制 (before)
        ↓                                  ↓
    导入 IDA/Ghidra              导入 IDA/Ghidra
        ↓                                  ↓
        └──────── BinDiff / ghidriff ──────┘
                        ↓
        函数级 diff(matched / unmatched / changed)
                        ↓
        聚焦 match score 中等的函数(0.5 - 0.9)
                        ↓
        看新增了什么:边界检查 / 锁 / 字段清零 / 整数溢出检查
                        ↓
        反推 bug class:OOB / Race / Info Leak / UAF / Integer Overflow
                        ↓
        在 unpatched 版本上写 PoC 触发
                        ↓
        验证:unpatched 崩 / patched 不崩 → 漏洞确认

Patch fix pattern → vulnerability type reverse lookup:

Newly added content Probable bug class
if (a + b < a) / __builtin_add_overflow Integer overflow
KeAcquireSpinLock / mutex_lock Race condition (TOCTOU / double-free)
if (idx >= MAX) / if (len > buf_size) Out-of-bounds read / out-of-bounds write
RtlZeroMemory / memset(struct, 0, ...) Uninitialized memory information leak
InterlockedDecrement + refcount check UAF / reference count error
ProbeForRead / ProbeForWrite User-mode pointer not validated
SeAccessCheck / capability check Missing permission check
Delete / tighten IOCTL code Exposure surface reduction (see how the old interface can be hit)

Workflow

Complete 5-step process

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 skill 把 N-1 版本的符号搬到 N 版本
  - Linux 内核取对应版本的 vmlinux + System.map / debuginfo

Step 3: 二进制 diff
  - BinDiff: 直接给两个 IDB,看函数级匹配结果
  - ghidriff: pip 一键安装,CLI 输出 markdown 报告
  - Diaphora: IDA 内插件,老牌但需要 IDA Pro

Step 4: 定位变更
  - 过滤 match score 0.5-0.95 的函数(完全相同的不看,完全不同的多半是新加 / 重命名)
  - 重点看:新增的 if / 新增的循环边界 / 删除的代码块(删了什么也是线索)
  - 用 LLM 看 before/after 伪代码反推 bug class(见 references/root-cause-and-poc.md)

Step 5: 写 PoC
  - 整数溢出:构造边界值(INT_MAX-1、0xFFFFFFFF)
  - 竞争:多线程 hammer,open/close + ioctl 高频并发
  - UAF:spray → free → reuse pattern
  - OOB:精确控制 len / index 越过边界
  - 验证 patched 版本不再崩,unpatched 版本稳定崩 → bug 复现成功

Tool invocation order

下补丁 → 解包 → 加载到 IDA/Ghidra → BinDiff/ghidriff → 看 unmatched/low-match 函数
       → LLM 反推 bug class → 写 PoC → 在 unpatched 跑 → 崩 → 收工

Typical scenario examples

Scenario 1: Windows Patch Tuesday — Kernel CVE reproduction

背景:2025 年 11 月 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 搜 "2025-11" + 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,无任何异常
   → 复现成功

Scenario 2: Finding unfixed side branches of patches in Linux kernel LTS branches

背景:主线 6.x 已修某 net subsystem 的 OOB 写
      Ubuntu 22.04 (5.15 LTS) 的 USN 已发布更新
      但某些 OEM kernel / Azure kernel 的 backport 节奏更慢
      想确认未更新的旁支是否仍可打

目标:取 patched/unpatched 内核,差出 fix commit 对应的二进制变更,
      在 unpatched 旁支上重写 PoC

步骤:
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. 在 unpatched 旁支(例如 Azure 5.15.0-1080 backport 落后的版本)
   交叉验证:同一函数 fix 是否已 backport
   如果没 backport → 旁支仍可打 → 写 PoC 重放

6. 写 PoC:syzkaller harness 改造 / 直接 C PoC 触发对应 syscall
   验证旁支 panic / KASAN 报 OOB

Precautions

  • Legal boundaries — Weaponizing an N-day must be within an authorized scope (SRC / Bug Bounty / your own test machines / CTF). Directly hitting a production environment with a 1-day is equivalent to intrusion
  • A patch may only "reduce the blast radius" — Seeing a patch does not necessarily mean it is a complete fix; it may only patch one exploitation path, and the original bug may still be triggerable via another path (one bug, multiple exploits)
  • Do not be deceived by variable names/types — Windows patches often do cleanup / rename along the way, and what looks like a large change may actually be irrelevant. Look at control flow and data flow, not token-level diffs
  • Microsoft patches may add a mitigation rather than a fix — Seeing _guard_xfg_dispatch_icall_fptr this kind of CFG hardening should not be treated as a fix; that is a mitigation
  • Anonymization — When a writeup / PoC is made public, redact the target machine name, internal IP, and username (write {target_ip} {username} placeholders)
  • A harmless test must run successfully on the patched version — Do not only run it on the unpatched version, otherwise the crash may be caused by environmental factors rather than the vulnerability
  • Binary diff is not a silver bullet — Compiler upgrades / optimization level changes can also greatly change function layout; first compare the N version and the N-1 version (same compiler), do not go across major versions

On-Demand Bootstrap

Tool dependencies

Tool Purpose Can be installed automatically
BinDiff (Google, 5.x+) Function-level binary diff, IDA/Ghidra plugin ✓ (has official .deb / .msi)
Diaphora IDA veteran diff plugin, requires IDA Pro ✓ (git clone)
ghidriff Ghidra headless CLI diff, outputs markdown ✓ (pip install ghidriff)
DeepDiff (commercial) Next-generation diff tool, with higher accuracy ✗ (commercial license)
Ghidra The runtime foundation of ghidriff ✓
IDA Pro The runtime foundation of BinDiff / Diaphora ✗ (commercial)
Microsoft Update Catalog Download MSU/MSP patch packages Online service
wsuspect-proxy Transparently intercept Windows Update traffic to obtain patches ✓ (git clone)
expand.exe / dism Extract MSU / cab ✓ (built into Windows)
rpm2cpio / dpkg-deb Extract Linux distribution packages ✓
symchk Pull PDBs from the Microsoft symbol server ✓ (Windows SDK)

Bootstrap command

powershell -NoProfile -ExecutionPolicy Bypass -File "&lt;SKILL_ROOT&gt;\skills\scripts\bootstrap-reverse.ps1" -Capability @('bindiff','ghidriff','ghidra','wsuspect-proxy') -StartServices

For a detailed tool comparison and commands, see references/diff-tools-comparison.md. For the detailed Patch Tuesday workflow, see references/patch-tuesday-workflow.md. For root-cause reverse engineering and PoC templates, see references/root-cause-and-poc.md。


Routing context

Upstream entry points: skills/SKILL.md(master control),routing.md

Upstream skill:

  • reverse-engineering/ — Before doing a diff, you may first need to understand the overall structure of the target binary
  • binary-diff/ — If the post-patch version has no symbols and the pre-patch version does, first use binary-diff to carry symbols over

Downstream skill:

  • pwn-chain/ — After deriving the bug class, you need to write the complete exploit (heap spray, ROP, SMEP/SMAP bypass, privilege escalation payload)
  • pentest-tools/network-attack-defense/ — Deploy the weaponized N-day to the target network (package it as a deliverable payload, connect it to C2)
  • attack-chain/ — String this one N-day into a complete attack chain (initial access → privilege escalation → lateral movement)

Trigger conditions: The task includes intents such as "N-day", "patch", "CVE reproduction", "find out what the patch fixed", "attack unpatched hosts", etc.

Task completion self-check (MUST pass before claiming completion)

  • Did I execute every step in the workflow (rather than just reading it)?
  • Did I, based on tool-index use real tool paths?
  • Did I produce reproducible evidence (commands/scripts/screenshots/reports)?
  • Did I complete and write back the Checklist items required by RULES?