The definitive Amcache.hve forensic reference: every key, every value, every timestamp

Amcache.hve is the single richest execution-artifact source on a modern Windows host. It is also one of the most misunderstood. This post is the reference I wish existed when I first started pulling hives off compromised machines: every subkey, every value, every timestamp, what the schema looked like in each Windows release, and — just as importantly — the claims about Amcache that are not actually true.

If you are looking for tool-level documentation rather than the artifact itself, see the AmcacheParser complete guide and the output columns reference.


1. What Amcache.hve actually is#

Amcache.hve is a registry hive written by Windows' Application Compatibility / Program Compatibility Assistant subsystem. It is not a security artifact by design. Microsoft uses it to feed compatibility telemetry into the Customer Experience Improvement Program and the Compatibility Appraiser, both of which decide which installed software might break on upgrade.

The reason it matters to DFIR is a side effect of that purpose: in order to assess whether a program is safe to upgrade, Windows needs to enumerate programs, drivers, devices, and files on the machine. That enumeration is dumped — with hashes, paths, publishers, sizes, and timestamps — into Amcache.hve.

Path#

C:\Windows\AppCompat\Programs\Amcache.hve

A .LOG1 / .LOG2 transaction-log pair sits alongside it. Both logs must be replayed into the hive before parsing if the hive was not cleanly unmounted. Most modern tools (AmcacheParser, the browser parser, RegRipper) do this for you, but never delete the .LOG files before triage — they may contain the writes that hold your evidence.

Who writes it#

  • compatTelRunner.exe — driven by the scheduled task \Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser.
  • Also touched by aeinv.dll (Application Experience Inventory) and the broader CompatTelemetry stack.

By default the appraiser runs daily and on logon, but the cadence varies by Windows build and group policy. Do not assume Amcache data is real-time. A binary executed five minutes before a shutdown may not appear at all; one executed an hour before may appear with a KeyLastWriteTimestamp reflecting the appraiser run, not the execution.

Acquisition#

The hive is held open by the OS at runtime. To grab a live copy you need raw-NTFS access:

  • KAPE with the Amcache target
  • Velociraptor Windows.Registry.Amcache
  • FTK Imager → File System → C:\Windows\AppCompat\Programs
  • RawCopy64.exe / CopyRawFiles.ps1
  • From an E01/AFF4/VHDX image, just read the file normally

A shadow-copy snapshot (vssadmin list shadows) often gives you an earlier hive that contains evidence the current one has rolled off.


2. Schema evolution: Windows 7 through Windows 11#

Amcache's schema has changed substantially. If you walk into a case expecting Windows 10 1607 keys on a Windows 7 hive, you will think the artefact is empty. It is not — it just looks different.

Windows version Amcache present? Dominant schema
Windows 7 RTM / SP1 (pre-KB2952664) No (uses RecentFileCache.bcf) n/a
Windows 7 SP1 + KB2952664 (2015) Yes Root\File\{VolumeGUID}\{FileRef} + Root\Programs
Windows 8 / 8.1 Yes Root\File + Root\Programs
Windows 10 1507 – 1511 Yes Root\File + Root\Programs (transitional)
Windows 10 1607 (Anniversary) Yes Root\InventoryApplicationFile and the wider Inventory* family introduced
Windows 10 1703 – 1809 Yes Inventory schema stable; minor field additions
Windows 10 1903 – 22H2 Yes Inventory schema, LongPathHash, additional driver fields
Windows 11 21H2 / 22H2 / 23H2 / 24H2 Yes Inventory schema, expanded device records, more PnP detail

The 1607 jump is the biggest. Pre-1607 hives have a handful of keys with maybe a dozen values each. Post-1607 hives have ten-plus top-level Inventory* containers, each with rich nested data.

Legacy schema (Win7 → Win10 1511)#

Root\
  File\
    {Volume GUID, e.g. "{abcd1234-...}"}\
      {NTFS File Reference, e.g. "0000abcd00000001"}\
        ... values ...
  Programs\
    {ProgramId}\
      ... values ...
  Orphan\
  Generic\

The interesting values under each File\{Vol}\{FileRef} subkey were numbered (0, 1, 2, ... 101, ...). The mapping is well documented in Willi Ballenthin's original 2013/2015 research and reproduced in the Mandiant blog. Highlights:

Value Meaning
0 Product name
1 Company name
2 PE FileVersion
3 Language code (LCID)
5 BinaryFileVersion
6 BinaryProductVersion
c FileDescription
f PE LinkDate (FILETIME)
11 Last modified (FILETIME)
12 Created (FILETIME)
15 Full path
17 Last modified (alternative FILETIME slot)
100 ProgramId
101 FileId (SHA-1 with 0000 prefix)

