One carving contract, one single-pass sweep engine — the same carver recovers a deleted artifact from unallocated disk and from a memory image.
forensic-carve is the SecurityRonin fleet's carving foundation. A per-format
carver sees only &[u8] windows, so it is medium-agnostic by construction; the
sweep engine runs one aho-corasick detection pass over supplied regions (disk
unallocated extents or memory VAD regions), materializes only the window each hit
needs (detection ≠ materialization — a large artifact is never truncated to a scan
chunk), and hands it to the matching carver.
use forensic_carve::{Carver, Signature, CarveContext, CarvedItem, RecoveryMethod};
struct SqliteCarver;
impl Carver for SqliteCarver {
fn format(&self) -> &'static str { "sqlite" }
fn signatures(&self) -> &[Signature] {
const S: &[Signature] = &[Signature::new(b"SQLite format 3\0", 0)];
S
}
fn max_window(&self) -> u64 { 1 << 30 }
fn carve(&self, window: &[u8], ctx: &CarveContext) -> Vec<CarvedItem> {
// validate the header, bound the DB, then:
vec![CarvedItem::artifact_bytes(
"sqlite", ctx.base_offset(), 0.9,
ctx.recovery_method(), // echoed — UnallocatedCarve on disk, MemoryCarve in RAM
window.to_vec(),
)]
}
}use forensic_carve::{sweep, Region, CarveOptions, RecoveryMethod, registered_carvers};
let opts = CarveOptions { recovery_method: RecoveryMethod::UnallocatedCarve, ..Default::default() };
let items = sweep(&source, unallocated_regions, ®istered_carvers(), &opts);
// each item: the medium-neutral CarvedItem + its source offset + the region's attribution tagsource is any RegionSource (a positioned read_at): a disk ImageSource, or a
memory VirtualAddressSpace whose read_virt un-scatters physically-discontiguous
pages. Carvers register themselves with inventory::submit!, so a binary that
force-links them collects the whole set via registered_carvers() — the consumer
never depends on the parser crates.
Every carved item carries a RecoveryMethod — how it was recovered, set by which
sweep ran (carving is a recovery method):
| Variant | Source |
|---|---|
Tombstone |
a deletion the filesystem recorded (--deleted) |
FileInternalCarve |
a located artifact's own slack (freelist/WAL/ElfChnk) |
UnallocatedCarve |
whole-image unallocated carving (--unallocated) |
MemoryCarve |
a memory image (process VA region or physical frame) |
- Input-fuzzed.
fuzz_sweepdrives arbitrary bytes, out-of-range/zero-length regions, and arbitrary chunk sizes through the engine (138k+ execs, 0 crashes). - Panic-free by lint.
unwrap_used/expect_usedare denied in production; the engine returns no items on any malformed input rather than panicking. #![forbid(unsafe_code)]— nounsafe, anywhere.
Governing design: SecurityRonin fleet ADR 0001 (carving — one flag taxonomy, one sweep engine, one contract).