OUI-SPY · Volume 4

OUI-SPY Volume 4 — Detection Methodology I: Wi-Fi


4.1 About this Volume

This is the first of two volumes on how the OUI-SPY ecosystem actually decides that a radio in earshot belongs to a surveillance device. It covers the Wi-Fi side — the half of the problem that runs in 802.11 promiscuous mode. Volume 5 covers the Bluetooth Low Energy side, and Volume 6 takes the flagship flock-you firmware apart define-by-define, including the companion dashboard.

The reason these three volumes are the heart of the dive is that detection methodology is the one axis on which OUI-SPY genuinely differs from every other “surveillance scanner” on the bench. A tool such as SquachWatch (covered in its own Hack Tools dive) matches a broad catalogue of named signatures and surfaces them on a colour touchscreen. OUI-SPY does something narrower and, in the Wi-Fi case, more forensic: it grades every hit on a five-tier confidence scale, with the top tier reserved for a frame that passes an information-element fingerprint, not merely a MAC-prefix match. The firmware is headless — a passive piezo buzzer on one GPIO and nothing else is required — so almost everything of interest is in the logic, not the hardware. That is why these volumes lean on tables and ASCII rather than photographs.

The material in this volume is drawn from the flock-you README (the methodology gold source) as fetched 2026-10-16. Where the README summarises rather than lists a value — most importantly the exact byte fields of the tier-4 IE fingerprint — the gap is flagged rather than guessed.

Scope note. Everything in this volume is passive receive. The Wi-Fi detection path never transmits: it puts the radio in monitor mode and listens. The asterisk on the word “passive” belongs to the BLE active-scan phase (Volume 5) and to the offensive Red-edition tools (Volume 9), not here.


4.2 The OUI as a detection key

The brand name is a pun with a real technical anchor. OUI is the Organizationally Unique Identifier — the top 24 bits of a 48-bit MAC address, assigned by the IEEE Registration Authority to the organisation that makes the radio. Every Ethernet or Wi-Fi interface a vendor ships carries that vendor’s OUI in the high half of its burned-in address:

 48-bit MAC address
 ┌───────────────────────┬───────────────────────┐
 │ OUI (24 bits) │ NIC-specific (24 b) │
 │ b4: 1e: 52 │ xx: xx: xx │
 └───────────────────────┴───────────────────────┘
 ^ ^
 │ └── bit 0 of first octet = I/G (individual/group)
 └────────────── bit 1 of first octet = U/L (universal/local)

Two bits of the very first octet matter to this methodology:

  • I/G bit (bit 0, least-significant of the first octet): 0 = unicast, 1 = group/multicast. Detection targets are individual devices, so this is 0 for the hits that matter.
  • U/L bit (bit 1): 0 = a globally unique, IEEE-assigned address; 1 = a locally-administered address (LAA) that software chose. Modern phones randomise their MACs by setting this bit, which is why a naïve scanner is tempted to skip LAA frames as noise.

That temptation is a trap here, and the README says so explicitly: one of the 34 target prefixes — 82:6b:f2 — has the locally-administered bit set, and the firmware must not install an “LAA skip filter.” A camera that advertises from a locally-administered-looking prefix would otherwise be filtered out as a randomising phone.

The detection premise, then: surveillance hardware is built from a small, slowly-changing set of radio modules and vendor assignments. Enumerate the OUIs those modules use, watch the air for any frame whose transmitter sits in that set, and you have a cheap, deterministic first-pass filter that a $7.50 microcontroller can run at line rate.


4.3 The 34-prefix OUI union

flock-you compiles a union of 34 MAC prefixes into a byte table during setup(), so the matcher runs out of IRAM and can be evaluated inside the Wi-Fi receive callback without touching flash. The union has two very different halves by provenance.

Community set — 32 prefixes. Thirty-one come from @NitekryDPaul’s nite-oui-collection (the 2026-07-16 revision), the crowd-sourced list of prefixes observed on Flock Safety automated-licence-plate-reader (ALPR) cameras. The thirty-second, 82:6b:f2, comes from the DeFlockJoplin contribution and is the locally-administered one discussed above.

Table 1 — 3. The 34-prefix OUI union

