Skip to content
HN On Hacker News ↗

Going beneath NTFS: USN Journal, dfir_ntfs, and artefact-driven investigations

▲ 17 points 1 comments by ankitg12 4w ago HN discussion ↗

Pangram verdict · v3.3

We believe that this entire text is AI.

99 %

AI likelihood · overall

AI
0% human-written 100% AI-generated
SEGMENTS · HUMAN 0 of 1
SEGMENTS · AI 1 of 1
WORD COUNT 1,433
PEAK AI % 99% · §1
Analyzed
Jul 30
backend: pangram/v3.3
Segments scanned
1 windows
avg 1433 words each
Distribution
0 / 100%
human / AI fraction
Verdict
AI
Pangram v3.3

Article text · 1,433 words · 1 segments analyzed

Human AI-generated
§1 AI · 99%

A skilled attacker who has spent any time studying forensics will know to modify file timestamps. Some will go further and delete their tools, clear event logs, and rename artefacts before exfiltrating or detonating. What most do not account for, because most training does not cover it carefully, is that NTFS keeps a layered audit trail spread across at least three separate structures, and cleaning one of them rarely touches the others.

The Master File Table, the USN Journal, and the $LogFile each capture a different dimension of file system activity, at a different granularity and with different retention characteristics. When an analyst knows how to correlate all three, the story they tell is significantly harder to fully suppress than anything a single log or a timestamp suggests.

This article walks through that structure in practical terms: what each artefact contains, how to extract it, and where the intersections between them are most useful for investigations.

In brief

NTFS stores file metadata in at least two independent locations per file: $STANDARD_INFORMATION and $FILE_NAME inside the MFT. Attackers can modify one but not both through standard APIs. The USN Journal logs every file system change event sequentially, survives file deletion, and typically retains approximately 20 days of activity on an active volume. The $LogFile is a low-level transaction log that records redo/undo operations on NTFS metadata, providing independent evidence of when attributes were last written. dfir_ntfs and MFTECmd are complementary tools: one gives you programmatic access to raw NTFS structures; the other gives you analyst-ready CSV output for timeline correlation. File carving remains useful when MFT metadata is corrupted or missing, but it is best treated as a last resort. Correlating all three artefact layers produces a more robust timeline than any single source can provide.

The structure underneath the filesystem

Before getting into tooling, it helps to have a clear model of what NTFS actually stores about a file, because the forensic value of these artefacts only becomes obvious once you understand the redundancy involved.

Every file on an NTFS volume has at least one entry in the Master File Table, or $MFT (earlier overview). Each MFT entry is 1024 bytes and contains, among other things, two distinct sets of timestamps. The first set lives in the $STANDARD_INFORMATION attribute: the four MACB timestamps (Modified, Accessed, Created, $MFT entry modified) that most tools and the Windows Explorer interface expose. The second set lives in the $FILE_NAME attribute, which the NTFS kernel driver writes when the file is created and updates under a narrower set of circumstances. The critical forensic implication is that $FILE_NAME timestamps are written by the kernel and cannot be modified through standard Win32 APIs like SetFileTime. Most timestomping tools only reach $STANDARD_INFORMATION.

That asymmetry is the most reliable single indicator of timestamp manipulation available in NTFS forensics. A file where $STANDARD_INFORMATION Born is earlier than $FILE_NAME Born is, under normal filesystem operation, an impossibility. The kernel copies $SI values from $FN at creation time; any later backdating of $SI will diverge from the kernel-written $FN values. When you see that divergence, you are reading a contradiction in the metadata record, not making an inference.

The MFT also stores the file’s logical size, physical allocation, attribute list, and, for small files (typically under around 700 bytes), the file content itself as a resident attribute inside the MFT entry. This matters for carving: deleting a resident file does not free any cluster, it just marks the MFT entry as available for reuse. The content survives until the entry is overwritten.

USN Journal: the filesystem’s event stream

The USN Journal (\$Extend\$UsnJrnl) is an NTFS feature that has been available since Windows 2000 (dedicated post) and is enabled by default on modern Windows systems. Its primary stream, $J, records a sequential log of every file system change on the volume: file creates, renames, deletes, attribute changes, security descriptor updates, and more. Each record contains a 64-bit USN identifier, the filename, a parent MFT reference, a reason code bitmask (for example, USN_REASON_FILE_CREATE, USN_REASON_RENAME_OLD_NAME, USN_REASON_BASIC_INFO_CHANGE), and a timestamp.

The $MAX alternate data stream stores metadata about the journal itself, including the configured maximum size, which controls how far back the journal extends. On an active volume, this typically covers approximately 20 days of activity, though heavily active systems may retain significantly less. You can inspect this on a live system: fsutil usn queryjournal C:

