Registry Parser
All articles

Paired Bluetooth devices: the RegRipper bthport plugin

8 min read

Most registry execution artifacts answer "what ran here." The RegRipper bthport plugin answers a different and often more valuable question: "what was physically near this machine, and paired to it, long enough to matter." Every Bluetooth device that has ever paired to a Windows host leaves a persistent record under the BTHPORT service key, keyed by the device's MAC address, carrying its friendly name and — on newer builds — timestamps for when it was last seen and last connected. That makes BTHPORT a proximity artifact. A phone, a headset, a wireless keyboard, a file-transfer-capable laptop: if it paired, it is on disk, and it stays there long after the device is gone.

Where it lives

The data is in the SYSTEM hive under:

SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices\<MAC>

Each subkey under Devices is one paired device. The subkey name is the device's 48-bit Bluetooth MAC address as twelve hex digits, no separators — for example a4c138f01b2c. The bthport plugin reformats that into the conventional colon-delimited, upper-case form (A4:C1:38:F0:1B:2C) for the output table, falling back to the raw subkey name if it does not match the twelve-hex-digit pattern. So if you see something other than a clean MAC in the first column, the subkey name itself was non-standard; do not assume the tool mangled it.

A word on CurrentControlSet, because this is where careless analysis goes wrong. On a live system it is a volatile alias the kernel builds at boot — it does not exist as a stored key in the hive file you carry out of an image. An offline SYSTEM hive contains ControlSet001, ControlSet002, and a Select key whose Current value names the active set. The plugin resolves this for you (its currentControlSet helper reads Select\Current and points at the right ControlSetNNN), but if you are spelunking by hand, navigate to the real ControlSet001\Services\BTHPORT\... path — searching literally for CurrentControlSet in an offline hive finds nothing. Check the non-current control set too: a device present in ControlSet002 but not the current one can indicate a pairing that predates the last clean shutdown or was rolled back.

What each value holds

Inside a device subkey the plugin reads a small set of values. The two it leans on hardest:

  • Name — the device's friendly name, the string it advertised during pairing ("Galaxy S23", "Jabra Elite 4", "Logitech K380"). It is stored as REG_BINARY, not a tidy REG_SZ. The bytes are the name text, NUL-terminated, and the plugin decodes them as UTF-8/ASCII, truncating at the first NUL and stripping non-printable bytes. Most names are plain ASCII and decode cleanly. Be aware, though, that across builds these name bytes have been seen both as single-byte (UTF-8/ASCII) and as UTF-16 with interleaved NUL bytes; a strict UTF-8 decode of a UTF-16 string lands on the first interior NUL and may surface only the first character. If a name comes back suspiciously short or empty, pull the raw Name bytes into a hex view before concluding the field was blank.

  • LastSeen and LastConnected — 64-bit Windows FILETIME timestamps, decoded by the plugin from the first eight bytes of each value. LastSeen is the more recent radio-level observation (the device was in range and discoverable/advertising); LastConnected is the last time an actual connection was established. The distinction matters: a device can be seen without connecting.

Here is the honest hedge, and the plugin's own note says as much: these timestamp values are build-dependent. They are reliably present on Windows 10 and later; on Windows 7 and 8.x device subkeys frequently carry no LastSeen/LastConnected at all, and even on Windows 10/11 the exact set of values written varies by version, driver stack, and device class. Treat their presence as a bonus, not a guarantee. When they are absent the plugin emits empty cells for those columns and you fall back to the key's last-write time (see below). Do not represent an empty timestamp as "the device was never connected" — it almost always means "this build did not record it here."

The columns

The plugin produces one row per paired device with these columns:

MAC address       Device name       Last seen (UTC)       Last connected (UTC)       Key written (UTC)

The final column, Key written (UTC), is the registry key's own LastWrite timestamp — the fallback the note refers to. Every key carries a LastWrite FILETIME regardless of build, so even on a host that never wrote LastSeen/LastConnected you still get a time for the device subkey. Interpret it carefully: it reflects the last modification to the key's values, typically the last meaningful pairing or connection event, but it can also move on unrelated metadata churn. Treat it as a lower bound — "this device was relevant at least as recently as X" — not as a connection log entry.

