Reverse-replay / NTFS $LogFile
Recover the timestamps a file carried before it was stomped.
logflip walks the NTFS $LogFile undo chain backward to reconstruct pre-tamper state, then corroborates across three independent channels before it will ever call something tampering.
809 tests passing / mypy --strict / ruff clean / Python 3.11+
No public tool performs reverse-replay of NTFS $LogFile to reconstruct pre-tamper state and identify the tampering tool family.
the gap that is the entire reason this tool exists / NTFS Log Tracker, the closest prior art, reaches ~50% fidelity and does not perform the backward LSN walk.
The timestamps you read are whatever the attacker last wrote.
Timestomping writes attacker-controlled values into the $STANDARD_INFORMATION attribute of an MFT record. After the write, $SI reflects only what the attacker last set. The original timestamps are gone from the attribute.
The before-image survives in the $LogFile undo record. Every metadata change logged by NTFS leaves a redo and an undo entry in the circular $LogFile buffer. The undo entry carries the exact bytes that were in $SI before the stomp. logflip walks that chain backward to recover them.
$STANDARD_INFORMATION
$LogFile undo record (before-image)
A verdict is earned by agreement, not asserted from one signal.
The image is parsed ($MFT + $LogFile + $UsnJrnl, with USA fixup and multi-page RCRD reassembly), then three independent channels must agree.
01
Reverse-replay inversion
Backward LSN walk through the $LogFile undo chain. Each undo entry carries the before-image bytes from $STANDARD_INFORMATION. Walking backward reconstructs pre-tamper $SI without guessing.
02
SI-vs-FN delta screen
$STANDARD_INFORMATION versus $FILE_NAME - an independent source. $FILE_NAME is updated only at create, rename, or reparent, so divergence flags a likely stomp. Necessary but not sufficient on its own.
03
databaseFingerprint-DB attribution
Byte-pattern match against a signed, HMAC-verified tool-family database. The third and gating channel. Without a signed database and a real engagement key, this gate does not unlock.
GUARD
Confirmation has to be earned. By design, it is hard to reach.
A confirmed verdict requires agreement from distinct failure modes, so a single noisy channel can never carry a conviction on its own. The shipped fingerprint families are metadata-only (every pattern_hex is empty), so an empty-pattern guard makes a spurious byte match structurally impossible.
BY DESIGN
| Verdict | Meaning |
|---|---|
| clean | No byte disagreement on the target record. |
| provisional | Disagreement and an SI-vs-FN delta surfaced, no family confirmed. The ceiling with a stub DB or demo key. |
| confirmed | Every gate passed against a signed DB and a non-demo key. The stub DB and demo key can never reach this. |
| anomaly | Single-source lead only. Surfaced by scan as investigation, never as proof. |
Watch it run, then read the evidence it produced.
A real recording of the CLI, paired with the actual signed HTML report. No simulation, no upload.
The run
The evidence it produced
LOGFLIP Analysis Report
Best-effort recovered $SI (provisional)
logflip runs locally. Your evidence never leaves your machine.
BY DESIGN
What it catches, honestly.
Family identifiers trace to the signed DB manifest (tool_family value). One family is detected; one is documented as non-attributable. Both are shown honestly.
psstomp - PowerShell SI-only stomp
Updates $STANDARD_INFORMATION and leaves $FILE_NAME untouched. Detected through the SI-vs-FN delta channel: the discrepancy between SI and the independent FN timestamp surfaces the stomp.
setmace - dismount raw-write
Writes raw sectors after dismounting the volume, bypassing the log entirely. Emits no $LogFile or $UsnJrnl evidence and equalizes SI and FN timestamps. Non-attributable through any of the three pipeline channels. Documented honestly, not hidden.
Honest scope and limits.
Measured over 42 real-Windows images. A controlled-corpus methodology demonstration, consistent with Daubert reliability requirements. Not a real-world population rate.
Per-family FP rate is a structural zero.
The empty-pattern matcher guard precludes any byte match. Every shipped family carries an empty pattern_hex, making a spurious match structurally impossible.
Coverage window.
The $LogFile / $UsnJrnl rollover blind window (roughly 4 to 12h on active volumes) is the primary limit. Events older than the live window yield INCONCLUSIVE.
The honest ceiling on real input.
Reverse-replay and the SI-vs-FN delta can surface a finding, but byte-pattern tool-family attribution is unavailable without a signed DB and real key. provisional is the honest ceiling; confirmed is never reached on real input. This is the correct never-false-confirm behavior.
A standards-grade CLI. Scriptable, signed, auditable.
python -m pip install -e ".[dev]"
python -m logflip detect --image disk.img \
--mft-record 5 --output leaf.json --report report.html
Exit codes: 0 clean / 2 finding / 1 error. Keys are read from raw 32-byte files via --key-file, never the command line.
Evidence integrity
HKDF-SHA256 domain-separated keys, signatures over the RFC 8785 (JCS) canonical form, constant-time HMAC comparison. A single flipped byte fails verify-db; a tampered leaf fails verify-leaf.
Quality
809 tests passing, 18 skipped (need ntfsprogs or a live volume). mypy --strict clean. ruff clean. Python 3.11+. MIT licensed.

