ESP32 Marauder · Volume 4
ESP32 Marauder Firmware Volume 4 — Wi-Fi Scanning Subsystems
Probe-request sniffer, beacon sniffer, PMKID capture, EAPOL 4-way handshake, AP+client mapping, channel strategy, pcap/csv output
Contents
1. About this volume
Vol 4 covers the Wi-Fi scanning half of Marauder’s Wi-Fi capability surface — passive captures only. Vol 5 covers the active attacks (deauth, beacon spam, Evil Portal). The two volumes form a pair; many real engagements use Vol 5 attacks to induce Vol 4 captures (the deauth-and-rejoin pattern in § 6.3 is the canonical example).
Five capture types live in this volume: probe-request sniffer (§ 3), beacon sniffer (§ 4), PMKID capture (§ 5), EAPOL 4-way handshake capture (§ 6), and AP+client mapping (§ 7). All five share the same underlying tap into the air — ESP32 promiscuous mode (§ 2) — and the same output paths (§ 9). The workflow recipes in § 10 chain the captures into end-to-end use cases.
The host-side analysis pipeline (pcap → hashcat / Wireshark / scapy) is Vol 9. This volume’s responsibility ends when bytes land on the SD card.
2. The promiscuous-mode capture path
2.1 How Marauder taps the air
ESP32’s Wi-Fi radio supports a promiscuous mode where the driver hands every received 802.11 frame to a user-registered callback, rather than only frames addressed to the device’s MAC. This is the foundation of every Marauder Wi-Fi scan.
The path:
- Firmware calls
esp_wifi_set_promiscuous(true). - Firmware installs a packet-filter mask via
esp_wifi_set_promiscuous_filter()— Marauder typically filters for management frames + EAPOL, drops everything else. - Firmware registers a callback via
esp_wifi_set_promiscuous_rx_cb(). - For every matching frame, the callback fires in IRQ context with a buffer pointer + length + RSSI + channel + timestamp.
- Callback parses the frame header, extracts the fields of interest, appends to a ring buffer.
- Main loop drains the ring buffer to SD and to the display.
Important constraints:
- The callback fires in interrupt context — must be fast (< 100 µs typical), must not call blocking APIs.
- Frame parsing in the callback is minimal — just enough to decide whether to keep the frame.
- The Wi-Fi stack still maintains the radio (frequency hopping, etc.) — promiscuous mode is “additionally feed me frames”, not “let me drive the radio.”
2.2 802.11 frame anatomy refresher
The frame types Marauder cares about, all in the IEEE 802.11-2020 § 9 frame format:
| Frame type | Subtype | What Marauder does with it |
|---|---|---|
| Management | Beacon (0x08) | AP-list build (§ 4) — RSN IE extracted for PMKID |
| Management | Probe Request (0x04) | Client probe-list (§ 3) |
| Management | Probe Response (0x05) | AP characterization; correlation with probe requests |
| Management | Deauth (0x0C) | Capture-side: see who’s deauthing whom. Attack-side: Vol 5 § 2 |
| Management | Disassoc (0x0A) | Same as deauth for capture purposes |
| Management | Auth (0x0B) | Tracks association attempts |
| Management | Association Req / Resp (0x00 / 0x01) | Same |
| Data | EAPOL (0x88) over LLC | The 4-way handshake frames (§ 6) — the only data-frame subtype Marauder cares about |
Each frame header carries:
- Type/subtype (2-byte Frame Control)
- Addresses (1-3 MACs depending on type — typically src, dst, BSSID)
- Sequence number (per-source incrementing counter)
- Per-frame metadata from the driver (RSSI, channel, timestamp)
Marauder extracts these in the IRQ callback, then writes them into the appropriate ring buffer based on type/subtype.
3. Probe-request sniffer
3.1 What gets captured
A probe request is what a Wi-Fi client emits when it’s looking for known networks. Each probe request is one frame containing the SSID the client is asking about (or a wildcard for “anyone, identify yourself”). Marauder captures the source MAC + SSID + RSSI + channel + timestamp for every probe request the promiscuous mode hands up.
Output (per probe request, csv format):
MAC,SSID,RSSI,channel,timestamp
A4:5E:60:11:22:33,HomeNetwork,-72,6,2026-05-13T14:32:17
A4:5E:60:11:22:33,,−72,6,2026-05-13T14:32:18 # wildcard probe (broadcast SSID)
A4:5E:60:11:22:33,CoffeeShop_WiFi,-72,6,2026-05-13T14:32:19
The same MAC issues many probe requests in sequence — once it’s enumerated its preferred-network list it’s effectively broadcasting that user’s recent network history.
3.2 MAC randomization and what survives it
Modern OSes (iOS 14+, Android 10+, Windows 10+) randomize the MAC in probe requests by default — each unique SSID gets a stable randomized MAC for the duration the client is in range, but a different randomized MAC for a different visit. This breaks the simplest “track this MAC across visits” attack.
What still works (forward-ref Vol 9 § 5 for the analysis pipeline):
- SSID set fingerprinting — if the same client probes the same unusual combination of SSIDs (HomeNetwork + CompanyVPN + Mom’sHouse + DentistOffice), that set is fingerprintable even when the MAC rotates. The set is the identity.
- Probe-burst timing — clients tend to probe in bursts with consistent inter-burst gaps. Helps de-anonymize.
- Manufacturer OUI — even randomized MACs typically retain a locally-administered OUI prefix. Doesn’t get you to identity but does narrow the device class.
For unrandomized probe requests (legacy devices, IoT, devices with randomization disabled), the MAC is the identity directly.
3.3 Workflow
- Marauder menu: WiFi → Sniffer → Probe Request
- Lock channel (static-channel mode, § 8) or let it hop (default).
- Run for 5-30 minutes in a target area.
- Output lands on SD as
probes_<timestamp>.csvorprobes_<timestamp>.pcap(selectable via settings). - Stop with Back / Select-Stop.
- Transfer SD to host (Vol 9 § 5 for the clustering analysis).
For a casual “who’s been here recently” walk, 10 minutes typically captures 30-100 unique MACs at a moderate-traffic site.
4. Beacon sniffer / SSID enumeration
4.1 Beacon anatomy
Every Wi-Fi AP broadcasts beacon frames every 102.4 ms (default 100 TUs = 102.4 ms; some APs use 200 ms or 1024 ms intervals to save power). Each beacon carries:
- BSSID (AP MAC)
- SSID (network name, or empty if hidden)
- Channel (in the DS Parameter Set IE)
- Encryption advertisement (open / WEP / WPA / WPA2 / WPA3 in the RSN IE)
- Supported rates
- Capability flags (Privacy bit, Short Preamble, etc.)
- Optional IEs (Vendor-specific, HT/VHT capabilities, Country code, etc.)
Marauder’s beacon sniffer captures every beacon and builds an AP list keyed by BSSID. Duplicate beacons from the same BSSID are coalesced; the most recent RSSI replaces the prior one, and the count of beacons seen accumulates.
4.2 Hidden-SSID detection
“Hidden” SSIDs broadcast beacons with an empty SSID field. Marauder shows these in the AP list as <HIDDEN> with the BSSID populated.
To reveal the SSID, watch for one of:
- Probe requests that name the hidden SSID — clients announce the SSID name when they’re looking for it.
- Probe responses that the hidden AP sends in response to a directed probe — these include the SSID.
- Association requests — when a client tries to associate, the SSID is included.
Marauder correlates BSSID-matched probe responses and association requests, automatically populating the SSID once revealed. The “hidden” status is purely cosmetic — no real privacy gain.
4.3 Encryption-type extraction
The RSN Information Element (RSN IE) in the beacon carries the AP’s encryption advertisement. Marauder parses it into an encryption-type label:
| Marauder label | What it means | Common cracking target? |
|---|---|---|
| Open | No encryption | Trivial — no cracking; just connect |
| WEP | 64-bit or 128-bit WEP | Vol 9 § 7 aircrack-ng path; rare in 2026 |
| WPA | Original WPA-PSK or WPA-Enterprise | Crack via 4-way handshake; same hashcat 22000 path as WPA2 |
| WPA2 | WPA2-PSK (most common SOHO target) | 4-way handshake → hashcat 22000 |
| WPA2 (PMKID-exposed) | WPA2 AP with PMKID in beacon RSN IE | PMKID directly to hashcat 22000 — fastest path |
| WPA3 / SAE | WPA3 Personal | Not crackable with current Marauder workflow; harder offline path |
| WPA3 mixed | WPA2/WPA3 transition mode | Crackable via the WPA2 transition path |
The encryption type drives which capture is worth attempting. Vol 9 § 4 covers the host-side cracking decision tree.
5. PMKID capture
5.1 What PMKID is
PMKID (Pairwise Master Key Identifier) is a 16-byte hash derived from:
PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AP_MAC || Client_MAC)
where PMK = PBKDF2(passphrase, SSID, 4096, 256) for WPA2-PSK.
The PMKID was originally designed for fast roaming — when a client reconnects to an AP it’s been associated with before, it sends the PMKID instead of doing the full 4-way handshake, and the AP verifies by recomputing.
In 2018, Steube (hashcat) showed that the PMKID is sometimes present in beacon RSN IE or in the first EAPOL message (M1) of a fresh association — and that having the PMKID + AP_MAC + Client_MAC + SSID is enough to crack the passphrase offline via dictionary attack (hashcat mode 22000). No 4-way handshake needed. No deauth needed. Just a passive observation of the beacon or the first frame of any association.
This is the shortest-distance attack against WPA2-PSK that exists. PMKID-vulnerable APs include many SOHO routers from Asus, TP-Link, ZyXEL, D-Link, and Netgear (firmware-version dependent).
5.2 Two collection paths
Marauder gets PMKIDs from two sources:
- From beacon RSN IE. Some APs include the PMKID in their broadcast beacons — pure passive collection, no provoking required. This is the cleanest path.
- From EAPOL M1. When a client associates with the AP, the AP’s first EAPOL message contains the PMKID. Marauder captures this opportunistically while watching for 4-way handshakes (§ 6) — if M1 contains a PMKID, save it; if M4 completes the full handshake, save that too.
The PMKID in M1 is guaranteed by the WPA2 spec (it’s not optional there); the PMKID in beacons is vendor-discretion and the 2018 attack surface that not all APs expose.
5.3 Marauder’s PMKID workflow
- Marauder menu: WiFi → Sniffer → PMKID/Probe (the unified PMKID + EAPOL sniffer)
- Channel strategy: hopping is acceptable for opportunistic PMKID harvest; static is better for targeted harvest of a specific AP.
- Output to SD as
pmkid_<timestamp>.pcap(pcap format compatible with hcxpcapngtool — Vol 9 § 4). - Run for hours-to-days in a static deployment for a maximal harvest.
- Transfer pcap to host; convert with
hcxpcapngtool -o output.hc22000 input.pcap; crack with hashcat mode 22000.
Typical PMKID density: at a SOHO neighborhood, expect 5-15 unique vulnerable APs per square block in a 24-hour passive collection.
6. EAPOL 4-way handshake capture
6.1 The 4-way handshake mechanics
When a WPA2-PSK client associates with an AP, the two parties run a 4-way handshake to derive a per-session key. The four messages:
- M1 (AP → Client) — AP sends a random nonce (ANonce). PMKID may be present here (see § 5.2).
- M2 (Client → AP) — Client sends its random nonce (SNonce) + MIC computed over message using the derived PTK.
- M3 (AP → Client) — AP confirms with another MIC; includes the group temporal key (GTK).
- M4 (Client → AP) — Client acknowledges.
For an offline crack, hashcat needs M2 (or M3) + the SSID + AP_MAC + Client_MAC + the two nonces. The PMKID-based attack of § 5 is essentially “use M1’s PMKID and skip the rest” — but if PMKID isn’t present, M2 or M3 are needed.
6.2 What Marauder needs to capture
Marauder captures the EAPOL frames as raw 802.11 in pcap. For a successful hashcat crack, the pcap needs to contain at minimum one of:
- M1 + M2 (most common useful pair)
- M2 + M3 (also works)
- M1 with PMKID (PMKID path, § 5)
Capturing partial handshakes (e.g., M2 only with no preceding M1) gives hashcat insufficient context. The conversion tool (hcxpcapngtool) tells you what’s usable; treat its output as authoritative.
6.3 The deauth-and-rejoin pattern
The canonical “force a handshake” workflow:
- Identify target. Run AP scan (§ 4), pick the WPA2-PSK AP whose handshake is wanted. Note BSSID and channel.
- Lock to target channel. Static-channel mode (§ 8.2).
- Start EAPOL sniff. Marauder menu: WiFi → Sniffer → PMKID/Probe with target BSSID set.
- Identify a connected client. Watch the AP-list mode for clients associated with the target BSSID. Note client MAC.
- Fire deauth at the target client. Marauder menu: WiFi → Attack → Deauth with target = client MAC, sender = AP MAC. Send 5-10 deauth frames.
- Client re-associates. When the client comes back, M1-M4 fly. Marauder captures them.
- Stop sniff. Pull SD card, hand off pcap to Vol 9 § 4.
Without a connected client the workflow stalls at step 4. In that case, fall back to PMKID-from-beacon if available, or wait for an organic association (sit on a coffee-shop AP at peak hour and someone will join).
Operational considerations (full treatment in Vol 11):
- Deauth is noisy — IDS-detectable. Don’t deploy on networks you don’t own.
- Deauth can affect other clients on the same AP — narrow targeting.
- A spoofed-source deauth is what Marauder sends; the spoofed source = AP’s BSSID. From a logging-AP perspective, the AP appears to be deauthing its own clients — which doesn’t show up in most consumer AP logs but does show up in enterprise IDS.
7. AP + client mapping
Marauder’s AP+client mapping mode combines beacon scan (§ 4) with probe-response correlation and EAPOL observation to build a per-AP connected-client list. Output looks like:
BSSID SSID Channel RSSI Clients
A4:5E:60:AA:BB:CC HomeNetwork 6 -45 3
└ C0:25:5C:11:22:33 -52 (last seen 2026-05-13T14:32:00)
└ DC:A6:32:44:55:66 -58 (last seen 2026-05-13T14:31:50)
└ A4:5E:60:77:88:99 -47 (last seen 2026-05-13T14:32:05)
08:96:D7:DD:EE:FF CompanyGuest 11 -67 1
└ F0:18:98:00:11:22 -71 (last seen 2026-05-13T14:32:08)
Use cases:
- Reconnaissance — who’s on what AP, how many users, signal strength.
- Client targeting — pick a client for the deauth-and-rejoin handshake capture (§ 6.3).
- Site survey — coverage and channel-utilization mapping.
The mapping mode is a higher-level abstraction over the raw beacon and probe-response captures — it’s a UI convenience, not a different capture path. Output is a synthesized csv built from the underlying beacon/probe-response data.
8. Channel hopping vs static-channel mode
8.1 Default hopping pattern
By default, Marauder hops channels at ~250 ms intervals across the configured channel set. Patterns vary by build flag:
COUNTRY_US— channels 1, 6, 11 (the non-overlapping subset) cycled, OR 1-11 sequentialCOUNTRY_DE/COUNTRY_ANY— 1-13 sequentialCOUNTRY_JP— 1-14 sequential
The hopping pattern can be overridden per-scan from the menu (some menus expose “Hop Pattern: 1,6,11 / 1-11 / 1-13 / Custom”).
Hopping is the right default for survey workloads (probe-request, beacon scan, general AP enumeration). The miss-rate is the trade-off: a frame that arrives while the radio is on a different channel is lost. For probe requests (which clients repeat aggressively when looking for networks) this is fine — you’ll see the next probe in 30-60 seconds even if you missed one. For EAPOL handshakes (single transient event) hopping is catastrophic.
8.2 Static mode for handshake capture
When the workload is EAPOL handshake capture for a specific AP, hopping must be disabled. The flow:
- Identify target AP and its channel (from a prior scan).
- Lock Marauder to that channel via Settings → Channel → Static.
- Start the EAPOL sniff.
Static mode reduces the miss-rate to effectively zero for frames on the locked channel. For multi-AP captures, run one static session per channel (or use a Marauder host with PSRAM that can hold an all-channels passive scan for hours).
8.3 Region channel-plan considerations
Most consumer APs in the US use channels 1, 6, or 11 (the non-overlapping subset). Some recent APs auto-select among 1-11 based on observed congestion. Channels 12-14 are not used in the US.
In the EU, channels 12-13 are common. Japan uses channel 14 (and only Japan does). For international site surveys, set the country flag to the broadest applicable region (COUNTRY_ANY) and accept that the hop cycle is longer.
The country flag is firmware-build-time in mainline — change it requires re-flashing with a different build. Ghost ESP exposes the country code at runtime (more convenient for travel).
9. Output formats
9.1 pcap
The canonical capture format for EAPOL handshakes, PMKID material, and any case where the host-side tool wants raw 802.11 frames. Marauder writes pcaps with:
- Link type 105 (
LINKTYPE_IEEE802_11) — raw 802.11 frames without any radiotap header. - Per-packet header carries timestamp (seconds + microseconds), captured length, original length.
Wireshark, tshark, scapy, hcxpcapngtool all consume Marauder pcaps natively. The lack of a radiotap header means per-frame channel and RSSI are not embedded in the pcap — those are written to a sibling csv in some Marauder builds (or lost in older builds). For PMKID/EAPOL workflows this is fine; for RF-survey workflows it can be limiting.
Filename pattern: pcap_<sniffmode>_<timestamp>.pcap in /marauder/pcaps/.
9.2 csv
For probe-request, beacon, AP-list, and BLE captures, csv is the more useful format. Marauder writes a header row + one data row per observation. Columns vary by scan mode but typically include:
- MAC (source for probes, BSSID for beacons)
- SSID (when applicable)
- RSSI (dBm)
- Channel
- Timestamp (ISO 8601 if RTC is available; otherwise milliseconds-since-boot)
Filename pattern: <scanmode>_<timestamp>.csv in /marauder/.
9.3 On-screen scrollback
The TFT shows the most-recent N observations as a scrolling list (where N depends on display resolution — typically 8-15 rows for the v6.1’s 2.8″). Older entries scroll off and are lost from the on-screen view but remain in the SD-card output.
Display refresh rate is throttled — typically once per second under heavy capture load, more often when idle. The throttling is intentional to avoid blocking the main loop (Vol 3 § 6 + § 7).
10. Workflow recipes
10.1 Site-survey passive walk
Goal: catalog the Wi-Fi environment at a site over 10-30 minutes.
- Insert SD card. Power on Marauder. Verify SD mount + free space.
- Set channel mode to hopping, country code matching the site.
- Menu: WiFi → Sniffer → AP+Client. Start.
- Walk the site at a moderate pace; pause 30-60s at each location of interest.
- Stop scan. SD output:
apclient_<ts>.csvwith the synthesized AP+client map;probes_<ts>.csvwith all probe requests observed;beacons_<ts>.csvwith all beacons. - Transfer SD to host. Open in Wireshark/Excel/Python.
Expected yield: 50-200 unique APs in a city block; 100-500 unique probe-request MACs in a coffee-shop hour.
10.2 Targeted handshake capture
Goal: capture a 4-way handshake for a specific WPA2-PSK AP whose BSSID is known.
- From a prior survey, identify target BSSID + channel + a known associated client MAC.
- Set channel to static, lock to target channel.
- Menu: WiFi → Sniffer → PMKID/Probe with BSSID filter = target. Start.
- Confirm sniffer is running on the target channel (status bar shows channel + frames-captured count).
- Menu: WiFi → Attack → Deauth with target client MAC. Send 5-10 frames. Return to sniffer.
- Watch the frame-captured counter — when the client reassociates, M1-M4 fly. Counter jumps.
- Stop sniffer. SD output:
pcap_pmkid_<ts>.pcap. - Host:
hcxpcapngtool -o handshake.hc22000 pcap_pmkid_*.pcap→hashcat -m 22000 handshake.hc22000 wordlist.txt.
Expected duration: 1-2 minutes from start-of-scan to handshake captured (depends on client responsiveness). If no client is associated, switch to PMKID-only path (next recipe).
10.3 PMKID harvest sweep
Goal: harvest as many PMKID-vulnerable APs as possible over a deployment period.
- Set channel mode to hopping; country code matching the area.
- Menu: WiFi → Sniffer → PMKID/Probe. Start.
- Deploy in static location (parked car, conference table) or walk a route over hours.
- Stop after deployment ends. SD output:
pcap_pmkid_<ts>.pcap. - Host:
hcxpcapngtool -o pmkid_harvest.hc22000 pcap_pmkid_*.pcapto convert; the tool reports how many PMKIDs were extracted vs how many were skipped for incompleteness. - Crack with hashcat mode 22000 against rockyou + common SOHO router patterns (
?u?l?l?l?l?d?d?d?detc.).
Expected yield: 10-30% of WPA2-PSK APs in range will yield PMKID in a multi-hour collection (the rest aren’t running PMKID-vulnerable firmware). Crack success against rockyou is ~30-50% on residential APs; lower on commercial.
11. Resources
Standards and references
- IEEE 802.11-2020 § 9 (Frame formats): canonical reference
- IEEE 802.11i (key management amendment, folded into 2020 base)
- RFC 4017 (EAP method requirements)
- hashcat WPA-PMKID-PBKDF2 mode 22000 docs: https://hashcat.net/wiki/doku.php?id=cracking_wpawpa2#new_attack_on_wpa_wpa2_using_pmkid
- Original PMKID attack write-up (Steube, 2018): https://hashcat.net/forum/thread-7717.html
Tools
- Wireshark: https://www.wireshark.org/
- hcxtools (hcxpcapngtool et al): https://github.com/ZerBea/hcxtools
- hashcat: https://hashcat.net/hashcat/
- aircrack-ng (legacy WPA workflow): https://www.aircrack-ng.org/
- bettercap (active engagement): https://www.bettercap.org/
Forward references in this series
- Wi-Fi attacks (deauth, beacon spam, Evil Portal): Vol 5
- Host-side analysis of captures (pcap → Wireshark / scapy / hashcat): Vol 9
- Operational posture (detection, legal, power): Vol 11
Forward-back references
- Capture mechanics live in the promiscuous-mode plumbing covered in Vol 3 § 5.2
- Channel-region build flags catalogued in Vol 3 § 9
- SD card directory layout for capture output: Vol 8 § 2
This is Volume 4 of a twelve-volume series. Next: Vol 5 walks the Wi-Fi attack catalogue — deauth, beacon spam, probe spam, Evil Portal — and the build-flag gating that makes some of these opt-in at compile time.