A realistic decoded row:

MAC address:        58:CB:52:9A:1D:E4
Device name:        Florian's iPhone
Last seen:          2026-06-14 08:11:42 UTC
Last connected:     2026-06-14 08:11:40 UTC
Key written:        2026-06-14 08:11:42 UTC

That single row places a specific, named personal device in radio range of, and connected to, this machine at a timestamp to the second.

The forensic value

This is the part that makes BTHPORT punch above its weight.

It is proximity evidence. Bluetooth Class 2 radios — phones, headsets, keyboards, most consumer gear — have an effective range on the order of ten metres, often much less through walls. A device that paired and connected was, at that moment, physically near the machine. That is a different and stronger claim than "an account logged in." A paired iPhone named with the suspect's name, last connected during the window of interest, places a person at the keyboard in a way a network artifact cannot.

It identifies the device, and through it, the person. The friendly name is whatever the owner set, and people name their phones after themselves constantly ("Florian's iPhone," "Sarah's AirPods"). Even when the name is generic, the MAC address is a hard identifier you can correlate against the suspect's seized phone, against MDM inventory, against access-point logs, or against another machine's BTHPORT.

It is a data-exfiltration vector. Bluetooth supports file transfer (OBEX/OPP) and, with a phone tethered, full network egress that bypasses the wired/Wi-Fi monitoring an organisation actually watches. A paired phone or laptop connected during a suspected exfil window is a lead worth pulling hard — correlate it against what files were touched, what shell activity ran, and what the USB device history shows for the same window. Bluetooth and USB are the two short-range egress paths that leave registry residue; check both.

It survives the device's departure. The subkey persists after the device is unpaired in some workflows, and certainly after the device simply walks away. You are reading a historical record, not a snapshot of what is connected now.

MAC OUI vendor lookup

The first three octets of every MAC are the Organizationally Unique Identifier — the IEEE-assigned vendor prefix. Run the MAC through an OUI lookup (the IEEE registry or any offline OUI database) and 58:CB:52:... becomes "Apple, Inc." even when the Name value is blank. That alone often hints at the device class: an Apple OUI on a host whose user claims to own only Android is a discrepancy worth chasing. The OUI confirms the manufacturer, not the model — and randomised/locally-administered MACs (second-least-significant bit of the first octet set) will not resolve to a real vendor. If the lookup fails, check that bit before assuming a bad read.

Pitfalls worth stating plainly

  • Do not over-claim from a single timestamp. "Last connected" is the last connection, not the only one. BTHPORT does not keep a connection history — there is no count, no per-session log, just the most recent times and the key write. For frequency or earlier activity, pull the SYSTEM hive from VSS snapshots and diff the device subkeys across time.
  • Empty name, real device. A blank Device name cell usually means an encoding mismatch or a device that paired without advertising a name, not the absence of a device. The MAC is authoritative.
  • Build variance is the rule. Everything about which values get written here varies by Windows version. Anchor your report in what is actually present in the hive in front of you, and say so.

Tools

  • RegRipper's bthport plugin. The reference implementation; read the source to see exactly which values it pulls and how it handles the FILETIMEs and the name bytes. Run it against a SYSTEM hive and you get one block per paired Bluetooth device.
  • Eric Zimmerman's Registry Explorer / RECmd will walk BTHPORT\Parameters\Devices directly; useful for eyeballing the raw Name bytes when a decode looks wrong.
  • The parser on this site implements bthport as a standard plugin — you can analyze a SYSTEM hive in your browser and get the MAC, friendly name, last-seen and last-connected times, and the key-write fallback in one table, with no upload of the evidence file off your machine. See the full RegRipper plugins reference for the rest of the SYSTEM-hive plugin set.

Bottom line

BTHPORT will not tell you what code executed, and it keeps no connection history. What it does, better than almost any other registry artifact, is tie a named, manufacturer-identifiable, physically-present device to a machine at a timestamp. In a proximity question — was this person here, was that phone tethered for exfil, does the suspect's seized handset match what paired to the workstation — the bthport plugin is the first place to look, and the MAC is the identifier you carry into the rest of the investigation.