#Prefix#Prefix#Prefix#Prefix
170:c9:4e99c:2f:9d17d0:39:572558:00:e3
23c:91:8010c0:35:3218e8:d0:fc2690:35:ea
3d8:f3:bc1194:08:5319e0:4f:43275c:93:a2
480:30:4912e4:aa:ea20b8:1e:a42864:6e:69
5b8:35:3213f4:6a:dd2170:08:942948:27:ea
614:5a:fc14e0:0a:f62258:8e:8130a4:cf:12
774:4c:a11524:b2:b923ec:1b:bd3114:b5:cd
808:3a:881600:f4:8d243c:71:bf3282:6b:f2

Firmware-extracted set — 2 prefixes. These two are the standout provenance of the whole project, and they get their own section below.

Table 2 — 3. The 34-prefix OUI union

#PrefixOwner / meaning
33b4:1e:52Flock Safety’s own IEEE MA-L block
3400:03:7fQualcomm Atheros QCA9377 default radio MACs

The two sets do not overlap. The union is a flat lookup: a prefix is either in the table or it is not, and membership alone never decides the tier — that depends on where in the frame the match landed and whether the probe-request fingerprint also fired (§8).


4.4 Firmware-dump provenance: the two extracted prefixes

The community set is empirical — prefixes people saw on cameras in the wild. The two firmware-extracted prefixes are different in kind: they come from a static analysis of a Flock Safety ALPR firmware image (README codename hpnotiq, dated 2026-09-16), and they explain why the cameras radiate what they radiate.

 Flock ALPR firmware image ("hpnotiq", 2026-09-16)
 │
 ▼ static extraction
 ┌──────────────────────────────┐
 │ b4:1e:52 ← Flock Safety │ the vendor's own MA-L assignment:
 │ MA-L (IEEE) │ the "front-door" identity of the device
 ├──────────────────────────────┤
 │ 00:03:7f ← Qualcomm Atheros │ the Wi-Fi SoC inside the camera:
 │ QCA9377 defaults │ the "back-door" identity of the chip
 └──────────────────────────────┘
  • b4:1e:52 is the block IEEE assigned to Flock Safety as a hardware manufacturer. A frame transmitted from this prefix is, by construction, a Flock-branded interface announcing itself with its registered identity.
  • 00:03:7f is the default MAC range of the Qualcomm Atheros QCA9377 — the 802.11 Wi-Fi/Bluetooth combo SoC inside the cameras. Devices that never had a vendor MAC written over the chip default, or that fall back to it, broadcast from this prefix. Detecting the silicon is more durable than detecting the brand: Flock can change its MA-L assignment far more easily than it can change the Wi-Fi chip it designed the board around.

Why this matters for the dive’s thesis. The firmware-dump prefixes are the single clearest reason OUI-SPY is categorised as a forensic detector rather than a signature scraper. The community list answers “what have people seen”; the firmware list answers “what is the device physically made of.” Pairing the two is what lets the tool catch a camera whose observed prefix has rotated but whose Qualcomm SoC default is unchanged.


4.5 Promiscuous mode and the capture path

On Wi-Fi, the ESP32-S3 radio is put into promiscuous (monitor) mode: it hands every 802.11 frame it demodulates to a receive callback, regardless of destination. That callback is the hot path, and its design is the difference between a scanner that keeps up with the air and one that drops frames.

 RF in ──▶ ESP32-S3 Wi-Fi PHY ──▶ promiscuous RX callback (runs in Wi-Fi task)
 │
 │ 1. cheap filters: frame type, RSSI_MIN gate
 │ 2. prefix match against the 34-OUI IRAM table
 │ 3. wildcard-probe / IE fingerprint checks
 │ 4. push compact record ──┐
 ▼ │
 alertQueue[32] ◀────────────────────┘ (lock-free ring)
 │
 ▼
 loop() ──▶ drain queue ──▶ update detection table ──▶ cooldown ──▶ JSON + tone

The receive callback does only fast matching. It never allocates, never logs, never touches the buzzer. When a frame qualifies, it writes a compact record into a 32-slot lock-free ring buffer (alertQueue[32]) and returns immediately. The main loop() drains that queue at its own pace: it updates the live detection table, applies the per-MAC cooldown, emits the JSON detection line over USB-CDC, and drives the tone. This split keeps the time-critical PHY callback bounded and means a burst of hits — a camera spraying probes every ~125 ms — cannot stall the radio.

