Skip to content
API Documentation
BastionGuard™
carving.hpp
Go to the documentation of this file.
1// carving.hpp -- file-system-agnostic file carving via magic signatures.
2//
3// File carving recovers files by scanning the raw disk for known magic
4// byte sequences. It works when filesystem metadata (MFT / inode table /
5// catalog B-tree) is destroyed but the file content is still intact on
6// disk. It complements the per-filesystem recovery -- carving runs
7// when filesystem recovery has been tried, OR when the user explicitly
8// asks to carve unallocated space.
9//
10// Core pipeline:
11// 1. Read the disk in chunks (16 MiB by default), with a sliding
12// overlap so that magic bytes spanning a chunk boundary are not
13// missed.
14// 2. For each chunk, scan for known magic byte sequences at every
15// byte offset (Boyer-Moore not needed; the inner loop is small
16// enough to be fast with a simple match).
17// 3. When a magic is found, invoke its FORMAT-SPECIFIC handler:
18// - parse the header to determine file size (header-driven
19// formats like BMP, WAV, ZIP)
20// - search for a footer signature within a reasonable window
21// (footer-terminated formats like JPEG, PNG, PDF, GIF)
22// - fallback to a fixed max size if neither works
23// 4. Validate post-magic structure to minimize false positives.
24// 5. Write the recovered bytes to <output>/carved/<format>/
25// <offset>_<id>.<ext>.
26//
27// Honest limits:
28// - Recovers FILE CONTENT only; no filenames, no directory structure
29// (the on-disk dirent/inode is gone -- carving doesn't change that).
30// - Fragmented files: only the FIRST contiguous run is recovered.
31// A defragmented disk yields nearly-100% recovery; a fragmented
32// one will recover partial files (the first chunk only).
33// - False positives: minimized via post-magic validation but not zero.
34// A 3-byte JPEG magic can statistically appear in random data.
35// - Encrypted or compressed-on-the-fly volumes (BitLocker, FileVault,
36// LUKS): NOT carved -- the bytes on disk are encrypted, magics
37// don't appear.
38
39#pragma once
40
41#include "models.hpp"
43#include "disk_reader.hpp"
44
45#include <cstdint>
46#include <string>
47#include <vector>
48
49namespace carving {
50
52 // Limit the scan to the first N bytes of the disk. 0 means no limit
53 // (= scan the whole disk). Defaults to 16 GiB to keep runtime
54 // bounded on huge disks; the user can override.
55 uint64_t max_bytes_to_scan {16ull * 1024 * 1024 * 1024};
56
57 // Maximum file size we are willing to carve. Beyond this we cap the
58 // output (= prefix of the file is saved). Most user document files
59 // are well under 500 MB; carving larger probably means a false
60 // positive runaway.
61 uint64_t max_file_size {500ull * 1024 * 1024};
62
63 // If set, skip carving formats whose magic is short (<=3 bytes) to
64 // reduce false positives. Default: keep all (the per-format
65 // validators do their own filtering).
66 bool skip_short_magic {false};
67};
68
69// Run the carving pass on `reader`. Recovered files are appended to
70// `recovered`; progress and warnings to `logs`.
71//
72// Returns true if any files were carved (false if zero results, but
73// not an error condition).
74bool run_carving(DiskReader& reader,
75 const std::string& output_dir,
76 const CarvingOptions& opts,
77 std::vector<RecoveredFileRecord>& recovered,
78 std::vector<std::string>& logs,
79 std::string& error);
80
81} // namespace carving
bool run_carving(DiskReader &reader, const std::string &output_dir, const CarvingOptions &opts, std::vector< RecoveredFileRecord > &recovered, std::vector< std::string > &logs, std::string &error)
Definition carving.cpp:954