There are forensic tools capable of carving file records and index entries ($I30) from memory dumps, but there is much more NTFS-related metadata which isn’t exposed by usual memory forensics frameworks. For example, file control blocks.
A file control block is created when a file is opened. It is used by the NTFS driver to track various internal things. From a forensics perspective, file control blocks are valuable because they contain five timestamps for each opened file.
In particular, every file control block contains so-called duplicated information and the “real” last access timestamp field.
Duplicated information is a metadata block found in the $FILE_NAME attribute within a file record or an index entry, it contains four timestamps (MACE) and some other file metadata: within a file record, these MACE timestamps are usually out-of-sync; within an index entry, these timestamps are set to the current ones (but not always). In memory, duplicated information is used to keep timestamps before they are written to a disk.
A “real” last access timestamp is stored outside of duplicated information
until there is a reason to update the last access timestamp on a disk: before this update is written to a disk, the “real” last access timestamp is copied to the in-memory duplicated information block (update, 2020-02-10: this is not always the case, a “new” timestamp can be kept outside of duplicated information, in the “real” last access timestamp field).
And, unfortunately, the layout of file control blocks isn’t available in debug symbols. Some things (like their signature) can be reverse engineered, but obviously the full layout differs across versions of Windows.
Because of this, I decided to extract limited information from file control blocks and to implement an algorithm to guess the offsets of key fields (duplicated information and a “real” last access timestamp): locate four FILETIME timestamps (which are stored without gaps between them) of duplicated information and then locate another FILETIME timestamp (a “real” last access timestamp) after duplicated information. Also, a file reference number seems to be stored at the same offset in multiple versions of Windows tested. The updated version of the dfir_ntfs project is already on GitHub!
A memory dump found in the 2018 Lone Wolf Scenario contains 10110 file control blocks (this number includes file control blocks from freed memory and remnant data, because the dfir_ntfs project doesn’t even try to locate a corresponding pool tag, which could be absent in remnant data). 27 file control blocks have two different last access timestamps (one in duplicated information plus a “real” one). For example:
- Path: “/ProgramData/Microsoft/Windows Defender/Scans/History/Results/Resource“.
- $STANDARD_INFORMATION timestamps:
- M: 2018-04-06 12:27:06.792022,
- A: 2018-04-06 12:27:06.792022,
- C: 2018-03-27 09:22:47.264672,
- E: 2018-04-06 12:27:06.792022.
- Timestamps in the file control block:
- M: 2018-04-06 12:27:06.792022 (the same as the M timestamp above),
- A: 2018-04-06 08:31:50.194366,
- C: 2018-03-27 09:22:47.264672 (the same as the C timestamp above),
- E: 2018-04-06 12:27:06.792022 (the same as the E timestamp above),
- A (“real”): 2018-04-06 12:27:06.792022 (the same as the A timestamp in the previous list).
And we have one additional last access timestamp! It should be noted that tools like fsutil report a “real” last access timestamp, not the one currently stored on a disk, so there is a way to collect in-memory timestamps without doing RAM imaging.
An uncompressed hibernation file from my Windows 10 physical machine (which doesn’t contain a full memory dump, just memory data for the fast startup) contains 698 file control blocks with two different last access timestamps in each (8792 file control blocks in total).
So, if you need more timestamps for your timelines, give it a try!