For today’s post, I’m finally going to get to the head honcho of NTFS files: the MFT. This is without a doubt the most important NTFS metadata file, as it is the “pointer of pointers”. Short for “Master File Table”, the MFT, or $MFT file, contains an entry for every file and directory on a file system.
In the interest of brevity, I’m going to refer to this file as either $MFT or MFT going forward.
The file $MFT is entry 0 in, well, itself! Here’s a screenshot of
istat output from our test image for it’s MFT:
Let’s start from the top:
- As with every other file, this file has a $LogFile sequence number.
- This file has $STANDARD_INFORMATION and $FILE_NAME attributes, both of which display timestamps we are already familiar with.
- The MFT has Hidden and System flags, which again line up with other NTFS files we’ve analyzed before.
- The MFT itself has four attributes; unfortunately the fourth gets buried at the “end” of our
istatoutput, but here’s a screenshot:
- As seen from above, the MFT also has a
$BITMAPattribute, which is used to manage MFT allocations (aka deleted vs. active files). Due to the size of the file, the
$BITMAPattribute itself large and also non-resident.
- Lastly, we can see that the
$DATAattribute is also sizeable, which speaks to the size of the disk.
The size of the MFT starts out fairly small; however, as files are added to the system, the MFT grows. This can cause some issues in MFT fragmentation; in fact, notice the clusters occupied by the
$BITMAP attribute. The
$DATA attribute of the MFT starts contiguous, but also may get fragmented. To help prevent issues, the file system reserves 12.5% of the volume space for the MFT.
As previously mentioned, NTFS is simply a collection of attributes. This is why I examined attributes prior to discussing the MFT. Now, let’s look at how this comes together in an MFT entry. As previously mentioned, each MFT entry is 1,024 bytes. Here’s a snippet of the first MFT entry from my test image, which of course is it’s own entry:
Let’s break this down:
- Bytes 0–3 (
46 49 4c 45) contain the MFT entry signature,
FILE. This will be marked as
BAADif an error was found in the entry.
- Bytes 4–5 (
30 00) provide the offset to the fixup array, which is 48 bytes in the entry.
- Bytes 6–7 (
03 00) provide the number of entries in the fixup array; 3 in this case.
- Bytes 8–15 (
c6 55 43 d7 01 00 00 00) provide the
$LogFilesequence number (this converts to 7906481606)
- Bytes 16–17 (
01 00) provide the MFT sequence value; 01 in this case.
- Bytes 18–19 (
01 00) provide the link count; a value of 01 means this file has only one name.
- Bytes 20–21 (
38 00) provide the offset to the first attribute; 56 bytes.
- Bytes 22–23 (
01 00) provide the flags (is the file in-use and/or is this a directory?); a value of 01 says this is a file
- Bytes 24–27 (
A8 01 00 00) provide the used size of the MFT entry, where as
- Bytes 28–31 (
00 04 00 00) provide the allocated size of the MFT entry. The allocated size is 16,384 bytes.
- Bytes 32–39 (
00 00 00 00 00 00 00 00) determine whether this entry is a base entry or not; a value of zero means it is.
- Bytes 40–41 (
06 00) provide the next attribute ID to be assigned; 06 means that there are already five attributes.
- Bytes 42+ contain attributes and fixup values.
Attributes within the MFT
Prior to each attribute within the MFT, there is an attribute header. We did not cover this in the previous attribute post, but will examine it here. Each attribute header is 16 bytes in length. Here’s a sample of the first attribute header:
Let’s break this down:
- Bytes 0–3 (
10 00 00 00) provide the attribute type ID; 16, in this case, represents $STANDARD_INFORMATION
- Bytes 4–7 (
60 00 00 00) provide the length of the attribute; 96 bytes.
- Byte 8 (
00) determines whether the attribute is resident or not
- Byte 9 (
00) provides the length of the object’s name; this value means there is no name.
- Byte 10–11 (
18 00) provide the offset to the object’s name; byte 24.
- Bytes 12–13 (
00 00) provide attribute flags; in this case, there are none.
- Bytes 14–15 (
00 00) provide the attribute ID, which is unique to each MFT record.
IF the attribute is resident, we then have the following values:
- Bytes 16–19 provide the size of the content
- Bytes 20–21 provide the offset to the content
MFT Base Entries
Above I discussed whether the MFT entry was a base entry; bytes 32–39 in the MFT header tell us this. If an MFT entry gets so large that it requires multiple entries to track all the attributes, then there will be a value that points “back” to the MFT base entry.
Resident vs Non-Resident
Over the course of this entire NTFS series, I have referred to files as either reisdent or non-resident. If you’re not familiar with these terms, then take a look at tthe $DATA attribute which was covered in a previous post. As you can see from the MFT structure above, there is a possibility that there will be “extra” space within the 1,024-byte MFT entry after all the attributes have said their piece. If it’s possible that a file is small enough that it fits within this space, then it is said to be resident. If the file requires the usage of clusters outside of the
$DATA attribute, then it is said to be non-resident.
Until tomorrow, Happy Forensicating!