USB and device history from Amcache: InventoryDeviceContainer and InventoryDevicePnp
Beyond PE binaries, Amcache's modern schema records every device
Windows has enumerated on the host. The two sub-keys that matter
for this — Root\InventoryDeviceContainer and
Root\InventoryDevicePnp — together give analysts one of the
cleanest answers to "what hardware has ever touched this
machine?" that Windows offers.
This page is the practical guide to USB and peripheral investigations using Amcache: what each key records, how to read the two together, and the limits you need to know about.
For the broader artefact reference, see the Amcache complete reference; for the surrounding schema, see Amcache registry structure.
What Amcache captures vs the traditional sources#
Historically, "USB device history" investigations on Windows have relied on:
HKLM\SYSTEM\CurrentControlSet\Enum\USB— every USB device Windows has enumerated.HKLM\SYSTEM\CurrentControlSet\Enum\USBSTOR— USB mass-storage devices specifically.setupapi.dev.log(C:\Windows\INF\setupapi.dev.log) — driver install log with timestamps.- Per-user
NTUSER.DATfor mount-point history.
Those sources remain the most authoritative for USB mass storage in particular. Amcache adds a parallel view that is often faster to parse and richer in friendly names:
| Source | Best for |
|---|---|
Enum\USB / USBSTOR (registry) |
Authoritative device history, especially mass storage. |
setupapi.dev.log |
Driver-install timestamps for first connect. |
NTUSER.DAT mount points |
Per-user mount and last-connect data. |
Amcache InventoryDeviceContainer |
Friendly names, vendor / model, paired/connected state. |
Amcache InventoryDevicePnp |
PnP enumeration record per interface. |
In a triage context, Amcache is faster — one hive parse and you have a tabular view of every device with friendly names. For evidence, you want all the sources, not just Amcache.
InventoryDeviceContainer#
The user-facing view. One sub-key per "device container" Windows tracks — a logical device, not a low-level interface. Each entry has:
| Field | Meaning |
|---|---|
FriendlyName |
The display name Windows assigns: "Brother HL-L2350DW", "SanDisk Cruzer Glide", "Logitech BRIO". |
Manufacturer |
Vendor string. |
ModelName |
Model identifier from the device. |
ModelNumber |
Model number, if separate. |
Categories |
Device categories: Printer, Storage, Display, Network, Bluetooth, MultimediaDevice, ... |
DiscoveryMethod |
How Windows enumerated it: DeviceEnumeration, Manual, BluetoothPairing, ... |
IsConnected |
1 if connected at last inventory. |
IsPaired |
1 if paired (Bluetooth specifically). |
IsActive |
1 if Windows considers it currently active. |
Icon |
Path to the device's icon resource. |
KeyLastWriteTimestamp |
When the record was last updated — closest thing to "last seen" for the device. |
This is the cleanest "what hardware has been connected here?" table Windows exposes. Friendly names, categories, and a last-update timestamp per device, in a single CSV after AmcacheParser.
InventoryDevicePnp#
The technical view. One sub-key per device interface the PnP
manager has enumerated. Where InventoryDeviceContainer lists
"Brother HL-L2350DW" once, InventoryDevicePnp may list the
printer's USB interface, its print interface, and any virtual
interfaces it exposed. Fields:
| Field | Meaning |
|---|---|
InstanceId |
PnP instance identifier, e.g. USB\VID_05E0&PID_1701\ABC123. |
BusReportedDescription |
What the device told Windows it was. |
DeviceClass |
Driver class GUID. |
DeviceId |
PnP device ID. |
Manufacturer |
Vendor string. |
Model |
Model string. |
Service |
Driver service. |
DriverName |
Driver file backing the device. |
KeyLastWriteTimestamp |
When the PnP record was last updated. |
InstanceId is the join key between
InventoryDeviceContainer and InventoryDevicePnp: take an
InstanceId from one and find the matching row in the other to
get both the user-facing name and the technical IDs.
Reading the two together#
A clean pattern for "list every device that has ever been on this host with friendly name, category, and PnP instance":
$containers = Import-Csv .\HOST_amcache_DeviceContainers.csv
$pnps = Import-Csv .\HOST_amcache_DevicePnps.csv
# Join on InstanceId where present
$containers | ForEach-Object {
$c = $_
$pnp = $pnps | Where-Object { $_.InstanceId -eq $c.InstanceId } | Select-Object -First 1
[pscustomobject]@{
FriendlyName = $c.FriendlyName
Categories = $c.Categories
Manufacturer = $c.Manufacturer
InstanceId = $c.InstanceId
BusDesc = $pnp.BusReportedDescription
Service = $pnp.Service
IsConnected = $c.IsConnected
LastSeen = $c.KeyLastWriteTimestamp
}
} | Sort-Object LastSeen -DescendingThis produces a per-device table that is dramatically easier to
scan than raw Enum\USB exports.
USB mass-storage focus#
For the classic "did a USB drive connect to this host on $DATE?" question, filter to storage categories:
Import-Csv .\HOST_amcache_DeviceContainers.csv |
Where-Object {
$_.Categories -match 'Storage|Disk|USB.*Mass'
} |
Select-Object FriendlyName, ModelName, Manufacturer, IsConnected, KeyLastWriteTimestamp |
Sort-Object KeyLastWriteTimestamp -DescendingFor each surviving row, cross-reference with Enum\USBSTOR for
the authoritative serial number and first-/last-connect timestamps.
Amcache gives you a fast triage view; USBSTOR gives you the
evidence-grade detail.
Investigative use cases#
Insider-threat data-exfiltration triage#
A common scenario: you suspect an employee copied data to a USB drive before resigning. The Amcache device list gives you a chronological view of every storage device the host has seen, typically over many months.
Pattern:
- From
DeviceContainers.csv, filter to storage categories. - Sort by
KeyLastWriteTimestampdescending. - Identify any device whose last-seen time falls in the suspicion window.
- Pivot to
USBSTORfor the serial number, then toNTUSER.DATmount-point history for that serial to confirm the user account that mounted it. - Cross-reference with file-system access timestamps for files of interest in the same window.
Unauthorised peripheral connection#
For environments where peripherals are policy-restricted (printers,
audio devices, networked storage), Amcache's
InventoryDeviceContainer is a quick scan for non-compliant
devices:
Import-Csv .\HOST_amcache_DeviceContainers.csv |
Where-Object {
$_.Manufacturer -notmatch '^(YourCompany|YourApprovedVendor)' -and
$_.Categories -match 'Printer|Display'
} |
Select-Object FriendlyName, Manufacturer, Categories, KeyLastWriteTimestampAdjust the allowlist to your environment.
Bluetooth pairing history#
DiscoveryMethod = BluetoothPairing rows show every device that
was paired over Bluetooth, with friendly names. Useful for "did
the user pair their phone / personal headset / personal keyboard?"
questions in regulated environments.
Identifying counterfeit / unknown devices#
A row in DevicePnps.csv whose BusReportedDescription is
generic ("USB Device", "Unknown Device") and whose Manufacturer
is blank or unbranded, paired with a DeviceContainers.csv row
that has no FriendlyName, is often a malicious or counterfeit
HID device — a "BadUSB" pen-test tool, an unbranded keyboard
emulator, or a malicious data-cable.
Limits and caveats#
KeyLastWriteTimestamp is not "first connect"#
It is "last update". For a device that connects regularly, you see
recent timestamps. For a device that connected once a year ago, you
see the one-year-old timestamp. For first-connect timestamps,
parse setupapi.dev.log.
Not every device leaves an Amcache entry#
Devices that connect and immediately disconnect between appraiser
runs may never be inventoried. For short-window USB investigations
(seconds to minutes), setupapi.dev.log and USBSTOR are more
reliable.
Friendly names are vendor-controlled#
The FriendlyName is whatever the device tells Windows it is. A
malicious USB device can claim to be "Microsoft Wireless Mouse"
and Windows displays that name. Pair with BusReportedDescription
and physical inspection.
Some categories are noisy#
InventoryDeviceContainer records virtual devices, software
audio endpoints, and platform-internal devices alongside real
peripherals. Filter on Categories and on whether IsPaired or
Manufacturer is set to cut the noise.
See also#
- Amcache complete reference — the artefact in full.
- Amcache registry structure —
where
InventoryDeviceContainerandInventoryDevicePnpsit in the hive. - AmcacheParser output columns explained
— every field in
*_DeviceContainers.csvand*_DevicePnps.csv. - Amcache for malware investigation — the binary-focused triage playbook (pair with device history for full-host triage).
To explore the device history on your own hive without installing anything, drop a file on the parser home page — it parses entirely in your browser.
Related posts
- Volatility and Amcache: extracting the hive from memory images
A practical guide to recovering Amcache from a Windows memory image using Volatility — when memory-side recovery is the only option, which plugins to use, and how to hand off to AmcacheParser.
- RegRipper amcache plugin: what it does and when to use it
A practical guide to RegRipper's amcache plugin — what it parses, how its text output differs from AmcacheParser's CSV, and when to reach for it instead of (or alongside) the Zimmerman tool.
- AmcacheParser output columns explained: every CSV field decoded
A field-by-field reference for AmcacheParser's CSV output — FileId, PathHash, ProgramId, LinkDate, BinFileVersion, IsPeFile, and every other column, with the pivots that matter in DFIR.
- AmcacheParser download guide: official sources, mirrors, and verification
Every way to download Eric Zimmerman's AmcacheParser — Get-ZimmermanTools, direct download, KAPE, Velociraptor — with checksum verification and air-gapped install patterns.