The definitive Amcache.hve forensic reference: every key, every value, every timestamp
Amcache.hve is the richest single execution-artefact source on a modern Windows host, and one of the most misunderstood. This is the field-by-field reference for the artefact itself. Every key. Every value. Every timestamp. What the schema looked like in each Windows release, and which claims about Amcache are not actually true.
For tool-level documentation, see the AmcacheParser complete guide and the output columns reference.
1. What Amcache.hve actually is#
A registry hive written by Windows's Application Compatibility / Program Compatibility Assistant subsystem. Not a security artefact by design. Microsoft uses it to feed compatibility telemetry into the Customer Experience Improvement Program and the Compatibility Appraiser, both of which exist to decide which installed software might break on upgrade.
The reason it matters in DFIR is a side effect of that purpose. To assess whether a program is safe to upgrade, Windows enumerates programs, drivers, devices, and files on the machine. That enumeration, with hashes, paths, publishers, sizes, and timestamps, is what lands in Amcache.hve.
Path#
C:\Windows\AppCompat\Programs\Amcache.hve
With a .LOG1 / .LOG2 transaction-log pair alongside. Both logs must be replayed into the hive before parsing if the hive was not cleanly unmounted. Modern tools (AmcacheParser, the browser parser, RegRipper) do this for you, but never delete the .LOG files before triage. They may hold the writes that contain 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.
Default cadence is daily on Windows 10/11 workstations and on logon, but it varies by build, GPO, and battery state. Do not assume Amcache data is real-time. A binary executed five minutes before shutdown may never appear. One executed an hour before may appear with a KeyLastWriteTimestamp reflecting the appraiser run, not the execution.
Acquisition#
The hive is held open at runtime. To grab a live copy you need raw NTFS access:
- KAPE with the
Amcachetarget. - Velociraptor
Windows.Registry.Amcache. - FTK Imager > File System >
C:\Windows\AppCompat\Programs. - RawCopy64.exe, CopyRawFiles.ps1.
- From an
E01/AFF4/VHDXimage, just read the file normally.
Volume Shadow Copies (vssadmin list shadows) often give you an earlier hive containing evidence that has since rolled off the current one.
2. Schema evolution: Windows 7 through Windows 11#
Amcache's schema has shifted a lot. Walk into a case expecting Windows 10 1607 keys on a Windows 7 hive and 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 |
| Windows 10 1703 - 1809 | Yes | Inventory schema stable; minor field additions |
| Windows 10 1903 - 22H2 | Yes | Inventory schema, LongPathHash, more 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}\
{NTFS File Reference}\
... values ...
Programs\
{ProgramId}\
... values ...
Orphan\
Generic\
Values under each File\{Vol}\{FileRef} are numbered (0, 1, 2, 101, etc.). The mapping is documented in Willi Ballenthin's 2013/2015 research and reproduced in the Mandiant blog. Highlights:
| Value | Meaning |
|---|---|
0 |
Product name |
1 |
Company name |
2 |
PE FileVersion |
3 |
Language 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\
Modern sub-keys carry named values, not numeric, which makes them much easier to read. The rest of this post is the field-by-field reference for those values.
3. Root\InventoryApplicationFile (the workhorse)#
One sub-key per file Windows has inventoried. 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) | Single most useful pivot. |
LongPathHash |
string | Internal path-dedup hash | Useful for joining records across reboots. |
FileId |
string | "0000" + SHA-1(first 31 MiB) |
Strip 0000 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 it, do not date by it. |
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. |
Usn |
qword | USN journal sequence number at inventory | |
AppxPackageFullName |
string | UWP package full name | Store apps. |
AppxPackageRelativeId |
string | UWP package-relative ID |
Two FileId formats#
Two formats coexist:
0000+ 40 hex - SHA-1 of the first 31 MiB. Dominant since Windows 8.0001+ 32 hex - MD5. Rare, mostly historical.
When pivoting to threat intel, always check the prefix and strip it. Submitting the raw FileId to VirusTotal returns zero hits and wastes meaningful triage time.
Associated vs unassociated#
A file with a non-empty ProgramId matching an existing InventoryApplication sub-key is "associated". Windows linked it to an installed product. A file with blank or zero ProgramId is "unassociated".
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 sub-key per registered application (MSI installs, Add/Remove Programs, Store apps).
| 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 at install |
InstallDateArpLastModified |
Add/Remove last-modified date |
PackageFullName |
UWP full name |
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 through 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. |
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, look at the KeyLastWriteTimestamp of each. Old + signed + recently inventoried is 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 sub-key per logical device. Notable values: Categories, DiscoveryMethod, FriendlyName, Manufacturer, ModelName, ModelNumber, IsConnected, IsPaired, Icon.
InventoryDevicePnp is the technical enumeration: one sub-key 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. Often the cheapest answer to "did device X ever attach to this host?" without wading through Setup logs.
7. Root\InventoryApplicationShortcut and minor keys#
InventoryApplicationShortcut: one sub-key per.lnkWindows knows about. CarriesShortcutPath,TargetPath, parentProgramId. Pair with the LNK parser and jump list data for "what did the user pin/launch 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. Rarely relevant.
8. Timestamps: the part everyone gets wrong#
Amcache exposes at least five distinct kinds of "when". 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 sub-key | Closest thing to "when Amcache observed this". Your authoritative pivot. |
LinkDate |
PE header TimeDateStamp |
When compiler/linker stamped the binary. Attacker-controlled, frequently faked. |
InstallDate (InventoryApplication) |
Whatever the installer wrote | Best-effort; reflects installer behaviour. |
InstallDateArpLastModified |
Add/Remove Programs 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 says Tuesday. Not the date the file was first observed.
So:
- You cannot assume
KeyLastWriteTimestampis "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#
Many older blog posts claim "Amcache proves execution". This is not safe. Maxim Suhanov's 2018 work ("Windows ShellBag and Amcache forensics: just stop relying on single-source signals") demonstrated that the appraiser inventories files that have not executed - files merely present in the directories the appraiser scans.
What Amcache reliably proves:
- The file existed on the system at inventory time.
- Its hash, path, publisher, and PE metadata at that moment.
What Amcache does not prove on its own:
- That the file executed.
- When the file was first placed on disk.
- That the user (rather than the system) is responsible.
For execution, corroborate with Prefetch, Sysmon 1, Security 4688, Shimcache, BAM/DAM, UserAssist, or SRUM. Amcache is a great triage artefact and a strong supporting artefact, but it is a weak sole-source execution witness.
9. ProgramId and FileId#
ProgramId (44 characters)#
Hash derived from the application's name, version, publisher, and language. Exact algorithm is not officially documented but practically:
- Same product installed on two machines usually has the same
ProgramId. - A point-release upgrade usually changes 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 (0000 + 40 hex)#
The content hash:
FileId = "0000" + SHA1(first 31 MiB of file content)
For files under 31 MiB, FileId[4:] equals the file's full SHA-1. For larger files it is a prefix hash and will not match a whole-file SHA-1. A 200 MB packed installer has a FileId that does not match its full-file SHA-1, and VT lookups keyed on the full hash may miss while lookups on the Amcache value hit (or 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. Patterns:
- Selective key deletion by a SYSTEM-level actor between appraiser runs.
Set-ItemProperty-style writes to plant misleadingLinkDateorPublishervalues on 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-Experienceevent logs).
Defensive corroborations:
.LOG1/.LOG2often hold pre-tamper state.- Volume Shadow Copies of
Amcache.hvefrom prior days give before/after. - The USN journal records writes to the hive file itself.
Microsoft-Windows-Application-Experience/Program-Telemetryevent log records appraiser runs.
If a hive looks too tidy - sparse InventoryApplicationFile, 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 strongest joined to neighbours. The joins that pay off:
| 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, 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, SRUM |
| 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 Security 4688 is reportable. A finding sourced from Amcache alone is a lead.
12. Tools that read Amcache#
No single tool is best for everything. A working DFIR shop keeps several around.
| Tool | Strengths | Reach for it when |
|---|---|---|
| AmcacheParser (Eric Zimmerman) | Canonical, well-tested, KAPE-integrated, CSV | Bulk processing, KAPE pipelines, court-ready output |
RegRipper (amcache.pl) |
Text reports, narrative timelines | You want a human-readable summary |
| Browser parser (this site) | Zero install, client-side WebAssembly, no upload | Quick triage, classroom demos, locked-down laptops |
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 | 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#
Most of what is "known" about Amcache comes from a small number of researchers. If you only have time to read four things:
- Willi Ballenthin (Mandiant). The original Amcache field mapping for the legacy schema. Still canonical for pre-1607 hives.
- Andrea Fortuna. Multiple posts walking through the
Inventory*schema as it evolved through Windows 10. - Maxim Suhanov. Registry-internals work, plus the most rigorous treatment of what Amcache does and does not prove. His work killed the "Amcache = execution" myth.
- Eric Zimmerman's tool notes. Read AmcacheParser's release notes; that's where 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 Windows build is recording is to look.
Related#
Related posts
- AmcacheParser output columns explained: every CSV field decoded
Field-by-field reference for AmcacheParser's CSV output. FileId, PathHash, ProgramId, LinkDate, BinFileVersion, IsPeFile, and every other column, with the pivots that matter.
- Volatility and Amcache: extracting the hive from memory images
When you only have a RAM dump, Volatility extracts the in-memory copy of Amcache.hve. Hand off to AmcacheParser. The cases where this is the only option.
- RegRipper amcache plugin: what it does and when to use it
RegRipper's amcache plugin produces a plain-text Amcache report. Useful when you're already running RegRipper across other hives or need narrative output. Use AmcacheParser when you need CSV.
- AmcacheParser download guide: official sources, mirrors, and verification
Where to get AmcacheParser. Get-ZimmermanTools, direct download, KAPE, Velociraptor. Plus checksum verification and the air-gapped install pattern.