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.DAT for 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 -Descending

This 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 -Descending

For 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:

  1. From DeviceContainers.csv, filter to storage categories.
  2. Sort by KeyLastWriteTimestamp descending.
  3. Identify any device whose last-seen time falls in the suspicion window.
  4. Pivot to USBSTOR for the serial number, then to NTUSER.DAT mount-point history for that serial to confirm the user account that mounted it.
  5. 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, KeyLastWriteTimestamp

Adjust 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#

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

Back to all posts