You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: add Phase 18 ESE Integrity Hardening section to PLAN.md
Documents Phases 18-A/18-B/18-C (Severity enum, EseIntegrity unified
analyser, input robustness hardening) — the spec that was implemented
in the preceding six commits.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Modelled on `vhdx-forensic`'s `VhdxIntegrityAnomaly::severity()` and `WinevtIntegrity` unified analyser pattern. **Scope: detection and robustness only — no repair.**
1037
+
1038
+
ESE databases (including SRUM's `SRUDB.dat`) are frequent targets of anti-forensic manipulation. The existing `ese-integrity` crate has three anomaly variants but lacks severity stratification, a unified entry-point analyser, and coverage of the two highest-value structural checks: per-page checksum validation and B-tree consistency.
1039
+
1040
+
---
1041
+
1042
+
### Phase 18-A — `Severity` enum + `severity()` on `EseStructuralAnomaly`
Add `Severity` enum (identical definition to `vhdx-forensic`'s `Severity`; no shared dep — each crate owns its own copy per the no-cross-crate-import rule):
RED commit: Add stub `Severity` enum; add stub `severity()` returning `Severity::Info` for all variants; add new variant stubs with empty detection bodies; write tests asserting exact severity for every variant (old and new).
1144
+
1145
+
GREEN commit: Implement `severity()` per table above; implement detection logic for new variants.
`analyse()` short-circuits after `Critical` findings (analogous to `VhdxIntegrity::analyse()` halting after `ContainerTruncated`): if `check_layout()` returns `TruncatedDatabase`, the page and B-tree checks are skipped (they would produce false positives on missing pages).
1182
+
1183
+
`check_layout()` runs first; if the buffer is smaller than `ESE_HEADER_SIZE` (8192 bytes for the dual-shadow header), `analyse()` returns a single `TruncatedDatabase` immediately.
`EseHeader` stores `last_page_number: u32`. Iteration multiplies by `DB_PAGE_SIZE` (4096 or 8192 for large pages). No overflow check.
1211
+
1212
+
Fix: explicit `usize` overflow check on `page_number as usize * page_size`; return `Err` or emit `TruncatedDatabase` anomaly.
1213
+
1214
+
**2. Page size trust**
1215
+
1216
+
`EseHeader::page_size` is read directly as a slice offset multiplier. A crafted header with `page_size = 0` or `page_size > 32768` panics.
1217
+
1218
+
Fix: validate `page_size ∈ {4096, 8192, 16384, 32768}` immediately after header parse; reject all other values.
1219
+
1220
+
**3. Record offset trust within page**
1221
+
1222
+
Tag array entries in a page contain `offset` + `size` fields. No bounds check against `DB_PAGE_SIZE`.
1223
+
1224
+
Fix: check `offset + size <= page_bytes.len()` before slicing; return `Err` on violation.
1225
+
1226
+
**4. Checksum algorithm selection**
1227
+
1228
+
Two checksum variants (XOR-based legacy, ECC-based Vista+). The selection flag `PAGE_FLAG_NEW_FORMAT` may not be set on all Vista+ images. Add fallback: try both; report mismatch only if neither matches.
1229
+
1230
+
**TDD plan — Phase 18-C:**
1231
+
1232
+
For each gap: write a test with a crafted malformed buffer that currently panics or gives wrong output; then fix the parsing path. Tests live in `ese-core/tests/robustness_tests.rs` and `ese-integrity/tests/robustness_tests.rs`.
1233
+
1234
+
---
1235
+
1236
+
### Implementation order
1237
+
1238
+
1. Phase 18-A RED → Phase 18-A GREEN (severity + new variants)
1239
+
2. Phase 18-B RED → Phase 18-B GREEN (unified analyser) — depends on Phase 18-A severity enum
1240
+
3. Phase 18-C (robustness hardening) — independent; can be done in parallel with 18-B
| Create |`crates/ese-core/tests/robustness_tests.rs`| Malformed input tests for page/header parsing |
1248
+
| Create |`crates/ese-integrity/tests/robustness_tests.rs`| Malformed input tests for unified analyser |
1249
+
1250
+
### What is deliberately excluded
1251
+
1252
+
**No `ese-repair` crate.** ESE databases have a dual-shadow header (shadow copy at page 1), which is the only structurally repairable component. However, rewriting evidence file checksums or page-level bytes without an out-of-band reference is forensically dangerous. Detection and documentation of the anomaly is the correct forensic response. Callers who need working-but-annotated data can use `ese-carver` for page-level recovery.
0 commit comments