USB device history: the RegRipper usbstor plugin
8 min read
When someone asks "did data leave this machine on a USB stick", the first place you look is USBSTOR. The RegRipper usbstor plugin reads the SYSTEM hive and enumerates every USB mass-storage device the OS has ever enumerated as removable storage: thumb drives, external HDDs, SD-card readers presenting as disks, phones in mass-storage mode. Windows never forgets one of these. It writes a subkey the first time the device is seen and leaves it there forever, which is exactly what you want in a data-exfiltration investigation and exactly what users do not realise is happening.
This is the artifact for USB-borne data-exfil questions. Not the only one — you correlate it with three or four others — but the one you start from.
Where it lives
Two keys carry the bulk of the story, both under the active control set:
SYSTEM\CurrentControlSet\Enum\USBSTOR
SYSTEM\CurrentControlSet\Enum\USB
USBSTOR is the device class for USB mass storage. Its subkeys are named by the device descriptor the firmware reported, in the form:
Disk&Ven_SanDisk&Prod_Cruzer_Blade&Rev_1.00
So immediately you get vendor, product, and revision parsed straight out of the subkey name — no decoding, just split on & and strip the Ven_/Prod_/Rev_ prefixes. The plugin in this site's parser surfaces that subkey name verbatim as the Device class column and lets you read the vendor/product yourself; some RegRipper output splits it for you. Either way the value is the same string the device firmware advertised, which is worth remembering: it is attacker-controllable. A cheap drive can claim to be a SanDisk. Treat the vendor/product as a label, not an identity.
Under each device subkey is one more level: the instance ID, which is where the identity actually lives.
The serial number and the & tell
Each Disk&Ven_... key has child subkeys named by the device's instance ID. For a well-behaved device that ID is the iSerialNumber string baked into the USB descriptor:
USBSTOR\Disk&Ven_SanDisk&Prod_Cruzer_Blade&Rev_1.00\
4C530001120607115201&0
That 4C53... is the unique hardware serial. It is the value you pivot on across every other artifact, because it survives reformatting, relabelling, and moving the drive between machines. Find the same serial in two different SYSTEM hives and you have proven the same physical device touched both hosts.
Here is the detail that catches people. Look at the second character of the instance ID. If it is an &, the device did not supply a unique serial number, and Windows generated one for it:
USBSTOR\Disk&Ven_Generic&Prod_Flash_Disk&Rev_8.07\
7&1f2a3b4c&0
The leading 7& (a single hex digit, then &) is the giveaway. The USB spec makes iSerialNumber optional, plenty of bargain-bin controllers omit it, and Microsoft assigns a substitute that is tied to the port/bus path, not the device. That substitute is not stable: plug the same serial-less drive into a different USB port and you get a different instance ID, a different subkey, a fresh "first connect". So before you assert "this exact drive was here", check character two. An & means your identity is weak and the timeline you build on it is per-port, not per-device. RegRipper's usbstor.pl flags this; do not skip past it.
First connect, last connect, last removal
The connect/disconnect timestamps are the heart of a USB timeline, and on modern Windows they do not live in the value data — they live in a device Properties set under each instance, keyed by a property-set GUID and a numeric property ID. The parser reads these three from under:
...\<instance>\Properties\{83da6326-97a6-4088-9453-a1923f573b29}\<id>
0064— first install / first connect (FILETIME)0066— last arrival / last connected (FILETIME)0067— last removal (FILETIME)
Each is an 8-byte little-endian FILETIME at offset 0 of the property value. Together they bracket the device's life on the host: 0064 is when it was first ever seen, 0066 is the most recent insertion, 0067 is the most recent unplug. The gap between a 0066 and the following 0067 is one session — and the length of that session is your dwell time, which matters when the question is whether there was time to copy gigabytes.
These properties are a Windows 8-and-later thing. On Win7 and earlier they are absent or sparse, and the fallback is the subkey LastWrite time of the instance key, which approximates last activity but does not distinguish arrival from removal. The parser exposes that as a separate Key written column precisely so you do not confuse a fallback marker with a real connect timestamp. If you only have the LastWrite, say "last activity around X", not "connected at X".
A typical parsed row reads:
Device class: Disk&Ven_SanDisk&Prod_Cruzer_Blade&Rev_1.00
Serial/instance: 4C530001120607115201&0
Friendly name: SanDisk Cruzer Blade USB Device
First install: 2026-06-09 08:14:02 UTC
Last connected: 2026-06-14 17:41:55 UTC
Last removed: 2026-06-14 18:09:30 UTC
The FriendlyName value comes from the instance key directly and is the human label the user would have seen in Explorer. Useful for reports and for matching a device to a witness statement, nothing more.
The CurrentControlSet gotcha
CurrentControlSet is a runtime symlink. It only exists when the kernel is running. In an offline SYSTEM hive pulled from disk or an image, there is no CurrentControlSet key — there are ControlSet001, ControlSet002, and a Select key whose Current value (a number) tells you which set was active. This parser resolves it the correct way: read Select\Current, and if it is, say, 1, the live path is ControlSet001\Enum\USBSTOR. If Select is missing it falls back to ControlSet001, then to the literal CurrentControlSet for the rare loaded-hive case.
Why it matters for USB work: the inactive control set can hold device entries the active one has dropped or that differ in timestamps. If you point a tool at the wrong set, you can miss a device entirely or read a stale connect time. Confirm which set you parsed. Any plugin that hard-codes CurrentControlSet against an offline hive is reading nothing.
Correlation: turning a serial into a story
USBSTOR tells you a device existed and when it connected. It does not tell you a drive letter, a volume, or what was copied. You get those by pivoting on the serial and the device path:
MountedDevices(SYSTEM\MountedDevices) maps drive letters and volume GUIDs to device paths. The USBSTOR instance ID appears inside those binary device-path values (UTF-16). Match it and you learn the drive letter the device was assigned. A 12-byte value there is an MBR mapping (4-byte disk signature plus 8-byte partition offset); anything longer is a device path you can string-match against the serial.- MountPoints2 (
NTUSER.DAT,...\Explorer\MountPoints2) is per-user and links a volume GUID to a specific user profile. This is how you attribute the insertion to a user, not just a host — the USBSTOR key inSYSTEMis system-wide and says nothing about who was logged on. - Windows Portable Devices (
SOFTWARE\Microsoft\Windows Portable Devices\Devices) carries the friendly name and last-known drive letter for MTP/WPD-class devices and often the same mass-storage drives, useful for the volume label. Enum\USB(the second key above) is the broader USB device tree, keyed byVID_xxxx&PID_xxxx. The parser pulls VID/PID andLocationInformationfrom it. It is how you tie the storage device back to its USB hardware IDs and physical port, and it catches devices that enumerate over USB but not as mass storage.
The build order in practice: USBSTOR gives you the device, serial, and connect/removal times. MountedDevices gives the drive letter. MountPoints2 in each user's NTUSER.DAT gives the user. Then you leave the registry — setupapi.dev.log, the Microsoft-Windows-Partition / Kernel-PnP event logs, LNK files and Jump Lists referencing the drive letter, and shellbags for folders browsed on the removable volume. That last one is worth a read on its own; see the ShellBags forensics notes. Each source adds one column the registry alone cannot: a file path, a copy, a user click.
Building the insertion timeline
With the three property timestamps across all devices you can lay out, per device:
first_install (0064) ── device ever seen
last_connected (0066) ── most recent plug-in
last_removed (0067) ── most recent unplug
Sort by 0066 and you have the order of recent insertions. Cross-reference each 0066/0067 pair against logon sessions and file-system MFT timestamps for the exfiltration window. A drive whose 0064 is the same day as the resignation email, with a session long enough to copy the data set, is the row that ends up in the report. Just remember these are the last arrival/removal, not a full history — for repeated insertions of the same drive you need the event logs and, ideally, VSS copies of the SYSTEM hive to reconstruct earlier connects.
Tools
- RegRipper's
usbstorplugin (usbstor.pl). EnumeratesEnum\USBSTOR, parses vendor/product/revision and serial, flags the non-unique&-serial case, and reads the0064/0066/0067device properties on modern hives. Source on GitHub. Pair it with themountdev,mp2, andport_devplugins to get drive letters and per-user attribution in one pass. - Eric Zimmerman's Registry Explorer / RECmd, with the USB-focused batch files, produces the same data in CSV and resolves the control set for you.
- The parser on this site reads the active control set correctly, splits the USBSTOR subkey into device class / serial / friendly name, and surfaces all three property timestamps plus the LastWrite fallback in a single table. You can analyze a SYSTEM hive in your browser without uploading it anywhere.
For the full set of SYSTEM-hive plugins and what each one extracts, see the RegRipper plugins reference.
Further reading
- The SANS USB-forensics material (the FOR500/FOR508 device-tracking sections and the associated posters) remains the standard walkthrough of the
USBSTOR/MountedDevices/MountPoints2correlation chain. Worth reading once end to end. - Harlan Carvey's Windows Registry Forensics and his blog notes on
usbstor.plfor the reasoning behind the serial-number&check.
USBSTOR will not tell you a single file was copied. What it tells you — which physical drives touched this host, when each was first seen, and when it was last plugged and pulled — is the spine of every USB-exfiltration timeline. Get the serial, check character two, resolve the right control set, and pivot out to MountedDevices and MountPoints2 for the drive letter and the user. The rest of the case hangs off that.