Standard File Attributes
The previous section outlined how we process an MFT entry and the attribute headers. Each attribute header points to a resident or non-resident location where the attribute content can be found. This section explains how we process each of the different attribute content types.
$STANDARD_INFORMATION Attribute
The $STANDARD_INFORMATION attribute, which has a type identifier of 16, is always resident and contains the basic metadata for a file or directory. It exists in every file and directory and is typically the first attribute because it has the lowest type identifier. It has the (non-essential) fields given in Table 13.5.
Byte Range |
Description |
Essential |
---|---|---|
07 |
Creation time |
No |
815 |
File altered time |
No |
1623 |
MFT altered time |
No |
2431 |
File accessed time |
No |
3235 |
Flags (see Table 13.6) |
No |
3639 |
Maximum number of versions |
No |
4043 |
Version number |
No |
4447 |
Class ID |
No |
4851 |
Owner ID (version 3.0+) |
No |
5255 |
Security ID (version 3.0+) |
No |
5663 |
Quota Charged (version 3.0+) |
No |
6471 |
Update Sequence Number (USN) (version 3.0+) |
No |
The four time values are stored as the number of one hundred nanoseconds since January 1, 1601 UTC. The same time fields also exist in the $FILE_NAME attribute, but these are the ones that Windows displays when you view the properties of a file, and these are the ones that are updated. The ID values are used for either application-level features or security. The Security ID value is the index to the $Secure file, not the Windows SID value. The flag values are given in Table 13.6.
Flag Value |
Description |
Essential |
---|---|---|
0x0001 |
Read Only |
No |
0x0002 |
Hidden |
No |
0x0004 |
System |
No |
0x0020 |
Archive |
No |
0x0040 |
Device |
No |
0x0080 |
#Normal |
No |
0x0100 |
Temporary |
No |
0x0200 |
Sparse file |
No |
0x0400 |
Reparse point |
No |
0x0800 |
Compressed |
No |
0x1000 |
Offline |
No |
0x2000 |
Content is not being indexed for faster searches |
No |
0x4000 |
Encrypted |
No |
Many of these flags are the same as were seen with FAT, and a description of them can be found there. The flags for encrypted and sparse attributes are also given in the attribute headers, so I consider them to not be essential in this location. This is debatable, though, because another person could claim that this flag is essential and the MFT entry header values are not essential.
Let us take a look at a $STANDARD_INFORMATION attribute. We can view the attribute by using icat and specifying the attribute type. This removes the standard header for us automatically and gives us only the content. The contents of the attribute for the $MFT file are
# icat -f ntfs ntfs1.dd 0-16 | xxd 0000000: 305a 7a1f f63b c301 305a 7a1f f63b c301 0Zz..;..0Zz..;.. 0000016: 305a 7a1f f63b c301 305a 7a1f f63b c301 0Zz..;..0Zz..;.. 0000032: 0600 0000 0000 0000 0000 0000 0000 0000 ................ 0000048: 0000 0000 0001 0000 0000 0000 0000 0000 ................ 0000064: 0000 0000 0000 0000 ........
The first eight bytes show the creation time, which is the same for each of the four time fields. Bytes 32 to 35 give the flag value, which is 0x00000060, and includes bits for hidden and system, which is expected for a file system metadata file. Bytes 36 to 39 and 40 to 43 show that file versions are not being used, and 44 to 47 show that the class ID is 0. The owner ID in bytes 48 to 51 is 0, and the security ID in bytes 52 to 55 is 1. The rest of the values are 0, which is not surprising for $MFT because it is not typically applied to any user's quota, and most systems do not have change journaling enabled, so the USN would not be assigned.
$FILE_NAME Attribute
The $FILE_NAME attribute, which has a type identifier of 48, is used for two purposes. It is placed in an MFT entry to store the file's name and parent directory information, and it is used in a directory index. When it is used in an MFT entry, it does not contain any essential information, but it does when it is used in a directory index.
For a standard file or directory, this will be the second attribute and is always resident. If a file requires multiple MFT entries, the $ATTRIBUTE_LIST attribute will occur between the $STANDARD_INFORMATION attribute and this attribute. The $FILE_NAME attribute has the fields given in Table 13.7.
Byte Range |
Description |
Essential |
---|---|---|
07 |
File reference of parent directory |
No |
815 |
File creation time |
No |
1623 |
File modification time |
No |
2431 |
MFT modification time |
No |
3239 |
File access time |
No |
4047 |
Allocated size of file |
No |
4855 |
Real size of file |
No |
5659 |
Flags (see Table 13.6) |
No |
6063 |
Reparse value |
No |
6464 |
Length of name |
Yes / No |
6565 |
Namespace (see Table 13.8) |
Yes / No |
66 + |
Name |
Yes / No |
The final three name fields are essential when this attribute is used in the directory index, but not when it is used in the MFT entry for a file. The flag field uses the same values as $STANDARD_INFORMATION does, and they were previously listed.
The namespace byte identifies what rules the name follows. Its values are given in Table 13.8.
Name space value |
Description |
---|---|
0 |
POSIX: The name is case sensitive and allows all Unicode characters except for '/' and NULL. |
1 |
Win32: The name is case insensitive and allows most Unicode characters except for special values such as '/', '', ':', '>', '<', and '?'. |
2 |
DOS: The name is case insensitive, upper case, and no special characters. The name must have eight or fewer characters in the name and three or less in the extension. |
3 |
Win32 & DOS: Used when the original name already fits in the DOS namespace and two names are not needed. |
To view a $FILE_NAME attribute, we will look at $MFT again and specify the attribute type 48:
# icat -f ntfs ntfs1.dd 0-48 | xxd 0000000: 0500 0000 0000 0500 305a 7a1f f63b c301 ........0Zz..;.. 0000016: 305a 7a1f f63b c301 305a 7a1f f63b c301 0Zz..;..0Zz..;.. 0000032: 305a 7a1f f63b c301 0040 0000 0000 0000 0Zz..;...@...... 0000048: 0040 0000 0000 0000 0600 0000 0000 0000 .@.............. 0000064: 0403 2400 4d00 4600 5400 ..$.M.F.T.
The first eight bytes are for a file reference, so the upper two bytes are the sequence number and the lower six bytes are the MFT entry. Therefore, the parent directory is MFT entry 5, and its sequence is 5, which is the entry for the root directory. The next eight bytes are for the creation time and are the same value as the other three time values in the attribute.
Bytes 40 to 47 and 48 to 55 show the allocated and actual sizes of the file, respectively. Both of these values are set to 16,384 bytes (0x4000). In reality, the $DATA attribute for this file is 8,634,368 bytes, so this is clearly not accurate. Many files have these sizes set to 0, but it is accurate when this attribute is used in a directory index.
The flag values at bytes 56 and 57 are set to 0x0006, which are the hidden and system flags. These were the same flags we saw in $STANDARD_INFORMATION. Byte 64 shows that the name is 4 letters long, and byte 65 shows it is in name space 3, which is both DOS and Win32 compliant. The name is in UTF-16 Unicode and can be seen starting in byte 66. The name is $MFT.
As a final example, consider a file with two $FILE_NAME attributes because Windows required that a DOS name exist. This file has $FILE_NAME attributes for both a DOS name space and a Win32 name space. We will not dissect them in detail, but the output is shown here:
# icat -f ntfs ntfs1.dd 5009-48-2 | xxd 0000000: 3920 0000 0000 0300 00b6 89a9 086a c401 9 ...........j.. 0000016: 00b6 89a9 086a c401 00b6 89a9 086a c401 .....j.......j.. 0000032: 00b6 89a9 086a c401 0000 0000 0000 0000 .....j.......... 0000048: 0000 0000 0000 0000 2020 0000 0000 0000 ........ ...... 0000064: 0b01 3500 3700 3300 3900 3800 3400 3000 ..5.7.3.9.8.4.0. 0000080: 3800 6400 3000 3100 8.d.0.1.
Notice that byte 65 shows the name space as 1, which is Win32. The name in this entry is "57398408d01." Now, we will look at the next $FILE_NAME attribute, which has the same type identifier of 48, but its attribute identifier is 3:
# icat -f ntfs ntfs1.dd 5009-48-3 | xxd 0000000: 3920 0000 0000 0300 00b6 89a9 086a c401 9 ...........j.. 0000016: 00b6 89a9 086a c401 00b6 89a9 086a c401 .....j.......j.. 0000032: 00b6 89a9 086a c401 0000 0000 0000 0000 .....j.......... 0000048: 0000 0000 0000 0000 2020 0000 0000 0000 ........ ...... 0000064: 0802 3500 3700 3300 3900 3800 3400 7e00 ..5.7.3.9.8.4.~. 0000080: 3100 1.
This attribute has a name space in byte 65 of 2, which is DOS. The name in this entry is "573984~1."
$DATA Attribute
The $DATA attribute is the simplest to understand because it has no native structure. After the header, there is only raw content that corresponds to the contents of a file. It has a type identifier of 128 and has no minimum or maximum sizes. If the content is over 700 bytes, it will probably be a non-resident attribute. For most files, this is the last attribute in the MFT entry. Note that directories can have $DATA attributes in addition to their index attributes.
$ATTRIBUTE_LIST Attribute
An $ATTRIBUTE_LIST attribute exists in an MFT entry to show where other attributes can be located. It is used for files that have attribute headers that will not fit into one MFT entry and contains a list with an entry for every attribute in the file or directory. The attribute has a type identifier of 32 and each list entry has the fields in Table 13.9.
Byte Range |
Description |
Essential |
---|---|---|
03 |
Attribute type |
Yes |
45 |
Length of this entry |
Yes |
66 |
Length of name |
Yes |
77 |
Offset to name (relative to start of this entry) |
Yes |
815 |
Starting VCN in attribute |
Yes |
1623 |
File reference where attribute is located |
Yes |
2424 |
Attribute ID |
Yes |
The starting VCN value is used when multiple MFT entries are needed to describe a single attribute. When that occurs, the additional entries will have non-zero starting VCN values. The attribute header should also show that it has a non-zero starting VCN.
Let us take a look at a file with an $ATTRIBUTE_LIST attribute.
# icat -f ntfs ntfs1.dd 5009-32 | xxd 0000000: 1000 0000 2000 001a 0000 0000 0000 0000 .... ........... 0000016: 9113 0000 0000 0800 0000 0000 0000 0000 ................ 0000032: 3000 0000 2000 001a 0000 0000 0000 0000 0... ........... 0000048: 9113 0000 0000 0800 0300 0000 0006 0000 ................ 0000064: 3000 0000 2000 001a 0000 0000 0000 0000 0... ........... 0000080: 9113 0000 0000 0800 0200 0200 502d 40bc ............P-@. 0000096: 8000 0000 2000 001a 0000 0000 0000 0000 .... ........... 0000112: 3713 0000 0000 1200 0000 0000 1000 0000 7............... 0000128: 8000 0000 2000 001a 2014 0000 0000 0000 .... ... ....... 0000144: ad13 0000 0000 0800 0000 0000 0000 0000 ................
The first four bytes show the type of the first entry, which is 16 (0x10) and therefore the $STANDARD_INFORMATION attribute. Bytes 4 to 5 show that the length of this list entry is 32 bytes (0x0020) and bytes 16 to 21 show that the attribute is located in MFT entry 5,009 (0x1391), which is the one that we are currently looking at.
The next two entries start at bytes 32 and 64 and are for $FILE_NAME attributes, which have a type identifier of 48 (0x30). Both of those attributes are also located in the current MFT entry.
Byte 96 is where the first entry for the $DATA attribute begins. Bytes 104 to 111 show that this $DATA attribute is for VCN 0 of the attribute, and bytes 112 to 117 show that the attribute is located in MFT entry 4,919 (0x1337). A second entry for the $DATA attribute begins at byte 128. We can tell they are part of the same $DATA attribute because the ID value in both data structures is equal to 0. Bytes 136 to 143 show us that the second entry has a starting VCN of 5,152 (0x1420). In other words, the $DATA attribute in the first entry had enough space in the MFT entry to describe the first 5,152 clusters. The rest of the cluster runs are stored in a $DATA attribute in MFT entry 5,037 (0x13ad), which we can see in bytes 144 to 149.
Figure 13.4 shows a summary of this file. It has one $STANDARD_INFORMATION and two $FILE_NAME attributes in the base MFT entry 5,009, and the headers for the $DATA attribute are located in entries 4,919 and 5,037.
Figure 13.4. Layout of attribute list entries for sample image.
Recall from Chapter 12 that the non-base MFT entries will not have the standard $FILE_NAME and $STANDARD_INFORMATION attributes. We can verify this by looking at one of the entries in this example. The output from running istat on the non-base entry 4919 is as follows:
# istat f ntfs ntfs1.dd 4919 MFT Entry Header Values: Entry: 4919 Sequence: 18 Base File Record: 5009 $LogFile Sequence Number: 66117460 Allocated File Links: 0 [REMOVED] Attributes: Type: $DATA (128-0) Name: $Data Non-Resident size: 5787792 929409 929410 929411 929412 929413 929414 929415 929416 [REMOVED]
This MFT entry has only a $DATA attribute, and we can see that the header shows the base record to be entry 5,009. The link count is 0 because there are no names pointing to it.
$OBJECT_ID Attribute
The $OBJECT_ID attribute has a type identifier of 64 and stores a file's 128-bit global object identifier that can be used to address the file instead of its name. This allows a file to be found even when its name is changed. The $Extend$ObjId index is sorted by the object IDs of files and contains the file reference address where each file can be found. The attribute has only four fields, and typically only the first one is defined. The fields are given in Table 13.10.
Byte Range |
Description |
Essential |
---|---|---|
015 |
Object ID |
Yes |
1631 |
Birth volume ID |
No |
3247 |
Birth object ID |
No |
4863 |
Birth domain ID |
No |
Many files that have an object ID assigned have only the first value, and the attribute size is 16 bytes. The $Volume file frequently contains an $OBJECT_ID attribute, and it is shown here:
# icat -f ntfs img.dd 3-64 | xxd 0000000: fe24 b024 e292 fe47 95ac e507 4bf5 6782 .$.$...G....K.g.
$REPARSE_POINT Attribute
The $REPARSE_POINT attribute has an attribute identifier of 192, and it is used for files that are reparse points. Reparse points are used for symbolic links, junctions, and mount points for volumes. Microsoft defines some $REPARSE_POINT attribute contents, but application-specific ones also can be developed. The contents of a junction and mount point have the structure shown in Table 13.11.
Byte Range |
Description |
Essential |
---|---|---|
03 |
Reparse type flags |
Yes |
45 |
Size of reparse data |
Yes |
67 |
Unused No |
|
89 |
Offset to target name (relative to byte 16) |
Yes |
1011 |
Length of target name |
Yes |
1213 |
Offset to print name of target (relative to byte 16) |
Yes |
1415 |
Length of print name |
Yes |
The type flags for a junction or mount point will have the 0xa0000000 flag set. Here we see a reparse point that links to c:windows:
# icat -f ntfs ntfs2.dd 167-192 | xxd 0000000: 0300 00a0 2800 0000 0000 1c00 1e00 0000 ....(........... 0000016: 5c00 3f00 3f00 5c00 6300 3a00 5c00 7700 .?.?..c.:..w. 0000032: 6900 6e00 6400 6f00 7700 7300 0000 1200 i.n.d.o.w.s.....
Byte 8 to 9 show that the offset to the target name is 0 bytes, so it starts at byte 16. Its length is given in bytes 10 to 11, and we see that it is 28 bytes (0x1c). In Unicode, we see the name of the target as "??c:windows."