Modern schema (Win10 1607+)#

Root\
  InventoryApplication\
    {ProgramId}\          ← installed-program record
  InventoryApplicationFile\
    {Name|FileId}\        ← per-file record
  InventoryApplicationShortcut\
  InventoryApplicationFramework\
  InventoryApplicationDriver\
  InventoryDeviceContainer\
  InventoryDevicePnp\
  InventoryDeviceInterface\
  InventoryDriverBinary\
  InventoryDriverPackage\
  InventoryMiscellaneousUUPInfo\
  Programs\               ← legacy, often still present
  File\                   ← legacy, often empty on modern OS
  Orphan\
  Generic\

Each modern subkey carries named values (not numeric), which makes them much easier to read. The rest of this post is the field-by-field reference for those modern values.


3. Root\InventoryApplicationFile — the workhorse#

One subkey per file Windows has inventoried. This is where attacker binaries, side-loaded DLLs, and ad-hoc tooling tend to appear.

Value Type Meaning Forensic note
Name string File name e.g. mimikatz.exe
LowerCaseLongPath string Full path (lower-cased) The single most useful pivot.
LongPathHash string Hash Windows uses internally for path dedup Useful for joining records across reboots.
FileId string "0000" + SHA-1(first 31 MiB) Strip the 0000 prefix for VT / TI lookups.
Publisher string X.509 CN or PE company resource Empty = unsigned.
Version string PE FileVersion
BinFileVersion string PE VS_FIXEDFILEINFO.dwFileVersion
BinProductVersion string PE VS_FIXEDFILEINFO.dwProductVersion
ProductName string PE resource ProductName
ProductVersion string PE resource ProductVersion
LinkDate string or FILETIME PE TimeDateStamp Attacker-controlled. Group by, do not date by.
BinaryType string pe32, pe64, pe32_arm64, pe32_managed, ... Filter for native PE when threat hunting.
Size dword/qword File size in bytes
Language dword PE resource LCID
IsPeFile dword (0/1) Is this a PE? Almost always 1 here.
IsOsComponent dword (0/1) Windows-shipped binary Filter to 0 to cut noise.
ProgramId string 44-char identity hash of parent app Empty/zero = "unassociated" file.
Usn qword USN journal sequence number at inventory
AppxPackageFullName string UWP package full name Populated for store apps.
AppxPackageRelativeId string UWP package-relative ID

Two FileId formats#

Two formats coexist in the wild:

  • 0000 + 40 hex chars — SHA-1 of the first 31 MiB of the file. This is the dominant format from Windows 8 onward.
  • 0001 + 32 hex chars — MD5; rare and mostly historical.

When pivoting to threat-intel feeds, always check the prefix and strip it. Submitting the raw FileId to VirusTotal will return zero hits and waste a meaningful amount of triage time.

"Unassociated" vs "associated"#

A file with a non-empty ProgramId that points at an existing InventoryApplication subkey is "associated" — Windows linked it to an installed product. A file with a blank or zero ProgramId is "unassociated" and could not be tied to any registered application.

Attacker tooling is almost always unassociated. Filtering InventoryApplicationFile to unassociated entries with a LowerCaseLongPath under \Users\, \AppData\, \ProgramData\, \Temp\, or \PerfLogs\ is the cheapest, most productive triage filter on a typical commodity-malware case.


4. Root\InventoryApplication — installed-program records#

One subkey per registered application (MSI installs, Add/Remove Programs entries, Store apps, etc.).

Value Meaning
Name Display name
Version Application version
Publisher Publisher string
RootDirPath Install directory
Source MSI, AddRemoveProgram, WindowsUpdate, ...
InstallDate Install date (string or FILETIME)
Type Application, OptionalFeature, ...
Language LCID
MsiPackageCode MSI package GUID
MsiProductCode MSI product GUID
RegistryKeyPath Uninstall key (SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\...)
UninstallString Command-line to uninstall
OSVersionAtInstallTime Windows version when installed
InstallDateArpLastModified Add/Remove last-modified date
PackageFullName UWP full name (if applicable)

InstallDateArpLastModified is underused. If a row's InstallDate and its ARP-last-modified value diverge by months, you may be looking at a replaced binary (think DLL side-load via a legitimate installer left behind by IT).


5. Root\InventoryDriverBinary — kernel-mode artefacts#

The single best source for BYOVD (bring-your-own-vulnerable-driver) hunts.

