SecurityRonin/ewf-forensic
GitHub: SecurityRonin/ewf-forensic
针对 EWF/E01 取证镜像的七层完整性分析库,可检测签名伪造、链攻击、哈希篡改等多种异常,并对描述符校验和提供安全的非破坏性修复。
Stars: 0 | Forks: 0
ewf-forensic
针对 EWF / E01 镜像的取证完整性分析与修复
[](https://crates.io/crates/ewf-forensic) [](https://docs.rs/ewf-forensic) [](LICENSE) [](https://github.com/SecurityRonin/ewf-forensic/actions/workflows/ci.yml) [](https://www.rust-lang.org) [](https://github.com/sponsors/h4x0r) **验证镜像。信任证据。** `ewf-forensic` 是一个零依赖\*的 Rust 库,它读取原始的 EWF v1 (E01) 字节并准确报告存在的问题——以及哪些可以自动修复——而不会修改您的原始证据。 它能检测签名伪造、损坏的节链、循环链攻击、Adler-32 描述符损坏、卷几何结构不一致、表不匹配、越界块指针以及跨越七个不同分析层的 MD5 哈希不匹配。节描述符的 CRC 错误可在内存中修复;哈希不匹配将作为 `CannotRepair` 呈现,由您决定下一步操作。 \* `md-5` 是唯一的运行时依赖。 ## 安装 ``` [dependencies] ewf-forensic = "0.1" ``` ## 检查内容 ### 第 1 层 — 文件头 | 异常 | 严重程度 | |---------|----------| | `InvalidSignature` — EVF 魔术字节已损坏或缺失 | **严重** | | `SegmentNumberZero` — 段号字段为 0(无效) | 错误 | ### 第 2 层 — 节描述符完整性 | 异常 | 严重程度 | |---------|----------| | `SectionDescriptorCrcMismatch { offset, section_type, computed, stored }` — 描述符字节 [0..72] 的 Adler-32 与存储的校验和不匹配 | 错误 | ### 第 3 层 — 节链 | 异常 | 严重程度 | |---------|----------| | `SectionChainBroken { at_offset, next_offset }` — `next` 指针为零、超出 EOF 或向后指(循环) | **严重** | | `SectionGapNonZero { gap_offset, gap_size }` — 连续节之间存在非零字节 | 警告 | | `SectionGapZero { gap_offset, gap_size }` — 连续节之间存在零填充字节(在对齐填充的镜像中合法;作为结构性异常予以记录) | 信息 | ### 第 4 层 — 节完整性 | 异常 | 严重程度 | |---------|----------| | `VolumeSectionMissing` — 未找到 `volume` 或 `disk` 节 | **严重** | | `UnknownSectionType { offset, type_name }` — 节类型字符串不在 EWF v1 规范中 | 警告 | | `DoneSectionMissing` — 链在没有 `done` 节的情况下结束 | 警告 | ### 第 5 层 — 卷几何结构 | 异常 | 严重程度 | |---------|----------| | `BytesPerSectorInvalid { bytes_per_sector }` — 不是 512 或 4 096 | 错误 | | `ChunkSizeInvalid { sectors_per_chunk, bytes_per_sector }` — 为零或不是 2 的幂 | 错误 | | `SectorCountMismatch { declared, expected }` — `sector_count` 超出有效范围 `((chunk_count−1)×spc, chunk_count×spc]`;最后一块的填充是正常的,不进行标记 | 错误 | ### 第 6 层 — 表完整性 | 异常 | 严重程度 | |---------|----------| | `TableChunkCountMismatch { in_volume, in_table }` — 表头中的条目数与卷中的不同 | 错误 | | `TableEntryOutOfBounds { chunk_index, entry_offset, file_size }` — 块偏移量解析超出 EOF | 错误 | | `TableEntryOutsideSectorsRange { chunk_index, entry_offset, sectors_start, sectors_end }` — 条目解析位于文件内但在扇区数据主体之外(例如,指向描述符或表本身) | 错误 | ### 第 7 层 — 哈希验证 | 异常 | 严重程度 | |---------|----------| | `HashMismatch { computed, stored }` — 解压后扇区数据的 MD5 与存储的哈希不匹配 | 错误 | | `HashSectionMissing` — 未找到 `hash` 节 | 警告 | ## 使用方法 ### 分析 E01 镜像 ``` use ewf_forensic::{EwfIntegrity, Severity}; fn main() -> std::io::Result<()> { let data = std::fs::read("evidence.E01")?; let findings = EwfIntegrity::new(&data).analyse(); if findings.is_empty() { println!("clean — no anomalies detected"); return Ok(()); } for anomaly in &findings { let tag = match anomaly.severity() { Severity::Critical => "[CRITICAL]", Severity::Error => "[ERROR] ", Severity::Warning => "[WARNING] ", Severity::Info => "[INFO] ", }; println!("{tag} {anomaly:?}"); } Ok(()) } ``` ### 按严重程度分类 ``` use ewf_forensic::{EwfIntegrity, Severity}; let data = std::fs::read("evidence.E01").unwrap(); let findings = EwfIntegrity::new(&data).analyse(); let critical: Vec<_> = findings.iter() .filter(|a| a.severity() == Severity::Critical) .collect(); if !critical.is_empty() { eprintln!("{} critical finding(s) — image may be unreadable", critical.len()); } ``` ### 内存中修复(非破坏性) `EwfRepair` 绝不会触碰您的原始文件。它会克隆字节,仅应用安全的机械性修复(Adler-32 重算),并返回修补后的缓冲区以及包含已修复内容和无法修复内容的完整审计跟踪。 ``` use ewf_forensic::{EwfIntegrity, EwfRepair}; let original = std::fs::read("evidence.E01").unwrap(); let report = EwfRepair::new(original.clone()).repair(); // What was fixed automatically for r in &report.repairs { println!("repaired: {r:?}"); } // What still needs human review for c in &report.cannot_repair { println!("cannot repair: {c:?}"); } // Verify the patched image is now clean let post = EwfIntegrity::new(&report.data).analyse(); assert!(post.iter().all(|a| !matches!( a, ewf_forensic::EwfIntegrityAnomaly::SectionDescriptorCrcMismatch { .. } ))); // Write the repaired copy — original is untouched std::fs::write("evidence_repaired.E01", &report.data).unwrap(); ``` ### 可修复与不可修复项 | 异常 | 可修复? | 原因 | |---------|:-----------:|--------| | `SectionDescriptorCrcMismatch` | 是 | Adler-32 可从已有的字节中确定性地重新计算得出 | | `HashMismatch` | 否 | 无法确定是扇区数据还是存储的哈希是权威的 | | 所有其他项 | 否 | 结构性损坏需要分析师的判断 | ## 设计 - **干净镜像零分配** — 分析器返回一个空的 `Vec`,并且除了您传入的切片外,不触及任何堆内存。 - **无 unsafe 代码** — `ewf_forensic` 本身不包含任何 `unsafe` 块。 - **对抗性输入下不会 panic** — 每个解析器路径都是有界的;循环攻击和整数溢出都得到了明确处理。经 libfuzzer 验证(450 万次迭代,零崩溃)。 - **针对真实采集数据进行过验证** — 三个公开的 E01 样本(exFAT、邮件语料库、MMLS)中零误报,包含每个块 zlib 解压缩在内的完整 MD5 哈希验证。三个小镜像作为测试样本提交并在 CI 中运行。有关镜像来源、下载 URL 和复现步骤,请参见 [docs/VALIDATION.md](docs/VALIDATION.md)。 - **MSRV 1.85** — 无 nightly 版本要求,无不稳定特性。 ## 模糊测试 ``` cargo +nightly fuzz run fuzz_integrity cargo +nightly fuzz run fuzz_repair ``` 每次推送时,这两个目标都会在 CI 中运行 30 秒。要在本地运行更长时间,请移除 `-max_total_time`。 ## 异常目录 [`docs/anomaly-catalog.md`](docs/anomaly-catalog.md) 将每个可检测的异常映射到其威胁场景——证据压制、篡改、插入、重定向和解析器攻击——并记录了已知的检测限制。 ## 许可证 MIT — 详见 [LICENSE](LICENSE)。 [隐私政策](https://securityronin.github.io/ewf-forensic/privacy/) · [服务条款](https://securityronin.github.io/ewf-forensic/terms/) · © 2026 Security Ronin Ltd标签:CRC校验, E01, EWF, EWF格式, MD5校验, Rust, 可视化界面, 哈希校验, 域渗透, 完整性分析, 数字取证, 数字证据验证, 数据恢复, 数据防篡改, 文件结构解析, 电子数据取证, 网络安全, 网络流量审计, 自动化脚本, 证据保全, 通知系统, 镜像文件修复, 隐私保护, 零依赖库