SecurityRonin/peripheral-forensic
GitHub: SecurityRonin/peripheral-forensic
一款纯 Rust 实现的 Windows 外部设备连接取证工具,将 setupapi 设备安装日志解析为带威胁分级和 MITRE 映射的结构化外设接入时间线。
Stars: 0 | Forks: 0
# peripheral-forensic
[](https://crates.io/crates/peripheral-core)
[](https://crates.io/crates/peripheral-forensic)
[](https://docs.rs/peripheral-forensic)
[](https://www.rust-lang.org)
[](LICENSE)
[](https://github.com/sponsors/h4x0r)
[](https://github.com/SecurityRonin/peripheral-forensic/actions)
[](https://github.com/rust-secure-code/safety-dance/)
**将其指向 Windows 的 `setupapi.dev.log`,即可返回经过严重性分级的外部设备异常——包括具备 DMA 能能的 Thunderbolt/FireWire/PCIe 攻击面、可移动大容量存储设备、BadUSB 型 HID 设备,以及削弱了归因能力的 OS 合成序列号——输出格式为 `forensicnomicon::report::Finding`。**
一个工作区,两个 crate:
- **[`peripheral-core`](https://crates.io/crates/peripheral-core)** —— 读取器:将 `setupapi.dev.log` (Vista+) 和 `setupapi.log` (XP) 的设备安装日志解析为统一的 [`DeviceConnection`] 数据流——进行总线分类,提取 VID/PID/iSerial,并为每个时间戳标记为“权威”或“推断”。纯 Rust 实现,无 `unsafe`,无正则引擎,无日期库。
- **[`peripheral-forensic`](https://crates.io/crates/peripheral-forensic)** —— 分析器:将连接流转换为经过严重性分级的 [`forensicnomicon::report::Finding`](https://crates.io/crates/forensicnomicon),从而让外部设备证据能够与其余取证工具套件进行统一聚合。
## 在 30 秒内审计 setupapi 日志
```
[dependencies]
peripheral-forensic = "0.1" # pulls in peripheral-core
```
```
use peripheral_core::setupapi::parse_setupapi;
use peripheral_forensic::{audit, source};
let log = std::fs::read_to_string(r"C:\Windows\INF\setupapi.dev.log")?;
let devices = parse_setupapi(&log, "setupapi.dev.log");
for anomaly in audit(&devices) {
let finding = anomaly.to_finding(source("evidence-host"));
println!("[{:?}] {} — {}", finding.severity, finding.code, finding.note);
// e.g. [Some(High)] PERIPHERAL-DMA-CAPABLE-DEVICE — a Thunderbolt device … consistent with a direct-memory-access attack surface (MITRE T1200)
}
# Ok::<(), std::io::Error>(())
```
`audit(&devices)` 返回强类型的 [`DeviceAnomaly`] 流;`audit_findings(&devices, scope)` 可以通过一次调用完成从解析到 `Finding` 的转换。格式错误或乱码的日志会逐行降级处理,绝不会引发 panic。
## `DeviceConnection` 模型
每个设备安装节标题对应一条记录。取证警告被固化在**类型**中,而不仅仅是在文档中:
- **`device_serial` 是 USB iSerial——与 `volume_serial` 是完全不同的字段。** 文件系统卷序列号和设备硬件序列号是两码事;将它们分离为不同字段意味着两者在关联分析时绝不会混淆。
- **`serial_is_os_generated: bool`** —— 如果实例 ID 序列号的第二个字符是 `&`(例如 `7&1c2c4f0a&0`),则为 `true`。这代表 Windows 合成了该序列号,因为设备没有暴露真实的 iSerial,因此将其归因到特定物理设备的能力较弱。OS 生成的值*不会*被报告为真实的 `device_serial`。
- **每个时间戳都是 `Stamp { value, confidence }`。** 来自 setupapi 节标题的 `first_install` 是 `Authoritative`(权威);而源自注册表的 `last_arrival` / `last_removal`(未公开的 `0066` / `0067` 设备属性)是 `Inferred`(推断)——这些将在 v0.2 版本中提供。
- **关联连接键**(`parent_id_prefix`, `volume_guid`, `drive_letter`, `volume_serial`, `disk_signature`)和**威胁视角**(`dma_capable`, `mitre`)构成了记录的其余部分。
## 总线分类与威胁视角
Enumerator(设备实例 ID 的前导 token)对 [`Bus`] 进行分类,从而驱动两种威胁视角:
| 类别 | 总线 | 视角 | MITRE |
|---|---|---|---|
| **具备 DMA 能力** | FireWire, Thunderbolt, PCIe, ExpressCard | 总线主控直接内存访问攻击面 | T1200 |
| **大容量存储**(非 DMA) | USB 大容量存储, eSATA, SD/MMC, SCSI/SAS, NVMe | 数据暂存/外泄,autorun payload | T1052.001 / T1091 |
| **HID / 无线** | USB-HID, Bluetooth | 击键注入 | T1200 |
eSATA 是一种 SATA/存储传输协议,**明确不具备** DMA 能力。(注意:SD-Express 隧道化传输 PCIe,*可以*具备 DMA 能能;v0.1 将单纯的 `SD` 视为传统的非 DMA SD/MMC 总线——区分 SD-Express 需要 v0.2 注册表源提供的设备能力位。)
## 异常代码
每一个异常都是一个**观察结果**(“与……一致”);由检查人员得出结论。这些代码构成了一个稳定且已发布的契约。
| 代码 | 严重性 | 类别 | 观察内容 |
|---|---|---|---|
| `PERIPHERAL-DMA-CAPABLE-DEVICE` | 高 | 威胁 | 检测到 FireWire / Thunderbolt / PCIe / ExpressCard 设备连接——与直接内存访问攻击面一致 (MITRE T1200) |
| `PERIPHERAL-MASS-STORAGE-CONNECTED` | 中 | 威胁 | 检测到可移动大容量存储设备连接——与数据暂存/外泄或 autorun payload 传递一致 (MITRE T1052.001 / T1091) |
| `PERIPHERAL-HID-DEVICE` | 中 | 威胁 | 检测到人机接口设备连接——与 BadUSB 等击键注入硬件一致 (MITRE T1200) |
| `PERIPHERAL-OS-GENERATED-SERIAL` | 低 | 完整性 | 设备未暴露真实的 iSerial(Windows 合成了一个)——与设备归因能力变弱一致 |
## 解析内容(setupapi 格式覆盖范围)
`parse_setupapi(text, file)` 处理两种标题语法,并剥离了现实世界中的 `>>> ` / `<<< ` 节标记:
- **Vista+** —— 描述在前,时间戳在后:`[Device Install (Hardware initiated) - USB\VID_0781&PID_5583\ 2023/04/15 14:23:11.456]`
- **XP** —— 时间戳在前:`[2005/05/12 12:34:56 632.5] Device Install - USB\VID_...`
VID/PID、enumerator 和 iSerial 从设备实例 ID 中提取;节标题时间成为权威的 `first_install`。不匹配任何一种语法的行将被跳过——绝不会引发 panic。
## v0.2 路线图:注册表 `Enum\` + EVTX
最丰富的来源——Windows 注册表 `SYSTEM\CurrentControlSet\Enum\` 键(USBSTOR/USB 序列号,`ParentIdPrefix`)、`MountedDevices`(卷序列号 / 驱动器号 / 磁盘签名关联)、未公开的 `0066` / `0067` Last-Arrival / Last-Removal 设备属性 `FILETIME`,以及 EVTX 设备连接事件——需要(尚未发布的)`winreg-core` 和 `winevt-forensic` 工具套件 crate。这些被推迟到 **v0.2**;v0.1 的范围仅限于完全自包含的 `setupapi.dev.log` 源和完整的数据模型。
## 信任,但要验证
专为从潜在受损系统中获取的不可信日志而构建:
- **`#![forbid(unsafe_code)]`** 在两个 crate 中全面启用——无 FFI,无 C 绑定。它可以在任何操作系统上读取由 Windows 生成的日志。
- **在恶意输入下无 panic**——解析过程宽容(有损 UTF-8)且进行了边界检查;工作区在生产代码中拒绝使用 `clippy::unwrap_used` / `expect_used`。截断或乱码的日志会逐行降级,绝不会崩溃。
- **经过模糊测试**——两个 `cargo-fuzz` 目标(`setupapi` 解析,`forensic` 完整的解析→审计 pipeline);一个 `fuzz.yml` CI 工作流会构建并对每个目标进行冒烟测试。
- **基于精确规格的测试夹具验证**——分析器针对符合 Microsoft SetupAPI 文本日志语法的 `setupapi.dev.log` / `setupapi.log` 测试夹具进行了端到端测试,并成功重现了植入的 DMA / 大容量存储 / HID / OS 生成序列号痕迹(见 `forensic/tests/real_data.rs`)。
```
cargo test
cargo +nightly fuzz run forensic # requires nightly + cargo-fuzz
```
## 定位
`peripheral-forensic` 是 SecurityRonin 取证套件中的一个分析器。读取器/分析器的分离模式映射了 `ntfs-core`/`ntfs-forensic`;调查结果以共享的 `forensicnomicon::report` 词汇表发出,因此 [`issen`](https://github.com/SecurityRonin/issen) 可以将外部设备证据与磁盘、内存和日志工件进行关联。
[隐私政策](https://securityronin.github.io/peripheral-forensic/privacy/) · [服务条款](https://securityronin.github.io/peripheral-forensic/terms/) · © 2026 Security Ronin Ltd
标签:AMSI绕过, Rust, 可视化界面, 威胁检测, 数字取证, 网络流量审计, 自动化脚本, 设备识别, 通知系统