File System Fragmentation Mapping and Time-Lining
You often can’t trust a standard “MAC times” timeline when an adversary timestomps $STANDARD_INFORMATION, renames files, or deletes entire directories. This guide teaches you how to map the physical fragments of a file across the disk and reconstruct a resilient chronology from NTFS internals and low-level journals-so you can explain what really happened even when typical metadata is gone.
At a high level, you will:
- Identify the file system geometry (cluster size, offsets) and extract unallocated space for carving. Tools like fsstat and blkls from The Sleuth Kit (TSK) provide those fundamentals fsstat manual and blkls manual. (sleuthkit.org)
- Carve for file signatures to find fragments independent of the file system’s directory structures (e.g., PhotoRec’s header/structure carving) PhotoRec documentation. (cgsecurity.org)
- Map carved fragments and known files to physical clusters (LCNs) and virtual cluster numbers (VCNs) using NTFS runlists and APIs that expose VCN↔LCN mappings (FSCTL_GET_RETRIEVAL_POINTERS) Microsoft FSCTL_GET_RETRIEVAL_POINTERS and RETRIEVAL_POINTERS_BUFFER. (learn.microsoft.com)
- Correlate fragments with NTFS metadata records (MFT), the Update Sequence Number (USN) Change Journal, and the NTFS transaction log ($LogFile) to build a timeline not reliant on potentially manipulated MAC times USN Change Journals overview, USN record structure, and $LogFile analysis tooling. (learn.microsoft.com)
Why this works: NTFS separates “what data sits where” (runlists mapping VCNs to LCNs) from file names and times. It also appends low-level summaries of changes into the USN Journal ($Extend$UsnJrnl) and records transaction details in $LogFile. Even when $MFT timestamps are forged, those other structures often retain independent evidence of creation, writes, renames, and deletes USN Change Journal records behavior and NTFS attribute types including $STANDARD_INFORMATION and $FILE_NAME. (learn.microsoft.com)
Technical Background
- NTFS stores every file as a set of attributes inside Master File Table (MFT) records. Data for large files is non-resident and described by data runs (runlists) mapping VCNs to LCNs Windows Internals/NTFS on-disk and linux-ntfs data runs explainer. (flylib.com)
- The file’s “ID” (File Reference Number) is 64 bits: low 48 bits are the MFT record index, high 16 are the sequence number (incremented when an MFT slot is reused) MS-FSA product behavior and MFT_SEGMENT_REFERENCE. (learn.microsoft.com)
- $STANDARD_INFORMATION (0x10) and $FILE_NAME (0x30) store overlapping timestamps that update differently; comparing them helps spot timestomping artifact note on MACB differences. (artefacts.help)
- USN Journal lives at $Extend$UsnJrnl, with two named streams: $J (records) and $MAX (journal metadata). Microsoft documents these stream names for NTFS metadata $J and $MAX stream names. (learn.microsoft.com)
- USN entries log change reasons using bit flags (e.g., DATA_OVERWRITE, FILE_CREATE). Renames produce two records (old parent/name and new parent/name). Timestamps are FILETIME USN_RECORD_V2. (learn.microsoft.com)
- USN journals can be queried and managed (fsutil usn) and they wrap/purge old entries; deletion/recreation requires admin privileges fsutil usn docs and Change Journal Records behavior including trimming. (learn.microsoft.com)
- $LogFile implements the NTFS Logging File Service (LFS) with restart and log record pages (RSTR/RCRD) holding redo/undo metadata updates; retention is circular and short on busy systems. Practical parsers can reconstruct attribute/runlist changes for a file reference LogFileParser project. (github.com)
- $Bitmap tracks which clusters are in use; deletion of non-resident data flips those bits to free, but remnants can persist in unallocated space $Bitmap artifact note. (artefacts.help)
- Volume Shadow Copy Service (VSS) snapshots use copy-on-write or redirect-on-write, preserving prior block versions for point-in-time access-useful for historic $MFT/$J/$LogFile states VSS provider methods. (learn.microsoft.com)
Step-by-Step Guide
Follow this workflow on a forensic image (E01/raw) mounted read-only.
- Establish the file system geometry
- Identify the NTFS partition and cluster size:
# Show NTFS stats (cluster size, first data unit, etc.)
fsstat -f ntfs image.E01
FS geometry (especially cluster size) is needed to translate byte offsets from carved data to cluster indexes fsstat manual. (sleuthkit.org)
- Extract unallocated space and, if needed, all data units
# Unallocated only (default)
blkls -f ntfs -i ewf image.E01 > image.unalloc
# All blocks (allocated + metadata) if you need complete scanning
blkls -f ntfs -i ewf -e image.E01 > image.everything
blkls concatenates chosen data units; you’ll use blkcalc later to map between unit numbers in this stream and the original image blkls manual and blkcalc manual. (manpages.opensuse.org)
- Carve for candidate fragments
- Run a content-based carver that ignores file system metadata. Example with PhotoRec (stand-alone or via Autopsy’s module):
Photorec: select target > options > file types > carve
PhotoRec searches for known headers/structures and can validate some formats (e.g., JPEG via libjpeg; OLE by internal FAT) but fragmentation can still break results PhotoRec approach and limitations. Advanced research shows strategies for fragmented reassembly (e.g., smart carving, bifragment gap carving) DFRWS 2007 object validation and bifragment gap carving overview. (cgsecurity.org)
- Map carved bytes back to disk clusters
- Determine where a hit lies in terms of data unit N in image.unalloc, then use blkcalc to translate to the original file system cluster index-and, if needed, ifind to see which MFT entry currently owns that cluster (or confirm it’s unallocated):
# Map unallocated stream unit 12345 back to the original FS unit
blkcalc -f ntfs -i ewf -u 12345 image.E01
# Example output: regular FS unit = 987654
# If the unit is allocated, find which MFT entry owns it
ifind -f ntfs -d 987654 image.E01
ifind “-d” finds the metadata structure that allocated a given data unit-linking a block back to a file when possible ifind manual and Autopsy data unit mapping guidance. (sleuthkit.org)
- Decode NTFS runlists (for known files) and build a fragment map
- For files that still have MFT entries (even deleted but not overwritten), inspect the runlist to enumerate LCN extents:
# Inspect an MFT record in detail
istat -f ntfs image.E01 <MFT_entry_number>
Under the hood, NTFS non-resident $DATA attributes store runlists mapping VCNs to LCNs; large/fragmented files may spill into an $ATTRIBUTE_LIST across multiple MFT records Windows Internals NTFS overview and resident vs non-resident attributes. (flylib.com)
- Programmatically, Windows offers FSCTL_GET_RETRIEVAL_POINTERS to retrieve VCN→LCN extents for a file handle; combine with FSCTL_GET_RETRIEVAL_POINTER_BASE to convert to absolute offsets FSCTL_GET_RETRIEVAL_POINTERS and FSCTL_GET_RETRIEVAL_POINTER_BASE. (learn.microsoft.com)
- Parse $MFT, USN $J, and $LogFile
- MFTECmd parses $MFT and can also parse $J and $LogFile into CSV or bodyfile outputs:
MFTECmd.exe -f C:\$MFT --csv C:\out
MFTECmd.exe -f C:\$Extend\$UsnJrnl:$J --csv C:\out
MFTECmd.exe -f C:\$LogFile --csv C:\out
MFTECmd capability list (MFT, $J, $LogFile) is documented in the project README MFTECmd. (github.com)
- Alternative dedicated parsers exist, e.g., UsnJrnl2Csv for $J and LogFileParser for $LogFile UsnJrnl2Csv and LogFileParser. (github.com)
- Build a non-traditional timeline
- Create a traditional bodyfile if you want a baseline:
# Collect MAC times from all FSes in an image into body format
tsk_gettimes image.E01 > body.txt
# Or create from fls/ils then use mactime
mactime -b body.txt -z UTC > timeline.csv
The bodyfile format and mactime process are standard TSK timeline components mactime manual and TSK gettimes. (sleuthkit.org)
-
Now enrich it with $J and $LogFile events and with your fragment-level cluster map. USN logs change reason flags and parent references (FileReferenceNumber and ParentFileReferenceNumber), enabling precise sequences of create→write→rename→delete independent of $SI/$FN times USN_RECORD_V2 fields. (learn.microsoft.com)
-
If Volume Shadow Copies exist, repeat MFT/USN/$LogFile extraction for each snapshot to time-travel the evidence state VSS overview. Tools like ntfs-linker can correlate base+VSS sets automatically ntfs-linker. (learn.microsoft.com)
- Reconnect fragments to activity
- When you find a fragment’s LCN range, look for $LogFile transactions that updated mapping pairs (runlist changes) for the same MFT File Reference around the same time, and match USN reason flags (DATA_EXTEND/OVERWRITE, RENAME_NEW_NAME/OLD_NAME) to the file’s lifecycle LogFileParser capabilities and USN reason flags. (github.com)
Key Artifacts and Evidence
- $MFT (root:$MFT) - file inventory, attributes, and runlists for non-resident data. Compare $STANDARD_INFORMATION vs $FILE_NAME timestamps to detect anomalies NTFS attributes and MACB behavior. (learn.microsoft.com)
- $Bitmap (root:$Bitmap) - allocation bitmask; confirms whether a cluster is free/used and helps interpret where deleted file data could remain artifact note. (artefacts.help)
- $Extend$UsnJrnl:$J and :$MAX - change journal data ($J) and journal metadata ($MAX) NTFS stream names and Change Journal basics. (learn.microsoft.com)
- $LogFile (root:$LogFile) - transactional records (redo/undo) for metadata changes; limited retention, but can reconstruct runlist changes for recent activity LogFileParser. (github.com)
- $I30 (directory index: $INDEX_ROOT/$INDEX_ALLOCATION/$BITMAP) - contains $FILE_NAME entries with their own MACB times; deletions can leave recoverable index records and slack I30 artifact overview. (artefacts.help)
What each tells you and why it matters:
- $MFT: who the file “was,” where its data lived (runlists), and two independent timestamp sources. Critical for tying fragments to an identity.
- $Bitmap: whether the cluster is logically free (useful for showing data persistence after deletion).
- USN $J: a sequential record of changes (create, write, rename, delete) tied to file references and parents-excellent for order-of-events even when times are forged.
- $LogFile: the “how” of metadata changes, including mapping-pairs updates; supports reconstructing where content moved and when.
- $I30: directory-view timestamps to corroborate/contrast against $MFT, plus carves of deleted entries.
Identification Techniques
- Fragment carving and validation
- Prefer structure-aware validation (e.g., verify JPEG markers, ZIP central directory) to reduce false positives DFRWS 2007 object validation. (dfrws.org)
- For two-fragment cases, consider bifragment gap carving to bridge a header with a second fragment when the gap is bounded method overview. (klennet.com)
- Cluster-to-file correlation
- Map LCNs to file references via runlists (MFT/FSCTL) and via ifind on unit numbers ifind manual and FSCTL_GET_RETRIEVAL_POINTERS. (sleuthkit.org)
- Timeline correlation
- Merge USN records (with reason flags and parent FNs) and $LogFile transactions for the same FileReference; check for RENAME_OLD_NAME followed by RENAME_NEW_NAME, then DATA_OVERWRITE/EXTEND during encryption or staging USN record semantics. (learn.microsoft.com)
Practical Examples
Example A - Reassembling a deleted DOCX (ZIP) beyond timestamps
- Carve a PK… ZIP header from unallocated and find its offset in image.unalloc.
- Use blkcalc to map unallocated unit → original FS unit; ifind to check if any current MFT entry owns it. If none, treat as orphaned fragment blkcalc manual and ifind manual. (sleuthkit.org)
- Parse $J and search for that FileReference: look for FILE_CREATE then DATA_EXTEND and later FILE_DELETE around the incident window USN semantics. (learn.microsoft.com)
- Parse $LogFile for UpdateMappingPairs/CreateAttribute transactions for the same FileReference to recover (or infer) runlist extents near the time of creation/extension LogFileParser. (github.com)
- Reassemble by joining adjacent LCN runs and format-validating the ZIP central directory. If only two fragments, a bounded search for the second fragment using bifragment gap carving may succeed bifragment method. (klennet.com)
- Add entries to your timeline showing content write growth (DATA_EXTEND), rename to final name, and delete, independent of MAC times Change Journal Records. (learn.microsoft.com)
Example B - Mapping ransomware activity without relying on MAC times
- USN often shows waves of RENAME_OLD_NAME/RENAME_NEW_NAME and DATA_OVERWRITE as encryption proceeds; correlate those with $LogFile transactions touching many FileReferences in a tight window USN reason flags. (learn.microsoft.com)
- Export $J from each VSS to show when particular directories were last in a clean state VSS overview. (learn.microsoft.com)
Validation and Pitfalls
- Assuming USN is infinite: NTFS trims the journal to conserve space; old entries are deleted and the journal can be cleared by admins Change Journal Records trimming and fsutil usn deletejournal. (learn.microsoft.com)
- Misreading rename sequences: renames produce two records (old/new) and final “CLOSE” summary records may coalesce reason bits; order matters USN_RECORD_V2 semantics. (learn.microsoft.com)
- Equating $SI and $FN times: they update under different rules; compare them and $I30 entries to spot timestomping MACB differences. (artefacts.help)
- Forgetting sparse/compressed behavior: an LCN of −1 in retrieval pointers indicates sparse/compressed conditions and needs special handling RETRIEVAL_POINTERS_BUFFER note. (learn.microsoft.com)
- Over-trusting carvers: header/footer carving can mis-join fragments or miss fragmented files. Use structure validation and, where feasible, smart-carving strategies DFRWS 2007. (dfrws.org)
Best Practices
- Always capture geometry first (cluster size), then preserve multiple evidence layers: $MFT, $J, $LogFile, $Bitmap, and VSS snapshots fsstat and VSS overview. (sleuthkit.org)
- Normalize time to UTC and annotate the source for each event (MFT vs USN vs $LogFile vs VSS) to defend your sequence in court mactime. (sleuthkit.org)
- Use file references (with sequence numbers) as primary keys when correlating across artifacts; they’re designed to detect MFT slot reuse MS-FSA file ID behavior. (learn.microsoft.com)
- Automate correlation where possible (e.g., ntfs-linker over base+VSS) but verify with manual spot-checks ntfs-linker. (strozfriedberg.github.io)
Takeaways
By combining content carving with NTFS-level cluster mapping and journal correlation, you can reconstruct a defensible story about a file’s life even when an attacker manipulates or deletes standard metadata. Use runlists (VCN↔LCN), USN reason flags, and $LogFile transactions to tie fragments to identities and actions, then timeline them across the base volume and any VSS snapshots. This non-traditional approach bypasses volatile metadata and focuses on durable, corroborating evidence across multiple layers of the NTFS stack NTFS internals overview and Change Journals. (flylib.com)
Sources / References
- Microsoft Learn - Change Journals (NTFS): https://learn.microsoft.com/en-us/windows/win32/fileio/change-journals
- Microsoft Learn - Change Journal Records: https://learn.microsoft.com/en-us/windows/win32/fileio/change-journal-records
- Microsoft Learn - USN_RECORD_V2: https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ns-winioctl-usn_record_v2
- Microsoft Learn - fsutil usn: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/fsutil-usn
- Microsoft Learn - NTFS Stream Names ($J, $MAX): https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/6b5e7e75-c2ad-4769-ad96-37077ee69702
- Microsoft Learn - FSCTL_GET_RETRIEVAL_POINTERS (Win32): https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-fsctl_get_retrieval_pointers
- Microsoft Learn - RETRIEVAL_POINTERS_BUFFER: https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ns-winioctl-retrieval_pointers_buffer
- Microsoft Learn - FSCTL_GET_RETRIEVAL_POINTER_BASE: https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-fsctl_get_retrieval_pointer_base
- Microsoft Learn - MFT_SEGMENT_REFERENCE: https://learn.microsoft.com/en-us/windows/win32/devnotes/mft-segment-reference
- Microsoft Open Specs - MS-FSA (File IDs behavior): https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fsa/4e3695bd-7574-4f24-a223-b4679c065b63
- Microsoft Open Specs - NTFS Attribute Types: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/a82e9105-2405-4e37-b2c3-28c773902d85
- Sleuth Kit - fsstat manual: https://www.sleuthkit.org/sleuthkit/man/fsstat.html
- Sleuth Kit - blkls manual: https://sleuthkit.org/sleuthkit/man/blkls.html
- Sleuth Kit - blkcalc manual: https://www.sleuthkit.org/sleuthkit/man/blkcalc.html
- Sleuth Kit - ifind manual: https://www.sleuthkit.org/sleuthkit/man/ifind.html
- Sleuth Kit - mactime manual: https://www.sleuthkit.org/sleuthkit/man/mactime.html
- Sleuth Kit - tsk_gettimes manual: https://www.sleuthkit.org/sleuthkit/man/tsk_gettimes.html
- Autopsy Help - Data Unit Analysis: https://www.sleuthkit.org/autopsy/help/data_mode.html
- CGSecurity - PhotoRec Data Carving: https://www.cgsecurity.org/wiki/PhotoRec_Data_Carving
- DFRWS - Carving Contiguous and Fragmented Files (Garfinkel): https://dfrws.org/presentation/carving-contiguous-and-fragmented-files-with-object-validation/
- Klennet - File carving methods (Bifragment gap): https://www.klennet.com/carver/carving-methods.aspx
- linux-ntfs - Data Runs concept: https://flatcap.github.io/linux-ntfs/ntfs/concepts/data_runs.html
- Windows Internals excerpt - NTFS on-disk: https://flylib.com/books/en/3.169.1.103/1/
- artifacts.help - $MFT, $MFTMirr, $Bitmap: https://artefacts.help/windows_mft.html
- artifacts.help - NTFS MACB timestamps ($SI vs $FN): https://artefacts.help/windows_macb_timestamps.html
- artifacts.help - $I30 Index Attributes: https://artefacts.help/windows_i30.html
- GitHub - EricZimmerman/MFTECmd: https://github.com/EricZimmerman/MFTECmd
- GitHub - jschicht/LogFileParser: https://github.com/jschicht/LogFileParser
- GitHub - jschicht/UsnJrnl2Csv: https://github.com/jschicht/UsnJrnl2Csv
- Microsoft Learn - Volume Shadow Copy Service: https://learn.microsoft.com/en-us/windows-server/storage/file-server/volume-shadow-copy-service
- Stroz Friedberg - ntfs-linker: https://strozfriedberg.github.io/ntfs-linker/