Value Meaning
DriverName Driver file name
DriverInBox True if shipped with Windows
DriverIsKernelMode True for ring-0 drivers
DriverSigned Signed-flag claim (do not trust blindly — check the cert separately)
DriverType Bit flags: legacy / PnP / service / file-system / ...
DriverVersion Driver version string
DriverCompany Company string
Product Product name
ProductVersion Product version
WdfVersion Windows Driver Framework version, if applicable
Service Backing service name
Inf .inf filename
DriverPackageStrongName Strong name
DriverTimeStamp PE link date of the driver
ImageSize Image size in bytes
Hash SHA-1 of the driver

For BYOVD: sort by DriverTimeStamp ascending, filter DriverSigned to true, then look at the KeyLastWriteTimestamp of each record. Old, signed, recently-inventoried drivers are the high-signal set. Cross-reference against loldrivers.io for known-abused names and hashes.


6. Root\InventoryDeviceContainer and Root\InventoryDevicePnp#

InventoryDeviceContainer is the user-facing device list: "Brother HL-L2350DW", "Logitech BRIO", "Samsung Galaxy S22". One subkey per logical device. Notable values: Categories, DiscoveryMethod, FriendlyName, Manufacturer, ModelName, ModelNumber, IsConnected, IsPaired, Icon.

InventoryDevicePnp is the technical enumeration: one subkey per device interface, with BusReportedDescription, DeviceClass, DeviceId, InstanceId, Manufacturer, Service, DriverName.

Pair the two on InstanceId to get both the marketing name and the PnP hardware IDs. This is often the cheapest answer to "did device X ever attach to this host?" without wading through Setup logs.


7. Root\InventoryApplicationShortcut and other minor keys#

  • InventoryApplicationShortcut — one subkey per .lnk that Windows knows about. Carries ShortcutPath, TargetPath, and the parent ProgramId. Useful for "what was pinned to the taskbar on $DATE."
  • InventoryApplicationFramework — .NET / runtime framework records.
  • InventoryApplicationDriver — bridge between an installed application and the driver it shipped.
  • InventoryDriverPackage — INF-level package records.
  • InventoryMiscellaneousUUPInfo — Unified Update Platform staging info; rarely relevant.

8. Timestamps: the part everyone gets wrong#

Amcache exposes at least five distinct kinds of "when," and they mean different things. Misreading them is the most common error in Amcache findings.

Timestamp Source What it actually says
KeyLastWriteTimestamp Registry last-write of the subkey Closest thing to "when Amcache observed this." This is your authoritative pivot.
LinkDate PE header TimeDateStamp When the compiler/linker stamped the binary. Attacker-controlled, frequently faked.
InstallDate (InventoryApplication) Whatever the installer wrote Best-effort; reflects installer behavior, not necessarily ground truth.
InstallDateArpLastModified Add/Remove Programs key last-modified Useful for detecting replacement of an existing app.
DriverTimeStamp PE link date of a driver Same caveats as LinkDate.

The KeyLastWriteTimestamp gotcha#

KeyLastWriteTimestamp is the last time the registry key was written, which is the last time the appraiser touched the record. If Windows re-evaluated the file last Tuesday because of a metadata change, the timestamp will say Tuesday — not the date the file was first observed.

That means:

  • You cannot assume KeyLastWriteTimestamp is "first seen."
  • You can assume it is "last touched by the appraiser."
  • For "first seen," correlate against shadow copies of prior Amcache hives, or against the USN journal entry referenced by Usn.

The "Amcache = execution" myth#

You will read in many older blog posts that "Amcache proves execution." This is not safe to claim. Maxim Suhanov's research (2018, "Windows ShellBag and Amcache forensics: just stop relying on single-source signals") demonstrated that the Compatibility Appraiser will inventory files that have not been executed — for example, executables present in directories the appraiser scanned.

What Amcache reliably proves:

  • The file existed on the system at the inventory time.
  • Its hash, path, publisher, and PE metadata at that moment.

What Amcache does not prove on its own:

  • That the file was executed.
  • When the file was first placed on disk.
  • That the user (rather than the system) is responsible.

For execution evidence, corroborate with Prefetch, Sysmon EventID 1, Security 4688, ShimCache, BAM/DAM, UserAssist, or SRUM. Amcache is a fantastic triage artefact and a strong supporting artefact, but it is a weak sole-source execution witness.


9. ProgramId and FileId: how the identifiers work#

ProgramId (44 characters)#

A hash derived from the application's name, version, publisher, and language. The exact algorithm has not been formally documented by Microsoft, but the practical consequences are:

  • The same product installed on two machines will (usually) have the same ProgramId.
  • A point-release upgrade will (usually) change it.
  • It is not a content hash — two different binaries from the same product share a ProgramId.

