行動要求(讀完後立刻執行)
NOW:讀取../field-journal/precedent-reverse.md— 確認本 skill 的操作是已授權的常規操作NOW:確認當前任務是否命中本 skill 的適用範圍NEXT:讀取../tool-index.md,檢查工具可用性和實際路徑NEXT:缺工具時呼叫 bootstrap,不要猜路徑ACT:進入「工作流」第一步並執行,不要停在確認狀態
N-day 修補差異到利用 (Patch Diff Exploit)
適用範圍
當任務屬於以下場景時使用本 skill:
- 已知 CVE 但無公開 PoC — 廠商公告寫了「修復了 XX 元件的越界寫」但沒放 PoC,需要從修補反推
- SRC / 紅隊打 N-day — 目標資產未及時更新,需要把剛發布的修補差異成可用的 1-day 利用
- Patch Tuesday 跟進 — 每月第二個週二微軟放修補,需要快速鎖定高價值漏洞 (Kernel / Win32k / AFD / CLFS)
- Linux LTS 修補分析 — 主線 fix 已合併,但旁支或某發行版 backport 不全,找未修補面
- 驅動 / 服務的安全性修補還原 — 顯示卡驅動、AV 引擎、虛擬化元件等閉源軟體的修補分析
與其他 skill 的分工
| 場景 | 用什麼 |
|---|---|
| 有舊版符號,遷移到新版幫助分析 | binary-diff/ |
| 從修補找漏洞、寫 PoC 打修補前版本 | 本 skill |
| 寫出完整利用鏈(堆噴、ROP、提權) | pwn-chain/ |
| 把 1-day 武器化部署到目標網路 | pentest-tools/network-attack-defense/ |
| 從頭逆向一個二進位檔 | ida-reverse/ / radare2/ |
差異的關鍵:binary-diff 的目標是讓新版可分析(把舊符號搬過來),本 skill 的目標是找出修補修了什麼 bug 然後打修補前的版本。前者服務防禦側 / 研究側分析,後者服務攻擊側武器化。
核心原理
修補後二進位 (after) 未修補二進位 (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 不當機 → 漏洞確認
修補修復模式 → 漏洞類型反查:
| 新增內容 | 大概率的 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 | 暴露面收斂(看老介面怎麼打) |
工作流
5 步完整流程
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 復現成功
工具呼叫順序
下修補 → 解包 → 載入到 IDA/Ghidra → BinDiff/ghidriff → 看 unmatched/low-match 函式
→ LLM 反推 bug class → 寫 PoC → 在 unpatched 跑 → 當機 → 收工
典型場景範例
場景 1:Windows Patch Tuesday — Kernel CVE 復現
背景: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,無任何異常
→ 復現成功
場景 2:Linux 核心 LTS 分支修補找未修的旁支
背景:主線 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
注意事項
- 法律邊界 — 武器化 N-day 必須在授權範圍內(SRC / Bug Bounty / 自有靶機 / CTF)。對生產環境直接打 1-day 等同入侵
- 修補可能只是「減小爆炸半徑」 — 看到 patch 不一定就是完整修復,有可能只是補一個利用路徑,原始 bug 仍可從別的路徑觸發(一魚多吃)
- 變數名/類型不要被欺騙 — Windows 修補經常順手做 cleanup / rename,看似變更很大但實際無關。要看控制流和資料流,不要看 token 級 diff
- 微軟的修補可能加了 mitigation 而不是 fix — 看到
_guard_xfg_dispatch_icall_fptr這種 CFG 強化不要當成 fix,那是 mitigation - 匿名化 — writeup / PoC 公開時脫敏目標機器名、內網 IP、使用者名(寫
{target_ip}{username}佔位) - patched 版本上要能跑通無害化測試 — 別只在 unpatched 上跑,否則可能是環境因素導致的當機,不是漏洞
- 二進位 diff 不萬能 — 編譯器升級 / 優化等級變化也會讓函式 layout 大變,先用 N 版本和 N-1 版本(同一編譯器)對比,不要跨大版本
按需自舉(On-Demand Bootstrap)
工具依賴
| 工具 | 用途 | 可自動安裝 |
|---|---|---|
| BinDiff (Google, 5.x+) | 函式級二進位 diff,IDA/Ghidra 外掛 | ✓ (有官方 .deb / .msi) |
| Diaphora | IDA 老牌 diff 外掛,需要 IDA Pro | ✓ (git clone) |
| ghidriff | Ghidra headless CLI diff,輸出 markdown | ✓ (pip install ghidriff) |
| DeepDiff (商業) | 新一代 diff 工具,準確度更高 | ✗ (商業授權) |
| Ghidra | ghidriff 的運行底座 | ✓ |
| IDA Pro | BinDiff / Diaphora 的運行底座 | ✗ (商業) |
| Microsoft Update Catalog | 下 MSU/MSP 修補包 | 線上服務 |
| wsuspect-proxy | 透明攔截 Windows Update 流量取修補 | ✓ (git clone) |
| expand.exe / dism | 解 MSU / cab | ✓ (Windows 內建) |
| 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/— 如果修補後版本無符號、修補前有符號,先用 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 復現」、「找修補修了什麼」、「打未更新主機」等意圖
任務完成自檢(聲稱完成前 MUST 通過)
- 我是否執行了工作流中的每一步(而不是只閱讀)?
- 我是否基於
tool-index使用了真實工具路徑? - 我是否產出了可復現證據(命令/腳本/截圖/報告)?
- 我是否完成並回寫了 RULES 要求的 Checklist 項?