Bluetooth Attacks
Definition
Section titled “Definition”Bluetooth attack analysis covers both radio stacks: Bluetooth Classic (BR/EDR — audio, hands-free, legacy HID) and Bluetooth Low Energy (BLE — the modern everything: wearables, trackers, keyboards, locks, beacons, medical sensors). The analysis spans the pairing models and their trust boundaries (Legacy Pairing’s PIN-era weaknesses, Secure Simple Pairing/Secure Connections’ ECDH, BLE pairing with and without bonding), the GATT world (services and characteristics an attacker enumerates on any BLE device), the advertisement layer (the beacons every BLE device broadcasts, their MAC randomization, and what they leak), and the attack families: device tracking, GATT exploitation, HID spoofing/injection, pairing downgrade and MITM, and the tracker-detection problem that consumer creep (AirTag/FindMy-class devices [verify current ecosystems]) turned into a mainstream security topic. BLE’s design assumptions — short range, casual pairing UX, battery-first simplicity — mean most devices ship with more attack surface than their threat model assumed, and the discipline here is enumerating that surface honestly, frame by frame.
Why It Matters
Section titled “Why It Matters”Bluetooth is the personal-area perimeter nobody drew on a map: every employee’s desk has a BLE mouse/keyboard/headset, every pocket a phone advertising dozens of services, every facility a population of wearables and trackers — all radio, none of it behind the network’s firewalls. The attack consequences span practical ranges: HID spoofing turns a $10 dongle into keystroke injection against a workstation (the mouse-jacker class), pairing MITM on legacy-paired devices exposes audio and data streams, GATT exploitation reads whatever the device’s profile exposes (locks, medical data, asset tags), and advertising-layer tracking follows people via the MAC/UUID patterns their devices broadcast — with the corporate twist that the same trackers employees carry can be detected and responded to, making the analysis both offensive skill and safety feature. For defenders, BT is chronically unmanaged: device policies rarely distinguish a BLE thermostat from a BLE keyboard, pairing events are invisible to most SOCs, and the advertising noise floor makes anomalies hard to baseline — which is exactly why frame-level literacy (this module’s craft) matters: it turns the noise into a catalog (who is advertising what, which devices pair with what, which GATT surfaces exist) from which policy and detection can finally be written. And the history teaches the pattern analysts should expect again: each pairing-model generation closed the previous one’s holes (Legacy PIN → SSP → LE Secure Connections), while implementations kept shipping the old modes — so the analysis always starts with “which pairing mode is this actually using?”
Detailed Explanation
Section titled “Detailed Explanation”BLE’s architecture is advertising-centric, and everything observable starts there:
BLE ADVERTISING MODEL 3 adv channels: 37 (2402), 38 (2426), 39 (2480 MHz) ADV report: [MAC][payload][RSSI] payload IEs: flags, local name, TX power, service UUIDs (16/128-bit), manufacturer data MAC: public | static | RPA (resolvable private addr -- rotates via IRK; anti-tracking by design)
GATT PROFILE (post-connection surface) service UUID -> characteristics -> read/write/notify e.g. 0x180F Battery, 0x180D Heart Rate, custom vendor UUIDs (the interesting ones)
PAIRING MODES & TRUST Legacy Pairing: PIN-based, ECDH absent -> MITM-able LE Legacy (BLE 4.0-4.1): TK from Just Works -> MITM-able LE Secure Connections (4.2+): ECDH P-256 + numeric comparison/passkey -> MITM-resistant IF user verifies
ATTACK FAMILIES tracking: adv MAC/UUID patterns across space+time GATT abuse: enumerate + exploit exposed characteristics HID spoofing: impersonate keyboard/mouse -> keystrokes pairing MITM: downgrade/legacy modes BlueBorne-class: stack RCE history [verify per CVE]The advertisement layer is the recon surface: every BLE device beaconing on the three advertising channels announces its MAC, name fragments, service UUIDs, and vendor-specific manufacturer data — and the privacy feature (Resolvable Private Addresses, rotating MACs resolved only by paired devices’ IRKs) is precisely what tracker-detection has to work around, which is why tracker payloads (Apple FindMy’s advertisement format, Samsung SmartTag patterns) are identifiable by payload content rather than MAC. The GATT layer is the exploitation surface: once connected (pairing requirements vary per characteristic), the attacker enumerates services and characteristics, and the vendor-custom UUIDs are where the real exposures live — unlock commands, diagnostic writes, firmware-update endpoints without authentication. The HID surface is the highest-corporate-impact family: BLE keyboards and mice that pair without user verification (or that accept re-pairing when the dongle “sleeps”) let an attacker inject keystrokes — the classic mouse-jacker: spoof the dongle, wait for the victim’s click, type. The pairing models determine MITM-ability: Just Works (no user verification) is MITM-able by construction; passkey entry is MITM-able on legacy stack math but protected under LE Secure Connections’ ECDH; numeric comparison is MITM-resistant if the user actually compares the numbers. The BlueBorne-era history (2017 stack RCEs across platforms [verify CVE set]) taught the standing lesson: BT stacks are attack surface exposed by default (discoverable, connectable), and the patch cadence for embedded BT stacks is slower than any desktop OS. The analysis craft is per-device: identify the stack era, the pairing mode actually in use, the GATT surface actually exposed, and the advertisement pattern actually emitted — then map all four to the attack families they enable.
Common Techniques
Section titled “Common Techniques”| Technique | Target | What it does | Tooling | Notes |
|---|---|---|---|---|
| BLE advertisement scan | All BLE devices | Catalog MACs/names/UUIDs/RSSI | btmgmt, bettercap, custom | Passive recon |
| RPA/tracking analysis | Privacy devices | Correlate rotating MACs | Payload-pattern analysis | Tracker detection |
| GATT enumeration | BLE peripherals | Read services/characteristics | gatttool, bettercap BLE | Post-connection |
| GATT characteristic abuse | Locks/medical/custom | Write unlock/diagnostic commands | Per-device RE | [verify per device] |
| HID spoofing | Keyboards/mice | Inject keystrokes via pairing | Peripheral emulation | Corporate-impact king |
| Legacy pairing MITM | Legacy-paired devices | Intercept PIN/TK exchange | Proxmark/BT adapters | Old devices still ship |
| Just-Works MITM | JW-paired devices | Intercept unverified pairing | MITM-capable adapter | No user check |
| Tracker detection (defensive) | FindMy/SmartTag payloads | Alert on stalking patterns | Payload parsers | Safety feature |
| Beacon spoofing | iBeacon/Eddystone | Impersonate location beacons | Advertisers | Proximity-app abuse |
| Stack CVE classes | Discoverable devices | BlueBorne-era RCE families | Per-CVE tooling | Patch-dependent [verify] |
Full Working Code
Section titled “Full Working Code”blescan.py — a BLE advertisement analyzer that parses hcidump -R raw output (textual hex, universally available on Linux BT hosts): catalogs devices by MAC type (public/static/RPA heuristic), extracts local names, service UUIDs, and manufacturer-specific payloads, applies tracker-payload heuristics (Apple FindMy offline-finding shape), and produces the area’s BLE inventory. stdlib only (no scapy BT dependency — hcidump text is the interface).
#!/usr/bin/env python3"""blescan.py — BLE advertisement analyzer (hcidump -R input).Usage: hcidump -R | python blescan.py [--window 60] python blescan.py hcidump.txt --json ble.jsonParses HCI adv reports from hcidump raw hex text.std-in or file; stdlib only."""import argparse, json, re, sys, timefrom collections import defaultdict
APPLE_MFG = b"\x4c\x00" # little-endian 0x004CFINDMY_TYPES = {0x10, 0x12} # offline-finding payload [verify]
def parse_hcidump(lines): """hcidump -R: '> 043E 2B02 01 00 01 A2E400D...' rows.""" pkts = [] buf = [] for line in lines: line = line.strip() if re.match(r"^[<>]", line): if buf: pkts.append("".join(buf)) buf = [] continue hexpart = re.sub(r"[^0-9A-Fa-f]", "", line.split(" ", 1)[-1]) buf.append(hexpart) if buf: pkts.append("".join(buf)) return [bytes.fromhex(p) for p in pkts if p]
def parse_adv_payload(data): """BLE adv structure: len(1) type(1) data... sequences.""" out = {"name": None, "uuids": [], "mfg": None, "flags": None} i = 0 while i + 1 < len(data): ln = data[i] if ln == 0 or i + 1 + ln > len(data): break atype = data[i + 1] adata = data[i + 2:i + 1 + ln] if atype == 0x01 and adata: out["flags"] = adata[0] elif atype in (0x08, 0x09): out["name"] = adata.decode(errors="replace") elif atype == 0x02 and len(adata) >= 2: for j in range(0, len(adata) - 1, 2): out["uuids"].append( int.from_bytes(adata[j:j + 2], "little")) elif atype == 0xFF: out["mfg"] = adata i += 1 + ln return out
def mac_kind(mac_bytes): """Public/static/RPA heuristic from the two MSBs.""" msb = mac_bytes[5] # hcidump order: LSB first if msb & 0xC0 == 0xC0: return "static" if msb & 0xC0 == 0x40: return "rpa" return "public"
def analyze(pkts): devices = defaultdict(lambda: { "name": None, "uuids": set(), "mfg_seen": set(), "count": 0, "first": None, "last": None, "tracker_suspect": False}) for pkt in pkts: # HCI LE Advertising Report event: 0x040E .. 0x3E if len(pkt) < 14 or pkt[0] != 0x04 or pkt[1] != 0x3E: continue if pkt[3] != 0x02 or pkt[4] not in (0x00, 0x01, 0x02, 0x03): continue # not LE adv report subevent num = pkt[5] off = 6 for _ in range(num): try: etype = pkt[off] mac = bytes(reversed(pkt[off + 1:off + 7])) # rssi at pkt[off+13]; data len pkt[off+12] dlen = pkt[off + 12] payload = pkt[off + 13:off + 13 + dlen] except IndexError: break kind = mac_kind(mac) adv = parse_adv_payload(payload) key = (mac.hex(":"), kind) d = devices[key] d["count"] += 1 d["first"] = d["first"] or time.time() d["last"] = time.time() if adv["name"]: d["name"] = adv["name"] d["uuids"].update(adv["uuids"]) if adv["mfg"]: d["mfg_seen"].add(adv["mfg"][:8].hex()) if adv["mfg"][:2] == APPLE_MFG and \ len(adv["mfg"]) > 2 and \ adv["mfg"][2] in FINDMY_TYPES: d["tracker_suspect"] = True off += 13 + dlen return devices
def main(): ap = argparse.ArgumentParser() ap.add_argument("input", nargs="?", help="hcidump -R text file; stdin if -") ap.add_argument("--json") args = ap.parse_args() if args.input and args.input != "-": lines = open(args.input, encoding="utf-8", errors="replace").readlines() else: lines = sys.stdin.readlines() pkts = parse_hcidump(lines) devices = analyze(pkts) print(f"== BLE inventory: {len(pkts)} HCI packets, " f"{len(devices)} devices ==") trackers = [] for (mac, kind), d in sorted(devices.items(), key=lambda kv: -kv[1][ "count"]): tag = " [TRACKER?]" if d["tracker_suspect"] else "" print(f" {mac} [{kind:>6}] n={d['count']:<4} " f"{d['name'] or '-':<20}{tag}") if d["tracker_suspect"]: trackers.append(mac) if trackers: print(f"\n[!] {len(trackers)} tracker-payload " f"devices observed — apply your " f"anti-stalking workflow") if args.json: json.dump({f"{m}|{k}": {"name": d["name"], "count": d["count"], "uuids": sorted(d["uuids"]), "mfg": sorted(d["mfg_seen"]), "tracker_suspect": d["tracker_suspect"]} for (m, k), d in devices.items()}, open(args.json, "w"), indent=2) print(f"[+] {args.json}")
if __name__ == "__main__": main()Code Walkthrough
Section titled “Code Walkthrough”parse_hcidump()(lines 20-32) handles hcidump’s textual format: rows starting with>or<begin a packet, continuation lines append hex, and non-hex characters are stripped — the streaming text format every Linux BT host produces without extra tooling, which is why this parser (not a scapy BT dependency) is the interface.- The HCI event filter (lines 75-80) selects LE advertising reports precisely: event 0x0E-class framing (0x04 0x3E) with subevent 0x02 (advertising report) and its legacy variants — everything else (ACL data, inquiries) is skipped rather than mis-parsed.
mac_kind()(lines 63-68) implements the privacy classification from the two most significant bits of the MAC (hcidump presents LSB-first, so thereversedslice at line 70 matters): 0b11 = static, 0b01 = RPA (resolvable private, the anti-tracking rotation), 0b00 = public. The kind column is the report’s privacy literacy.- The tracker heuristic (lines 91-95) flags Apple manufacturer payloads (0x004C little-endian) whose third byte matches the offline-finding types — the FindMy advertising shape [verify payload spec per current iOS] — turning the anti-stalking concern into a per-device boolean.
parse_adv_payload()(lines 35-56) walks the BLE adv structures (len/type/data chains): names (0x08/0x09), 16-bit service UUIDs (0x02), and the manufacturer blob (0xFF) that feeds the tracker check — the three IEs that carry 95% of recon value.
How It Reaches The Target
Section titled “How It Reaches The Target”The BLE advertisement reaches the target space continuously and invisibly — every desk, pocket, and wearable broadcasts on a schedule the device chose, and the analyzer reaches it with a $10 dongle and passive listening. The inventory reaches the corporate security program as the map it has never had: which HID devices (keyboards/mice — the injection-impact class), which medical/wearable classes, which trackers, which RPA-privacy devices versus which public-MAC relics — the catalog from which BT policy (permitted device classes, pairing rules, HID restrictions) is finally writable. The tracker detection reaches the personal-safety layer: the same payload heuristics that an attacker uses to find devices tell an employee (or the SOC, via an opt-in service) that a FindMy-class tag has been traveling with them — the anti-stalking feature Apple and Google built detection specs for [verify current spec] and that corporate endpoints can run. The GATT and pairing analysis reaches the vendor conversation as the per-device assessment (which characteristics are exposed unauthenticated, which pairing mode the device actually negotiates) that procurement and IoT onboarding should be demanding. On the attack side, the HID surface reaches the corporate risk register with unusual force: a spoofed keyboard is a workstation compromise (T1056-adjacent execution), and the defense is peripheral-side pairing discipline (bonding, PIN, disable re-pair) plus radio hygiene (unpair dormant dongles). And the whole inventory reaches the quarterly review as the BLE baseline diff — new device classes, new trackers, new RPA patterns — the personal-area equivalent of the airspace baseline.
Exploitation Chain
Section titled “Exploitation Chain”- Scan — passive hcidump capture from lab desk: 23 BLE devices, 2 HID-class, 1 tracker payload
- Classify — blescan.py: RPA-privacy phones, public-MAC peripherals, FindMy-shape tag flagged
- Select — corporate BLE keyboard with re-pair-open behavior (GATT/SDP review)
- Spoof — lab peripheral emulation pairs as the keyboard (authorized bench)
- Inject — keystroke channel opens: Win+R sequence typed into the bench workstation
- Observe — no endpoint alert: HID input is trusted by design; the gap is peripheral trust
- Contain — unpair dormant dongles, enforce bonding+numeric-compare on new HID, policy update
- Baseline — BLE inventory diff added to quarterly review: HID class + tracker flags tracked
Building Your Own Tool
Section titled “Building Your Own Tool”trackerhunt.py — the anti-stalking tracker detector: consumes a sequence of blescan JSON inventories (windows across time/movement) and applies the FindMy/SmartTag heuristics — persistent tracker payloads, co-mobility patterns (same tracker present in every window regardless of location), and absence at rest — producing the moving-tracker alert with evidence. The defensive counterpart of the WI5 scan.
Design decisions
Section titled “Design decisions”- Co-mobility over presence. A tracker at your desk might be your keyboard’s tag; a tracker present at office, gym, and home windows is stalking-shaped — the tool requires persistence across distinct location windows, not mere repeated presence.
- Payload-first identity. RPA MACs rotate, so tracker identity is the payload (FindMy public key prefix [verify spec]), not the MAC — the tool tracks payload families across MAC churn.
- Conservative alerts. Anti-stalking alerts that fire on co-workers’ earbuds destroy trust; the tool requires the tracker-family payload plus cross-window co-mobility before alerting, with an explicit “verify physically” instruction rather than automated accusation.
- Windows as data, not sessions. The input is a directory of inventory JSONs with timestamps — the user (or phone agent) captures windows; the tool correlates, keeping capture and analysis separated.
Full source
Section titled “Full source”#!/usr/bin/env python3"""trackerhunt.py — moving-tracker detector over BLE inventories.Usage: python trackerhunt.py --dir inventories/ [--min-windows 3]Input: blescan.py --json outputs, filenames timestamped.stdlib only."""import argparse, glob, json, os, sysfrom collections import defaultdict
APPLE_MFG_HEX = "4c00"FINDMY_TYPE_BYTES = {"10", "12"} # [verify per spec]
def load_windows(d): windows = [] for p in sorted(glob.glob(os.path.join(d, "*.json"))): try: data = json.load(open(p, encoding="utf-8")) except (OSError, json.JSONDecodeError): continue ts = os.path.basename(p).replace(".json", "") windows.append((ts, data)) return windows
def tracker_payloads(dev_entry): """Return payload identities that look tracker-like.""" identities = set() for mfg in dev_entry.get("mfg", []): if mfg[:4] == APPLE_MFG_HEX and \ mfg[4:6] in FINDMY_TYPE_BYTES and len(mfg) >= 16: # payload family = type + key prefix (RPA-proof) identities.add((mfg[4:6], mfg[6:20])) return identities
def analyze(windows, min_windows): sightings = defaultdict(lambda: defaultdict(int)) windows_seen = defaultdict(set) for ts, inv in windows: for dev, entry in inv.items(): kind, _ = dev.split("|", 1) for pid in tracker_payloads(entry): s = sightings[pid] s["payload"] = pid s["count"] = s.get("count", 0) + 1 s.setdefault("windows", set()).add(ts) alerts = [] for pid, s in sightings.items(): w = s.get("windows", set()) if len(w) >= min_windows: alerts.append((pid, sorted(w))) return alerts
def main(): ap = argparse.ArgumentParser() ap.add_argument("--dir", default="inventories") ap.add_argument("--min-windows", type=int, default=3) ap.add_argument("--json") args = ap.parse_args() windows = load_windows(args.dir) if not windows: sys.exit("no inventory JSONs found") print(f"[*] {len(windows)} inventory windows loaded") alerts = analyze(windows, args.min_windows) if not alerts: print("[+] no co-mobility trackers detected " f"(>= {args.min_windows} windows)") return print(f"[!] {len(alerts)} tracker candidates " f"persistent across >= {args.min_windows} " f"windows:") for pid, w in sorted(alerts, key=lambda a: -len(a[1])): print(f" payload {pid[0]}/{pid[1][:8]}… " f"windows: {w[:6]}") print("\nverify PHYSICALLY before any accusation — " "co-mobility includes your own devices") if args.json: json.dump({"alerts": [{"payload": list(p), "windows": w} for p, w in alerts]}, open(args.json, "w"), indent=2)
if __name__ == "__main__": main()Walkthrough
Section titled “Walkthrough”load_windows()(lines 15-23) treats each inventory JSON as a window keyed by its filename timestamp — the user’s capture discipline (different times, different places) is the input contract, and the tool correlates rather than collects.tracker_payloads()(lines 27-34) extracts the RPA-proof identity: the manufacturer payload’s type byte + key prefix survives the MAC rotation, so tracking happens by payload family. The comment marks the spec-dependency ([verify per spec]) where Apple/Google documents rule.- The co-mobility rule (lines 48-51) is the alert’s spine: a payload seen in ≥ N distinct windows is stalking-shaped; presence in one window is just a device. The N default (3) is conservative by design — the tool’s next line says why: co-mobility includes your own devices, and the physical-verify instruction (line 60) is part of the output, not an afterthought.
Compilation and test procedure
Section titled “Compilation and test procedure”capture three windows at three locations (desk, cafe, home)
Section titled “capture three windows at three locations (desk, cafe, home)”$ hcidump -R > raw1.txt; python blescan.py raw1.txt —json inv_20261014_0900_desk.json $ hcidump -R > raw2.txt; python blescan.py raw2.txt —json inv_20261014_1200_cafe.json $ hcidump -R > raw3.txt; python blescan.py raw3.txt —json inv_20261014_1900_home.json
== BLE inventory: 412 HCI packets, 19 devices == D0:39:72:xx:xx:11 [ rpa] n=41 - [TRACKER?] …
correlate across windows
Section titled “correlate across windows”$ python trackerhunt.py —dir inventories/ —min-windows 3 [*] 3 inventory windows loaded [!] 1 tracker candidates persistent across >= 3 windows: payload 12/0f2ab1… windows: [‘20261014_0900_desk’, …]
physical verify: find the tag (or conclude it’s your own)
Section titled “physical verify: find the tag (or conclude it’s your own)”then file the finding per your anti-stalking runbook
Section titled “then file the finding per your anti-stalking runbook”Detection considerations
Section titled “Detection considerations”BLE detection lives at two layers: radio-side (BLE sniffers/SDR watching advertisement patterns — the tools above) and endpoint-side (phones and laptops already see the advertisements natively — Apple/Google’s own tracker-detection specs [verify current status] run on the phone, and enterprise MDM can surface those alerts). The HID injection class is detected behaviorally on the endpoint: keystroke sequences without corresponding physical presence (impossible-travel for input devices), new HID pairing events (Windows Security/Sysmon-adjacent BT pairing logs [verify channel]), and dongle re-pairing events — the pairing log is the telemetry most estates never read. Your own tooling hygiene: passive capture only; any transmission (spoofing, pairing) is bench-gated. WIDS products mostly ignore BLE (Wi-Fi-focused); dedicated BLE monitoring exists [verify market] but the DIY inventory diff is deployable at zero cost. The standing metrics: BLE device-class inventory (HID count, tracker count, RPA ratio) per quarterly sweep, and the HID pairing-event log review — two reviews that turn the personal-area perimeter from invisible to governed.
Improvements to add
Section titled “Improvements to add”- GATT enumerator: post-connection service/characteristic walk with per-device profile report (authorized bench only).
- Payload-spec updates: maintain FindMy/SmartTag payload-format versions as data files [verify per ecosystem spec].
- HID pairing event ingestion: parse Windows BT pairing event logs into the inventory (endpoint-side view).
- RSSI-based co-location: weight co-mobility by RSSI proximity to reduce far-away-tag false positives.
- Multi-user correlation: opt-in fleet mode correlating co-mobility across consenting devices (office safety feature).
Detection — Defender View
Section titled “Detection — Defender View”| Signal | Source | ID | Notes |
|---|---|---|---|
| Tracker payload co-mobility | blescan+trackerhunt | payload family | Anti-stalking workflow |
| New HID pairing events | OS BT logs [verify channel] | pairing audit | The injection door |
| Dongle re-pair events | Endpoint logs | peripheral policy | Dormant-dongle risk |
| Unknown GATT services | Bench assessment | per-device RE | Vendor conversations |
| Legacy pairing mode in use | Pairing capture | stack-era audit | MITM-able devices |
| BLE device-class inventory | Quarterly sweep | baseline diff | Policy substrate |
| Discoverable-classic devices | BT scan | exposure finding | BlueBorne-era surface |
| Beacon spoofing (proximity apps) | App logs / infra | deployment finding | Location-app abuse |
| Personal devices on corp desks | Sweep + policy | hygiene finding | Perimeter bleed |
| Wazuh ingestion of endpoint BT logs | HIDS/SIEM | [verify rule IDs per deployment] | Pairing telemetry join |
Evasion Techniques
Section titled “Evasion Techniques”BLE evasion is privacy-feature abuse and payload crafting. RPA rotation defeats MAC-based tracking by design — countered by payload-family identity (the tracker tools above track the payload, not the MAC), which is why tracker payloads embed stable key material. Payload randomization: trackers randomize payload timing and adjacency to defeat naive “always advertising” detection — countered by co-mobility correlation across windows (persistence in presence, not in cadence). GATT permission gating: services that demand pairing before revealing characteristics hide their surface from unauthenticated enumeration — countered by pairing-mode analysis (Just Works pairing is a permission gate that opens to anyone) and by bonding-spoofing where pairing state is weakly enforced [verify per stack]. HID bond hijack: waiting for the real keyboard to disconnect, then pairing with the dongle’s memory of a “remembered” device — countered by disabling re-pairing on dormant HID links and by endpoint alerts on pairing events. Classic-stack invisibility: non-discoverable classic devices skip inquiry responses — countered by connection-window listening (passive sniffing of existing pico-nets, where legal) and by the fact that discoverability ≠ connectability confusion still leaves most devices connectable. Firmware heterogeneity: embedded BT stacks patch slowly, so one vulnerable earbuds model persists across a fleet for years — countered by the inventory diff (model classes with known CVEs surface per sweep) and procurement gates. The meta-pattern mirrors the airspace: the personal-area radio is unmanaged airspace too, and the side that baselines it — device classes, pairing modes, payload families — converts noise into governance.
⚠️ What caught me: my BLE tracker-hunt “found a stalker” on the first office run — a FindMy-payload device co-located across all three windows, exactly the stalking pattern. Before escalating, I walked the floor with a phone and found it: a colleague’s second laptop bag, with his own AirTag inside, parked three desks from mine — my co-mobility math was flawless and my interpretation was wrong, because his bag commutes with the office population too. The tool’s verify-physically instruction existed because of this exact class of false positive, but I’d nearly skipped it in the excitement of a “hit”. Since then, the runbook requires two physical verifications before any person is mentioned in a tracker finding, and the report template has a “was it just someone’s bag” field — the metric that keeps the safety tool from becoming a harassment tool.
Lab Practice
Section titled “Lab Practice”- Inventory your desk: run the hcidump capture for 20 minutes and
blescan.py; classify every device by kind (HID/audio/tracker/RPA) — your personal-area perimeter, mapped. - Tracker drill (consented): have a colleague carry a FindMy-class tag through your capture windows; run
trackerhunt.pyand confirm the co-mobility alert, then physically verify — the full anti-stalking workflow with a benign ground truth. - HID pairing audit: pair a lab BLE keyboard, capture the pairing exchange, and identify the pairing mode (Just Works vs numeric compare) from the frames — the MITM-ability verdict, read from the wire.
- GATT walk: on the lab peripheral, enumerate services/characteristics (gatttool/bettercap, authorized bench) and note which characteristics are writable without authentication — the vendor conversation starter.
- Baseline diff: repeat the desk inventory a week later and diff; count new/vanished devices and any new tracker flags — the personal-area quarterly review, practiced at desk scale.
Interview Questions
Section titled “Interview Questions”- Technical: Compare BLE pairing modes on MITM resistance — which models are exploitable, what user interaction each requires, and what the frames reveal about the mode in use?
- Technical: How do Resolvable Private Addresses work, and why must tracker detection key on payload families rather than MACs?
- Scenario: Your tracker tool alerts on a payload present in 4 windows across 3 locations. What is the verification workflow before you say the word “stalker” to anyone?
- Conceptual: Why is HID the highest-corporate-impact BLE attack family, and what pairing discipline closes it?
- Conceptual: How does the BlueBorne era inform your assessment of embedded BT stacks today?
- Deep-dive: Design the corporate BLE governance program: device-class inventory, pairing policy, tracker safety integration, and the quarterly baseline review.
- Practical: Procurement wants to approve a BLE door lock. What does your GATT/pairing assessment require before the yes/no, and what evidence do you produce?
Related Modules
Section titled “Related Modules”WI1 (Wireless Fundamentals & Recon (802.11)) · WI6 (RF & SDR Fundamentals) · WI9 (RFID/NFC) · F1 (Networking Fundamentals) · BT12 (Wireless IDS)