A frame is discarded before it ever reaches the prefix table if its RSSI is below RSSI_MIN (default −95 dBm). That floor is deliberately generous: it exists to drop frames so weak they can’t be reliably fingerprinted, not to range-gate the detector.


4.6 Channel hopping and dwell

2.4 GHz Wi-Fi has only three non-overlapping channels in the common plan — 1, 6, and 11 — and a monitor-mode radio can sit on exactly one at a time. The scanner therefore hops, and the dwell time is tuned against the cameras’ own probe cadence.

Table 3 — 6. Channel hopping and dwell

ModeChannel sequenceNotes
CHANNEL_MODE_CUSTOM (default)11 → 6 → 1 (descending)the three non-overlapping channels
FULL_HOP11 → 1 (descending, all)every channel, higher miss risk per channel
SINGLEone fixed channelpark on a known camera channel

Dwell is CHANNEL_DWELL_MS = 250 ms per channel. The cameras emit wildcard probe requests at roughly 125 ms intervals, so a 250 ms dwell is two probe-intervals — long enough that a transmitting camera on the current channel will, with high probability, emit at least one probe inside the window.

 time ─────────────────────────────────────────────────────────▶
 ch11 [■■■■■] ch6 [■■■■■] ch1 [■■■■■] ch11...
 250 ms 250 ms 250 ms
 camera probes: · · · · · · · · · (~every 125 ms)
 └── two probe-intervals land inside each 250 ms dwell ──┘

There is a documented inconsistency: older README prose describes ascending channel order, while the code hops descending (11 → 6 → 1). The behaviour of the shipped firmware is the descending order; the ascending note is stale text.


4.7 The wildcard probe-request IE fingerprint

This is the highest-confidence Wi-Fi signature and the reason a hit can reach tier 4. A plain OUI match tells you a frame came from a targeted prefix; the fingerprint tells you the frame is shaped like a Flock camera’s probe. All four conditions must hold:

 ┌─ TIER-4 GATE ───────────────────────────────────────────────┐
 │ │
 │ (1) 802.11 management frame ── type = 0, subtype = 4 │
 │ (Probe Request) │
 │ AND │
 │ (2) SSID IE (tag 0) present, length = 0 (wildcard probe) │
 │ AND │
 │ (3) addr2 (transmitter) OUI ∈ 34-prefix union │
 │ AND │
 │ (4) remaining IE fields match the DeFlockJoplin/ │
 │ LiteON signature │
 │ │
 │ all four true ─────────────▶ wifi_wildcard_probe_ie_sig │
 │ (1)(2)(3) true, (4) false ─▶ wifi_wildcard_probe (tier 3) │
 └──────────────────────────────────────────────────────────────┘

Each condition earns its place:

  1. Management type 0 / subtype 4 = Probe Request. A client looking for networks. Cameras that act as Wi-Fi stations probe for their backhaul; this is the frame they leak most often and most predictably.
  2. Wildcard SSID. The SSID information element (tag number 0) is present but has length zero — a “broadcast” probe asking every AP to respond, rather than naming one network. This is characteristic behaviour, not proof on its own.
  3. Transmitter in the OUI union. addr2 is the actual source radio. Requiring the OUI match on the transmitter address (not a receiver or BSSID field) is what distinguishes a tier-4/tier-3 wildcard-probe hit from the weaker addr1/addr3 tiers (§8).
  4. The IE fingerprint. Beyond the wildcard SSID, a probe request carries a sequence of further information elements — supported rates, extended capabilities, vendor-specific tags — whose exact contents and ordering form a per-firmware signature. flock-you matches these against a reference signature contributed as “DeFlockJoplin / LiteON.” The technique follows the Pintor & Atzori (2022) line of research on probe-request IE fingerprinting.

Gap, stated honestly. The flock-you README does not publish the exact IE field values that constitute condition (4); it names the signature and cites the research but keeps the byte table in the source. The precise tier-4 fingerprint bytes are therefore unverified from the README alone.If conditions (1)–(3) hold but the IE fingerprint (4) does not match, the hit is still a wildcard probe from a targeted OUI — it drops one tier to tier 3 (wifi_wildcard_probe) rather than being discarded. The IE fingerprint raises confidence; it is not a gate on detection itself.


4.8 The five-tier confidence model

Every Wi-Fi (and BLE) detection is graded. The grade is the product’s signature idea, so it is worth stating the full model as a table even though two of its rows are BLE methods covered in Volume 5.

