A Journey into NTFS: Part 5

Matt B
5 min readJan 30, 2017

--

In yesterday’s post, I spent some time discussing common NTFS attributes. Experienced DFIR analysts may have noticed that I left out three key attributes that I’m going to cover today:

  • $INDEX_ROOT
  • $INDEX_ALLOCATION
  • $BITMAP

Index Attributes

Before digging into each specific attribute, it’s important to note that these attributes are typically found associated with NTFS indexes. This post will focus on directories, which are a type of NTFS index. For directories, the three aforementioned attributes get the collective name of $I30 — hopefully that term seems familiar. We can also analyze them as three separate attributes.

If you remember yesterday, when we dug into the MFT file $AttrDef, we saw that these attributes have their own type IDs and respective sizes. Here’s a snippet of the parsed data from $AttrDef:

Screenshot of parsed $AttrDef attributes

As easily seen, three attributes do not have a size limit, however $INDEX_ROOT will always be resident. Let’s start there.

$INDEX_ROOT

This attribute has an attribute type ID of 144. Here’s a snippet of the $INDEX_ROOT attribute for the root folder (C:\).

icat output showing the $INDEX_ROOT attribute from the root directory of a test image

Here’s how this attribute is structured:
* Bytes 0–3 (30 00 00 00) provide the type of attribute in index. An attribute type ID 30, as previously discussed, is $FILE_NAME.
* Bytes 4–7 (01 00 00 00) provide the collation sorting rule. This particular value enforces filename sorting (01)
* Bytes 8–11 (00 10 00 00) provide the size of each index record in bytes — 4,096 bytes in this case.
* Byte 12 (01) provides the size of index records in clusters. We can easily do this math by knowing the size of our sectors, and how many sectors per cluster.
* Bytes 13–15 are often blank, and unused.
* Bytes 16+ contain node headers. More on this in a moment.

$INDEX_ATTRIBUTES

This attribute contains additional index records outside of what’s stored inside of $INDEX_ROOT. This attribute has an attribute type ID of 160. There is no size limit on this attribute, and it will be as large as it needs to be to contain the directory contents and their related attributes. Here’s a snippet of the beginning of the $INDEX_ATTRIBUTES attribute for the root folder:

icat output showing the $INDEX_ATTRIBUTES attribute from the root directory of a test image

Here’s how this attribute is structured:
* Bytes 0–3 (49 4e 44 58) provide the index record signature (INDX, which many analysts are familiar with)
* Bytes 4–5 (28 00) provide the offset to the fixup array
* Bytes 6–7 (09 00) provide the number of entries in the fixup array.
* Bytes 8–15 (74 32 43 02 02 00 00 00) provide the $LogFile sequence number for the directory — we will visit this NTFS artifact in a different post.
* Bytes 16–23 (00 00 00 00 00 00 00 00) provide the Virtual Cluster Number (“VCN”), which applies to non-resident data streams.
* Bytes 24+ provide the node header.

Node Headers

As mentioned above, each of the previous two attributes end in Node Headers. The node header is simply the area of data prior to index entries that identify where the list of entries starts and stops. Let’s look at the node header for our example $INDEX_ROOT:

Let’s break this one down:

  • Bytes 0–3 (10 00 00 00) provide the offset of the start of the index entry list; this value is relative to the node header itself. With the node header starting at byte 16, the index entry list starts at byte 32.
  • Bytes 4–7 (28 00 00 00) provide the offset of the end of the used index entry list.
  • Bytes 8–11 (28 00 00 00) provide the offset to the end of the allocated index entry list. The previous two values are the same at 40 bytes. Our total $INDEX_ROOT attribute is 56 bytes, which is our 16 byte header + 40 bytes index entry list.
  • Bytes 12–15 (01 00 00 00) provide flags for the index entry list. A flag of 01 means that there are children nodes (directories), which can be found in $INDEX_ALLOCATION.

$BITMAP

The last and final attribute is one that helps keep the structure together: $BITMAP. This attribute is very similar to the $Bitmap file, which keep track of the index allocations. Here’s a screenshot of the contents of the $BITMAP attribute from the root directory.

Attributes for the root directory, MFT entry 5

Similar to the file $Bitmap, this file flags bits as the allocation is made. As our current value is 01 00 00 00 00 00 00 00, we obviously have only one index record allocated. As there aren’t too many files within this folder, our $INDEX_ALLOCATION also only takes up one cluster. Let’s look at a couple of larger folders. Here’s C:\Windows:

istat output for the folder C:\Windows
$BITMAP attribute for the directory C:\Windows

Windows is a bit larger, however it’s well-known that Windows also contains a wide range of sub-folders as well. Let’s look at C:\Windows\System32:

istat output for the folder C:\Windows\System32
$BITMAP attribute for the directory C:\Windows\System32

Wow! As expected, as the folder grows, so does the $INDEX_ALLOCATION attribute. Remember that $INDEX_ALLOCATION attributes contain index records that are often 4,096 bytes in length.

Index Entry

The final piece to cover when examining directory index attributes is an index entry record. After attribute and node headers, we finally get to the actual index contents — aka, the file listing. Let’s look at a sample index entry record for directories:

  • Bytes 0–7 (00 00 00 00 00 00 01 00) provide the MFT file reference.
  • Bytes 8–9 (60 00) provide the length of this index entry; 96 bytes.
  • Bytes 10–11 (4a 00) provide the length of the corresponding $FILE_NAME attribute; 74 bytes.
  • Bytes 12–15(00 00 00 00) provide flags; there are none in this case.
  • Bytes 16+ provide the $FILE_NAME attribute.
  • The last n-8 bytes (00 00 00 00 00 00 01 00) provide the Virtual Cluster Number (“VCN”) of a child node. We’ll cover this in another post.

Index entry records continue to list all the contents of the directory. We can also recover information about deleted files from these attributes. If a file is deleted, it’s $FILE_NAME attribute may not be removed from the various index attributes. Most forensic tools will recover these remaining attributes; sometimes, they may be the only evidence we have!

Until tomorrow, Happy Forensicating!

--

--

Matt B
Matt B

Written by Matt B

Be selective with your battles.

No responses yet