Use ProgramId to pivot, never to identify a file.

FileId (44 characters with 0000 prefix)#

This is a content hash:

FileId = "0000" + SHA1(first 31 MiB of file content)

For files smaller than 31 MiB, FileId[4:] is a full SHA-1 of the file and will match the SHA-1 reported by any other tool. For files larger than 31 MiB, FileId[4:] is a SHA-1 of the first 31 MiB only — it will not match a full-file SHA-1.

This matters: a 200 MB packed installer will have a FileId that does not match its full-file SHA-1, and a VT lookup keyed on the full hash may miss while a lookup keyed on the Amcache value would hit (and vice versa). When in doubt, search both.


10. Anti-forensics and tampering#

Amcache can be tampered with. The hive lives on disk and can be modified offline. Known patterns:

  • Selective key deletion by a SYSTEM-level actor between appraiser runs.
  • Set-ItemProperty style writes to plant misleading LinkDate or Publisher values for a binary the attacker wants to look benign.
  • Hive replacement with a hive harvested from a clean machine.
  • Disabling the appraiser scheduled task (visible in Task Scheduler history and Microsoft-Windows-Application-Experience event logs).

Defensive corroborations:

  • The .LOG1 / .LOG2 files often contain pre-tamper state.
  • Volume Shadow Copies of Amcache.hve from prior days give you a before/after.
  • The USN journal records writes to the hive file itself.
  • Microsoft-Windows-Application-Experience/Program-Telemetry event log records appraiser runs.

If a hive looks too tidy — sparse InventoryApplicationFile entries, no unassociated rows, perfect publisher coverage — be suspicious. A normal Windows desktop accumulates thousands of file records over its lifetime.


11. Cross-artefact corroboration#

Amcache is at its strongest when joined to its neighbors. The joins that pay off most often:

Question Join Amcache against
Was this binary actually executed? Prefetch .pf files, Sysmon 1, BAM/DAM, ShimCache, UserAssist
When was it placed on disk? $MFT $STANDARD_INFORMATION and $FILE_NAME timestamps, USN journal
Where did it come from? InstallSource in Programs, Zone.Identifier ADS, browser history, email gateway logs
Did it phone home? DNS logs, Sysmon 3, firewall logs
What user ran it? Security 4688, BAM/DAM (per-SID), UserAssist (per-NTUSER)
Earlier state of this hive? Shadow Copies, prior backups, KAPE Triage collections

A finding sourced from Amcache plus Prefetch plus a Security 4688 is reportable. A finding sourced from Amcache alone is a lead.


12. Tools that read Amcache#

No single tool is best for every situation. A working DFIR shop keeps several around.

Tool Strengths When to reach for it
AmcacheParser (Eric Zimmerman) Canonical, well-tested, KAPE-integrated, CSV output Bulk processing, KAPE pipelines, court-ready output
RegRipper (amcache.pl plugin) Text reports, great for narrative timelines When you want a human-readable summary
This browser parser Zero install, runs entirely client-side via WebAssembly, no upload Quick triage, classroom demos, third-party laptops where you cannot install software
Velociraptor Windows.Registry.Amcache Fleet-wide collection and parsing EDR-style sweep across hundreds of hosts
Magnet AXIOM / EnCase GUI + integrated case management Commercial-tool shops
Python python-registry / Rust nt-hive Programmatic access Custom pipelines, research

If you want to skip installs entirely, drop a hive on the home page and you will see every key and value in a few seconds. Nothing leaves the browser.


13. Further reading (the sources that actually move the field forward)#

Most of what is "known" about Amcache comes from a small number of researchers. If you only have time to read four things, read these:

  • Willi Ballenthin (Mandiant) — the original Amcache field mapping for the legacy schema. Still the canonical reference for pre-1607 hives.
  • Andrea Fortuna — multiple posts walking through the Inventory* schema as it evolved through Windows 10.
  • Maxim Suhanov — registry-internals work, and the most rigorous treatment of what Amcache does and does not prove. His work is what killed the "Amcache = execution" myth.
  • Eric Zimmerman's tool notes — read the release notes for AmcacheParser; they are how new schema fields get publicly documented first.

Then read your own hives. The schema in the wild contains fields no single blog post covers, and the only reliable way to know what your build of Windows is recording is to look.


See also#

Have a hive you want to look at right now? Drop it on the parser home page — it parses in your browser, locally, in a couple of seconds.

Related posts

Back to all posts