The Amcache.hve binary format, in practice
The first time you crack open Amcache.hve in a hex editor you will see the four ASCII bytes regf at offset zero and feel mildly disappointed. There is no exotic schema. The Amcache is a perfectly ordinary Windows registry hive, which is both the reason it is easy to parse and the reason almost every analyst writes a bad parser before they write a good one.
This post is the version of "how the file is laid out" that I wish someone had handed me before I started caring about offsets. It is opinionated about which subkeys earn your time and which ones I have never used in a real case.
regf, very briefly#
regf is the on-disk format for all NTUSER.DAT, SYSTEM, SOFTWARE, SAM and SECURITY hives, plus the Amcache. It is documented well enough by Microsoft and re-documented better by the open-source community, in particular Maxim Suhanov's yarp project and Eric Zimmerman's notes that ship with his tools.
A few facts that matter when you are debugging a broken parse:
- The file is divided into 4 KiB blocks called "hbins". The first 4 KiB is the file header. Everything after is hbins.
- Each hbin contains a chain of cells. Cells with a positive size field are free, cells with a negative size field are allocated. Yes, that is backwards from what you would design today, and yes, every parser has been bitten by it.
- Keys are
nkcells. Values arevkcells. Subkey lists arelf,lh,ri,li. Big values usedbcells. If you have ever seen "unknown cell signature" in a parser log, that is usually because the cell type table is incomplete or the hive is corrupt at the bin boundary. - The hive carries a sequence number pair at the top. If
primaryandsecondarydo not match, the hive was being written when it was captured, and the transaction logs need to be replayed before the content can be trusted.
The Amcache uses none of these structures unusually. Whatever wrote your favourite NTUSER.DAT parser will, modulo bugs, read the Amcache.
The subkeys that pay rent#
The interesting content lives under Root\InventoryApplication, Root\InventoryApplicationFile, Root\InventoryDeviceContainer, Root\InventoryDriverBinary, Root\InventoryDriverPackage, and Root\InventoryApplicationShortcut. There are other roots, including Root\InventoryApplicationFramework and the legacy Root\File on older Windows 7 builds, but the six above are where I spend 95% of my time.
InventoryApplication#
One subkey per installed (or once-installed) application, named with the ProgramId, a 16-byte identifier derived from the publisher, name and version. The values inside are an installer's-eye view of the software: Name, Publisher, Version, InstallDate, RootDirPath, Source (MSI / AddRemoveProgram / etc.), Type (Application / Game / Hotfix), Language. MSI installers tend to populate these fields well. Bundled or sideloaded software, less so.
InstallDate here is a DateTime-as-string value, not a FILETIME. It is what the installer reported, not what the filesystem saw. Treat it as advisory.
InventoryApplicationFile#
The subkey you will read most often. One entry per executable Appraiser has indexed, named with a key like notepad.exe|abcd1234ef567890. Each entry carries FileId (the 0000-prefixed SHA-1), LowerCaseLongPath, OriginalFileName, Name, Publisher, ProductName, ProductVersion, Version, BinaryType, Size, LinkDate, Language, IsPeFile, IsOsComponent, and a back-reference to the parent ProgramId.
The value I trust least is LowerCaseLongPath. It is the path Appraiser saw at scan time, which is fine, but renamed or relocated files leave behind stale entries with paths that no longer correspond to anything. The value I trust most is FileId. Hashes do not lie even when paths do.
InventoryDeviceContainer#
Devices the system has seen, both internal and external. Keyed by a container ID. Values include Manufacturer, ModelName, ModelNumber, FriendlyName, Categories, and a few BLE/USB-specific fields. This is the subkey I reach for when I need to corroborate a USB story, ideally cross-checked against SYSTEM\ControlSet001\Enum\USBSTOR from the main registry hives.
It is not a substitute for the proper USB artifacts. The Amcache will tell you a Logitech receiver has been on this box; it will not tell you which user plugged in which thumb drive at what time. Use it for breadth, not depth.
InventoryDriverBinary and InventoryDriverPackage#
Two related keys covering kernel-mode driver inventory. InventoryDriverBinary is one entry per .sys file Appraiser has seen, with the usual FileId, DriverName, DriverCompany, Service, DriverSigned, DriverInBox, DriverIsKernelMode, plus the LinkDate and product strings. InventoryDriverPackage covers .inf packages, with Class, ClassGuid, Date, Provider, Version and the inbox/signed flags.
These two keys are why "Bring Your Own Vulnerable Driver" investigations almost always begin with the Amcache. An attacker drops gdrv.sys or RTCore64.sys, loads it, exploits it, deletes it. The binary is gone from disk by the time you arrive. The InventoryDriverBinary entry, with its SHA-1, often is not.
InventoryApplicationShortcut#
Each subkey corresponds to an LNK file the Appraiser examined, identified by a hash and carrying the lower-case path. Fewer fields than the other inventories, but it is one of the few sources that will tell you a .lnk pointing at removable media existed on the host. Pair with the LNK parser for the actual target details, since Amcache's record is shallow.
Parsing it without inventing your own bugs#
There are three tools I actually use in case work, in roughly descending order of how often they touch the hive on my analyst workstation.
Eric Zimmerman's AmcacheParser#
The default. AmcacheParser.exe -f Amcache.hve --csv .\out\ -i will give you one CSV per inventory subkey, with -i enabling inclusion of non-PE files (useful for catching scripts that got picked up). The schema it emits is, for better or worse, what most other tools normalised to. If you need to write internal tooling, mirror the column names.
Two flags I always set: --mp to keep the millisecond precision on timestamps (the default rounded format hides timing details that occasionally matter), and --nl to keep entries without a LinkDate (skipping them by default has bitten me when chasing kernel drivers).
RegRipper#
Harlan Carvey's rip.exe with the amcache plugin (and the newer amcache_tln for timeline output). Older but still useful, particularly on Windows 7 hives where the legacy Root\File subkey is still present and AmcacheParser sometimes skips it. The plugin output is text, not CSV. Live with it, or grep.
yarp#
Maxim Suhanov's pure-Python regf library. This is what I use when I need to do something the existing tools do not do, like walk free cells looking for deleted records or compare two snapshots of the same hive. The API exposes raw cells, transaction log replay, and a sane object model for keys and values. yarp-print is a handy CLI when you just want to dump a hive.
If you are building automation, yarp is the right floor to build on. If you are responding to an incident at 02:00, AmcacheParser is faster.
The transaction logs are not optional#
Amcache.hve.LOG1 and Amcache.hve.LOG2 are the dirty-page logs the kernel uses to keep the hive consistent across crashes. The format is documented (HvLE blocks for modern Windows, the older DIRT format on Win7). They matter to you because:
- If acquisition happened while the hive was being written, the main file is inconsistent and the logs hold the missing pages. AmcacheParser and yarp both replay them automatically when present. RegRipper, depending on version, does not.
- Recently-deleted subkeys frequently still exist in the log pages. I have recovered entries from
.LOG1that were purged from the main hive minutes before acquisition. Always grab the LOGs alongside the hive, never just the.hve. - A mismatched sequence number on the hive is your cue that you need the logs. If primary != secondary on the header, do not parse without them. Better tools will refuse; worse tools will produce garbage and not warn you.
What I never bother with#
Honest list. I have never closed a case using InventoryApplicationFramework, the Orphan subkey, or InventoryMiscellaneousMemorySlotArrayInfo (yes, that exists). They are noise. If you find yourself digging there because the obvious keys came up empty, you have probably been handed a host where the Appraiser was disabled, and your time is better spent on the MFT, the USN journal, and the Security event log.
Further reading#
- Maxim Suhanov's yarp and his Windows registry file format specification.
- Eric Zimmerman's AmcacheParser.
- Harlan Carvey's RegRipper and the
amcacheplugin source as a teaching reference. - Microsoft's Registry hive file format for the boring-but-canonical version of the structures above.
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 timestamps, decoded
Every FILETIME and DateTime-as-string field across the Amcache keys, what each really tracks, and how Win7, Win10 and Win11 disagree about the same artifact.
- Amcache registry structure: every key explained
Key-by-key tour of Amcache.hve. Root\InventoryApplicationFile, InventoryApplication, InventoryDriverBinary, the legacy Programs and File keys, and what every notable value means.