Table 4 — 8. The five-tier confidence model

Tierdetection_methodGateBuzzer
4wifi_wildcard_probe_ie_sigOUI + wildcard SSID + IE fingerprint matchtwo-note chirp 2000 → 2800 Hz
3wifi_wildcard_probeOUI + wildcard SSID, IE did not matchtwo-note chirp 1400 → 1800 Hz
2wifi_oui_addr2, ble_name, ble_mfg, ble_gatt_svctransmitter-OUI match, or any BLE firmware-derived hitsingle blip 1200 Hz
1wifi_oui_addr1, wifi_oui_addr3OUI seen in addr1 (receiver) or addr3 (BSSID)single blip 800 Hz
0wifi_ssidSSID keyword match (OFF by default)single blip 600 Hz

Three rules govern how a tier sticks to a device:

  • Highest tier wins and never drops. Once a given MAC has been seen at, say, tier 4, its label stays tier 4 even if later frames from it only qualify at tier 2. Confidence ratchets up, never down.
  • A higher tier can pre-empt the cooldown. The per-MAC ALERT_COOLDOWN_MS (default 5000 ms) suppresses repeat alerts — but if a device that was blipping at tier 2 suddenly produces a tier-4 frame, the stronger hit is allowed through immediately rather than waiting out the cooldown.
  • The audio encodes the tier. The buzzer tone is the readout on a headless device: a rising two-note chirp means “high confidence, probably a real camera”; a single low blip means “a weak positional match, treat with suspicion.” An operator learns to read the pitch without a screen.

The tier is monotonic in confidence from top to bottom. Tier 4 requires the most to be true (the full IE fingerprint); tier 0 is a bare SSID keyword hit and is disabled by default precisely because it is the easiest to spoof or trip accidentally.

 confidence
 ▲
 T4 │ ████████████ IE fingerprint — "this is Flock-shaped"
 T3 │ █████████ wildcard probe from a target OUI
 T2 │ ██████ transmitter-OUI / BLE firmware signature
 T1 │ ███ OUI only in addr1 / addr3 (can misfire)
 T0 │ █ SSID keyword (off by default)
 └────────────────────────────────────────────▶ what must be true

4.9 Frame-to-buzzer: the full decision flow

Putting §5–§8 together, this is the life of a single 802.11 frame from antenna to audio:

 ┌──────────────────────────┐
 802.11 frame ──────▶│ RSSI ≥ RSSI_MIN (−95)? │── no ─▶ drop
 └────────────┬─────────────┘
 │ yes
 ▼
 ┌──────────────────────────┐
 │ type/subtype of frame? │
 └───┬───────────────┬───────┘
 mgmt probe req │ │ data / other mgmt
 (type0 sub4) │ │
 ▼ ▼
 ┌──────────────────────┐ ┌──────────────────────────┐
 │ wildcard SSID (len0) │ │ OUI in addr2? ─▶ TIER 2 │
 │ AND addr2 ∈ OUI? │ │ OUI in addr1/addr3? ─▶ T1 │
 └──────┬────────────────┘ │ SSID keyword (if on)? ─▶ T0│
 │ yes └────────────┬─────────────┘
 ▼ │
 ┌───────────────────┐ │
 │ IE fingerprint OK? │── no ─▶ TIER 3 │
 └────────┬──────────┘ │
 │ yes │
 ▼ │
 TIER 4 │
 │ │
 └───────────────┬─────────────────────┘
 ▼
 ┌──────────────────────────────────────┐
 │ highest-tier-wins table update │
 │ per-MAC ALERT_COOLDOWN_MS (5000 ms) │
 │ (higher tier pre-empts cooldown) │
 └───────────────┬────────────────────────┘
 ▼
 tone for tier + JSON line over USB-CDC + LED

The important structural point: tiering happens before the cooldown, and the cooldown is per-MAC, so a crowded street full of targeted devices still produces one readable alert per device per five seconds rather than a continuous scream — while a device that upgrades its tier still cuts through immediately.


4.10 Wi-Fi configuration knobs

The Wi-Fi behaviour is set by a block of #defines at the top of main.cpp. The full list lives in Volume 6; the ones that shape the Wi-Fi methodology specifically are:

Table 5 — lives in Volume 6; the ones that shape the Wi-Fi methodology specifically are

