reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
260
reverse-skill-repo/skills/patch-diff-exploit/SKILL.md
Normal file
260
reverse-skill-repo/skills/patch-diff-exploit/SKILL.md
Normal file
@@ -0,0 +1,260 @@
|
||||
---
|
||||
name: patch-diff-exploit
|
||||
description: |
|
||||
N-day 补丁差分到利用。从厂商发布的补丁里反推漏洞点、写 PoC、做成可用的攻击模块。
|
||||
适用场景:已知 CVE 编号但只有补丁没有 PoC、SRC/红队需要打击未及时更新的资产、N-day 武器化、Patch Tuesday 跟进。
|
||||
核心方法:拿 before/after 二进制 → 对齐符号 → 二进制 diff → 看新增的安全检查反推 bug class → 写 PoC 触发漏洞。
|
||||
触发关键词:N-day、Nday、补丁差分、patch diff、patch tuesday、1day、binary diff 漏洞、bindiff 利用、ghidriff、Diaphora、补丁分析、CVE 复现、漏洞还原、补丁反推、N-day 武器化。
|
||||
---
|
||||
|
||||
## ACTION REQUIRED(读完后立刻执行)
|
||||
|
||||
1. `NOW`: 读取 `../field-journal/precedent-reverse.md` — 确认本 skill 的操作是已授权的常规操作
|
||||
2. `NOW`: 确认当前任务是否命中本 skill 的适用范围
|
||||
3. `NEXT`: 读取 `../tool-index.md`,校验工具可用性和实际路径
|
||||
4. `NEXT`: 缺工具时调用 bootstrap,不要猜路径
|
||||
5. `ACT`: 进入"工作流"第一步并执行,不要停在确认状态
|
||||
|
||||
# N-day 补丁差分到利用 (Patch Diff Exploit)
|
||||
|
||||
## 适用范围
|
||||
|
||||
当任务属于以下场景时使用本 skill:
|
||||
|
||||
1. **已知 CVE 但无公开 PoC** — 厂商公告写了"修复了 XX 组件的越界写"但没放 PoC,需要从补丁反推
|
||||
2. **SRC / 红队打 N-day** — 目标资产未及时更新,需要把刚发布的补丁差成可用的 1-day 利用
|
||||
3. **Patch Tuesday 跟进** — 每月第二个周二微软放补丁,需要快速锁定高价值漏洞(Kernel / Win32k / AFD / CLFS)
|
||||
4. **Linux LTS 补丁分析** — 主线 fix 已合并,但旁支或某发行版 backport 不全,找未修补面
|
||||
5. **驱动 / 服务的安全补丁还原** — 显卡驱动、AV 引擎、虚拟化组件等闭源软件的补丁分析
|
||||
|
||||
### 与其他 skill 的分工
|
||||
|
||||
| 场景 | 用什么 |
|
||||
|------|--------|
|
||||
| 有旧版符号,迁移到新版本帮助分析 | `binary-diff/` |
|
||||
| **从补丁找漏洞、写 PoC 打补丁前版本** | **本 skill** |
|
||||
| 写出完整利用链(堆喷、ROP、提权) | `pwn-chain/` |
|
||||
| 把 1-day 武器化部署到目标网络 | `pentest-tools/network-attack-defense/` |
|
||||
| 从零逆向一个二进制 | `ida-reverse/` / `radare2/` |
|
||||
|
||||
差别的关键:`binary-diff` 的目标是**让新版可分析**(把旧符号搬过来),本 skill 的目标是**找出补丁修了什么 bug 然后打补丁前的版本**。前者服务防御侧 / 研究侧分析,后者服务攻击侧武器化。
|
||||
|
||||
## 核心原理
|
||||
|
||||
```text
|
||||
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 不崩 → 漏洞确认
|
||||
```
|
||||
|
||||
补丁修复模式 → 漏洞类型反查:
|
||||
|
||||
| 新增内容 | 大概率的 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 步完整流程
|
||||
|
||||
```text
|
||||
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 复现成功
|
||||
```
|
||||
|
||||
### 工具调用顺序
|
||||
|
||||
```text
|
||||
下补丁 → 解包 → 加载到 IDA/Ghidra → BinDiff/ghidriff → 看 unmatched/low-match 函数
|
||||
→ LLM 反推 bug class → 写 PoC → 在 unpatched 跑 → 崩 → 收工
|
||||
```
|
||||
|
||||
## 典型场景示例
|
||||
|
||||
### 场景 1:Windows Patch Tuesday — Kernel CVE 复现
|
||||
|
||||
```text
|
||||
背景: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 分支补丁找未修的旁支
|
||||
|
||||
```text
|
||||
背景:主线 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
|
||||
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 项?
|
||||
@@ -0,0 +1,271 @@
|
||||
# 二进制差分工具对比
|
||||
|
||||
补丁差分的核心工具是二进制 diff 引擎。本文档对比当前主流工具的强项、安装、典型命令、输出解读,以及组合工作流。
|
||||
|
||||
---
|
||||
|
||||
## 工具总览
|
||||
|
||||
| 工具 | 作者/厂商 | 底座 | License | 强项 | 弱项 |
|
||||
|------|---------|------|---------|------|------|
|
||||
| **BinDiff** | Google (zynamics) | IDA Pro / Ghidra / Binary Ninja | 免费 | 业界标杆,函数级匹配最稳,GUI 视图清晰 | 需要 IDA 才能玩到极致 |
|
||||
| **Diaphora** | Joxean Koret | IDA Pro | GPL | 老牌、活跃维护、SQLite 持久化、支持伪代码 diff | 重度依赖 IDA Pro,对超大二进制慢 |
|
||||
| **ghidriff** | Clearbluejar | Ghidra headless | Apache 2.0 | 纯 CLI,CI 友好,输出 markdown,免费开源 | 准确度依赖 Ghidra 反编译 |
|
||||
| **DeepDiff** (Karambit) | Karambit.AI | 自带 | 商业 | LLM 辅助、变量名重命名感知 | 商业授权 |
|
||||
| **radiff2** | radare2 项目 | radare2 | LGPL | 全开源、嵌入 r2 工作流 | 函数匹配能力弱于 BinDiff |
|
||||
| **patchdiff2** | tetrane | IDA | GPL | IDA 老插件,年代久 | 已基本被 BinDiff/Diaphora 取代 |
|
||||
|
||||
---
|
||||
|
||||
## BinDiff
|
||||
|
||||
### 安装
|
||||
|
||||
Linux:
|
||||
```bash
|
||||
wget https://github.com/google/bindiff/releases/latest/download/bindiff_8-amd64.deb
|
||||
sudo dpkg -i bindiff_8-amd64.deb
|
||||
```
|
||||
|
||||
Windows:
|
||||
```powershell
|
||||
# 从 https://github.com/google/bindiff/releases 下 .msi
|
||||
msiexec /i bindiff_8.msi /quiet
|
||||
# 自动注册到 IDA Pro 插件目录
|
||||
```
|
||||
|
||||
### IDA 内使用
|
||||
|
||||
1. 在 IDA 里加载 unpatched 二进制,分析完,`File → Produce file → BinExport` 导出 `old.BinExport`
|
||||
2. 加载 patched 二进制,同样导出 `new.BinExport`
|
||||
3. `Edit → Plugins → BinDiff` → 选 new.BinExport 对比 → 输出 .BinDiff 数据库
|
||||
|
||||
### CLI 用法
|
||||
|
||||
```bash
|
||||
# 直接两个二进制 diff(先用 binexport 提取)
|
||||
bindiff old.exe new.exe
|
||||
|
||||
# 或显式给 BinExport
|
||||
bindiff --primary=old.BinExport --secondary=new.BinExport \
|
||||
--output_dir=./bindiff_out/
|
||||
|
||||
# 输出: ./bindiff_out/old_vs_new.BinDiff (SQLite)
|
||||
```
|
||||
|
||||
### 输出读法
|
||||
|
||||
打开 .BinDiff 文件后,关键列:
|
||||
- `similarity` — 0.0 ~ 1.0,函数相似度
|
||||
- `confidence` — 算法信心
|
||||
- `algorithm` — 匹配算法 (name hash, function hash, MD index 等)
|
||||
|
||||
聚焦工作区:
|
||||
- **similarity 1.0 + confidence 1.0** — 完全不变,跳过
|
||||
- **similarity 0.0 (unmatched)** — 新增或重大重构,留意但通常是新功能
|
||||
- **similarity 0.5 ~ 0.95** — 重点目标,多半是修了 bug
|
||||
- **similarity 0.95 ~ 0.99** — 微调,可能是 mitigation 或 cleanup
|
||||
|
||||
GUI 内:双击函数 → 看 graph view 的 basic block 着色:
|
||||
- 灰:完全相同
|
||||
- 黄:相似但有指令差异
|
||||
- 红:新增或删除
|
||||
- 蓝:仅 patched 有的 block — **重点看这种**
|
||||
|
||||
---
|
||||
|
||||
## Diaphora
|
||||
|
||||
### 安装
|
||||
|
||||
```bash
|
||||
cd ~/idapro/plugins/
|
||||
git clone https://github.com/joxeankoret/diaphora.git
|
||||
# 在 IDA 里 File → Script file → ~/idapro/plugins/diaphora/diaphora.py
|
||||
```
|
||||
|
||||
### 工作流
|
||||
|
||||
1. IDA 打开 unpatched → 跑 `diaphora.py` → 选 "Export current database" → 保存 `old.sqlite`
|
||||
2. IDA 打开 patched → 跑 `diaphora.py` → 选 "Diff against another database" → 选 `old.sqlite` → 输出对比报告
|
||||
|
||||
### 输出读法
|
||||
|
||||
Diaphora 输出多个 tab:
|
||||
- **Best matches** — 高置信度匹配,跳过
|
||||
- **Partial matches** — 部分匹配,**重点看这里**
|
||||
- **Unreliable matches** — 算法不确定,可能误报
|
||||
- **Unmatched in primary / secondary** — 单边出现的函数
|
||||
|
||||
每个函数支持 side-by-side 伪代码 diff(IDA 反编译输出)。
|
||||
|
||||
### 关键 SQL 查询
|
||||
|
||||
Diaphora 用 SQLite 存数据,可写 SQL 找目标:
|
||||
|
||||
```sql
|
||||
-- 找出 diff 比例在中等区间的函数
|
||||
SELECT f1.name, f2.name, ratio
|
||||
FROM results
|
||||
WHERE ratio BETWEEN 0.5 AND 0.9
|
||||
ORDER BY ratio DESC;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ghidriff
|
||||
|
||||
### 安装
|
||||
|
||||
```bash
|
||||
pip install ghidriff
|
||||
# ghidriff 会自动下载 Ghidra 到 ~/.ghidra/ (首次运行需要联网)
|
||||
# 或指定 Ghidra 路径:
|
||||
export GHIDRA_INSTALL_DIR=/opt/ghidra_11.0
|
||||
```
|
||||
|
||||
### 基础用法
|
||||
|
||||
```bash
|
||||
# 最小命令
|
||||
ghidriff old.so new.so
|
||||
|
||||
# 指定输出目录 + 引擎
|
||||
ghidriff old.exe new.exe \
|
||||
-o ./diff_out/ \
|
||||
--engine VersionTrackingDiff \
|
||||
--threaded \
|
||||
--max-section-funcs-analyze 5000
|
||||
|
||||
# 看所有可用引擎
|
||||
ghidriff --list-engines
|
||||
# 常见: VersionTrackingDiff (默认), SimpleDiff, StructualGraphDiff
|
||||
```
|
||||
|
||||
### 输出格式
|
||||
|
||||
ghidriff 默认输出三种产物:
|
||||
1. **Markdown 报告** — 人类可读,包含 added / deleted / modified 函数清单 + 伪代码 diff 块
|
||||
2. **JSON 报告** — 程序化消费
|
||||
3. **GhidraProject** — 可以打开继续手工分析
|
||||
|
||||
报告关键章节:
|
||||
- `## Summary` — 总体统计 (匹配率)
|
||||
- `## Strings Diff` — 字符串变化(信息泄漏类 CVE 经常字符串变了)
|
||||
- `## Functions` → `### Modified` — 重点
|
||||
- 每个函数下: `before` / `after` 伪代码 + unified diff
|
||||
|
||||
### 推荐参数
|
||||
|
||||
```bash
|
||||
# Windows 内核大文件:限制单 section 分析数量,避免 OOM
|
||||
ghidriff ntoskrnl_old.exe ntoskrnl_new.exe \
|
||||
-o /tmp/nt_diff/ \
|
||||
--max-section-funcs-analyze 8000 \
|
||||
--max-section-funcs-full 800 \
|
||||
--threaded
|
||||
|
||||
# 大量小函数(驱动):开启所有 diff
|
||||
ghidriff afd_old.sys afd_new.sys -o /tmp/afd_diff/ --side-by-side
|
||||
```
|
||||
|
||||
### 配 LLM 自动总结
|
||||
|
||||
ghidriff 支持插件式输出,可以喂给 LLM 自动生成根因分析(见 root-cause-and-poc.md 的 LLM 章节)。
|
||||
|
||||
```bash
|
||||
# 输出 JSON 给下游 LLM 脚本消费
|
||||
ghidriff old new -o out/ --json-format
|
||||
python my-llm-summarizer.py out/diff.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## radiff2
|
||||
|
||||
### 安装
|
||||
|
||||
```bash
|
||||
# 通常随 radare2 安装
|
||||
sudo apt install radare2
|
||||
# 或源码
|
||||
git clone https://github.com/radareorg/radare2 && radare2/sys/install.sh
|
||||
```
|
||||
|
||||
### 用法
|
||||
|
||||
```bash
|
||||
# 字节级 diff
|
||||
radiff2 old.bin new.bin
|
||||
|
||||
# 函数级 diff (需要先各自 r2 分析)
|
||||
radiff2 -A -C old.bin new.bin # -A 分析, -C 函数级
|
||||
|
||||
# 输出 graph (Graphviz)
|
||||
radiff2 -g main old new | dot -Tpng -o diff.png
|
||||
|
||||
# JSON 输出
|
||||
radiff2 -j -A -C old new > diff.json
|
||||
```
|
||||
|
||||
适合:与 radare2 工作流深度集成的场景,或者 BinDiff/Ghidra 跑不动的小文件。
|
||||
|
||||
---
|
||||
|
||||
## DeepDiff (Karambit.AI, 商业)
|
||||
|
||||
特点:
|
||||
- 不依赖 IDA / Ghidra
|
||||
- 自带反编译器
|
||||
- 用 ML 模型做函数匹配,对 inline / rename / 控制流变化更鲁棒
|
||||
- 自动生成 root cause 假设
|
||||
|
||||
适合资金充足的团队批量处理 Patch Tuesday。本文档不展开,因需要商业授权。
|
||||
|
||||
---
|
||||
|
||||
## 工具组合工作流
|
||||
|
||||
### 推荐组合(按场景)
|
||||
|
||||
```text
|
||||
场景 A: 有 IDA Pro 授权,质量优先
|
||||
BinDiff (主) + Diaphora (副验证) + LLM 辅助根因
|
||||
|
||||
场景 B: 无 IDA,纯开源
|
||||
ghidriff (主) + LLM 辅助根因
|
||||
|
||||
场景 C: 批量 Patch Tuesday 流水线
|
||||
ghidriff CLI + JSON → 脚本筛选 → 人工 review top N
|
||||
|
||||
场景 D: 小型驱动 / 嵌入式 firmware
|
||||
radiff2 / ghidriff 都行
|
||||
```
|
||||
|
||||
### 粗筛 → 精看 流程
|
||||
|
||||
```text
|
||||
Step 1 (粗筛): 跑 ghidriff,过滤
|
||||
- 整体 matched 比例 < 90% → 警惕,多半对齐失败 (可能是不同编译器、不同混淆)
|
||||
- matched 比例 > 99% → 补丁很微小,可能只动 1-2 个函数
|
||||
- 列出 Modified 函数清单,按变更行数排序
|
||||
|
||||
Step 2 (优先级): 按以下加权
|
||||
- 函数名含敏感词 (Ioctl / DispatchIoCtrl / Probe / Copy / Length) +5
|
||||
- 出现在已知攻击面驱动 (afd/clfs/win32k) +5
|
||||
- 变更涉及 if 边界 / lock / refcount +3
|
||||
- 仅做字符串 / 日志变更 -3
|
||||
|
||||
Step 3 (精看): 把 top 10 函数喂给 BinDiff GUI 或 IDA 手工,
|
||||
或贴 before/after 伪代码给 LLM 反推 bug class
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见坑
|
||||
|
||||
- **对齐失败**:matched 比例 < 90% 时不要继续。先确认两个二进制是同一编译器版本、同一架构、同一优化等级。常见原因:跨大版本编译器、PGO/LTO 不同、ASLR rebase 没对齐
|
||||
- **inline 函数把 diff 撑大**:编译器决定 inline 的函数变了会让父函数大范围变红,但根本没改逻辑。要看真实控制流分支
|
||||
- **switch table 重排**:编译器可能重排 case,看着像新增 block,其实只是顺序变化
|
||||
- **Profile-Guided Optimization (PGO) 抖动**:连续两个版本的二进制即使源码一字不改也可能 layout 不同
|
||||
- **stripped Linux 内核**:没 debuginfo 时所有函数名都是 `FUN_xxxx`,必须先吃 BTF / kallsyms 或用 binary-diff 迁移符号
|
||||
@@ -0,0 +1,253 @@
|
||||
# Patch Tuesday 工作流
|
||||
|
||||
每月第二个周二 (Pacific Time) 微软发布安全更新,俗称 Patch Tuesday。这是 N-day 研究最稳定的输入源:补丁数量大、价值高、披露口径统一。本文档给出从订阅公告到拿到可对比二进制的完整流程。
|
||||
|
||||
---
|
||||
|
||||
## 1. 信息源订阅
|
||||
|
||||
| 来源 | 用途 | 备注 |
|
||||
|------|------|------|
|
||||
| MSRC Security Update Guide | 当月所有 CVE 列表 + CVSS + 受影响产品 | https://msrc.microsoft.com/update-guide/ 有 API |
|
||||
| MSRC CVRF API | 程序化拉当月 CVE JSON | `https://api.msrc.microsoft.com/cvrf/v3.0/cvrf/{YEAR}-{Mon}` |
|
||||
| Microsoft Update Catalog | 下 MSU/MSP 实物 | https://www.catalog.update.microsoft.com/ |
|
||||
| Patch Tuesday Dashboard (Tenable / Trend / Rapid7) | 第三方汇总优先级 | 看哪些标了 "exploited in the wild" |
|
||||
| ZDI advisories | ZDI 提交的 CVE 详细描述 | 经常有比 MSRC 更详细的 root cause hint |
|
||||
| Project Zero 周期性 issue tracker | 半年后会公开细节 | 可作为历史对照 |
|
||||
|
||||
### 拉当月 CVE 列表 (PowerShell)
|
||||
|
||||
```powershell
|
||||
$year = '2026'; $mon = 'May'
|
||||
$url = "https://api.msrc.microsoft.com/cvrf/v3.0/cvrf/$year-$mon"
|
||||
Invoke-RestMethod $url | ConvertTo-Json -Depth 10 | Out-File "C:\patches\msrc-$year-$mon.json" -Encoding utf8
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 锁定高价值补丁
|
||||
|
||||
按以下顺序过滤当月公告:
|
||||
|
||||
1. **CVSS >= 7.0**
|
||||
2. **Exploitation: Exploitation Detected / More Likely**
|
||||
3. **组件白名单**(高价值攻击面):
|
||||
- `Windows Kernel` (ntoskrnl.exe)
|
||||
- `Win32k` (win32k.sys, win32kfull.sys, win32kbase.sys)
|
||||
- `Ancillary Function Driver for WinSock` (afd.sys) — 历史 LPE 大户
|
||||
- `Common Log File System` (clfs.sys) — 过去三年多次被野利用
|
||||
- `Print Spooler` (spoolsv.exe, win32spl.dll)
|
||||
- `Cloud Files Mini Filter Driver` (cldflt.sys)
|
||||
- `NTFS` (ntfs.sys)
|
||||
- `Hyper-V` (vmswitch.sys, hvix64.exe, hvax64.exe)
|
||||
- `Cryptography Services` / `NTLM` / `Kerberos`
|
||||
- `RDP` (rdpcorets.dll, rdpbase.dll)
|
||||
4. **本地提权 (EoP) > RCE > Info Disclosure** — EoP 武器化门槛最低
|
||||
5. **是否有 KB 直接对应** — 没有 KB 号的(例如纯 Defender 定义更新)跳过
|
||||
|
||||
---
|
||||
|
||||
## 3. 下载 patched / unpatched 二进制
|
||||
|
||||
### 3.1 Microsoft Update Catalog 手动下
|
||||
|
||||
```text
|
||||
1. 访问 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5052000
|
||||
2. 按 Products 过滤 (Windows 11, Server 2022 等)
|
||||
3. 选目标架构 (x64 / arm64),下载 .msu
|
||||
4. 同时下 N-1 版本 (上个月的 KB 号) 作为 unpatched 基线
|
||||
```
|
||||
|
||||
### 3.2 程序化批量下
|
||||
|
||||
```powershell
|
||||
# msdownload 第三方脚本
|
||||
git clone https://github.com/JaschaUrbach/msu-downloader.git
|
||||
python msu-downloader.py --kb KB5052000 --arch x64 --out C:\patches\
|
||||
```
|
||||
|
||||
### 3.3 wsuspect-proxy 拦截真实流量取最新补丁
|
||||
|
||||
适用于:MSRC 还没在 Catalog 上架,但已通过 WU 推送给客户端的早期窗口。
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ctxis/wsuspect-proxy.git
|
||||
cd wsuspect-proxy
|
||||
# 在被测机器上手工设 WSUS = http://attacker:8530,触发 wuauclt /detectnow
|
||||
python wsuspect-proxy.py --listen 0.0.0.0:8530 --dump-cabs C:\patches\dump\
|
||||
```
|
||||
|
||||
### 3.4 Delta 包 vs Cumulative 包
|
||||
|
||||
- 微软现在主推 `.msu` cumulative update — 体积大但完整
|
||||
- 也有 `.msu` Express / Delta 包 — 体积小但只含差异,对差分研究不友好
|
||||
- 优先下 cumulative
|
||||
|
||||
---
|
||||
|
||||
## 4. 解包 MSU / CAB / MSP
|
||||
|
||||
### 4.1 MSU 解包(Windows)
|
||||
|
||||
```powershell
|
||||
# Step 1: MSU 是 cab 套娃,先解外层
|
||||
expand.exe Windows-KB5052000-x64.msu -F:* C:\patches\out\
|
||||
|
||||
# Step 2: 解里面的 .cab
|
||||
expand.exe C:\patches\out\Windows-KB5052000-x64.cab -F:* C:\patches\out\
|
||||
|
||||
# Step 3: 关键文件在 amd64_microsoft-windows-{component}_*\ 下
|
||||
# 例如 ntoskrnl.exe 在:
|
||||
# C:\patches\out\amd64_microsoft-windows-os-kernel_*\ntoskrnl.exe
|
||||
```
|
||||
|
||||
### 4.2 用 dism 装到离线镜像(拿干净的 patched 二进制)
|
||||
|
||||
```powershell
|
||||
# 挂载离线 WIM
|
||||
dism /mount-image /imagefile:install.wim /index:1 /mountdir:C:\mnt
|
||||
|
||||
# 应用补丁
|
||||
dism /image:C:\mnt /add-package /packagepath:Windows-KB5052000-x64.msu
|
||||
|
||||
# 提取目标二进制
|
||||
copy C:\mnt\Windows\System32\ntoskrnl.exe C:\patches\patched\
|
||||
|
||||
# 卸载
|
||||
dism /unmount-image /mountdir:C:\mnt /commit
|
||||
```
|
||||
|
||||
### 4.3 MSP (Office 等) 解包
|
||||
|
||||
```powershell
|
||||
# MSP 是 Windows Installer Patch
|
||||
msiexec /a base.msi /p update.msp TARGETDIR=C:\patches\office_patched
|
||||
|
||||
# 或用 lessmsi (推荐, 不动注册表)
|
||||
lessmsi x update.msp C:\patches\office_msp\
|
||||
```
|
||||
|
||||
### 4.4 用第三方工具一站式拆包
|
||||
|
||||
```powershell
|
||||
# PatchExtract by Greg Linares - 一条命令解多层
|
||||
.\PatchExtract.ps1 -PatchFile Windows-KB5052000-x64.msu -ExtractedFolder C:\patches\extracted\
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 取符号 (PDB)
|
||||
|
||||
```powershell
|
||||
# Windows SDK 自带 symchk
|
||||
symchk /v /r C:\patches\patched\ntoskrnl.exe /s SRV*C:\sym*https://msdl.microsoft.com/download/symbols
|
||||
symchk /v /r C:\patches\unpatched\ntoskrnl.exe /s SRV*C:\sym*https://msdl.microsoft.com/download/symbols
|
||||
```
|
||||
|
||||
注意:微软偶尔会延迟或下架某个版本 PDB。如果当前下不到 N-1 的 PDB,用 `binary-diff` skill 把 N-2 的 PDB 符号迁移到 N-1。
|
||||
|
||||
---
|
||||
|
||||
## 6. Windows 高价值二进制路径速查
|
||||
|
||||
| 文件 | 路径 | 关注组件 |
|
||||
|------|------|---------|
|
||||
| ntoskrnl.exe | System32\ | 内核核心、对象管理、Ob*、Ps*、Mm*、Io* |
|
||||
| win32k.sys | System32\ | GUI 子系统入口 |
|
||||
| win32kfull.sys | System32\ | GUI 完整版(桌面会话) |
|
||||
| win32kbase.sys | System32\ | GUI 基础库 |
|
||||
| afd.sys | System32\drivers\ | WinSock AFD,LPE 高发 |
|
||||
| clfs.sys | System32\drivers\ | CLFS,0-day 高发 |
|
||||
| cldflt.sys | System32\drivers\ | Cloud Files mini filter |
|
||||
| spoolsv.exe | System32\ | Print Spooler |
|
||||
| dwm.exe | System32\ | Desktop Window Manager |
|
||||
| lsass.exe | System32\ | LSA 认证 |
|
||||
| ntdll.dll | System32\ | syscall stub、PE loader |
|
||||
| ksecdd.sys | System32\drivers\ | Kernel security driver |
|
||||
|
||||
---
|
||||
|
||||
## 7. Linux 等价流程
|
||||
|
||||
### 7.1 信息源
|
||||
|
||||
| 来源 | 适用 |
|
||||
|------|------|
|
||||
| Ubuntu USN | https://ubuntu.com/security/notices |
|
||||
| Red Hat RHSA | https://access.redhat.com/security/security-updates/ |
|
||||
| Debian DSA | https://www.debian.org/security/ |
|
||||
| CentOS / Rocky / Alma announce list | 通常 mirror Red Hat |
|
||||
| upstream kernel CVE list | https://cve.kernel.org/ |
|
||||
|
||||
### 7.2 拉补丁包
|
||||
|
||||
```bash
|
||||
# Debian/Ubuntu
|
||||
apt download linux-image-5.15.0-101-generic
|
||||
apt download linux-image-5.15.0-100-generic
|
||||
apt download linux-image-unsigned-5.15.0-101-generic-dbgsym
|
||||
|
||||
# CentOS/Rocky
|
||||
dnf download --downloadonly --downloaddir=./patched kernel-5.14.0-362.18.1.el9_3
|
||||
dnf download --downloadonly --downloaddir=./unpatched kernel-5.14.0-362.13.1.el9_3
|
||||
```
|
||||
|
||||
### 7.3 解包
|
||||
|
||||
```bash
|
||||
# .deb
|
||||
dpkg-deb -x linux-image-5.15.0-101-generic_*.deb ./patched/
|
||||
|
||||
# .rpm
|
||||
rpm2cpio kernel-5.14.0-362.18.1.el9_3.x86_64.rpm | cpio -idmv -D ./patched/
|
||||
```
|
||||
|
||||
### 7.4 从 vmlinuz 还原 vmlinux
|
||||
|
||||
```bash
|
||||
# 用内核自带 scripts/extract-vmlinux
|
||||
wget https://raw.githubusercontent.com/torvalds/linux/master/scripts/extract-vmlinux
|
||||
chmod +x extract-vmlinux
|
||||
./extract-vmlinux ./patched/boot/vmlinuz-5.15.0-101-generic > vmlinux_5.15.0-101
|
||||
./extract-vmlinux ./unpatched/boot/vmlinuz-5.15.0-100-generic > vmlinux_5.15.0-100
|
||||
```
|
||||
|
||||
### 7.5 关注子系统路径
|
||||
|
||||
| 子系统 | 历史 N-day 高发函数前缀 |
|
||||
|--------|----------------------|
|
||||
| net/ | `__skb_*`、`sk_*`、`tcp_*`、`udp_*`、`nf_*` |
|
||||
| fs/ | `do_*`、`vfs_*`、`__lookup_*` |
|
||||
| io_uring/ | 整个子系统(近三年漏洞王) |
|
||||
| netfilter/ | `nft_*`、`nf_tables_*` |
|
||||
| net/sched/ | tc 各 qdisc |
|
||||
| drivers/net/ | 各 NIC 驱动 |
|
||||
| bpf/ | verifier 类 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 真实公开 CVE 案例参考
|
||||
|
||||
| CVE | 组件 | 类型 | 用于练手原因 |
|
||||
|------|------|------|------------|
|
||||
| CVE-2025-62215 | Windows Kernel | race condition + double free | 2025-11 公开,公告说"race + double free",差分入门题 |
|
||||
| CVE-2023-28252 | CLFS | OOB write → LPE | 野外利用,PoC 已公开,可对照学习方法 |
|
||||
| CVE-2022-37969 | CLFS | type confusion → LPE | 同样有公开分析 |
|
||||
| CVE-2021-40449 | Win32k | UAF → LPE | 公开报告完整 |
|
||||
| CVE-2022-21882 | Win32k | type confusion,由 CVE-2021-1732 不完整修复变出 | 经典"一鱼多吃"案例 |
|
||||
|
||||
练习建议:拿一个已经有公开分析的 CVE,按本流程独立差出来一次,再对照公开 writeup 校准方法论。
|
||||
|
||||
---
|
||||
|
||||
## 9. 速查清单
|
||||
|
||||
- [ ] MSRC 月度公告已读,筛出 CVSS≥7 且组件在白名单内的 CVE
|
||||
- [ ] 从 Catalog 下到 unpatched (N-1) 和 patched (N) 的 MSU
|
||||
- [ ] 用 expand / dism 取出目标 .exe / .sys / .dll
|
||||
- [ ] symchk 把 PDB 都吃到(吃不到走 binary-diff 迁移)
|
||||
- [ ] 用 BinaryNinja / IDA / Ghidra 各开两个工程
|
||||
- [ ] 跑 BinDiff / ghidriff,导出 diff 报告
|
||||
- [ ] 按相似度过滤函数,进 `references/root-cause-and-poc.md` 反推根因
|
||||
- [ ] 写 PoC,验证 unpatched 崩、patched 不崩
|
||||
- [ ] 回写 field-journal 记录复用经验
|
||||
@@ -0,0 +1,198 @@
|
||||
# 根因反推与 PoC 编写
|
||||
|
||||
拿到 diff 报告只是第一步。真正的工作是看着 before/after 反推出 bug class,然后写出能稳定触发的 PoC。本文档给出反推模式表、LLM 辅助 prompt、PoC 编写模板、验证方法。
|
||||
|
||||
---
|
||||
|
||||
## 1. 补丁修复模式 → 漏洞类型反查
|
||||
|
||||
### 1.1 整数溢出 / 下溢
|
||||
|
||||
**新增模式**:
|
||||
```c
|
||||
// 加法溢出检查
|
||||
if (a > UINT_MAX - b) goto error;
|
||||
if (a + b < a) goto error;
|
||||
__builtin_add_overflow(a, b, &sum);
|
||||
|
||||
// 乘法溢出检查
|
||||
if (a != 0 && b > UINT_MAX / a) goto error;
|
||||
__builtin_mul_overflow(a, b, &prod);
|
||||
|
||||
// 减法下溢检查
|
||||
if (a < b) goto error;
|
||||
```
|
||||
|
||||
**反推**:
|
||||
- 看 `a` 和 `b` 是否来自用户态可控输入
|
||||
- 通常前后会有 `kmalloc(a+b)` / `RtlAllocateHeap(size)` 等分配,溢出后分配过小 → 后续 memcpy → 堆 OOB 写
|
||||
|
||||
**PoC 思路**:
|
||||
- 让 `a + b` 实际溢出回小值,但拷贝长度还按未溢出的算
|
||||
- 边界值: `a = 0xFFFFFFF0, b = 0x100` (32 位) / `a = 0xFFFFFFFFFFFFFFF0, b = 0x100` (64 位)
|
||||
|
||||
---
|
||||
|
||||
### 1.2 越界读 / 越界写
|
||||
|
||||
**新增模式**:
|
||||
```c
|
||||
if (idx >= ARRAY_SIZE(arr)) return -EINVAL;
|
||||
if (offset + len > buf_size) return STATUS_INVALID_PARAMETER;
|
||||
if (len > sizeof(local_buf)) return -E2BIG;
|
||||
|
||||
// Windows 内核典型
|
||||
if (InputBufferLength < sizeof(MY_STRUCT)) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (req->Length > KERNEL_MAX) return STATUS_INVALID_PARAMETER;
|
||||
```
|
||||
|
||||
**反推**:
|
||||
- 看新增 if 守护了哪个后续操作(memcpy / memmove / 数组下标)
|
||||
- 没守护前的版本可以传超大 length / 超大 index
|
||||
|
||||
**PoC 思路**:
|
||||
- 把 length 字段设成超过 buf 的值
|
||||
- 把 index 字段设成 array_size + N
|
||||
- 用 IOCTL InputBufferLength 调到刚好绕过旧检查但触发新检查
|
||||
|
||||
---
|
||||
|
||||
### 1.3 竞争条件 (Race / TOCTOU)
|
||||
|
||||
**新增模式**:
|
||||
```c
|
||||
// 加锁
|
||||
KeAcquireSpinLockAtDpcLevel(&obj->Lock);
|
||||
mutex_lock(&inode->i_mutex);
|
||||
spin_lock(&list->lock);
|
||||
|
||||
// 引用计数原子化
|
||||
InterlockedIncrement(&obj->RefCount);
|
||||
ObReferenceObject(obj);
|
||||
get_file(file);
|
||||
|
||||
// 检查 - 操作之间不再释放锁
|
||||
```
|
||||
|
||||
**反推**:
|
||||
- 加锁说明此前同一对象在并发场景下被改了
|
||||
- 引用计数加 ref 说明此前对象可能在用的时候被释放
|
||||
- 找两个 syscall 路径,其中一个会修改 / 释放对象,另一个会用对象
|
||||
|
||||
**PoC 思路**:
|
||||
```c
|
||||
// 经典 hammer
|
||||
DWORD WINAPI thread_close(LPVOID arg) {
|
||||
while (running) CloseHandle((HANDLE)arg);
|
||||
return 0;
|
||||
}
|
||||
DWORD WINAPI thread_use(LPVOID arg) {
|
||||
while (running) DeviceIoControl((HANDLE)arg, IOCTL_X, ...);
|
||||
return 0;
|
||||
}
|
||||
// CreateThread 各开几个,sleep 30s 等崩
|
||||
```
|
||||
|
||||
- 多线程绑核 (SetThreadAffinityMask) 提高竞争概率
|
||||
- 用 `_mm_pause()` / `sched_yield()` 控制窗口
|
||||
- 配合 syscall pinning(同一对象的两个不同入口)
|
||||
|
||||
---
|
||||
|
||||
### 1.4 未初始化内存信息泄漏
|
||||
|
||||
**新增模式**:
|
||||
```c
|
||||
// 字段清零
|
||||
RtlZeroMemory(&output, sizeof(output));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
output.reserved = 0;
|
||||
output.padding = 0;
|
||||
output._pad1 = 0;
|
||||
|
||||
// 整个结构归零再赋值
|
||||
KeStackAttachProcess; output = (MY_STRUCT){0};
|
||||
```
|
||||
|
||||
**反推**:
|
||||
- 旧版从内核栈 / 内核堆拷数据到用户态时没清 padding / reserved 字段
|
||||
- padding 内残留前一次函数调用的栈数据 → 内核地址泄漏 (绕 KASLR)
|
||||
|
||||
**PoC 思路**:
|
||||
- 反复调 IOCTL 取 output buffer
|
||||
- 把每个字节按 8 字节解析,找像内核地址的值(Windows: 0xFFFFxxxx / Linux: 0xFFFFFFFFxxxxxxxx)
|
||||
- 找规律 → 推 kbase
|
||||
|
||||
---
|
||||
|
||||
### 1.5 UAF / 引用计数错误
|
||||
|
||||
**新增模式**:
|
||||
```c
|
||||
// Windows
|
||||
if (InterlockedDecrement(&obj->RefCount) == 0) {
|
||||
Free(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
// Linux
|
||||
if (refcount_dec_and_test(&obj->ref)) {
|
||||
kfree(obj);
|
||||
}
|
||||
|
||||
// 或新增 ObReferenceObject 在某条路径上(之前漏加 ref)
|
||||
```
|
||||
|
||||
**反推**:
|
||||
- 旧版某条出错路径 free 了对象但调用者还会用
|
||||
- 或者多路径同时持有指针,其中一条 free 后其他没感知
|
||||
|
||||
**PoC 思路**:
|
||||
```c
|
||||
// spray → free → reuse
|
||||
HANDLE objs[1000];
|
||||
for (int i = 0; i < 1000; i++) objs[i] = CreateObject(...);
|
||||
trigger_free(objs[500]); // 触发漏洞 free
|
||||
spray_kernel_pool(0xDEADBEEFDEADBEEF, target_sz); // 占住被 free 的洞
|
||||
use_after_free(objs[500]); // 触发用 -> 控数据
|
||||
```
|
||||
|
||||
- Windows 内核常用 `NtAllocateReserveObject` / Pipe 属性 / Window Class 名称喷
|
||||
- Linux 常用 `msgsnd` / `setxattr` / `userfaultfd`-stalled vma 喷
|
||||
|
||||
---
|
||||
|
||||
### 1.6 用户态指针未校验
|
||||
|
||||
**新增模式**:
|
||||
```c
|
||||
// Windows
|
||||
ProbeForRead(UserBuffer, Length, sizeof(ULONG));
|
||||
ProbeForWrite(UserBuffer, Length, sizeof(ULONG));
|
||||
|
||||
// __try/__except 包裹访问
|
||||
__try {
|
||||
Probe...
|
||||
RtlCopyMemory(KernelBuf, UserBuffer, Length);
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) { ... }
|
||||
|
||||
// Linux
|
||||
if (!access_ok(VERIFY_WRITE, ptr, size)) return -EFAULT;
|
||||
copy_from_user(kbuf, uptr, len);
|
||||
```
|
||||
|
||||
**反推**:
|
||||
- 旧版直接 deref 用户态指针没 ProbeForRead/access_ok
|
||||
- 用户态可以传内核地址 → 任意地址读 / 任意地址写
|
||||
|
||||
**PoC 思路**:
|
||||
- 传一个内核空间指针(例如 ntoskrnl 某个全局变量地址)作为输入指针
|
||||
- 内核执行 `*UserBuffer = X` 时实际写到内核地址 → 任意写
|
||||
|
||||
---
|
||||
|
||||
### 1.7 权限校验缺失
|
||||
|
||||
**新增模式**:
|
||||
```c
|
||||
if (!SeAccessCheck(...)) return STATUS_
|
||||
Reference in New Issue
Block a user