SecurityRonin/qcow2-forensic
GitHub: SecurityRonin/qcow2-forensic
纯 Rust 实现的 QCOW2 虚拟磁盘取证工具,提供镜像读取与头部异常分级审计功能。
Stars: 0 | Forks: 1
[](https://crates.io/crates/qcow2-core)
[](https://crates.io/crates/qcow2-forensic)
[](https://docs.rs/qcow2-core)
[](LICENSE)
[](https://github.com/SecurityRonin/qcow2-forensic/actions/workflows/ci.yml)
[](https://github.com/sponsors/h4x0r)
**纯 Rust QCOW2 取证:读取任何 QEMU/KVM/libvirt 磁盘镜像,并标记审查员需要了解的信息 —— 只需两行代码。**
QCOW2 镜像隐藏了原始 `dd` 永远不会包含的东西:证据静默依赖的 backing file、早期客户机状态的内部快照、加密头部,或是 QEMU 自身的 *dirty* / *corrupt* 标志。该工作区提供了一个无 panic 的读取器**以及**一个审计器,将这些事实作为分级发现呈现出来。
```
// What is this image, and what should I worry about? — no decoding, no key needed.
for finding in qcow2_forensic::audit_path("evidence.qcow2".as_ref())? {
println!("[{:?}] {}", finding.severity(), finding.note());
}
// [Medium] image references a backing file — it is an overlay and does not alone contain the full guest data
// [Low] image carries 3 internal snapshot(s) — additional captured guest states to examine
// [High] the corrupt bit is set — QEMU flagged the image as corrupt
```
```
[dependencies]
qcow2-core = "0.2" # the reader: Read + Seek over the virtual disk
qcow2-forensic = "0.1" # the auditor: header anomalies as report::Finding
```
## 两个 crate,一个目标
| Crate | 角色 | 适用场景… |
|-------|------|--------------------------|
| **`qcow2-core`** (`use qcow2::…`) | 读取器 | 解码虚拟磁盘 — `Read + Seek`、v2/v3、deflate 簇、稀疏零 — 或在不解码的情况下 `inspect()` 头部。 |
| **`qcow2-forensic`** | 分析器 | 将镜像头部事实评级为按严重性排名的 `forensicnomicon::report::Finding`s。 |
### 读取虚拟磁盘
```
use qcow2::Qcow2Reader;
use std::io::{Read, Seek, SeekFrom};
let mut reader = Qcow2Reader::open("disk.qcow2".as_ref())?;
println!("virtual size: {} bytes", reader.virtual_disk_size());
let mut sector = [0u8; 512];
reader.read_exact(&mut sector)?; // first sector
reader.seek(SeekFrom::Start(1 << 20))?; // two-level L1→L2 cluster lookup
```
`Qcow2Reader` 实现了 `Read + Seek`,因此它可以直接接入任何接受 reader 的文件系统 crate 中。
### 不解码进行检查(适用于读取器无法打开的镜像)
```
let info = qcow2::inspect("encrypted.qcow2".as_ref())?;
assert!(info.encryption_method != 0); // header facts even when the data is inaccessible
assert!(info.has_backing_file);
```
`inspect()` 是刻意宽容的 —— 它会报告 backing file、加密、快照以及 v3 不兼容特性位,而不是直接拒绝,这样审计器就能对被严格读取器拒绝的镜像进行分析。
## 审计器标记的内容
| 代码 | 严重性 | 含义 |
|------|:--------:|---------|
| `QCOW2-CORRUPT` | 高 | QEMU 设置了 corrupt 不兼容特性位 |
| `QCOW2-BACKING-FILE` | 中 | Overlay/差分镜像 — 非自包含 |
| `QCOW2-ENCRYPTED` | 中 | AES/LUKS 加密 — 没有 key 无法访问内容 |
| `QCOW2-EXTERNAL-DATA` | 中 | 客户机数据存储在外部数据文件中 |
| `QCOW2-INTERNAL-SNAPSHOTS` | 低 | 需要检查的其他已捕获客户机状态 |
| `QCOW2-DIRTY` | 低 | 未干净关闭(使用中或崩溃) |
每一项都是基于共享的 [`forensicnomicon`](https://crates.io/crates/forensicnomicon) 报告模型的一个*观察结果*(“与……一致”),因此 QCOW2 发现可以与磁盘取证运行的其余部分统一汇总。结论由审查员得出。
## 信任,但要验证
通过构造实现只读和无 panic:`#![forbid(unsafe_code)]`,生产环境解析器中没有 `unwrap`/`expect`/未检查的索引,每个长度/偏移量都进行了边界检查,并且 `cargo fuzz` 目标(`open`/`read`/`inspect`/`forensic`)在处理精心构造的字节时绝对不会发生 panic。解码**通过与 `qemu-img convert` 进行差异验证**以及真实的 CirrOS 云镜像进行了校验;`inspect()` 已针对真实的 qemu-img 生成的 backing file、快照和 LUKS 镜像进行了校验。参见 [`docs/validation.md`](docs/validation.md)。
## 相关 crate
SecurityRonin 取证舰队的一部分 —— 每个容器格式都是一个 `*-core` 读取器加上一个基于共享 `forensicnomicon` 报告模型的 `*-forensic` 分析器:
[`ewf-forensic`](https://github.com/SecurityRonin/ewf-forensic) (E01) ·
[`vmdk-forensic`](https://github.com/SecurityRonin/vmdk-forensic) (VMware) ·
[`vhdx-forensic`](https://github.com/SecurityRonin/vhdx-forensic) (Hyper-V) ·
[`ntfs-forensic`](https://github.com/SecurityRonin/ntfs-forensic) (NTFS) ·
[`iso9660-forensic`](https://github.com/SecurityRonin/iso9660-forensic) (光盘) ·
[`disk-forensic`](https://github.com/SecurityRonin/disk-forensic) (`disk4n6` 编排器)。
[隐私政策](https://securityronin.github.io/qcow2-forensic/privacy/) · [服务条款](https://securityronin.github.io/qcow2-forensic/terms/) · © 2026 Security Ronin Ltd
标签:QCOW2, Rust, 可视化界面, 安全审计工具, 数字取证, 文件解析, 网络流量审计, 自动化脚本, 虚拟机磁盘, 身份验证强制