Building a USB exfiltration timeline from the registry
7 min read
A departing engineer's manager flags that someone has been pulling files from a shared drive the week before the resignation took effect. Legal wants to know whether data left on removable media. You get an E01 of the workstation and a question that sounds simple: did anyone walk out with a USB stick full of source, and if so, which device, on which day, and was it this user. That is a USB forensics problem, and the registry answers most of it before you ever touch the file system. This post is the workflow I run for a USB exfiltration case — the artifacts that matter, the order to read them in, and how to chain a device serial all the way to a named user and the folders they browsed.
No single key gives you the whole story. A USB device timeline is something you assemble: device identity from one hive, drive-letter mapping from another, user attribution from a third, and the "what did they actually open" from a fourth. The skill is knowing which key carries which column and how they join. This is the scenario layer of the broader registry forensics for investigations workflow; each artifact below links out to its own deep-dive.
The artifacts that matter
Six places carry the USB story. One line each on what you get:
- USBSTOR (
SYSTEM\CurrentControlSet\Enum\USBSTOR) — device identity (vendor/product/serial) and the first-connect / last-connect / last-removal timestamps. Your starting point. See the USBSTOR deep-dive. - USB / Enum (
SYSTEM\CurrentControlSet\Enum\USB) — the broader USB device tree keyed byVID_xxxx&PID_xxxx, withLocationInformation(physical port) and VID/PID for hardware identity and for devices that enumerate over USB but never as mass storage. - MountedDevices (
SYSTEM\MountedDevices) — maps drive letters and volume GUIDs to device paths. This is the join between a USBSTOR serial and a drive letter / volume GUID. - MountPoints2 (
NTUSER.DAT\...\Explorer\MountPoints2) — per-user, links a volume GUID to a specific profile. The only artifact here that proves who. See the MountPoints2 deep-dive. - Windows Portable Devices / WPD (
SOFTWARE\Microsoft\Windows Portable Devices\Devices) — friendly name, volume label, and last-known drive letter for MTP-class devices: phones, cameras, anything that connects as a media device rather than a disk. The stick is only half the exfil surface; a phone in MTP mode never shows up in USBSTOR. - Bluetooth (
SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices) — paired Bluetooth devices, BD_ADDR and friendly name. OBEX file push and phone pairing are an exfil path people forget to look at. See the BTHPORT deep-dive. - ShellBags (
USRCLASS.DAT/NTUSER.DAT) — folders the user browsed in Explorer, including paths on the removable volume. This is the closest the registry gets to "what they opened". See the ShellBags deep-dive.
USBSTOR, USB, MountedDevices and BTHPORT live in SYSTEM. MountPoints2 and ShellBags are per-user, so you parse them once per NTUSER.DAT / USRCLASS.DAT on the box. WPD is in SOFTWARE. Load all of them; the case lives in the joins.
Chaining serial -> volume -> drive letter -> user
The pivot value is the device serial / instance ID from USBSTOR. Everything joins on it. Here is the chain end to end.
1. Serial, from USBSTOR. Each Disk&Ven_...&Prod_... subkey has an instance-ID child. For a well-behaved device that is the iSerialNumber from the USB descriptor:
USBSTOR\Disk&Ven_SanDisk&Prod_Cruzer_Blade&Rev_1.00\
4C530001120607115201&0
4C53... is the value you carry through every other key. Read the three device properties under ...\<instance>\Properties\{83da6326-97a6-4088-9453-a1923f573b29}\ while you are here: 0064 first connect, 0066 last connect, 0067 last removal. That is the device's timeline spine.
2. Volume GUID and drive letter, from MountedDevices. SYSTEM\MountedDevices holds two kinds of value name: \DosDevices\E: (a drive letter) and \??\Volume{GUID} (a volume GUID). The data of each is a binary device path. For USB storage that path contains the USBSTOR instance ID as UTF-16. String-match your serial inside the value data and you learn two things at once: the drive letter the device was assigned (E:), and the volume GUID that letter maps to.
\DosDevices\E: -> ...USBSTOR#Disk&Ven_SanDisk...#4C530001120607115201&0#...
\??\Volume{a1b2c3d4-...} -> ...USBSTOR#Disk&Ven_SanDisk...#4C530001120607115201&0#...
Same serial in both values, so E: == Volume{a1b2c3d4-...} == the SanDisk. Note: a 12-byte MountedDevices value is an MBR mapping (4-byte disk signature + 8-byte partition offset), not a device path — you can only string-match the longer device-path values.
3. User, from MountPoints2. MountedDevices is system-wide; it does not know who plugged the drive in. For that you go into each user's NTUSER.DAT and read Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2. The subkeys there are named by volume GUID — the same GUID you just resolved. Find {a1b2c3d4-...} under jsmith's MountPoints2 and you have attributed the volume to jsmith: that profile had the device mounted and visible in their session. The subkey LastWrite gives you a rough "when this user last interacted with it" stamp.
4. What they browsed, from ShellBags. With the drive letter in hand, parse ShellBags for that user and look for bag entries under E:\ or referencing the volume. ShellBags record folders opened in Explorer, so a bag for E:\exfil\customer-db proves the user navigated into that folder on the removable volume — and the bag's embedded MAC timestamps tell you roughly when. This is the difference between "a device was attached" and "this user opened these folders on it".
The full join, one device, one user:
USBSTOR serial 4C53...&0
└─ MountedDevices: serial -> E: + Volume{a1b2c3d4-...}
└─ MountPoints2 (NTUSER.DAT \jsmith): Volume{a1b2c3d4-...} present => user = jsmith
└─ ShellBags (\jsmith): E:\exfil\customer-db browsed
+ USBSTOR properties: first 2026-06-09, last connect 2026-06-14 17:41, removed 18:09
That row — device, user, drive letter, folders, and a connect/removal window long enough to copy the data set — is what goes in the report.
Gotchas
- The
&in the serial. Look at the second character of the instance ID. If it is&(e.g.7&1f2a3b4c&0), the device supplied no iSerialNumber and Windows generated a substitute tied to the port/bus path, not the device. Plug a serial-less drive into a different port and you get a different ID, a fresh subkey, a phantom "first connect". Your identity is per-port, not per-device — say so, and lean harder on volume GUID and friendly name. The USBSTOR notes cover this in full. - Serial uniqueness is firmware-asserted, not guaranteed. The vendor/product strings and even the serial are values the device firmware advertises. Cheap controllers clone them; a bargain drive can claim to be a SanDisk and reuse another unit's serial. Treat the serial as strong evidence of identity, not proof, especially across two hosts.
- CurrentControlSet does not exist offline. In an image there is no
CurrentControlSetsymlink — readSYSTEM\Select\Currentand use the matchingControlSet00N. Point a tool at the wrong set and you miss devices or read stale timestamps. Inactive control sets sometimes retain entries the active one dropped, which can be exactly the device you want. - Timezone. Every registry timestamp here is UTC (FILETIME / LastWrite). ShellBags embed DOS date/time that is local to the machine that wrote them. Resolve
SYSTEM\CurrentControlSet\Control\TimeZoneInformation, normalize everything to UTC, and state the offset in the report. Mixing a UTC USBSTOR connect with a local ShellBag timestamp is how you build a timeline that is wrong by hours and get it torn apart on cross-examination. - Last, not all. USBSTOR
0066/0067are the most recent arrival/removal, not full history. For repeated insertions of the same drive you need theKernel-PnP/Partitionevent logs and, ideally, VSS copies of theSYSTEMhive. - The drive is not the only channel. If USBSTOR is thin, check WPD for an MTP phone and BTHPORT for paired Bluetooth devices before you conclude nothing left the box.
Work the case in your browser
Drop the SYSTEM, SOFTWARE, and the relevant NTUSER.DAT / USRCLASS.DAT hives into the parser on this site. It resolves the control set correctly, splits the USBSTOR subkey into device class / serial / friendly name, surfaces the 0064/0066/0067 property timestamps, and parses MountedDevices, MountPoints2, WPD, BTHPORT and ShellBags so you can run the serial -> volume -> letter -> user join across hives without scripting it. Nothing is uploaded — the hives are parsed in the browser and discarded when you close the tab, which keeps chain of custody intact for SAM/SECURITY-adjacent evidence.
Build the timeline by sorting all device 0066 values, bracket each against logon sessions for the exfil window, and attach the per-user MountPoints2 and ShellBags rows. A device whose first-connect lands on the day of the resignation email, mounted under the target's profile, with browsed folders on the volume, is the spine of the finding.
Related
- Registry forensics for investigations — the scenario pillar this workflow sits under.
- USBSTOR: USB device history — device identity, serials, connect/removal timestamps.
- MountPoints2 — per-user volume attribution.
- BTHPORT / Bluetooth — paired devices and the Bluetooth exfil path.
- ShellBags forensics — folders browsed on the removable volume.