Digital Forensics / Advanced: models, validation, correlation, and reporting / Lesson 13
Model filesystem relationships without accessing media
Separate names, object identifiers, logical content, and storage mapping in a declared synthetic model.
On this page
Lesson goals
- Explain why a path is not a complete file identity.
- Keep logical byte order separate from a physical layout claim.
Use the filesystem’s own object model
A path names an entry in a namespace, while metadata and content can be represented by other structures. In ext4, directory entries reference inode numbers, and more than one entry can reference the same inode. Other filesystems use different structures and rules. The lesson’s model is deliberately simpler than ext4 and is not an on-disk parser. Preserve filesystem and volume scope when interpreting identifiers; the same number on another volume need not refer to the same object. A familiar path alone cannot establish historical content, ownership, or identity across time.
Show multiple names for one modeled object
The first program uses two synthetic names for one object id, then removes one name from a copied namespace. The other still resolves to the fixture content. This illustrates a relationship, not an actual unlink operation or recovery experiment. A real link count and object lifetime depend on the platform and state, and open references can add more context. Do not infer that a missing filename proves missing bytes or that matching names prove matching content. Keep name-level observations separate from metadata-level and content-level observations in the analytical notes.
names = {"notes-a.txt":"object-7", "notes-b.txt":"object-7"}
content = {"object-7": b"public fixture"}
after = dict(names)
del after["notes-a.txt"]
assert after["notes-b.txt"] == "object-7"
assert content[after["notes-b.txt"]] == b"public fixture"
assert "notes-a.txt" in names
print("one modeled name removed; shared object still referenced")
one modeled name removed; shared object still referenced
The complete program mutates an in-memory dictionary only and leaves the original fixture unchanged. It creates, deletes, mounts, or reads no actual file, volume, image, or device. It is not an ext4 implementation.
Reconstruct declared logical order explicitly
A file’s logical content order may differ from the physical order of its storage fragments. The second program concatenates two invented chunks according to a supplied logical map, then compares the result with an independently stated expected value. It does not discover fragments or recover a real file. Real mappings can include sparse regions, inline content, compression, encryption, or unsupported features. Never infer physical adjacency or original allocation history from this classroom list. Record the mapping source and validation limits before treating reconstructed content as a faithful representation of an artifact.
chunks = {9: b"world", 2: b"hello "}
logical_map = [2, 9]
reconstructed = b"".join(chunks[index] for index in logical_map)
assert reconstructed == b"hello world"
assert sorted(chunks) == [2, 9]
assert len(reconstructed) == 11
print("declared logical map reconstructs eleven fixture bytes")
declared logical map reconstructs eleven fixture bytes
The complete program combines two known byte values in memory. The map is fixture input, not a discovered extent table. It validates no physical layout, filesystem feature, storage device, or historical file content.
Interpret metadata with platform and feature context
Filesystem metadata fields can have feature-dependent meanings, units, checksums, and lifetime rules. A parser needs the relevant filesystem version and enabled features, not just a generic inode label. The official ext4 documentation illustrates why structure-specific reading matters, including metadata and directory relationships. This course does not implement those structures or access them. Treat an unsupported feature as a stated limitation rather than forcing it into a familiar layout. Preserve object references, raw values, and parser errors so later review can distinguish missing support from a genuinely absent object.
Keep model conclusions separate from media findings
Report the synthetic relationship demonstrated: two names referenced one object, and an explicit logical map produced expected bytes. Do not call those results evidence of actual hard links, deletion, allocation, or recovery on a real device. An approved real analysis would need trustworthy material, format-aware parsing, validation, and handling records. Logical size, allocated space, and available source bytes may answer different questions and should not be merged casually. A clear model is a teaching tool that helps formulate precise checks without pretending that those checks were performed against real media.
Common errors and fixes
A path is treated as timeless object identity
- Why it happens
- Namespace labels replace scoped metadata and content relationships.
- How to fix it
- Track volume, object reference, time, and content separately.
- Prevent it next time
- Review identity assumptions before joining artifacts.
A chunk list proves physical adjacency
- Why it happens
- Logical reconstruction is confused with storage layout.
- How to fix it
- State that the map is supplied and preserve layout uncertainty.
- Prevent it next time
- Separate logical and physical claims.
Unsupported features are parsed as a familiar format
- Why it happens
- The parser hides its capability boundary.
- How to fix it
- Retain unsupported status and use an approved validated interpretation.
- Prevent it next time
- Record filesystem and feature assumptions.
Check your understanding
1. One synthetic name is removed while another points to object-7. What is established?
Show worked solution
Only that the copied namespace retains one reference to the fixture object and its known content. No actual file was unlinked or recovered. Preserve that model scope and avoid generalizing it to a real filesystem’s deletion, open-reference, or storage behavior without separate evidence.
2. Why can identical inode numbers from two volumes be a bad join key?
Show worked solution
The identifier is scoped to its filesystem context and can also require time and generation context for historical analysis. Add the relevant volume and artifact relationships. A numeric match alone cannot establish that two records describe the same object or content.
Key takeaways
- Names, metadata objects, and content mappings are distinct layers.
- Identifiers need filesystem and temporal scope.
- Synthetic reconstruction establishes no real media finding.