◇ OpenCyber Academy
Engineering · Chapter 28 · English

Chapter 28 — Digital forensics and malware analysis: implementation I

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 28 — Digital forensics and malware analysis: implementation I

Lesson map

Lesson 28 published. Map, example, EX082.

flowchart TD
  N0["Learning outcomes"]
  N1["28.1 Hash chains"]
  N2["28.2 Canonical form"]
  N3["Lab — tamper-evident custody"]
  N4["28.3 Reading the result"]
  N5["28.4 Anchoring"]
  N6["28.5 Corrections"]
  N7["28.6 Performance"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
  N7 --> EX["Worked example"]
  EX --> Q["Exercise EX082"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["28.1 Hash chains"]
  N2["28.2 Canonical form"]
  N3["Lab — tamper-evident custody"]
  N4["28.3 Reading the result"]
  N5["28.4 Anchoring"]
  N6["28.5 Corrections"]
  N7["28.6 Performance"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX082"]
[Learning outcomes]
    |
    v
[28.1 Hash chains]
    |
    v
[28.2 Canonical form]
    |
    v
[Lab — tamper-evident custody]
    |
    v
[28.3 Reading the result]
    |
    v
[28.4 Anchoring]
    |
    v
[28.5 Corrections]
    |
    v
[28.6 Performance]
    |
    v
[Worked example] --> [Exercise EX082]

Learning outcomes

You will (1) implement a hash-chained custody log; (2) detect an edited entry; (3) explain why later links break; (4) decide how corrections are recorded.

28.1 Hash chains

Each custody entry's link value is the hash of the previous link plus the entry's content. Changing any entry changes its link and every later link, so editing history is detectable by recomputing the chain.

Written as a formula, link_n = H(link_{n−1} ‖ entry_n), where the first link uses a fixed starting value. A verifier only needs the entries and the hash function to recompute every link and compare them with the stored values. Because each link depends on all earlier entries, the latest link value works as a fingerprint of the entire history up to that point.

28.2 Canonical form

Entries are serialised with sorted keys so the same content always produces the same bytes; otherwise harmless reordering would break the chain.

JSON allows the same object to be written in many ways: key order, spacing, number formats and escaped characters can all differ. Priya fixes the rules: sorted keys, no extra whitespace, UTF-8 encoding and times always written as ISO strings. A test serialises the same entry built in two different orders and checks that the bytes, and therefore the hashes, are identical.

Lab — tamper-evident custody

"""Hash-chained chain-of-custody log; detect an edited entry."""
import hashlib, json
def chain(entries):
    prev, out = "0"*64, []
    for e in entries:
        prev = hashlib.sha256((prev + json.dumps(e, sort_keys=True)).encode()).hexdigest()
        out.append(prev)
    return out
log = [{"item": "EV-7", "who": "Officer A", "act": "seized"},
       {"item": "EV-7", "who": "Clerk B", "act": "received"},
       {"item": "EV-7", "who": "Examiner C", "act": "imaged"}]
sealed = chain(log)
log[1]["who"] = "Clerk Z"
now = chain(log)
bad = [i for i, (a, b) in enumerate(zip(sealed, now)) if a != b]
print("entries:", len(log), "first broken link:", bad[0] if bad else None, "links affected:", len(bad))

Run with python3 lab_custody.py. Verified output:

entries: 3 first broken link: 1 links affected: 2

28.3 Reading the result

Three entries are sealed. When entry 1 (the clerk's receipt) is changed from "Clerk B" to "Clerk Z", recomputation shows the first broken link at index 1, and 2 links affected: that entry and the one after it. Entry 0 still verifies, telling the reviewer where history diverged.

Pointing at the first broken link matters in practice. A reviewer knows that entries before index 1 are untouched, and that the change happened at or after the clerk's receipt. Combined with backups or anchored values, they can then find out what the entry originally said. The exercise also shows that a later entry breaks even though its own content did not change.

28.4 Anchoring

A chain alone can be entirely rebuilt by someone with write access. Periodically printing or externally storing the latest link value (anchoring) prevents silent rebuilding: a rebuilt chain will not match the anchored value.

At Northfield the daily monitoring report includes the latest link value and is emailed to the quality manager, who is outside the examination zone, and printed for a paper file. Rewriting history would therefore mean altering the server, the emailed reports and the paper copies together. Priya's verifier accepts an anchor value as input and reports whether the current chain still passes through it.

28.5 Corrections

Mistakes are corrected by a new entry stating the correction and referencing the original, keeping the chain intact.

A correction entry names the entry it corrects by index and link value, states the corrected field and its new value, and gives a reason and the approver. Displays show the corrected value with a marker, and a click shows the original. Because nothing is overwritten, the chain stays valid and the record shows both the error and how it was put right.

28.6 Performance

Hashing small entries is fast; the chain is verified in milliseconds even for thousands of entries.

Priya measures it: verifying a synthetic chain of 100,000 entries takes under a second on the oldest lab workstation. That means the full chain can be checked on every server start, not just in the nightly job. The figure is recorded in the performance notes with the hardware details, so a later slowdown would be noticed and investigated. Verification time grows linearly with the number of entries.

28.7 Tests

Tests cover an untouched chain, an edited entry, a deleted entry and a reordered pair.

Each test states which link should fail first. Editing entry 5 should fail at 5. Deleting entry 5 should fail at the entry that now sits at index 5, because its stored previous-link value no longer matches. Swapping entries 5 and 6 should fail at 5. A further test with an empty chain confirms that the verifier reports 'no entries' rather than a false pass. A last test changes only the stored link value, not the entry, and expects the verifier to catch it.

Worked example

Priya anchors the latest link value each day in the quality manager's signed log. When testing a full rebuild attack in a synthetic scenario, the rebuilt chain verifies internally but its final value differs from the anchor, so the rebuild is detected.

Synthetic case. Entries come from the lab script.

Errors and limits

A chain detects changes; it does not prevent them or say who made them — access logs do that.

Exercises

Synthesis

Hash chains with canonical form and external anchors make custody history tamper-evident.

Continue studying — chapter 28 of 50

← Chapter 27 (draft) · Course chapter index · Chapter 29 (draft) →