For DFIR purposes, the USN Journal is valuable because it tracks changes rather than static file states. A file that has been deleted, timestomped, or renamed still leaves records behind. Consider the case of a tool deployed by an attacker that was later cleaned up with SDelete or a similar secure deletion utility. SDelete’s characteristic behaviour is to rename the target file multiple times before deleting it (AAA.AAA, BBB.BBB, and so on), then issue the delete. Each rename operation generates a RENAME_OLD_NAME and RENAME_NEW_NAME record in the USN Journal, producing a distinctive signature that survives the deletion itself.

The timestomping detection case is equally clean. A USN_REASON_BASIC_INFO_CHANGE record at a specific timestamp, correlated with the $SI/$FN discrepancy in the MFT, gives you two independent sources converging on the same event. Adding a Prefetch file for the timestomping binary, if it executed, gives you a third.

To extract the $J stream from a forensic image, you need to bypass the filesystem layer, since Windows will not give you direct access to NTFS metadata files through normal file operations. Two approaches work well in practice.

Using MFTECmd (Eric Zimmerman’s tool): MFTECmd.exe -f “E:\Evidence$J” –csv C:\output\ –csvf usn.csv

The resulting CSV includes UpdateTimestamp, Name, FileAttributes, UpdateReasons, ParentEntryNumber, and ParentSequenceNumber. To reconstruct full paths, you need to parse the $MFT alongside it and join on the parent MFT entry number: MFTECmd.exe -f “E:\Evidence$MFT” –csv C:\output\ –csvf mft.csv

Load both in Timeline Explorer and join on ParentEntryNumber. From there, filtering on USN_REASON_FILE_DELETE within your incident window, or looking for FILE_CREATE followed by FILE_DELETE within 60 seconds, covers a large fraction of malicious tool deployment and cleanup patterns.

dfir_ntfs: going below the surface

dfir_ntfs, the Python library developed by Maxim Suhanov (original post), targets a different use case than MFTECmd. Where MFTECmd is optimised for analyst-facing CSV output, dfir_ntfs is a programmatic interface to raw NTFS internals. It parses $MFT, $UsnJrnl:$J, and $LogFile directly, can work against volume images and volume shadow copies, and exposes the underlying structures in Python objects rather than spreadsheet rows.

Installation is straightforward:

pip3 install https://github.com/msuhanov/dfir_ntfs/archive/1.1.19.tar.gz

A minimal MFT parsing session:

import dfir_ntfs.MFT as MFT

with open('$MFT', 'rb') as mft_file: mft = MFT.MasterFileTableParser(mft_file) for file_record in mft.file_records(True): if not file_record.is_in_use(): continue si = file_record.get_standard_information() fn = file_record.get_file_name() if si and fn: si_created = si.get_created_time() fn_created = fn.get_created_time() if si_created and fn_created: if si_created < fn_created: print(f"[TIMESTOMP] {fn.get_file_name()} SI:{si_created} FN:{fn_created}")

That pattern, scanning for MFT entries where $SI Born is earlier than $FN Born, is one of the fastest automated timestomping detection passes you can run on a raw image. The NTFS driver cannot produce that condition under normal operation, so false positives are rare and usually traceable to known edge cases (volume cloning, VSS interactions) rather than attacker activity.

The library also provides access to volume shadow copies, which is where many investigations recover artefacts that an attacker deleted after gaining access but before VSS snapshots were removed. From a shadow copy, you can extract a $MFT state from an earlier point in time and compare it against the live MFT to identify entries that have been deleted or modified in between.

The third layer: $LogFile and what it tells you

The $LogFile is the NTFS transaction journal, a structure designed primarily to ensure filesystem consistency across crashes. It is also an independent source of metadata write events that most analysts overlook entirely.

$LogFile records redo and undo operations for NTFS metadata updates, including attribute changes, in terms of Log Sequence Numbers (LSNs). Each MFT entry carries the LSN of the most recent transaction that modified it. When you find a suspicious timestamp in $STANDARD_INFORMATION and want to independently confirm when it was last written, the corresponding $LogFile entry for that LSN gives you an out-of-band timestamp for the transaction itself.

Practical extraction is straightforward with NTFS Log Tracker (available at ForensicNote) or through dfir_ntfs’ LogFile.py module. In Timeline Explorer, loading both the MFT CSV and the $LogFile CSV and cross-referencing by LSN gives you a three-source timeline per file:

$FILE_NAME Born: kernel-written, reliable, rarely tampered with. $STANDARD_INFORMATION timestamps: the attacker-facing values, modified by timestomping tools. $LogFile LSN timestamp: when the NTFS driver last wrote the $SI attribute, independent of the value it wrote.