The Amcache timestamps, decoded
There are at least nine fields in Amcache.hve that look like a timestamp. Two of them are not timestamps. Four of them mean different things on Windows 7 than on Windows 10. One of them is attacker-controlled. The other two are useful, sometimes, with caveats.
If you have ever been asked "when did this file appear on the host" and you answered using a single Amcache field, this post is the conversation you should have had with yourself first.
The two formats Windows uses, side by side#
The Amcache mixes two timestamp conventions in the same hive, which is a particular kind of design choice.
The first is the 64-bit FILETIME: 100-nanosecond intervals since 1601-01-01 UTC, stored little-endian. This is what the LastWrite on every registry key uses, and what some value-level fields store. Parsers handle it transparently. The semantics are usually "the registry wrote this entry at this moment".
The second is DateTime-as-string, where Microsoft chose to store a human-readable timestamp inside a REG_SZ value. Formats vary across builds: MM/DD/YYYY HH:MM:SS on Win10, ISO-8601-ish YYYY-MM-DD HH:MM:SS on some Win11 entries. The timezone is usually UTC but is occasionally local time on Win7 hives. Always check before you build a timeline; an off-by-one-timezone in a report is embarrassing.
Read the raw vk cell type if you are unsure. REG_QWORD and REG_BINARY of length 8 mean FILETIME; REG_SZ means parse the string and pray.
The fields, one by one#
Key LastWrite on InventoryApplicationFile\#
The single most useful timestamp in the hive. It is the FILETIME the registry wrote into the key header the last time the Compatibility Appraiser updated this file's entry. In practice this is "Appraiser noticed this file" or "Appraiser re-hashed this file because something about it changed".
It is not file creation, not file execution, not user activity. The first time Appraiser sees a freshly-dropped binary, the LastWrite is approximately the next scheduled run after the file appeared. Scheduled run cadence depends on the host, but a few hours is typical on a normally-configured system.
Sanity check: this timestamp should always be later than the file's own NTFS creation time from the MFT. If it is earlier, something is wrong (timestomping, a clock skew, or an attacker who edited the hive).
LinkDate (InventoryApplicationFile, InventoryDriverBinary)#
PE header IMAGE_FILE_HEADER.TimeDateStamp, stored as a DateTime string. It is the compile timestamp the linker stamped, which is whatever the build environment said it was.
Attacker-controlled. Trivially. link.exe /timestamp or post-link patching can set it to anything. Half of commodity malware ships with LinkDate = 1970-01-01 because nobody bothered. Better samples set it to a plausible 2018-2020 value. The polished ones match the LinkDate of a real Microsoft binary to blend in.
Useful for:
- Spotting blatantly wrong values (1970, 2099, or values that contradict the rest of the host's timeline).
- Distinguishing two builds of the same project, when both samples have honest compile times.
Not useful for: timeline. Do not put it on a timeline.
InstallDate (InventoryApplication)#
A DateTime string under each InventoryApplication\<ProgramId> key. The value is whatever the installer wrote, usually pulled from MSI metadata or the DisplayInstallDate value in the Uninstall key. For legitimately-packaged software (Office, Chrome, vendor MSIs) this is honest to the day, occasionally to the second.
For malware droppers, sideloaded tooling, or anything that did not go through a real installer, this field is either absent, set to zero, or set to whatever was convenient. Treat as advisory.
I use InstallDate to corroborate user-facing applications when the question is "when did this user install Chrome", not for adversary activity.
InstallDateMsi, InstallDateArpLastModified, InstallDateFromLinkFile (InventoryApplication)#
Same general meaning, different sources. Windows 10 build 1709 and later expose multiple install-date variants per application:
InstallDateMsi: from the MSI database, if the install used MSI.InstallDateArpLastModified: from the Add/Remove Programs (ARP) registry entry's last modification time.InstallDateFromLinkFile: from the Start Menu .lnk file's metadata, when the application created one.
When these three disagree by more than a few minutes, something interesting happened: a repair install, an upgrade, or a re-registration. When they agree, the install date is solid.
Key LastWrite on InventoryApplication\#
Different from InstallDate. This is the registry key's last write, which is updated whenever Appraiser refreshes the application entry. For most applications, the first write is close to install time and subsequent writes are infrequent. Useful as a corroboration check against InstallDate*.
Key LastWrite on InventoryDeviceContainer\#
The closest thing to "when did Windows last see this device" you will find in the hive. Updated when Appraiser refreshes the device record. Pair with the proper USB story (SYSTEM\ControlSet001\Enum\USBSTOR, Microsoft-Windows-Partition%4Diagnostic.evtx, setupapi.dev.log) for any USB question; the Amcache value alone is too coarse.
Key LastWrite on InventoryDriverBinary\ and InventoryDriverPackage\#
Same shape as the application keys. The LastWrite is "Appraiser refreshed this driver entry", which on a normally-running host happens shortly after the driver lands. For BYOVD investigations where the attacker dropped a vulnerable signed driver, the InventoryDriverBinary LastWrite is frequently the tightest bound you have on "when was this driver staged".
Key LastWrite on InventoryApplicationShortcut\#
When Appraiser indexed this .lnk. The shortcut itself has its own MAC times in the LNK file body, which the LNK parser will give you. The Amcache LastWrite is a separate, later, less-interesting timestamp. I use it as a sanity check, not as a finding.
What Win7, Win10 and Win11 do differently#
The hive is not the same across major builds, even when the key names look identical.
Windows 7 SP1 with the original Compatibility Appraiser had a much simpler hive. The top-level keys were Root\File, Root\Programs, Root\Generic, and Root\Orphan. The LastModified value under Root\File\<volume>\<fileid> was the explicit "file last modified per NTFS at Appraiser scan time", a different semantic from anything in the modern hive. If you are reading a Win7 hive, you cannot use Win10 field names. RegRipper's older amcache plugin handles this; AmcacheParser handles modern hives better than legacy ones.
Windows 8 / 8.1 introduced the InventoryApplication* keys but the schema was unstable. Several fields appear in 8.1 that disappear in 10 and vice versa. I would not recommend building automation against an 8.1 hive without inspecting the value list first.
Windows 10 builds through ~1709 had a thinner InventoryApplication schema. The three InstallDate* variants did not all exist. LinkDate was sometimes empty for PE files Appraiser could not fully parse.
Windows 10 1809 and later is the stable schema most current tooling targets. AmcacheParser's column set matches this.
Windows 11 adds a few values under InventoryApplicationFile (notably some signing-related fields) and changes the string format of certain DateTime values from US-locale to ISO-ish. The semantics of the core timestamps are unchanged.
In-place upgrades make a mess#
When a host upgrades from Windows 10 to Windows 11, or from one major 10 build to another, the Amcache is migrated, not regenerated. In practice:
- Old
InventoryApplicationFileentries are usually preserved with their original LastWrite from the pre-upgrade run. - The Appraiser re-scans everything post-upgrade, so within hours to days most LastWrites are refreshed.
- Schema changes mean some fields are populated on entries created post-upgrade and empty on entries that survived from before.
- A subset of entries are sometimes orphaned: the binary no longer exists but the key was never cleaned up during migration.
If your hive's LastWrite distribution shows two clusters separated by a clean gap, you are probably looking at a pre-upgrade and post-upgrade population. Confirm against setupact.log or the Setup channel in the Event Log before reading too much into it.
Practical sanity checks#
Before any timestamp goes into a report, run these in your head:
- Is the
InventoryApplicationFilekey LastWrite after the file's NTFS creation time? If not, something is wrong. - Is the LastWrite consistent with the Compatibility Appraiser task last-run time in
Microsoft-Windows-TaskScheduler%4Operational.evtx? Appraiser writes are batched; you should see clusters of LastWrites that coincide with task runs. - Are the
InstallDate*triplet underInventoryApplicationconsistent with each other? Disagreement is interesting. - Is
LinkDateplausible? 1970, 2099, or any value outside roughly 1995-now means the PE header was stamped, not that the file is that old. - Cross-check at least one Amcache timestamp against Prefetch execution times, Sysmon process create events, or USN journal file creation. If the cross-check disagrees, the Amcache is not necessarily wrong, but you need to explain the gap before you commit.
The Amcache will not lie to you on purpose. It will, however, hand you a perfectly reasonable-looking timestamp that means something completely different from what you assumed it meant. That is what every field in this post has in common.
Further reading#
- Yogesh Khatri's Amcache.hve in Windows 8, which still documents the field semantics better than any vendor source.
- Eric Zimmerman's AmcacheParser source for the canonical mapping of value names to columns.
- Microsoft's Compatibility Appraiser documentation, which is thin on forensics but useful for understanding the task cadence.
- 13Cubed's deep-dive videos on Amcache and Shimcache, particularly the timestamp segments.
Related posts
- What the Amcache actually tells you in a DFIR investigation
A practitioner's view on the Amcache.hve hive: what each entry really proves, where the timestamps lie to you, and the mistakes that keep showing up in incident reports.
- Amcache vs Shimcache: which artifact answers which question
Two adjacent Windows artifacts with very different forensic properties. What each really records, where their timestamps lie, and a decision table for casework.
- The Amcache.hve binary format, in practice
A walkthrough of the Amcache.hve on-disk structure: the regf hive layout, the subkeys that matter in DFIR, and the tools that read them without lying to you.
- Amcache timestamps explained: KeyLastWriteTimestamp vs LinkDate vs the rest
Every timestamp Amcache exposes, what each one means, and which one to pivot on. Confusing them is the #1 mistake new analysts make.