Among the various types of digital evidence, temporal footprints are especially valuable because they enable investigators to confirm the time of an intrusion and reconstruct the sequence of events surrounding an incident. In NTFS, two attributes within the Master File Table (MFT) store the MACB (also known as MACE) timestamps: the $STANDARD_INFORMATION ($SI) attribute and the $FILE_NAME ($FN) attribute.
All timestamps stored in the NTFS $STANDARD_INFORMATION ($SI) and $FILE_NAME ($FN) attributes are encoded as Windows FILETIME values. A FILETIME value represents the number of 100-nanosecond intervals elapsed since January 1, 1601, 12:00 A.M. (UTC). Because they are stored in UTC, these timestamps are not affected by local time zones or daylight saving time (DST). NTFS timestamps have a theoretical resolution of 100 nanoseconds. Both $SI and $FN provide four timestamp values commonly referred to as MACB, representing the following events:
- Modified – last modification of file content.
- Accessed – last access to file content.
- Changed—last modification of file metadata (i.e., changes to the MFT entry).
- Birth—file creation time (creation of the MFT entry).
The modification (M), access (A), and creation (B) timestamps of a file or directory are easily accessible through the Windows Explorer “Properties” dialog. These values are retrieved from the $STANDARD_INFORMATION ($SI) attribute. The fourth timestamp—the metadata change time (C)—is not shown to users and is generally hidden at the GUI level.
The timestamps stored in the $FILE_NAME ($FN) attribute are not directly visible to users and are not guaranteed to match those in $SI. When a file is created, all four timestamps in both $SI and $FN are initialized to the same values. However, while $SI timestamps may be updated by normal file operations (e.g., modifying content, accessing the file, or changing metadata), the timestamps in $FN are not directly updated by these actions. Instead, $FN timestamps are only refreshed when the $FN attribute itself changes, such as during file creation, copying, moving, renaming, or hard-link operations. In these cases, the operating system overwrites the existing $FN timestamps with the current values from $SI. Because Windows provides no API for directly modifying $FN timestamps, they are significantly more difficult to forge than the $SI timestamps presented to the user.
The $STANDARD_INFORMATION Attribute
![]() |
| Figure 1: The STANDARD_INFORMATION attribute hex dump |
Following the MFT header for an MFT entry (in this case, MFT entry 24102) is the $STANDARD_INFORMATION attribute. This attribute is always resident. The attribute ID for this attribute is 0x10 00 00 00. The first part of this attribute follows a regular pattern known as the attribute header, which is 24 bytes long in this case.
The bytes at offsets 0x38-0x3B make up the four-byte identifier for this attribute. These attribute IDs are defined in the $AttrDef metadata file. Bytes 0x3C-0x3F define the length of this attribute. This conforms with the common practice of defining the length of an entry immediately following the identifier. The length shown here (endian reversed) is 0x00000060, which is 96 decimal. An inspection of Figure 1 above shows that 96 bytes from the beginning of this attribute (offset 0x38), at byte offsets 0x98-0xA1, are the four values 0x30000000. These are a set of four bytes that should be another attribute ID. In this case, it is the ID for a FileName Attribute, which is a valid entry, as we will see later.
At byte 0x40 is the resident/non-resident flag. This is signified by 0x00 for a resident attribute and 0x01 for a non-resident attribute. The flag refers to the body of the attribute itself. Other attributes will have similar headers, in which each attribute will be defined as resident or non-resident. The next byte, at offset 0x41, indicates the length of the attribute name. In this case, the length is zero, since this attribute is not allocated a name.
The bytes at offsets 0x42-0x43 indicate the offset value to the start of the attribute content. These are not always used, as in this case, where they are shown as 0x0000. The bytes at offset 0x44-0x45 are identified as a set of flags that signify the following states: 0x0000 = normal, 0x0100 = compressed, 0x4000 = encrypted, and 0x8000 = sparse. It may well be the case that this field is included in the Attribute Header for use only with a $DATA Attribute.
The purpose of the bytes at offsets 0x46-0x47 is unclear. Some sources suggest they are used as some form of attribute ID. Exploration of other MFTs suggests that these may be used for some purposes that have not yet been sufficiently well identified by the writer. Part of the field may be used as a flag to show malware-infected and malware-cleaned files.
The four bytes from offset 0x48-0x4B define the length of the attribute content. In this case, the value is 0x00000048 (endian reversed), which is 72 bytes in decimal. This attribute header is 24 bytes long, and the complete attribute, including this header, is defined at bytes 0x3C-0x3F as 96 bytes. The value of the attribute content should therefore be 96 – 24 = 72, which is what is stored here.
The next two bytes, at offsets 0x4C-0x4D, indicate the offset from the beginning of this attribute to the start of the attribute proper. This is where the Standard Information attribute details start, after the header that is currently being deconstructed. The value is 0x0018, which equals 24 decimal. Noting from the figure above that the start offset for this attribute is 0x38, then the attribute content starts at offset 0x38 + 0x18 = 0x50.
Byte offset 0x4E is reported to be the “indexed” flag, and byte offset 0x4F is reported to be padding to an 8-byte boundary.
The $STANDARD_INFORMATION Attribute Content
The first 32 bytes of this attribute content from byte offset 0x50-0x6F in Figure 1 above refer to four dates and times. The values stored in these bytes are in a format known as a “FILETIME,” which we mentioned earlier. This is a 64-bit number (held here in little-endian format) that represents the number of 100-nanosecond intervals that have elapsed since 00:00:00 GMT on 1 January, 1601. The date and time values in these 32 bytes are decoded as follows.
- Byte offsets 0x50 - 0x57 → Create date and time → 2014-03-18 09:49:57.3083968 UTC.
- Byte offsets 0x58 - 0x5F → Last Modified date and time → 2014-03-18 09:49:57.3083968 UTC.
- Byte offsets 0x60 - 0x67 → Last MFT Record Change date and time → 2015-12-12 02:19:47.0810831 UTC.
- Byte offsets 0x68 - 0x6F → Last Access date and time → 2014-03-18 09:49:57.3083968 UTC.
Byte offsets 0x70-0x73 are used for file permission flags, which are similar to the FAT attribute byte in a directory entry. This attribute byte system, in the style of MS-DOS, is used on byte offset 0x70, with further attributes being set by byte offset 0x71. It is understood that the byte offsets 0x72 and 0x73 are reserved for similar use. In this case 0x00400020 (endian reversed) represents a file with the Archive bit set and not locally resident.
|
Flag Value |
Description |
|
0x00000001 |
Read only. A file that is read-only. Applications can read the file but cannot write to it or delete it. |
|
0x00000002 |
Hidden. The file or directory is hidden. It is not included in an ordinary directory listing. |
|
0x00000004 |
System. A file or directory that the operating system uses a part of or uses exclusively. |
|
0x00000010 |
Directory. The handle that identifies a directory. |
|
0x00000020 |
Archive. A file or directory that is an archive file or directory. Applications typically use this attribute to mark files for backup or removal |
|
0x00000040 |
Device. Reserved for system use |
|
0x00000080 |
Normal. A file that does not have other attributes set. This attribute is valid only when used alone. |
|
0x00000100 |
Temporary. A file that is being used for temporary storage. |
|
0x00000200 |
Sparse_File. A file that is a sparse file |
|
0x00000400 |
Reparse_Point. A file or directory that has an associated reparse point, or a file that is a symbolic link. |
|
0x00000800 |
Compressed. A file or directory that is compressed. For a file, all the data in the file is compressed. For a directory, compression is the default for newly created files and subdirectories. |
|
0x00001000 |
Offline. The data of a file is not available immediately. This attribute indicates that the file data is physically moved to offline storage. |
|
0x00002000 |
Not_Content_Indexed. The file or directory is not to be indexed by the content indexing service. |
|
0x00004000 |
Encrypted. A file or directory that is encrypted. For a file, all data streams in the file are encrypted. For a directory, encryption is the default for newly created files and subdirectories. |
|
0x00008000 |
Integrity Stream. The directory or user data stream is configured with integrity (only supported on ReFS volumes). |
|
0x00010000 |
Virtual. Reserved for system use |
|
0x00020000 |
No_Scrub_Data. The user data stream not to be read by the background data integrity scanner (AKA scrubber). When set on a directory it only provides inheritance. This flag is only supported on Storage Spaces and ReFS volumes. |
|
0x00040000 |
Recall_On_Open. When this attribute is set, it means that the file or directory has no physical representation on the local system; the item is virtual. |
|
0x00400000 |
Recall_On_DataAccess. When this attribute is set, it means that the file or directory is not fully present locally. |
|
0x10000000 |
Directory. Copy from corresponding bit in MFT record header flag (IS_DIRECTORY) |
|
0x20000000 |
Index_View. Copy from corresponding bit in MFT record header25 flag (IS_VIEW_INDEX) |
Byte offsets 0x74 - 0x77 are said to be allocated for “Maximum Number of Versions.” When zero, as here, it is understood that version numbering is disabled. This field is thought to be associated with network security, where there are multiple users and multiple files.
Byte offsets 0x78-0x7B are described as a “Version Number,” and byte offsets 0x7C-0x7F as a “Class ID.” If the ‘Maximum Number of Versions’ is 0 (0x00000000), Maximum Versions is disabled, and so is the ‘Version Number.’ Since Windows 10 version 180320, part of the ‘Version Number’ bytes (specifically the first byte, 0x78 in our sample case) has been used for the “Is Case Sensitive” flag. A value of 1 means that the directory is case sensitive. Since Windows 10 version 1809, part of the ‘Version Number’ bytes (specifically the second byte, 0x79 in our sample case) has been used for the “Reserve Storage ID” flag. Possible ‘Reserve Storage ID’ values include:
|
Hex |
Reserve ID |
Use |
|
00 |
None |
The file or directory is not associated with any particular storage reserve area. |
|
01 |
Hard |
Used by the system to help ensure there is sufficient disk space to download and install updates. |
|
02 |
Soft |
Used by the system to help ensure there is sufficient disk space to install updates. |
|
03 |
Max |
Marks the limit of predefined storage reserve IDs currently understood by the system. |
The Reserve Storage IDs can be queried on a live system as follows. It will show the reserved space for each Storage Reserve ID.
To get a list of MFT file records associated with a specific Storage Reserve ID, enter the following command.
fsutil storagereserve FindById c: X
//where X is either 1, 2, or 3It is claimed that byte offsets 0x80-0x83 are the “Owner ID.” No relevant records were found in our test MFT. Byte offsets 0x84-0x87 are understood to be a “Security ID.” It is claimed that byte offsets 0x88-0x8F are the “Quota Charged.” The MFT was parsed for any non-zero values in these bytes, but no relevant records were found. If it has a value of zero, as seen here, then it is understood that quotas are disabled.
It is claimed that byte offsets 0x90-0x97 are the “Update Sequence Number” for the file $USNJRNL. The MFT was searched for any non-zero values in these bytes, but no relevant records were found. When it has a value of zero, as seen here, likely, the $USNJRNL function has not been activated.
Windows Time Rules
To help analysts avoid common misinterpretations, SANS DFIR introduced a set of Windows Time Rules—practical guidelines that summarize how Windows updates timestamps across different artefacts. These rules help reduce mistakes, highlight anti-forensic gaps, and support consistent event reconstruction. Each operation alters different metadata. The table of time rules here relates to the $STANDARD_INFORMATION attribute.
Windows timestamp updates are notoriously dependent on the operating system version and a very specific combination of actions. These charts illustrate the differences between Windows 10 v1903 and Windows 11 v22H2. Use these rules as heuristics indicating common actions, but always perform testing of specific actions on specific OS versions when working with critical evidence. Access times in Windows 11 should be considered approximate, as they were sometimes noted to differ by up to a few seconds from the actual time of activity.
The $FILE_NAME Attribute
This is identified by its attribute numerical type identifier 0x30 00 00 00 (bytes 0x98-0x9B) or 0x00000030, which equals 48. This attribute is used to store the name of the file and is always resident. As defined in $AttrDef, this attribute has a minimum size of 68 bytes and a maximum of 578 bytes. This equates to a maximum filename length of 255 Unicode characters. A file record can have multiple Filename Attributes, for each type of Namespace or for Hard Links. At byte offsets 0x98 - 0xB7 of Figure 2 above are the details of this attribute header, which is exactly the same structure as that which we examined in Figure 1.
- Bytes 0x98-0x9B → Attribute ID → 0x300000.
- Bytes 0x9C-0x9F → Length of Attribute → 0x00000078 = 120 (from byte offset 0x98-0x10F).
- Byte 0xA0 → Resident/Non-resident flag → 0x00 = resident
- Byte 0xA1 → Length of name of attribute → 0x00 = no name
- Byte 0xA2-0xA3 → Offset to start of attribute content → 0x0000 = not used
- Byte 0xA4-0xA5 → Flags → 0x0000 = normal.
- Byte 0xA6-0xA7 → Not known → 0x0003.
- Byte 0xA8-0xAB → Length of attribute content → 0x0000005A = 90.
- Byte 0xAC-0xAD → Offset to the start of attribute content → 0x0018 = 0x98 + 0x18 = 0xB0.
- Byte 0xAE → Indexed flag → 0x01 = indexed.
- Byte 0xAF → Padding to an 8-byte boundary → 0x00
The FILE_NAME Attribute Content
Starting from byte offset 0xB0 is the FileName attribute content. The first 8 bytes of the attribute are a reference to the parent directory. We note that the value in these first six bytes is 0x000000000538, which is equivalent to 1336 in decimal. This is the record number of the directory \Program Files\WindowsApps\DeletedAllUserPackages\Microsoft.SkypeApp_2.5.0.1005_neutral_split.scale-140_kzf8qxf38zg5c\images\scale-140\emoticons\30\ in which this file appears. The subsequent two bytes 0x0001 denote the Sequence number of the parent directory.
To the trained eyes, four dates and times may be recognized between byte offsets 0xB8-0xD7. The date and time values in these 32 bytes are analyzed below.
- Byte offset 0xB8-0xBF → Create date and time → 2015-12-12 02:06:53.0318729 UTC.
- Byte 0ffset 0xC0-0xC7 → Last Modified date and time → 2015-12-12 02:06:53.0318729 UTC.
- Byte 0ffset 0xC8-0xCF → Last MFT Record Change date and time → 2015-12-12 02:06:53.0318729 UTC.
- Byte 0ffset 0xD0-0xD7 → Last Access date and time → 2015-12-12 02:06:53.0318729 UTC.
Byte offsets 0xD8-0xDF are an 8-byte number specifying the “allocated” size of the file. In this case, the “allocated” size is 0x0000000000000000 = 0 bytes. Byte offsets 0xE0-0xE7 are an 8-byte number specifying the “logical” size of the file. In this case, the real size is 0x0000000000000000 = 0 bytes.
Byte offsets 0xE8-0xEB are stated to be “Flags”. These are similar to the FAT attribute byte in a directory entry, in the style of MS-DOS. We discussed these kinds of flags when we examined byte offsets 0x70-0x73 for the STANDARD_INFORMATION attribute. The values that they can take are identical to those discussed in the STANDARD_INFORMATION attribute. In this case, 0x20 00 00 00 represents a file with the Archive bit set.
Byte offsets 0xEC-0xEF are reportedly used by extended attributes and reparse points. A search of the volume did not reveal any relevant records with non-zero entries at this location.
Byte offset 0xF0 is a one-byte field containing the length of the filename in characters. In this case, it is seen to be 0x0C, which is 12 decimal. In Unicode, which has two bytes per character, this will mean a byte length of 24. Inspection of the file name, BROKEN~1.PNG, which follows, shows this to be correct. The use of one byte to store this value imposes a restriction on the file name length of 255 characters. It should be noted that Unicode characters occupy 2 bytes but count as one character.
Byte offset 0xF1 is a one-byte field that records the type of the file name. In this case, it is seen to be 0x02, which indicates that it is DOS Type (8.3-compliant). Other valid values include:
- 0x00 = Posix Type
- 0x01 = Win32 Type (Long File Name)
- 0x02 = DOS Type (8.3-compliant)
- 0x03 = Win32 &DOS Type (both Win32- and DOS-compliant).
Of the four categories shown above, the most general is that of POSIX, with value 0x00, and this permits the use of all Unicode characters and allows a file length of up to 255 characters. Win32, with value 0x01, is a subset of POSIX, and this prohibits the use of a small number of Unicode characters. It is equivalent to the FAT Long File Name (LFN). DOS, with value 0x02, is a subset of Win32, and this permits only single-byte upper-case characters, prohibits the use of a small number of these, and requires file names to be constrained within the standard DOS 8.3 format. It should be noted that, for compatibility with other systems, it may be necessary to record both the Win32 file name and a DOS-compliant file name in two separate File Name Attributes. However, where the Win32 file name is itself DOS-compliant, this is not necessary, and the name needs only to be recorded once. The final category, Win32 & DOS, of value 0x03, is used to signal this situation; that the file name is both Win32- and DOS-compliant.
As can be seen, byte offsets 0xF2-0x109 contain the file name, the character length of which (12) is given in byte offset 0xF0. This file name field, of value here BROKEN~1.PNG, has to be of variable length to permit the use of long file names. The six bytes from offset 0x10A to 0x10F are padding that has been added to ensure the next Attribute starts on an 8-byte boundary. It appears to be standard practice for all Attributes to start on 8-byte boundaries.
An examination of the MFT shows that when a file name exceeds the constraints of the 8.3 DOS name, two File Name Attributes are present in the record: one containing the DOS-compliant 8.3 file name and one containing the Win32 Long File Name. The same holds true for our sample MFT record. The second File Name attribute spans byte offsets 0x110-0x18F in figure 2 above.
Byte offsets 0x16A-0x18D contain the long file name, the character length of which is 18 (0x12), as given in byte offset 0x168. The value here is brokenheart_30.png.
The timestamps in the $FILE_NAME attribute (FNA) are set to mirror the $STANDARD_INFORMANTION attribute (SIA) timestamps when the file is created and cannot be altered directly. However, FNA values are updated to mirror the SIA values whenever the file is renamed or changes location on the drive. Thus, Joakim Schicht, the author of SetMACE, uses a combination of SIA changes and moving: First the SIA timestamps are altered, the file is moved to a different directory causing the timestamps in the FNA to update and mirror the changes made to the SIA. The file has to be timestomped again before being relocated back to its original location because the FNA values will be updated again. Finally, the files SIA values are timestomped one last time to ensure they are set exactly how the user wants them. This method allowed for the timestamps stored in the SIA and the FNA to be modified with nanosecond precision making the detection of timestamp manipulation in NTFS difficult. Later, he realized that this method may leave additional evidence behind on the system and thus rewrote SetMACE to write directly to the system drive for versions 1.0.0.6 and newer. However, Microsoft patched this and currently direct access to the system drive is no longer allowed.
NTFS Timestamp Forensics
While previous research had focused on using timestamp rules to identify specific user actions, Xiaoqin Ding and Hengming Zou (2010) was the first to use these rules to identify timestamp manipulation using a set of conditions. For all file types, timestamps should satisfy conditions: $SI.M <=$SI.E, $SI.C<=$FN.C, $SI.C<=$SI.A. If any is false, the timestamps were probably tampered by anti-forensic tools. They were able to prove timestamp manipulation in an example case by comparing the values in the $FNA to the values in the $SIA and identifying inconsistencies. But some intra volume replacement may cause $SI.C>$FN.C or $SI.C>$SI.A and the corresponding $SI.E indicates the time of replacement. If $SI.E< $FN.E, the timestamps are unreliable.
If $SI.C<$FN.C and $FN.M=$FN.A=$FN.C=$FN.E, we can conclude that the file was moved from another volume and $FN.C is the last moving time. Meanwhile the file has not been renamed or moved after being relocated to the current volume.
If the condition $FN.M=$FN.A=$FN.C=$FN.E is false, while $SI.C<$FN.C and $SI.E>$FN.E is true, the file is replaced by another file with the same name and type in the same volume, and this file is created after the creation of the file that has been replaced. If $FN.M=$FN.A=$FN.C=$FN.E is false, but $SI.C=$FN.C, then $FN.MACE is copied from the $SI.MACE before the last renaming or moving within the volume.
If $SI.C>$SI.M, then the contents and the summary property of the file have not been modified in the current volume; If $SI.C=$SI.M, the file have not been modified since its creation; If $SI.C<$SI.M, $SI.M is the last modification time of the content or summary property of the file in the current volume.
For office files, if $FN.M=$FN.A=$FN.E>$SI.C, then $FN.M is the last modification time of the file contents in the current volume. If $SI.E=$FN.M also holds, then no renaming or intra-volume move happened after the modification. If $SI.E>$SI.M, the $SI.E is the time of last renaming/intra-volume moving/general property modification. If $SI.M=$FN.M is not satisfied, the timestamps must be altered. If $SI.M=$SI.E>$SI.A>=$SI.C, the $SI.M is the time of last modification on general property of the file.
For .exe files, $SI.E time of the .exe file must be newer or equal than the other seven timestamps. If this is not true, then they are not reliable.
For directories, the timestamps should satisfy $SI.M<=$SI.E, $SI.C=$FN.C, $SI.C<=$SI.A. If anyone is false, the timestamps are unreliable. If $SI.M=$SI.A=$SI.E>$SI.C, $SI.E indicates the last time of content change in the target directory. For each file or subdirectory, if its $SI.E times is the same as that of the parent directory, then this file or subdirectory is recently added or renamed. If no such file or subdirectory is found, then delete operations must have been performed within the directory.
Because timestomping tools and techniques are capable of altering all eight timestamps in the $MFT with nanosecond precision, none of the aforementioned rules can be utilized to identify timestamp manipulation (as long as an attacker followed the rules). This, therefore, compels an analyst to consider other detection methods.
While attackers can modify timestamps stored in the NTFS Master File Table, modifying all correlated NTFS artifacts consistently is far more difficult. One of the most valuable artifacts for exposing such manipulation is the NTFS USN Change Journal ($UsnJrnl:$J). The USN Change Journal is an NTFS metadata file that logs changes to files and directories on a volume. It is append-only and maintained by the NTFS driver. Each record in the $UsnJrnl:$J contains:
- Update Sequence Number (USN)
- File Reference Number (FRN)
- Parent FRN
- Timestamp (When NTFS logged the change)
- Reason flags (what changed)
- File name
The tables below shows the data structure for the $UsnJrnl:$J records: USN_RECORD v2 (Windows 7 and below, Windows Server 2008 R2 and below) and USN_RECORD v3 (Windows 8+, Windows Server 2012+).
|
Offset |
Size |
Description |
|
0x00 |
DWORD |
Size of journal entry |
|
0x04 |
WORD |
Major Version |
|
0x06 |
WORD |
Minor Version |
|
0x08 |
LONGLONG |
MFT Reference of the file that caused this entry |
|
0x10 |
LONGLONG |
Parent MFT Reference for the file that caused this entry |
|
0x18 |
LONGLONG |
USN for entry |
|
0x20 |
LONGLONG |
Timestamp |
|
0x28 |
DWORD |
Reason code (flags for type of change) (to be discussed below) |
|
0x2C |
DWORD |
Source information |
|
0x30 |
DWORD |
Security ID (SID) |
|
0x34 |
DWORD |
File Attributes |
|
0x38 |
WORD |
Size of file name (in bytes) |
|
0x3A |
WORD |
Offset to file name |
|
0x3C |
Variable |
File name |
|
V+0x3C |
Padding |
Padding (align to 8bytes) |
The USN_RECORD version is determined by the OS that created the journal, not the volume format alone. A disk created on Windows 7 (v2) and later mounted on Windows 10 may retain v2 records until the journal is recreated. Deleting and recreating the journal (fsutil usn deletejournal /d) on a newer OS forces v3 records.
|
Offset |
Size |
Description |
|
0x00 |
DWORD |
Size of journal entry |
|
0x04 |
WORD |
Major Version |
|
0x06 |
WORD |
Minor Version |
|
0x08 |
FILE_ID_128 |
MFT Reference of the file that caused this entry |
|
0x18 |
FILE_ID_128 |
Parent MFT Reference for the file that caused this entry |
|
0x28 |
LONGLONG |
USN for entry |
|
0x30 |
LONGLONG |
Timestamp |
|
0x38 |
DWORD |
Reason code (flags for type of change) (to be discussed below) |
|
0x3C |
DWORD |
Source information |
|
0x40 |
DWORD |
Security ID (SID) |
|
0x44 |
DWORD |
File Attributes |
|
0x48 |
WORD |
Size of file name (in bytes) |
|
0x4A |
WORD |
Offset to file name |
|
0x4C |
WCHAR |
File name |
|
V+0x4C |
Padding |
Padding (align to 8bytes) |
A critical point for forensic analysis is that the USN timestamp represents when NTFS observed the change, not the timestamps stored in the $STANDARD_INFORMATION or $FILE_NAME attributes. This distinction makes $J extremely useful for detecting timestamp manipulation.
The USN Journal update reason codes describe why a record was written to the NTFS Change Journal. Each entry logs changes to files or directories, allowing investigators to track activity at the file system level. USN reason codes are bitwise flags - meaning a single USN record can contain multiple reasons combined together. These appear under the Reason fields in tools MFTECmd or forensic suites.
|
Value |
Meaning |
|
USN_REASON_BASIC_INFO_CHANGE 0x00008000 |
A user has either changed one or more file or directory attributes (for example, the read-only, hidden, system, archive, or sparse attribute), or one or more time stamps. |
|
USN_REASON_CLOSE 0x80000000 |
The file or directory is closed. |
|
USN_REASON_COMPRESSION_CHANGE 0x00020000 |
The compression state of the file or directory is changed from or to compressed. |
|
USN_REASON_DATA_EXTEND 0x00000002 |
The file or directory is extended (added to). |
|
USN_REASON_DATA_OVERWRITE 0x00000001 |
The data in the file or directory is overwritten. |
|
USN_REASON_DATA_TRUNCATION 0x00000004 |
The file or directory is truncated. |
|
USN_REASON_EA_CHANGE 0x00000400 |
The user made a change to the extended attributes of a file or directory. These NTFS file system attributes are not accessible to Windows-based applications. |
|
USN_REASON_ENCRYPTION_CHANGE 0x00040000 |
The file or directory is encrypted or decrypted. |
|
USN_REASON_FILE_CREATE 0x00000100 |
The file or directory is created for the first time. |
|
USN_REASON_FILE_DELETE 0x00000200 |
The file or directory is deleted. |
|
USN_REASON_HARD_LINK_CHANGE 0x00010000 |
An NTFS file system hard link is added to or removed from the file or directory. An NTFS file system hard link, similar to a POSIX hard link, is one of several directory entries that see the same file or directory. |
|
USN_REASON_INDEXABLE_CHANGE 0x00004000 |
A user changes the FILE_ATTRIBUTE_NOT_CONTENT_INDEXED attribute. That is, the user changes the file or directory from one where content can be indexed to one where content cannot be indexed, or vice versa. Content indexing permits rapid searching of data by building a database of selected content. |
|
USN_REASON_INTEGRITY_CHANGE 0x00800000 |
A user changed the state of the FILE_ATTRIBUTE_INTEGRITY_STREAM attribute for the given stream. On the ReFS file system, integrity streams maintain a checksum of all data for that stream, so that the contents of the file can be validated during read or write operations. |
|
USN_REASON_NAMED_DATA_EXTEND 0x00000020 |
The one or more named data streams for a file are extended (added to). |
|
USN_REASON_NAMED_DATA_OVERWRITE 0x00000010 |
The data in one or more named data streams for a file is overwritten. |
|
USN_REASON_NAMED_DATA_TRUNCATION 0x00000040 |
The one or more named data streams for a file is truncated. |
|
USN_REASON_OBJECT_ID_CHANGE 0x00080000 |
The object identifier of a file or directory is changed. |
|
USN_REASON_RENAME_NEW_NAME 0x00002000 |
A file or directory is renamed, and the file name in the USN_RECORD structure is the new name. |
|
USN_REASON_RENAME_OLD_NAME 0x00001000 |
The file or directory is renamed, and the file name in the USN_RECORD structure is the previous name. |
|
USN_REASON_REPARSE_POINT_CHANGE 0x00100000 |
The reparse point that is contained in a file or directory is changed, or a reparse point is added to or deleted from a file or directory. |
|
USN_REASON_SECURITY_CHANGE 0x00000800 |
A change is made in the access rights to a file or directory. |
|
USN_REASON_STREAM_CHANGE 0x00200000 |
A named stream is added to or removed from a file, or a named stream is renamed. |
|
USN_REASON_TRANSACTED_CHANGE 0x00400000 |
The given stream is modified through a TxF transaction. |
When the file timestamps are directly modified, NTFS generates a USN record with the reason flag:
USN_REASON_BASIC_INFO_CHANGE
(0x00008000)This flag indicates a change to one or more of the following:
- Creation time
- Modification time
- Last access time
- MFT change time
- File attributes
Attackers who timestomp files inevitably trigger this event because timestamps reside in the file's basic metadata. While this flag can also appear during legitimate activity, its forensic value becomes apparent when correlated with other artifacts.
To find the MFT entry for the journal, we examine the contents of the \$Extend file system metadata directory, which is MFT entry 11. We see that it is MFT entry 80976. We display the $J attribute contents with icat.
Consider the journal entry for the file named SET9F6C.tmp whose truncated output is shown below. The MFT file reference (relative offsets 0x08-0x0F) for each of the journal entries of the file, with the value 0xBD3C010000000100, has been highlighted. The first 6 bytes of the 8-byte file reference, 0x00000001BD3C (endian reversed) give the MFT entry number, whose value is 81085 in decimal. The timestamp (When NTFS logged the change) (relative offsets 0x20-0x27) for each of the journal entries for the file is also highlighted. The values here are 0x590C847A8334D101, which, when converted, give the value 2015-12-12 02:19:07.1289433 UTC. The USN reason codes, relative offset (0x28-0x2B), are also highlighted.
.
- First journal entry reason code → 0x00000100 → FileCreate
- Second journal entry reason code → 0x80000100 → FileCreate|Close
- Third journal entry reason code → 0x00008000 → BasicInfoChange
- Fourth journal entry reason code → 0x80008000 → BasicInfoChange|Close
- Fifth journal entry reason code → 0x80000200 → FileDelete|Close
- Continue till all journal entry reason codes are interpreted
This process can be automated using Eric Zimmerman's MFTECmd or any other forensic tool of your choice.
The result is shown below which reveals several operations to modify the timestamp of the file.
Windows event logs do not record file timestamps directly. You cannot see a forged timestamp in an event log. What you can detect are:
- Processes, tools, and APIs commonly used to timestomp.
- Suspicious timing relationships between events and NTFS artifacts.
- Metadata-changing behaviour without corresponding file creation.
This makes Event logs corroborative evidence, not a standalone proof. High value event log sources include:
- Event ID 4688 - Process Creation. This is the single most important event. Look for processes known to alter timestamps: powershell.exe, cmd.exe, wmic.exe, python.exe, custom malware loaders, living-off-the-land binaries (LOLBins). Look for suspicious command-line indicators like the PowerShell command
(Get-Item file).CreationTime=. Also, look for offensive tools like timestomp.exe, metasploit payloads, and Cobalt Strike BOFs. Process execution times after the forged $SI timestamps but before the $JBASIC_INFO_CHANGEpossess a and strong correlation value. - Event ID 4663 - File Access. Look for an Access mask including
WRITE_ATTRIBUTES,WRITE_DAC, and access to suspicious files without write activity. Attribute write without content write is a classic timestomp pattern. - PowerShell operational logs event IDs 4103/4104 detect Script block logging and timestamp manipulation via .NET -
[System.IO.File]::SetCreationTime() Set-ItemProperty. Even if the attacker clears $SI, PowerShell logs often persist. - Event IDs 1, 35, 36, 37 (Microsoft-Windows-Time-Service), and Security event ID 4616 detect system clock changes and time synchronization anomalies. Some attackers change system time before file creation, then revert it. Sudden clock rollback + old-looking file timestamps + recent USN activity provides strong correlation.
Prefetch files are not stored on NTFS timestamps alone and are harder for attackers to perfectly manipulate compared to $SI/$FN timestamps. They provide:
- Independent execution timing
- Execution frequency
- Referenced file paths (DLLs, EXEs)
- Volume metadata and last execution times
This makes Prefetch an excellent cross-validation for detecting timestomping.
Each Prefetch file stores up to eight last execution times (Win 8+), which are stored internally in FILETIME format, and are not dependent on $SI/FN. If the Prefetch LastRunTime precedes file creation time or postdates file deletion or backdated modification, this is a strong indicator of timestomping.
Prefetch also maintains an execution counter. If the file claims ancient timestamps (e.g., 2016) but execution count is greater than 1 and clusters around a recent incident, timestamp manipulation may likely have occurred.
Prefetch files are created on the first execution of an executable. Compare the prefetch file $SI Creation time with the executable $SI Creation time. If, for example, a pattern such as indicated below was detected, the executable was likely introduced recently, but backdated.
- Executable Creation Time: 2017
- Prefetch Creation Time: 2025
Each Prefetch file contains a Volume Serial Number and a Volume creation timestamp (from NTFS). This allows for the detection of volume recreation and the detection of copy-in artifacts. If the executable's timestamps predate volume recreation, it is impossible without manipulation.









Post a Comment