Digital Forensics / Advanced: models, validation, correlation, and reporting / Lesson 14
Reason about memory and process records safely
Use created process snapshots to examine identity, parent relationships, and incomplete views without reading memory.
On this page
Lesson goals
- Explain why a PID or process name is not a stable identity across time.
- Retain missing relationships and acquisition limitations without labeling them malicious.
Distinguish a process record from a memory acquisition
A process inventory is a view of selected runtime metadata, while a memory image and its interpretation involve different material and assumptions. Live systems change during observation, and incomplete views can arise for many reasons. The Linux proc documentation is one platform reference; it is not a universal process schema. This lesson creates dictionaries only and reads no procfs, memory, dump, device, account, or live process. It provides no acquisition procedure and extracts no secrets. Every result concerns declared classroom records rather than an actual hostโs state.
Scope a process identity beyond its PID
A PID can be reused after a process exits, so equal numeric ids in different snapshots do not automatically identify one continuous process. Include the source context and a documented start-time or generation field when supported. The first program shows two invented records sharing a PID but differing in start marker. It demonstrates why a richer join key matters without claiming that these markers correspond to an actual operating-system time format. Process names can also be changed, duplicated, or misleading, so a name alone cannot establish executable integrity, operator identity, or intent.
first = {"source":"host-lab", "pid":42, "start":"generation-a", "name":"worker"}
second = {"source":"host-lab", "pid":42, "start":"generation-b", "name":"worker"}
identity = lambda p: (p["source"], p["pid"], p["start"])
assert first["pid"] == second["pid"]
assert first["name"] == second["name"]
assert identity(first) != identity(second)
print("same PID and name; distinct modeled process identities")
same PID and name; distinct modeled process identities
The complete program compares two local dictionaries with invented generation markers. It reads no host metadata and confirms no real PID reuse. The example establishes only that the selected identity key distinguishes the supplied records.
Keep missing parents as unresolved relationships
A parent id absent from a snapshot can reflect an incomplete view, exit, reparenting, parser support, or other platform behavior. It is not automatic proof of hidden malware. The second program separates a resolved parent from a missing reference and preserves both records in the accounting. This is a relationship check over synthetic data, not a process-tree detector. A real parent interpretation must consider source timing and platform semantics, including whether the reported relationship is creation-time or current state. Avoid inventing a parent node merely to make the graph visually complete.
processes = [{"pid":1,"parent":None}, {"pid":42,"parent":1}, {"pid":77,"parent":99}]
known = {p["pid"] for p in processes}
resolved = [p["pid"] for p in processes if p["parent"] in known]
unresolved = [p["pid"] for p in processes if p["parent"] is not None and p["parent"] not in known]
assert resolved == [42]
assert unresolved == [77]
assert len(resolved) + len(unresolved) + 1 == len(processes)
print("resolved and missing parent references retained")
resolved and missing parent references retained
The complete program organizes three invented records and counts one root separately. It performs no memory inspection, process enumeration, or malware detection. Missing reference 99 remains unexplained within the supplied fixture.
Compare views without assuming one is complete
Different tools or APIs may expose different runtime structures and require different symbols or version support. Disagreement can reveal a parser limitation, timing difference, or a real condition, so preserve it before choosing an explanation. A list of strings found in a memory-like fixture does not show which process used them or whether they were active at the relevant time. Content can be stale, duplicated, compressed, or unrelated. Do not interpret a suggestive path or domain as proof of execution or communication without supported object and time relationships.
Keep volatile-source limits in the report
Report the exact supplied record, extraction or mapping rule, identity key, timing context, and unresolved relationships. Explain that a synthetic snapshot is not a validated memory acquisition. Real volatile-material handling requires separate approved procedures, tools, authority, and privacy safeguards that are not performed here. The local examples teach identity and graph reasoning, not host triage or operational response. A careful finding can identify a missing relationship or conflicting view without converting it into an unsupported malware, persistence, or human-attribution claim.
Common errors and fixes
Equal PIDs across snapshots identify one process
- Why it happens
- Identifier reuse and source scope are ignored.
- How to fix it
- Use supported start/generation and source context.
- Prevent it next time
- Review identity keys before joining runtime records.
A missing parent proves malware
- Why it happens
- Incomplete relationships are assigned a malicious cause.
- How to fix it
- Retain alternatives and seek authorized corroboration.
- Prevent it next time
- Label unresolved references rather than inventing nodes.
A found string proves execution
- Why it happens
- Content presence is confused with object use and time.
- How to fix it
- Require supported process, source, and temporal relationships.
- Prevent it next time
- Keep string matches as leads with explicit limits.
Check your understanding
1. Two records share PID 42 and worker but have different start markers. What can be concluded?
Show worked solution
The chosen source/PID/start identity model distinguishes them. Their equal names and PIDs alone do not establish continuity. State that the markers are fictional and that no real process state was inspected, then preserve any uncertainty about how a real source defines start identity.
2. Why should unresolved parent 99 not be silently added as a known process?
Show worked solution
The fixture contains no record establishing that nodeโs properties or even its presence at the snapshot time. Add an explicit missing-reference marker if needed for display, clearly distinguished from an observed process. Do not fabricate a name, start time, or malicious role.
Key takeaways
- Runtime identifiers need source and temporal scope.
- Missing relationships are questions, not automatic malicious findings.
- Synthetic snapshots perform no memory acquisition or host inspection.