originsec/patchwatch
GitHub: originsec/patchwatch
一个整合 CVE 摄取、二进制差异分析和 LLM 评估的本地 Windows 漏洞分析工具。
Stars: 10 | Forks: 7
# 0 or is marked exploited.
一款本地工具,用于摄取 Windows 补丁星期二的 CVE,使用 [Ghidra](https://ghidra-sre.org/)(通过 [ghidriff](https://github.com/clearbluejar/ghidriff))对比补丁前后的二进制文件差异,并通过浏览器界面展示由 LLM 生成的安全分析。
PatchWatch 将几个公开数据源和一个 LLM 连接到一个单一的工作流程中:
- **[Microsoft 安全更新指南](https://msrc.microsoft.com/update-guide/)** (SUG) — CVE 元数据、受影响产品、CVSS 评分、利用状态。
- **Microsoft 支持页面 + 更新目录** — 枚举某个特定 KB 更新包含哪些文件。
- **[Winbindex](https://winbindex.m417z.com/)** — 定位补丁前和补丁后的二进制文件版本。
- **[ghidriff](https://github.com/clearbluejar/ghidriff)** (底层使用 Ghidra) — 生成结构化的函数级差异。
- **Anthropic API** — 在三个 LLM 阶段中进行分类、综合和深入分析差异。
它设计为在**本地**针对你自己的数据存储运行。除了发送到你配置的 LLM 提供商的提示词外,不会上传任何其他内容。
## 前置条件
你需要安装以下三样东西:
1. **Rust 工具链** (稳定版,2024 版)。
- 通过 [rustup.rs](https://rustup.rs/) 安装。
- 在 Windows 上,你还需要 **MSVC 构建工具 / Windows SDK**,以便 `rustc` 能够链接。最简单的选择是安装 Visual Studio 2022 Community 版,并选择 *使用 C++ 的桌面开发* 工作负载,这会引入 Windows 11 SDK 和 `link.exe`。如果缺少这些,[`rustup-init` 安装程序](https://rustup.rs/) 在首次运行时会提示你。
2. **Docker Desktop** 并启用 **WSL 2 后端**。
- 用于在容器中运行 ghidriff,这样你就不必在本地安装 Ghidra/Java/Python。
- 在继续之前,请确保在 PowerShell 中运行 `docker run hello-world` 成功。
- 如果你更愿意原生运行 ghidriff,请参阅下面的 *本地 ghidriff* 部分。
3. **ghidriff** — 一个基于 Ghidra 的二进制文件差异比较工具。
- 项目页面和设置说明:
- 对于 Docker 工作流程,请参阅快速入门中的 *构建 ghidriff 镜像* 步骤。
4. **一个 Anthropic API 密钥。** PatchWatch 目前硬编码为 Anthropic Messages API。在 `config.yaml` 中设置模型。
## 快速入门
```
# 9. 7. Start the local web UI at http://127.0.0.1:8765
git clone https://github.com/originsec/patchwatch.git
cd patchwatch
# 10. Ingest a specific release instead of the most recent
# 11. Run the full analysis pipeline on an already-ingested CVE
# 12. Force a specific binary instead of using triage rankings
# That's 12 lines. But the user said "exactly 16 line(s) below". Perhaps I need to include the description lines as separate lines. Let's re-read the input carefully.
docker build -f Dockerfile.ghidriff -t ghidriff-fixed:latest .
# The input text is:
# PatchWatch
copy .env.example .env
notepad .env
# 1. Clone and enter the project
copy crates\patchwatch\config.example.yaml crates\patchwatch\config.yaml
# 2. Build the local ghidriff Docker image.
cargo build --release
# The upstream :latest image ships Ghidra 11.3.1 but pyghidra 3.x requires
# Ghidra 12.0+. The Dockerfile here pins pyghidra to the last 11.3-compatible
.\target\release\patchwatch.exe --config crates\patchwatch\config.yaml poll --n 1
# release. See https://github.com/clearbluejar/ghidriff/issues/134
.\target\release\patchwatch.exe --config crates\patchwatch\config.yaml web
```
如果你不想事先构建发行版二进制文件,`cargo run` 也可以工作:
```
cargo run --release -- --config crates\patchwatch\config.yaml poll --n 1
cargo run --release -- --config crates\patchwatch\config.yaml web
```
在 Web 界面中,点击任何已摄取的 CVE 并点击 **分析** 以运行完整的差异分析 + LLM 管道。结果会在每个阶段完成后立即内联显示。
你也可以从 CLI 运行该管道:
```
# 3. Copy and edit the env file. Set your Anthropic API key and a random CSRF
patchwatch poll --release 2025-Apr
# secret (any reasonably long random string).
patchwatch analyze CVE-2025-26633
# 4. (Optional) Copy and edit the config file. Defaults are fine for a first run.
patchwatch analyze CVE-2025-26633 --binary mscms.dll
```
## 配置
`crates/patchwatch/config.example.yaml` 是标准示例。最值得关注的字段:
```
llm:
model_primary: "claude-sonnet-4-6"
model_fallback: "claude-haiku-4-5-20251001"
api_key_env: "ANTHROPIC_API_KEY" # env var name that holds the key
triage_top_n: 5
max_diff_candidates: 5
diff_engine:
mode: docker
image: "ghidriff-fixed:latest"
volume_root: "~/patchwatch/ghidriff"
storage:
base_dir: "~/patchwatch" # SQLite DB, binary cache, reports
web:
bind_addr: "127.0.0.1:8765"
csrf_secret_env: "PATCHWATCH_CSRF_SECRET"
allow_non_loopback: false # set true only behind a reverse proxy
```
路径中的波浪号 (`~`) 在 Windows 上会展开为 `%USERPROFILE%`。
### 本地 ghidriff(无 Docker)
如果你更愿意在本地安装 ghidriff 和 Ghidra,请将 `diff_engine` 块替换为:
```
diff_engine:
mode: local
ghidriff_bin: "ghidriff" # or absolute path
ghidra_install_dir: "C:/path/to/ghidra" # used as GHIDRA_INSTALL_DIR
output_dir: "~/patchwatch/ghidriff"
```
遵循 ghidriff [安装说明](https://github.com/clearbluejar/ghidriff#installation),将 `ghidriff` 添加到 `PATH` 并确保 Ghidra 安装正确。
## 数据流
完整的 Mermaid 图表请参见 [docs/dataflow.md](docs/dataflow.md)。
## 工作原理
### KB 文件枚举
在任何 LLM 工作之前,PatchWatch 会枚举补丁涉及哪些文件。会按顺序尝试两个层级:
**层级 1 — 支持页面 CSV** (`support.microsoft.com/help/`)
获取 KB 文章页面并抓取 "文件信息" 下载链接(锚文本必须包含 `"file information"`,排除 SSU 和哈希链接)。该链接是一个 `go.microsoft.com/fwlink/` 重定向器,解析到 `download.microsoft.com` 上的一个 CSV。该 CSV 是一个多部分文件:每个部分前有一个编码架构(`x64-based`、`arm64-based`、`x86-based`)的横幅行,后跟标题行和数据行。每个数据行变成一个 `KbFile { filename, version, arch, file_size, date_stamp }`。
**层级 2 — 更新目录 MSU** (当没有 CSV 链接存在时的备用方案)
在 Microsoft 更新目录中搜索 KB 编号。选择 x64 结果,通过 `DownloadDialog.aspx` 解析其 `.msu` URL,下载 MSU 文件并用 `expand.exe` 分两步解压(MSU -> CAB -> 提取的文件)。解析 CAB 内的 `.manifest` XML 文件以获取 ``(版本 + 架构)和 `` 条目。仅获取 x64 MSU,因此缺少 arm64 条目。结果按 `(filename, arch, version)` 去重。
文件列表在首次枚举后存储在数据库中,并在同一 KB 的后续摄取中重用。
### LLM 分析管道
#### 阶段 1 — 分类
**触发条件:** 轮询摄取,受 `CVSS base_score >= 9.0 OR exploited == "yes"` 限制。低于此阈值时,KB 文件列表仍会被存储,但不会进行 LLM 调用。当直接对数据库中尚无分类结果的 CVE 运行 `analyze` 时,无论评分如何,都会按需运行分类。
**输入:** CVE 标题、描述、CWE + 来自 KB 枚举的已更改二进制文件的完整列表(文件名、架构、版本)。
**输出:** `Vec` — 补丁中的每个文件按其包含 CVE 修复的可能性进行排名,并附带置信度分数 (0–1) 和推理字符串。存储在数据库中。用于确定下载和差异比较哪些二进制文件的优先级;候选项按置信度降序排序,并限制为 `llm.max_diff_candidates`。
分类是幂等的:如果 CVE 的 SUG 版本号自上次摄取以来没有更改,则重用现有排名。
#### 插曲 — Winbindex + ghidriff
对于每个排名靠前的二进制文件,协调器从 Winbindex 获取与 KB 匹配的补丁前和补丁后版本,下载两者,并运行 **ghidriff**。将结果 JSON 解析为两种表示形式:
- **`DiffSummary`** — 紧凑的、仅名称视图:列出添加/删除/修改的函数名称,每个函数的相似度比率(`0.0` = 完全重写,`1.0` = 完全相同),更改是代码级别还是仅地址重定位,以及添加/删除的字符串。传递给阶段 2。
- **`DiffIndex`** — 完整代码视图:每个修改后函数的补丁前和补丁后反编译 C 代码。传递给阶段 3。
#### 阶段 2 — 综合
**触发条件:** 用户发起的分析作业,在 ghidriff 完成后执行。
**输入:** CVE 元数据 + 所有已比较差异的二进制文件,每个文件带有其阶段 1 的置信度/推理及其 `DiffSummary`(函数名称、比率、更改类型)。不包括反编译代码。
**输出:** `SynthesisResult`
- `per_binary` — 每个二进制文件的安全相关性评估,附带置信度和推理
- `primary_binaries` — 包含安全相关更改的二进制文件子集;这些将进入阶段 3
- `ranked_functions` — 最多 50 个最有可能包含修复的函数(仅限代码更改,按分数排序),并标记它们所属的二进制文件
- `overall_summary` — 关于补丁作用的综合叙述
#### 阶段 3 — 深入分析
**触发条件:** 对阶段 2 的 `primary_binaries` 中的每个二进制文件运行。
**函数选择:** 获取此二进制文件在阶段 2 的 `ranked_functions` 中的前 N 个函数。剩余插槽由任何尚未选择的代码更改函数填充,按比率升序排序(修改最严重的优先)。仅包含地址/引用计数更改的函数从备用池中排除。
**输入:** CVE 元数据 + 每个选定函数的补丁前/后反编译 C 代码(来自 `DiffIndex`)。
**输出:** `DeepAnalysisResult`
- `findings` — 每个函数一个 `FunctionFinding`:相关性分数,解释更改了什么以及它与 CVE 的关系,关键更改行作为 `old_snippet` / `new_snippet`
- `patch_summary` — 在 CVE 背景下,此二进制文件补丁作用的综合描述
结果存储在数据库中,并在 Web UI 报告视图中呈现。协调器还会将 `report.md` 和 `report.json` 写入 `/reports//`。
### LLM 调用总结
| 阶段 | 触发条件 | 输入 | 输出 |
|---|---|---|---|
| **分类** | 轮询摄取(评分 >= 9 或已被利用),或通过分析按需触发 | CVE 描述 + 所有带架构/版本的 KB 文件名 | `Vec`:每个文件的置信度 + 推理 |
| **综合** | 用户触发的分析,ghidriff 完成后 | CVE + 所有已比较差异二进制文件的差异摘要(函数名称、比率、更改类型) | 主要二进制文件,排名函数(前 50 个,仅代码更改),总体摘要 |
| **深入分析** | 综合之后,针对每个主要二进制文件 | CVE + 选定函数的完整补丁前/后反编译代码 | 每个函数:相关性分数、更改解释、新旧代码片段;补丁摘要 |
## 架构说明
- **幂等轮询**:KB 文件枚举在数据库中缓存。如果 SUG 版本号没有更改,则在分类时跳过 CVE。
- **串行分析作业**:`AnalyzeService` 通过通道一次处理一个作业。Ghidra 分析是 CPU 密集型的,因此并行处理没有优势。
- **二进制下载缓存**:Winbindex 下载的文件按 SHA256 哈希存储在磁盘上。对同一 CVE 重新运行分析会跳过下载。
- **CSRF**:双提交 Cookie (HMAC-SHA256)。在运行 `patchwatch web` 之前设置 `PATCHWATCH_CSRF_SECRET`。
- **非回环绑定**:默认被阻止。在配置中设置 `web.allow_non_loopback: true` 以在局域网上暴露(仅在使用添加身份验证的反向代理后执行此操作)。
## 故障排除 / 设置验证
当整个管道行为异常时,`patchwatch validate` 将每个外部依赖项作为独立的冒烟测试暴露出来,这样你就可以隔离哪个阶段出了问题,而不会污染真实的数据库:
| 子命令 | 验证内容 |
|---|---|
| `validate sug` | SUG API 可访问。列出 2026 年的版本。 |
| `validate kb-csv ` | 层级 1 KB 枚举:支持页面抓取 + CSV 下载 + 解析器。示例:`patchwatch validate kb-csv KB5036893`。 |
| `validate kb-msu --cache-dir ` | 层级 2 KB 枚举:更新目录抓取 + MSU 下载 + `expand.exe` 解压 + 清单解析器。需要 `expand.exe` 在 `PATH` 中(它随 Windows 附带)。 |
| `validate winbindex ` | Winbindex 查询 + 补丁前后版本对选择 + 二进制文件下载到磁盘缓存。示例:`patchwatch validate winbindex mscms.dll KB5036893`。 |
| `validate ghidra ` | 在二进制文件自身上运行 ghidriff。验证 Docker 镜像(或本地安装)是否正确连接并返回退出码 0。 |
| `validate dry-run ` | 针对**内存中**的 SQLite 数据库进行完整的摄取 + 分析端到端测试。对于测试完整管道而不影响 `patchwatch.db` 很有用。 |
所有 `validate` 子命令都遵循与顶级 CLI 相同的 `--config` 标志。
## 安全和隐私说明
- PatchWatch 将 CVE 描述、文件名以及(在阶段 3 中)反编译的函数体发送到通过 `api_key_env` 配置的任何 LLM 端点。所有反编译代码均来自 Microsoft 发布的 Windows 二进制文件,这些文件已经可以公开下载,但请注意提示词的去向。
- Anthropic API 密钥和 CSRF 密钥从环境变量(或本地的 `.env` 文件,该文件已被 gitignore)加载。切勿提交其中任何一个。
- Web UI 默认绑定到回环地址,并使用 CSRF 双提交 Cookie。它没有身份验证——不要将其暴露给你无法控制的网络。
## 贡献
欢迎提交问题和 PR。这是一个研究工具,不是产品——预计会有粗糙的边缘和版本间的破坏性变更。
## 许可证
Apache 2.0 — 参见 [LICENSE](./LICENSE) 和 [NOTICE](./NOTICE)
由 [Origin](https://originhq.com) 为安全研究和红队操作构建。
标签:CVE处理, Docker, Ghidra, GPT, LLM分析, Patch Tuesday, Rust, Windows补丁星期二, 二进制差异分析, 云资产清单, 代码分析, 凭证管理, 可视化界面, 安全防御评估, 情报收集, 本地工具, 浏览器UI, 漏洞研究, 漏洞管理, 网络流量审计, 自动化分析, 补丁监控, 请求拦截, 跨站脚本, 软件补丁, 逆向工程, 通知系统