The most common question forensic analysts get from non-technical stakeholders is some variant of "can you prove this file existed?". When the file has been deleted from disk, the recycle bin emptied, and enough time has passed that the $MFT entry has been reused for something else, the answer almost always depends on what the USN journal still remembers. The journal is, in my experience, the most durable witness for "did this file ever exist" once everything else has been erased.
This post walks through what the journal preserves about deleted files, how to extract that evidence, and the cases where the journal is your last line.
What the journal keeps after deletion
When a file is deleted on NTFS, three things happen:
- The
$FILE_NAMEentry in the parent directory is unlinked. The directory'sINDEX_ALLOCATIONis rewritten without it. - The MFT entry is marked unused but not zeroed. The next file allocated to that entry overwrites the data runs, attributes and timestamps.
- The USN journal gets a
FileDelete | Closerecord naming the file, its parent reference, its MFT entry number and sequence, and the deletion timestamp.
The journal record is the most resilient of the three. The directory entry disappears the moment the parent is rewritten — sometimes within seconds on a busy volume. The MFT entry can be reused as soon as a new file is created — sometimes within minutes. The journal record sits in a ring buffer that turns over only after days or weeks.
For files deleted days ago, the journal typically gives you:
- The filename as a UTF-16 LE leaf. Just the leaf, no path.
- The parent directory MFT reference number. Combined with a parsed
$MFTit resolves to a path. - The deletion timestamp in FILETIME UTC.
- The MFT entry number and sequence number the file occupied. Useful for cross-referencing carved artefacts and
$LogFilebefore-images. - A lifecycle trace. The
FileCreate,DataExtend,BasicInfoChangeand rename records on the sameFileReferenceNumbertell you when the file was created, how it was written and whether its timestamps were ever modified before deletion.
A four-field tuple — MFT reference, filename, parent reference, deletion FILETIME — plus a creation event from earlier in the same journal is usually enough to satisfy a legal hold or to anchor a deeper investigation. Most of the time you also get the FileCreate record from the same $J, which gives you the file's age and a creation timestamp independent of $STANDARD_INFORMATION.
A minimal recovery workflow
With a parsed journal and a parsed $MFT (see the extraction guide for both):
- Filter by
FileDeletein the time window of interest. Sort by timestamp. This is your master list of deletions to triage. - Group by
FileReferenceNumberfor any deletion that matters. You get the file's full history: creation, writes, rename pairs, attribute changes and finally the delete. - Resolve the parent path via
$MFT. The parser on this page does it automatically when both files are supplied. Without$MFTyou stop at the leaf filename. - Cross-check
$LogFileif the deletion is very recent. It may still contain the "before" image of the directory entry, giving a second independent witness to the file's existence.
The combination "MFT reference, filename, parent path, creation timestamp, deletion timestamp, full lifecycle trace" is usually enough to write a defensible report.
When the parent path cannot be resolved
Sometimes the parent MFT entry has itself been recycled by the time you look — common on filesystem-busy hosts, particularly file servers and CI runners. The journal still gives you the filename and the parent reference number, but $MFT no longer knows what folder that reference used to point at.
Three fallbacks usually unstick the path:
Earlier RenameNewName records on the same parent reference. Group all journal records by parent reference. Any earlier RenameNewName whose new parent matches your unresolved reference, and whose own path resolves, tells you what folder that reference used to be.
$LogFile index entries. The crash-recovery log holds before-images of INDEX_ALLOCATION updates. Joachim Metz's libfsntfs and Jonas Schicht's LogFileParser extract them. On a recent enough deletion, the directory entry's before-image is still in $LogFile and resolves to a path.
Sibling files in the same parent reference. Group all journal records by parent reference. If one of the siblings was renamed into a directory whose MFT entry is still valid, pivot through it: the old parent at the time of rename is your unknown folder.
When none of those work, the parser will surface the file as "filename: notes.docx, parent: 1234-5" with no resolved path. That is intentional. Inventing a path you cannot verify is worse than admitting one is missing.
"Wiped" does not mean gone
File-shredding tools — CCleaner's secure delete, Eraser, BleachBit, sdelete — overwrite the file content and then delete it. They leave a louder journal trail, not a quieter one:
- Multiple
DataOverwrite | Closerecords on the file before itsFileDelete | Closeindicate intentional content overwriting. Normal deletion does not produce overwrites. - A
FileCreateplusDataOverwriteplusFileDeleteon the same file within seconds is the canonical evidence-destruction signature. - Where the shredder also wiped slack space by writing and then deleting filler files, those filler files have their own create/extend/overwrite/delete sequences — a swarm of records around the moment of destruction.
The MITRE ATT&CK mapping is T1485 Data Destruction for the content overwrite and T1070.004 File Deletion for the deletion itself. On a host where you suspect deliberate evidence destruction, the journal often gives you a tighter timestamp than any other artefact.
What about the file content
The USN journal never carries content. Only metadata about operations. If you need bytes back, the journal points you at the places to look:
- The MFT entry number of the deleted file. If the entry has not been reused,
$MFTstill holds the data runs and the content may be recoverable via The Sleuth Kit'sicator X-Ways. - The
$LogFilebefore-images for very recent deletions. - Volume Shadow Copies (VSS) if they exist on the host. The deleted file may live in a previous snapshot.
vssadmin list shadowson a live host orvshadowmountfrom libyal on an image will surface them. - Application-specific stores. OneDrive's online recycle bin, the Office "Autosaved" folder under
\Users\<u>\AppData\Roaming\Microsoft\Office\UnsavedFiles\, browser caches (the browser forensics tooling covers this), Outlook OST/PST staged copies. - The pagefile and a RAM dump if the file was open recently enough.
The journal's role is to tell you that a file existed and when it was deleted. Content recovery is downstream.
Practical limits
Ring-buffer window. Files deleted before the journal wrapped over the oldest record you can see are gone from this artefact. Pull $LogFile and shadow copies as complements.
Operations that do not hit the journal. Filesystem-level encryption changes that only update attributes, sparse-region writes that touch only the allocation map, and some NTFS reparse-point manipulations may produce no DataExtend or DataOverwrite records. The journal sees what NTFS chooses to log.
FileDelete with no preceding FileCreate. Means the file was created before the journal's current oldest record. Its lifecycle in $J is partial, but the deletion timestamp and parent reference still anchor a report.
Bind-mounted or volume-mounted shares. If the data lives on a remote filesystem, the journal on your host knows about local handles only. Pull the journal from the actual hosting filesystem.
Further reading
- Microsoft Learn — Change Journals covers the API surface and lifecycle that produces
FileDeleterecords. - The Sleuth Kit man pages —
icatandflsfor content recovery against still-allocated MFT entries. - SANS DFIR — the Windows Forensic Analysis poster puts the journal in context with
$LogFile, Volume Shadow Copies and other deletion-recovery artefacts on a single page. - Joachim Metz's libfsntfs — the open reference for
$LogFilebefore-image extraction when the deletion is fresh and the directory entry has not yet been overwritten elsewhere.