6.1 NTFS Architecture: Master File Table ($MFT) Record Structure & Attribute Headers
Key Takeaways
- The Master File Table ($MFT) serves as the definitive structural backbone of an NTFS volume, indexing every file and directory in fixed 1024-byte records, where records 0 through 15 are reserved for critical file system metadata files.
- Every MFT record begins with the 4-byte signature 'FILE' (0x454C4946 in little-endian) and incorporates an Update Sequence Number (USN) fixup array to validate physical sector integrity across 512-byte sector boundaries.
- MFT record attributes are either resident (data stored directly within the 1024-byte record boundary) or non-resident (data stored in external volume clusters tracked by compressed data runlists).
- The $STANDARD_INFORMATION attribute (0x10) stores general DOS flags and MACB timestamps accessible to user-mode APIs, whereas the $FILE_NAME attribute (0x30) stores secondary timestamps updated only during file movement or renaming.
- NTFS directories are structured as balanced B-Trees, holding small directory indexes inside resident $INDEX_ROOT (0x90) attributes and expanding larger directories into non-resident $INDEX_ALLOCATION (0xA0) b-tree nodes.
6.1 NTFS Architecture: Master File Table ($MFT) Record Structure & Attribute Headers
Quick Answer: The Master File Table ($MFT) is the central database of the Windows NT File System (NTFS). Every file and directory on an NTFS volume is allocated at least one 1024-byte MFT record (File Record Segment). Each record begins with the signature
FILE(0x454C4946in little-endian), contains an Update Sequence Number (USN) fixup array to detect torn sector writes, and holds a variable chain of attributes. Small files whose data fits within the record are stored as resident attributes; larger files become non-resident, utilizing data runs (runlists) that map Virtual Cluster Numbers (VCNs) to Logical Cluster Numbers (LCNs). Critical attributes include$STANDARD_INFORMATION(0x10, user-mode timestomp target),$FILE_NAME(0x30, kernel-protected timestamps), and$DATA(0x80, file payloads and alternate streams).
NTFS Architecture Fundamentals
Introduced with Windows NT 3.1, the New Technology File System (NTFS) was engineered to replace FAT by providing enterprise-grade reliability, security, scalability, and forensic auditability. Unlike FAT, which relies on static allocation tables and disconnected directory entries, NTFS treats all file system metadata as files.
Core Structural Characteristics of NTFS
- 64-bit Cluster Addressing: Supports theoretical volume sizes up to 2^64 clusters, with practical Windows implementations supporting volumes up to 256 TB (using 4 KB clusters) and up to 8 PB (using 2 MB clusters in modern Windows Server).
- Fault Tolerance & Metadata Journaling: Uses a write-ahead logging protocol via the
$LogFileto guarantee volume consistency across sudden power disruptions or kernel panics. - Granular Security: Native access control through Access Control Lists (ACLs) and Security Descriptors centralized within the
$Securesystem file. - Advanced Storage Primitives: Native support for Unicode file names (up to 255 UTF-16 characters), sparse files, per-file transparent compression (LZNT1), Encrypting File System (EFS), volume mount points, and Alternate Data Streams (ADS).
+-------------------------------------------------------------------------+
| NTFS VOLUME LAYOUT |
+-------------------------------------------------------------------------+
| VBR ($Boot) | System Files & $MFT | Data Cluster Space |
| Sector 0 - 15 | Records 0 - 15 + Users | User Files / Non-Res |
+-------------------------------------------------------------------------+
NTFS System Metadata Files (Records 0–15)
The first 16 records in the $MFT (MFT record numbers 0 through 15) are reserved exclusively for file system metadata. Each system file begins with a dollar sign ($) and fulfills a specialized operational and forensic role.
| Record # | System File | Type ID | Forensic Significance & Investigative Purpose |
|---|---|---|---|
| 0 | $MFT | Base Table | The Master File Table itself. Contains the master index of all files and directories on the volume. Forensic parsing recovers active files, deleted records, resident data, and directory structures. |
| 1 | $MFTMirr | Mirror | A duplicate backup of the first 4 records of $MFT (records 0–3: $MFT, $MFTMirr, $LogFile, $Volume). Located at the physical midpoint of the volume for catastrophic disaster recovery. |
| 2 | $LogFile | Journal | Transaction log implementing the ARIES recovery algorithm. Records low-level redo and undo metadata changes for crash consistency. Analyzed to prove file existence minutes prior to an incident. |
| 3 | $Volume | Metadata | Contains volume serial number, volume label, NTFS version, and volume state flags (such as the "dirty bit" indicating whether chkdsk must execute upon boot). |
| 4 | $AttrDef | Definitions | The Attribute Definition Table. Defines all attribute types supported by the volume, their hexadecimal identifiers (e.g., 0x10, 0x30, 0x80), allowable sizes, and indexing flags. |
| 5 | . | Root Directory | The root directory of the volume (\\). Serves as the hierarchical anchor point for all user-accessible paths and folders. |
| 6 | $Bitmap | Cluster Map | Cluster allocation bitmap for the entire volume. Each bit corresponds to one Logical Cluster Number (LCN): 0 = free / unallocated, 1 = allocated. Crucial for carving unallocated space. |
| 7 | $Boot | VBR | Volume Boot Record. Contains the BIOS Parameter Block (BPB), partition sector count, cluster size (typically 4096 bytes / 8 sectors), starting cluster of $MFT, and NTFS bootstrap loader code. |
| 8 | $BadClus | Defect List | Tracks bad or damaged storage clusters across the drive. Non-resident stream tracks physical defects. Anti-forensics actors may artificially allocate clusters here to conceal data from standard forensic imaging. |
| 9 | $Secure | Security Table | Centralized database of Security Identifiers (SIDs) and Access Control Lists (ACLs). Utilizes two internal streams: $SDH (Security Descriptor Hash index) and $SII (Security ID Index) to eliminate redundant ACL storage. |
| 10 | $UpCase | Unicode Table | Unicode uppercase translation table (128 KB). Enables case-insensitive file lookups in Win32 while maintaining case-sensitive fidelity for POSIX subsystem compatibility. |
| 11 | $Extend | Directory | Directory containing optional feature extensions, including $Quota (disk quotas), $ObjId (distributed link tracking), $Reparse (symbolic links/junctions), and $UsnJrnl (Change Journal). |
| 12–15 | Reserved | N/A | Reserved by Microsoft for future architectural expansion. |
[!NOTE] MFT record numbers
16through23are generally reserved for future use or hold initial user data, while user-created files and subdirectories typically start at record24or higher depending on the Windows operating system version and format parameters.
The 1024-Byte MFT Record Architecture
Every file and directory entry in NTFS is represented by a 1024-byte record (File Record Segment - FRS). If a file contains a vast number of attributes or heavily fragmented data runs that exceed 1024 bytes, NTFS allocates secondary records called child records, linking them to the primary record via the $ATTRIBUTE_LIST (0x20) attribute.
+-------------------------------------------------------------------------+
| 1024-BYTE MFT RECORD |
+-------------------------------------------------------------------------+
| Standard Record Header | Fixup Array | Attribute 1 | Attribute 2 | ... |
| Bytes 0x00 - 0x2F | 6-8 Bytes | $STD_INFO | $FILE_NAME | $DATA|
+-------------------------------------------------------------------------+
Binary Layout of the MFT Record Header
The record header occupies the first 48 to 56 bytes (offset 0x00 to 0x30 / 0x38) of the 1024-byte block.
| Byte Offset | Field Size | Field Name | Description & Forensic Interpretation |
|---|---|---|---|
0x00 - 0x03 | 4 Bytes | Magic Signature | ASCII string FILE (0x46 0x49 0x4C 0x45, little-endian 0x454C4946). If a hardware or write failure occurs, marked as BAAD (0x44414142). |
0x04 - 0x05 | 2 Bytes | Offset to Fixup Array | Byte offset from the record start to the Update Sequence Array (typically 0x2A 0x00 or 0x30 0x00). |
0x06 - 0x07 | 2 Bytes | Fixup Array Size / Count | Number of 2-byte entries in the fixup array (S + 1, where S is the sector count; for a 1024-byte record over two 512-byte sectors, count is 0x03 0x00). |
0x08 - 0x0F | 8 Bytes | $LogFile LSN | LogFile Sequence Number. Tracks the last transaction in $LogFile that altered this record. |
0x10 - 0x11 | 2 Bytes | Sequence Number | Incremented by 1 each time the MFT record is deallocated and reassigned to a new file. Detects dangling pointers and validates file references. |
0x12 - 0x13 | 2 Bytes | Hard Link Count | Number of directory entries pointing to this MFT record (e.g., hard links created via mklink /H). |
0x14 - 0x15 | 2 Bytes | Offset to 1st Attribute | Byte offset where the first attribute begins (commonly 0x38 0x00 = 56 decimal). |
0x16 - 0x17 | 2 Bytes | Record Flags | Bitmask indicating allocation and file type: 0x0000 = Deleted File; 0x0001 = Active File; 0x0002 = Deleted Directory; 0x0003 = Active Directory. |
0x18 - 0x1B | 4 Bytes | Real Size of Record | Exact number of bytes used by the record header and attributes within the 1024-byte buffer. |
0x1C - 0x1F | 4 Bytes | Allocated Size | Total allocated buffer size, always 0x00000400 (1024 bytes). |
0x20 - 0x27 | 8 Bytes | Base Record Reference | File Reference Number (FRN) of base record. 0x0000000000000000 if this is the base record; points to parent FRN if this is a child record. |
0x28 - 0x29 | 2 Bytes | Next Attribute ID | ID value assigned to the next attribute appended to this record. |
0x2A - 0x2F | Variable | Fixup Array (USA) | Contains the Update Sequence Number (USN) followed by the original 2-byte values swapped out from the ends of each 512-byte sector. |
Fixup Array & Update Sequence Number (USN) Protection
Hard drives write data in physical sectors (typically 512 bytes). Because an MFT record is 1024 bytes, saving an MFT record requires writing across two contiguous sectors. If power fails mid-write, a torn write occurs (Sector 1 written, Sector 2 stale).
To detect this corruption:
- Before writing the MFT record to disk, the operating system increments a 2-byte Update Sequence Number (USN) stored at the start of the Fixup Array.
- The OS copies the original last 2 bytes of Sector 1 (bytes 510–511) and Sector 2 (bytes 1022–1023) into the Fixup Array.
- The OS replaces the last 2 bytes of Sector 1 and Sector 2 with the USN value.
- When reading the record back from disk, the file system checks whether the last 2 bytes of each sector match the USN in the record header. If they match, the OS restores the original bytes from the Fixup Array into memory. If they do not match, the signature is overwritten with
BAAD, and the record is flagged as corrupt.
Resident vs. Non-Resident Attributes & Data Runs
In NTFS, every piece of data associated with a file—including its metadata, security settings, file name, and actual binary content—is stored as an attribute.
+-------------------------------------------------------------------------+
| STANDARD ATTRIBUTE HEADER (16 OR 64 BYTES) |
+-------------------------------------------------------------------------+
| Type ID (4B) | Length (4B) | Res Flag (1B) | Name Len (1B) | Name Off (2B)|
+-------------------------------------------------------------------------+
The Common Attribute Header
All attributes begin with a common header structure:
- Attribute Type ID (4 bytes): Numeric identifier (e.g.,
0x10 0x00 0x00 0x00for$STANDARD_INFORMATION). - Length of Attribute (4 bytes): Total length of the attribute including the header.
- Non-Resident Flag (1 byte):
0x00indicates Resident;0x01indicates Non-Resident. - Name Length (1 byte):
0x00for unnamed attributes (e.g., default data stream); >0 for named streams (e.g., Alternate Data Streams). - Name Offset (2 bytes): Offset to the Unicode stream name.
- Flags (2 bytes):
0x0001= Compressed,0x4000= Encrypted,0x8000= Sparse. - Attribute ID (2 bytes): Unique instance identifier within this MFT record.
Resident Attributes
When an attribute is resident (Non-Resident Flag = 0x00), the attribute's payload is stored directly inside the 1024-byte MFT record immediately following the attribute header.
- Value Length (4 bytes): Exact byte size of the attribute content.
- Value Offset (2 bytes): Offset from the start of the attribute header to where the content begins.
- Indexed Flag (1 byte):
0x01if indexed.
[!IMPORTANT] Forensic Impact of Resident $DATA: If a file is small (typically <= 700 bytes, such as small scripts, text documents, or batch files), its entire content is stored inside the
$DATA(0x80) attribute within the MFT record. When a resident file is deleted, the operating system marks the MFT record flag as0x0000(deleted) but does not zero out the record content. The entire file payload remains 100% intact and instantly recoverable from the$MFTitself, without scanning unallocated cluster space!
Non-Resident Attributes & Data Runs (Runlists)
When a file's content exceeds the available space in its 1024-byte MFT record, the $DATA attribute becomes non-resident (Non-Resident Flag = 0x01). The MFT record retains the attribute header, but the actual file content is written to clusters in the volume's Data Cluster Space.
The non-resident header contains:
- Starting Virtual Cluster Number (VCN) (8 bytes): Starting cluster relative to the file (typically 0).
- Ending VCN (8 bytes): Final VCN allocated to this stream.
- Offset to Runlist (2 bytes): Offset to the data run mapping from the start of the attribute header.
- Allocated Size (8 bytes): Cluster-aligned disk space allocated (VCN count * Cluster Size).
- Real Size (8 bytes): Exact physical byte size of the file.
- Initialized Size (8 bytes): Size of data written to disk (prevents reading uninitialized data).
Decoding Data Runs (Runlists)
A data run (or runlist) is a compact, variable-length byte structure that maps Virtual Cluster Numbers (VCNs within the file) to Logical Cluster Numbers (LCNs on the physical partition).
+-------------------------------------------------------------------------+
| DATA RUN BYTE STRUCTURE |
+-------------------------------------------------------------------------+
| Run Header Byte | Run Length | Run Offset |
| High: Offset Len | (VCN Count) | (Starting LCN) |
| Low: Length Len | L Bytes Wide | O Bytes Wide |
+-------------------------------------------------------------------------+
Each data run begins with a single Run Header Byte:
- Low Nibble (bits 0–3): Number of bytes representing the Run Length (number of contiguous clusters).
- High Nibble (bits 4–7): Number of bytes representing the Run Offset (starting LCN, signed relative offset from the previous run).
Worked Forensic Example 1: Single Data Run
Suppose raw hex analysis of an MFT record at the runlist offset reveals:
32 01 26 00 40 12 00
- Run Header Byte:
0x32- Low Nibble =
2-> Run Length is 2 bytes wide. - High Nibble =
3-> Run Offset is 3 bytes wide.
- Low Nibble =
- Run Length (2 bytes):
01 26-> In little-endian, this is0x2601= 9,729 clusters. - Run Offset (3 bytes):
00 40 12-> In little-endian, this is0x124000= Cluster 1,196,032. - Next Byte:
0x00-> Signifies the end of the runlist.
- Conclusion: The file is contiguous, occupying 9,729 clusters starting at physical cluster 1,196,032.
Worked Forensic Example 2: Fragmented Data Run with Signed Relative Offset
Suppose the hex reads:
21 10 50 08 21 08 B0 FF 00
- First Run (
21 10 50 08):- Header
0x21: Length is 1 byte, Offset is 2 bytes. - Length:
0x10= 16 clusters. - Offset:
0x0850= Cluster 2,128. - File occupies clusters 2,128 through 2,143.
- Header
- Second Run (
21 08 B0 FF):- Header
0x21: Length is 1 byte, Offset is 2 bytes. - Length:
0x08= 8 clusters. - Offset:
0xFFB0-> Because the high bit is set (0xF), this is a negative two's complement integer!0xFFB0= -80 decimal. - Relative Calculation: 2,128 + (-80) = Cluster 2,048.
- File continues for 8 clusters starting at cluster 2,048.
- Header
- Terminator:
0x00indicates end of runlist.
Core Attribute Headers in DFIR
While NTFS defines dozens of attribute types in $AttrDef, digital forensics focuses primarily on five core attributes.
+-------------------------------------------------------------------------+
| CORE NTFS ATTRIBUTES |
+-------------------------------------------------------------------------+
| 0x10: $STANDARD_INFO | Timestamps, DOS flags (User-mode accessible) |
| 0x30: $FILE_NAME | Parent FRN, Name, Timestamps (Kernel-protected) |
| 0x80: $DATA | Unnamed (payload) or Named (ADS streams) |
| 0x90: $INDEX_ROOT | Small resident directory B-Tree root node |
| 0xA0: $INDEX_ALLOC | Large non-resident directory B-Tree INDX buffers |
+-------------------------------------------------------------------------+
1. $STANDARD_INFORMATION (0x10)
Always resident. Contains general file metadata defined for DOS and Win32 compatibility:
- MACB Timestamps (32 bytes total): Four 64-bit Windows
FILETIMEvalues (number of 100-nanosecond intervals since January 1, 1601 UTC):- M - Modification (Last Written)
- A - Access (Last Accessed)
- C - MFT Record Change (Metadata Changed)
- B - Birth (File Created)
- DOS File Permissions (4 bytes): Bitmask (
0x01Read-Only,0x02Hidden,0x04System,0x20Archive). - Maximum Versions (4 bytes), Version Number (4 bytes), Class ID (4 bytes).
- Security ID (4 bytes): Key linking into
$Secure($SII/$SDHstreams).
[!WARNING] Timestomping Susceptibility: The timestamps inside
$STANDARD_INFORMATIONcan be altered arbitrarily by standard user-mode Win32 API functions such asSetFileTime()or adversary tools like Meterpreter'stimestompor PowerShell(Get-Item file).CreationTime = ....
2. $FILE_NAME (0x30)
Always resident. Contains directory linkage and file naming information. A file can have multiple $FILE_NAME attributes (e.g., one for its Win32 long name and another for its DOS 8.3 short name, or multiple names resulting from hard links).
- Parent Directory FRN (8 bytes): 6-byte MFT record number + 2-byte sequence number of the parent folder.
- Secondary MACB Timestamps (32 bytes): Independent set of Creation, Modification, MFT Change, and Access timestamps.
- Allocated & Real Size (16 bytes): File dimensions tracked at directory level.
- Flags (4 bytes): Directory/file flags.
- Name Length (1 byte) & Namespace (1 byte):
0= POSIX,1= Win32,2= DOS 8.3,3= Win32 & DOS. - File Name (Variable): UTF-16LE string.
[!IMPORTANT] The Timestomping Detection Anchor: The timestamps in
$FILE_NAMEare maintained directly by the NTFS kernel driver. Standard user-mode APIs likeSetFileTime()cannot update$FILE_NAMEtimestamps; they update only$STANDARD_INFORMATION. The$FILE_NAMEtimestamps are updated only when a file is created, moved, or renamed. If an examiner discovers that$STANDARD_INFORMATIONCreation Time is older than$FILE_NAMECreation Time, or if$FILE_NAMEshows a recent modification during an incident window while$STANDARD_INFORMATIONclaims the file was installed years ago, timestomping is scientifically proven.
3. $DATA (0x80)
Holds the raw content of the file. An MFT record can contain multiple $DATA attributes:
- Default Stream: Unnamed (
Name Length = 0). Contains standard file content. - Alternate Data Streams (ADS): Named streams (
Name Length > 0), such asinvoice.pdf:Zone.Identifier.
4. $INDEX_ROOT (0x90) & $INDEX_ALLOCATION (0xA0)
Directories do not store file payloads; they store indexes of other MFT records organized as B-Trees for O(log n) lookup speed:
- $INDEX_ROOT (
0x90): Always resident. Contains the root node of the B-Tree index. If a directory contains only a few files (typically fewer than 15–20), all directory entries fit entirely inside$INDEX_ROOT. - $INDEX_ALLOCATION (
0xA0): Non-resident. Used when a directory grows too large for$INDEX_ROOT. Contains external 4096-byte blocks called INDX records, each holding B-Tree child nodes. - $BITMAP (
0xB0): Maps the allocation of INDX blocks within$INDEX_ALLOCATION.
Practical DFIR Tool Commands & Workflows
Forensic examiners routinely inspect MFT structures using The Sleuth Kit (TSK) and commercial tools to extract evidence from raw disk images.
# 1. View volume file system details (cluster size, MFT starting cluster)
fsstat -o 2048 /dev/sdb1
# 2. Inspect MFT record 24500 (displays all attributes, timestamps, and runlists)
istat -o 2048 /dev/sdb1 24500
# 3. List directory contents including deleted entries (-d) and ADS streams (-R)
fls -o 2048 -r -d /dev/sdb1
# 4. Extract the raw content of an MFT record or specific attribute stream
icat -o 2048 /dev/sdb1 24500 > recovered_file.bin
# 5. Extract an alternate data stream ($DATA type 128, stream ID 3)
icat -o 2048 /dev/sdb1 24500-128-3 > extracted_stream.bin
[!TIP] In FTK Imager or Autopsy, navigating to
$MFTand viewing it in Hex mode allows you to quickly locate deleted records by filtering for records where bytes0x00-0x03equalFILEbut bytes0x16-0x17equal0x0000(deleted file) or0x0002(deleted folder). Resident files can then be carved directly from the hex viewer.
During a malware forensic investigation, an examiner parses an unallocated MFT record recovered from an NTFS disk image. The record begins with the magic ASCII string 'FILE', bytes at offset 0x16-0x17 are 0x0000, and the $DATA attribute (0x80) has a non-resident flag set to 0x00 with a value length of 412 bytes. What is the forensic state of this file?
A forensic analyst extracts the raw hexadecimal runlist for a non-resident $DATA attribute from an MFT record: '22 40 01 A0 0F 00'. What are the exact allocated length in clusters and the physical starting cluster (LCN) for this data run?
While investigating a compromised server, an incident response team discovers an executable named 'svchost_update.exe'. Examination of its MFT record reveals that its $STANDARD_INFORMATION attribute has a Creation Time of March 14, 2019, whereas its $FILE_NAME attribute has a Creation Time of September 22, 2026. How should the forensic examiner interpret this discrepancy?