DefineDefaultEffect on Wi-Fi detection
CHANNEL_MODECHANNEL_MODE_CUSTOM11 → 6 → 1 hop pattern
CHANNEL_DWELL_MS250dwell per channel; 2× camera probe interval
RSSI_MIN−95pre-match reject floor (dBm)
ALERT_COOLDOWN_MS5000per-MAC repeat-alert suppression
CHECK_ADDR11enable the tier-1 receiver-address check
CHECK_ADDR31enable the tier-1 BSSID check
ENABLE_SSID_MATCH0tier-0 SSID keyword match — off by default
PROCESS_MGMT_FRAMES1evaluate management frames (probes live here)
PROCESS_DATA_FRAMES1evaluate data frames (addr2/addr1/addr3 OUI)
MAX_DETECTIONS200live-table capacity

Two patterns to keep straight. ENABLE_SSID_MATCH defaults to 0 because the raw SSID keyword match (Flock, Flock-XXXXXX) is the weakest and most spoofable signal — turning it on gives you tier-0 hits you probably don’t want. CHECK_ADDR1/CHECK_ADDR3 default on but feed only tier 1, the tier the README itself admits “do misfire” — see §11.

The Flock SSID patterns themselves, for reference: cameras bring up a SoftAP named Flock-XXXXXX protected with WPA2 and the literal passphrase security, plus a bare Flock SSID. Even with SSID matching disabled, these are a useful human sanity-check when you dump the raw capture — but the firmware does not alert on them unless you flip ENABLE_SSID_MATCH.


4.11 Limitations and honest caveats

A methodology volume that only lists strengths is marketing. The Wi-Fi path has real edges, and the flock-you README is candid about them.

  • Tier-1 addr1/addr3 matches “do misfire.” addr1 is the receiver and addr3 is the BSSID — neither is the transmitting radio. An OUI appearing in those fields means a targeted device is being addressed or is the access point of record, which is weaker evidence than the device transmitting with its own OUI in addr2. The README explicitly warns these tier-1 hits produce false positives; that is exactly why they are tier 1 and not tier 2, and why the buzzer gives them the lowest, least-alarming tone.
  • The IE fingerprint bytes are not in the README. As noted in §7, tier-4’s condition (4) is named and cited but not published in the README; the exact fingerprint is in source.
  • Stale channel-order prose. README text says ascending; code hops descending. The shipped behaviour is descending (11 → 6 → 1).
  • Prefix lists drift. The 32 community prefixes track observed hardware; vendors can and do rotate MA-L assignments, retire modules, and change defaults. The firmware-extracted pair (§4) is more durable precisely because it keys on the silicon, but the community list needs periodic refresh from the upstream nite-oui-collection.
  • “Passive” is clean here, with an asterisk elsewhere. The Wi-Fi path is pure monitor-mode listening. The asterisk on “passive” is earned by the BLE active-scan phase (Volume 5) and the Red-edition transmit tools (Volume 9), not by anything in this volume.

Operator takeaway. Trust the pitch. A rising two-note chirp (tier 3/4) from a wildcard probe is strong evidence of a nearby Flock-class camera. A single 800 Hz blip (tier 1) is a prompt to look closer, not a confirmation — it may be a device merely addressed by a targeted radio, or a genuine coincidence in addr1/addr3.


4.12 Where this connects

The BLE half of the detection story — NimBLE passive scanning, the Penguin/Flock-GATT/ Nordic-DFU/Raven signatures, duty cycling, and the host-side Classic-Bluetooth corroboration that the ESP32 cannot do on its own — is Volume 5. The tier-2 BLE methods named in the five-tier table (ble_name, ble_mfg, ble_gatt_svc) are defined there.

The config defines touched on in §10, the per-MAC session storage and CRC envelope, the USB-CDC JSON protocol, and the Flask + GPS companion dashboard that turns this stream into a map are all taken apart in Volume 6, “flock-you in depth.”

The hardware the whole methodology runs on — the Seeed XIAO ESP32-S3, its GPIO3 buzzer, the U.FL antenna option for direction-finding — is Volume 3, which also carries the canonical “Where this firmware runs” supported-hardware table. The threat model (what Flock ALPR cameras, Penguin battery packs, Raven acoustic sensors, and Axon gear actually are and why they radiate) is Volume 2.

Comments (0)

  1. Loading…

Comments are held for moderation — nothing appears until approved.