ESP32 Marauder · Volume 9
ESP32 Marauder Firmware Volume 9 — Capture Analysis Pipelines
pcap → Wireshark / tshark / scapy / hashcat / aircrack-ng / bettercap — the host-side workflow
Contents
1. About this volume
Vol 9 closes the on-device-to-host loop. Vols 4 / 5 / 6 cover what Marauder captures and writes to the SD card; this volume covers what the operator does with those bytes once the card is pulled and attached to a workstation.
Five major host-side workflows live here:
- Wireshark interactive for everything (§ 2)
- tshark + scapy scripted for batch processing (§ 3)
- hashcat 22000 for offline WPA / PMKID cracking (§ 4) — the workflow with the highest payoff per engagement
- Clustering analysis of probe requests + BLE advertising for de-anonymization research (§ 5)
- Cred-log triage for Evil Portal output (§ 8)
The volume assumes the operator has a Linux host with hashcat, Wireshark, hcxtools, aircrack-ng, bettercap, and Python (with scapy and sklearn) installed. On macOS, all of these install via Homebrew; on Windows, WSL is the practical path.
2. pcap → Wireshark — interactive analysis
2.1 Loading Marauder pcaps
Open a Marauder pcap in Wireshark:
wireshark /path/to/sd/marauder/pcaps/eapol_2026-05-13T14-32-17.pcap
Wireshark identifies the link-type-105 (LINKTYPE_IEEE802_11) automatically. The capture displays as raw 802.11 frames — no Ethernet encapsulation, no radiotap header. Per-frame RSSI and channel are not embedded in the pcap (Vol 4 § 9.1) — Wireshark shows only the frame contents.
2.2 Display filters for management frames
The handful of display filters that handle most Marauder analysis:
| Filter | Selects |
|---|---|
wlan.fc.type == 0 | All management frames |
wlan.fc.subtype == 8 | Beacons only |
wlan.fc.subtype == 4 | Probe requests only |
wlan.fc.subtype == 5 | Probe responses only |
wlan.fc.subtype == 12 | Deauth frames |
wlan.fc.subtype == 0x0a | Disassoc frames |
wlan.bssid == aa:bb:cc:dd:ee:ff | All frames involving a specific BSSID |
wlan.sa == aa:bb:cc:dd:ee:ff | Frames sourced by a specific MAC |
eapol | EAPOL 4-way handshake frames |
wlan_rsna_eapol | EAPOL with the WPA decoder dissecting the key data |
wlan.fc.type == 0 && wlan.bssid contains 04:5e:60 | Frames involving APs from a vendor OUI prefix |
Combine with && and ||. Wireshark’s display-filter expression builder helps when unfamiliar with the field names.
2.3 Decryption with captured PSK
If you cracked the PSK (or know it), Wireshark can decrypt the data-frame payloads:
- Edit → Preferences → Protocols → IEEE 802.11.
- Add a decryption key with type
wpa-pwd. Format:passphrase:SSID. - Wireshark replays the EAPOL handshake from the pcap (must be in the same pcap) and derives the per-session keys.
- Data frames now decrypt — you can see DNS, HTTP, etc.
The 4-way handshake must be present in the same pcap for decryption to work. Marauder’s pcaps from the PMKID sniffer typically do contain a complete handshake (M1+M2+M3+M4 if captured cleanly); the pure PMKID-only path doesn’t preserve enough to decrypt traffic.
2.4 Validating a captured 4-way handshake
Before sending to hashcat, validate the pcap actually contains a usable handshake:
# Quick test:
tshark -r eapol.pcap -Y "eapol" -T fields -e frame.number -e wlan.bssid -e wlan_rsna_eapol.keydes.msgnr
# Output shows: frame#, BSSID, M-number (1, 2, 3, or 4)
# A usable capture: at minimum a paired M1+M2 or M2+M3 for the same BSSID.
Better: hcxpcapngtool -o /dev/null eapol.pcap and read its summary output — it tells you how many usable handshakes vs incomplete ones it found.
3. pcap → tshark / scapy — scripted analysis
3.1 tshark one-liners
tshark is Wireshark’s CLI counterpart — same filters and parsing.
Enumerate unique BSSIDs:
tshark -r beacons.pcap -Y "wlan.fc.subtype == 8" -T fields -e wlan.bssid | sort -u
Enumerate probe-request MAC + SSID pairs:
tshark -r probes.pcap -Y "wlan.fc.subtype == 4" -T fields \
-e wlan.sa -e wlan.ssid | sort -u
Count probe requests per source MAC:
tshark -r probes.pcap -Y "wlan.fc.subtype == 4" -T fields -e wlan.sa \
| sort | uniq -c | sort -rn | head -20
Extract all deauth frames with source + destination:
tshark -r capture.pcap -Y "wlan.fc.subtype == 12" -T fields \
-e frame.time -e wlan.sa -e wlan.da
tshark output is one row per matching frame; pipe into awk/sort/uniq for aggregation.
3.2 scapy for deeper analysis
scapy gives full Python access to every byte of every frame:
from scapy.all import rdpcap, Dot11ProbeReq
packets = rdpcap("probes.pcap")
# Cluster probe requests by source MAC
probes_by_mac = {}
for p in packets:
if p.haslayer(Dot11ProbeReq):
src = p.addr2 # source MAC
ssid_field = p.getlayer(Dot11ProbeReq).info
ssid = ssid_field.decode("utf-8", errors="replace") if ssid_field else ""
probes_by_mac.setdefault(src, set()).add(ssid)
# Print MACs with > 5 distinct SSID probes (highly identifying)
for mac, ssids in probes_by_mac.items():
if len(ssids) > 5:
print(f"{mac}: {sorted(ssids)}")
scapy can also synthesize and inject — useful for testing Marauder’s parser end-to-end on a known frame, or for building a custom analysis tool. The full scapy API is at https://scapy.readthedocs.io/.
4. Handshake / PMKID → hashcat (mode 22000)
4.1 pcap → 22000 conversion (hcxpcapngtool)
hashcat mode 22000 expects a specific format produced by hcxpcapngtool from the hcxtools package. Install:
# Ubuntu/Debian:
sudo apt install hcxtools
# Mac via Homebrew:
brew install hcxtools
# From source:
git clone https://github.com/ZerBea/hcxtools && cd hcxtools && make && sudo make install
Conversion:
hcxpcapngtool -o handshake.hc22000 eapol_2026-05-13T14-32-17.pcap
The tool reports what it found:
summary capture file
----------------------
file name......: eapol_2026-05-13T14-32-17.pcap
file type......: pcap 1.0
file hardware information......: unknown
file os information............: unknown
file application information...: unknown
network type...................: DLT_IEEE802_11
endianness.....................: little endian
read errors....................: flawless
packets inside.................: 18420
... (long output)
packets contain hashcat -m 22000 PMKID hash data: 7
packets contain hashcat -m 22000 EAPOL hash data: 12
The “PMKID hash data: 7” and “EAPOL hash data: 12” numbers are what you care about. Both write into handshake.hc22000.
The 22000 mode unifies WPA-PMKID-PBKDF2 + WPA-PBKDF2 + EAPOL — you crack everything in one hashcat invocation, regardless of capture source. The old separate modes 2500 / 16800 are deprecated.
4.2 The hashcat 22000 invocation
hashcat -m 22000 -a 0 handshake.hc22000 /path/to/wordlist.txt
# With rules:
hashcat -m 22000 -a 0 handshake.hc22000 wordlist.txt -r /path/to/best64.rule
# Mask attack (for known patterns):
hashcat -m 22000 -a 3 handshake.hc22000 '?u?l?l?l?l?d?d?d?d'
# Resume an interrupted run:
hashcat --restore
Cracked passwords end up in handshake.hc22000.pot (the pot file). View with hashcat -m 22000 handshake.hc22000 --show.
4.3 Wordlist strategy
| Wordlist | Source | Hit rate (informal) on residential APs |
|---|---|---|
| rockyou.txt | 2009 social-network leak | 30-50% |
| SecLists 10-million-password-list | Aggregated leaks | 40-60% |
| Custom (target name + variants + locale) | Hand-curated | 10-20% (but high-yield per hit when it works) |
| Phone-number patterns | ?d?d?d?d?d?d?d?d?d?d mask | High on cellular-provider default-config networks |
| Date patterns | ?d?d?d?d?d?d?d?d mask | High on user-set passwords using birthdays |
Practical default: start with rockyou + best64 rules. If that misses, try SecLists’ 10M-password-list. Then custom. Then masks.
4.4 Time estimates by GPU class
Rough hashcat 22000 cracking rates against a single hash, as of 2026:
| GPU | rockyou (14M words, ~5 sec/run) | rockyou + best64 rules | 8-char mask ?a?a?a?a?a?a?a?a |
|---|---|---|---|
| RTX 4090 | ~2 minutes | ~15 minutes | ~3 days |
| RTX 3080 | ~5 minutes | ~30 minutes | ~7 days |
| Mac M2 (CPU only) | ~30 minutes | ~3 hours | impractical |
| Intel laptop CPU | ~2 hours | ~12 hours | impractical |
GPU rental is the cost-effective path when you don’t have a heavy GPU on hand — RunPod or Vast.ai have RTX 4090 instances at ~$0.40-0.80/hour. A 5-minute rockyou run costs ~$0.05.
5. Probe-request clustering — who’s-looking-for-what
5.1 The SSID-set fingerprint
Modern OSes randomize MAC per-SSID-probe-target but each device still probes for the same set of remembered SSIDs. A device that probes for {HomeNetwork, CompanyVPN, MomsHouse, GymWiFi} is fingerprinted by that set even when the MAC rotates.
Use cases:
- De-anonymization research — identify whether the same person visited multiple sites by comparing SSID-set overlap.
- Targeted attack reconnaissance — find which SSIDs a target user is vulnerable to spoofing.
- Privacy auditing — quantify how much information leaks via probe requests at a venue.
5.2 A clustering recipe (Python + sklearn)
import csv
from sklearn.cluster import DBSCAN
from sklearn.feature_extraction.text import TfidfVectorizer
# Load Marauder probe-request csv
records = []
with open("probes.csv") as f:
reader = csv.DictReader(f)
for row in reader:
records.append((row["MAC"], row["SSID"]))
# Group by MAC into SSID sets
ssids_by_mac = {}
for mac, ssid in records:
if ssid: # ignore wildcard probes
ssids_by_mac.setdefault(mac, set()).add(ssid)
# Filter to MACs with >= 3 distinct SSIDs (worth clustering)
worth_clustering = {m: s for m, s in ssids_by_mac.items() if len(s) >= 3}
# Build TF-IDF features over the SSID sets
docs = [" ".join(sorted(s)) for s in worth_clustering.values()]
vec = TfidfVectorizer()
X = vec.fit_transform(docs)
# DBSCAN: cluster MACs whose SSID-sets overlap substantially
clustering = DBSCAN(eps=0.4, min_samples=2, metric="cosine").fit(X)
labels = clustering.labels_
# Group MACs by cluster
clusters = {}
for mac, label in zip(worth_clustering.keys(), labels):
if label != -1: # -1 = noise/outlier
clusters.setdefault(label, []).append(mac)
for cluster_id, macs in clusters.items():
print(f"Cluster {cluster_id}: {len(macs)} MACs")
common = set.intersection(*[worth_clustering[m] for m in macs])
print(f" Shared SSIDs: {sorted(common)}")
The cluster output identifies MAC groups whose SSID probes are similar enough to be plausibly the same person across MAC rotations. eps and min_samples tune sensitivity — narrow eps clusters only near-identical SSID-sets.
5.3 BLE manufacturer-data clustering
Same pattern works on BLE-scan output (Vol 6 § 4):
- Cluster BD_ADDRs by manufacturer-data subtype fingerprint + advertising-interval timing + TX-power.
- Apple AirPods Pro emits a distinct subtype pattern that’s stable per-device.
- iPhones in offline-finding mode (Find My) have a 2-second cadence that’s distinctive (Vol 6 § 6.1).
Bruce / Ghost ESP’s richer manufacturer-data parses (Vol 6 § 4.2) make this easier; mainline’s conservative parses require more host-side enrichment.
6. bettercap integration patterns
bettercap is the bigger-than-Marauder Wi-Fi/BLE attack tool — runs on a Linux host with a monitor-mode-capable Wi-Fi adapter. Marauder + bettercap is the natural pairing when Marauder isn’t enough:
- Marauder for reconnaissance (small form factor, low-profile site survey).
- bettercap for active engagement (full power, scripting, MITM, automated workflows).
Typical hand-off pattern:
- Marauder runs probe-request + AP scan over hours at the target site.
- SD card extracts to laptop; csv informs bettercap target list.
- bettercap on the laptop fires the targeted attacks (deauth-and-rejoin handshake capture, evil twin, MITM) with the operator parked nearby.
- Bettercap captures go to host disk; analysis identical to Marauder pcaps (§ 2-4).
bettercap supports a JavaScript-based scripting language for custom workflows. The Marauder→bettercap handoff is usually a manual “use these BSSIDs as targets” step rather than scripted, but for repeated engagements it can be automated.
bettercap docs and walkthroughs: https://www.bettercap.org/. Install: apt install bettercap on Linux or brew install bettercap on Mac.
7. aircrack-ng for legacy workflows
aircrack-ng is the older toolset — predates hashcat 22000 by years. Still useful when:
- CPU-only environment — aircrack-ng cracks on CPU (slower than hashcat-GPU but works without GPU). hashcat also supports CPU mode but aircrack-ng’s CPU implementation is faster for legacy modes.
- WEP networks (rare in 2026) — aircrack-ng has dedicated WEP cracking modes that hashcat doesn’t replicate.
- Legacy pcap formats — older capture tools that don’t produce hashcat-compatible output sometimes work directly with aircrack-ng.
- Replay attacks —
aireplay-ngis the canonical tool for ARP-replay attacks against WEP (only relevant for WEP, but if you’re cracking WEP at all, you need it).
The hashcat path is preferred for everything else. aircrack-ng’s WPA/WPA2 cracking is materially slower than hashcat 22000 on the same hardware.
8. Cred-log triage from Evil Portal
creds.txt from Evil Portal captures (Vol 5 § 5.4 + Vol 8 § 5):
2026-05-13T14:32:17, AP=MarauderGuest, IP=10.0.0.42, MAC=A4:5E:60:11:22:33, [email protected], password=hunter2
2026-05-13T14:35:08, AP=MarauderGuest, IP=10.0.0.43, MAC=DC:A6:32:44:55:66, [email protected], password=admin123
Parsing into a structured report:
import csv, re
with open("creds.txt") as f:
captures = []
for line in f:
if not line.strip():
continue
# Parse the comma-separated key=value pairs
fields = {}
for kv in line.strip().split(", "):
if "=" in kv:
k, v = kv.split("=", 1)
fields[k.strip()] = v.strip()
captures.append(fields)
# Sort by timestamp; deduplicate by email
seen = set()
unique = []
for c in captures:
email = c.get("email", "")
if email and email not in seen:
seen.add(email)
unique.append(c)
print(f"Total captures: {len(captures)}")
print(f"Unique emails: {len(unique)}")
for c in unique:
print(f" {c.get('email', '?')}")
Triage workflow:
- Parse and deduplicate.
- Validate captured emails against the engagement scope — were they actually authorized targets, or did bystanders enter credentials?
- Drop bystander credentials — purge from logs, document the purge in the engagement report.
- For in-scope captures, validate that the captured password actually works against the legitimate service (manual verification step; don’t include in automated tools to avoid accidentally locking accounts).
- Build the engagement-deliverable report — captured credentials + dates + per-capture justification.
- Hash + encrypt the source
creds.txtbefore delivery.
Chain-of-custody discipline (Vol 8 § 9 + Vol 11 § 7): treat Evil Portal output as evidence-grade. Don’t sloppy-handle the file.
9. Workflow recipes
Recipe A — Full handshake-to-crack pipeline
Goal: from a Marauder PMKID/EAPOL capture to a cracked passphrase.
# 1. Mount SD card. cd to pcaps directory.
cd /mnt/sd/marauder/pcaps
# 2. Convert all pcaps to 22000 format
hcxpcapngtool -o /tmp/all_handshakes.hc22000 *.pcap
# 3. Sanity-check — how many usable hashes?
wc -l /tmp/all_handshakes.hc22000
# 4. Crack with rockyou + best64 rules
hashcat -m 22000 /tmp/all_handshakes.hc22000 \
~/wordlists/rockyou.txt \
-r ~/hashcat/rules/best64.rule \
--status --status-timer 60
# 5. View cracked
hashcat -m 22000 /tmp/all_handshakes.hc22000 --show
Recipe B — Probe-request de-anonymization study
Goal: identify which MACs at a venue are plausibly the same person across MAC rotations.
# 1. Collect via Marauder (Vol 4 § 10.1) — 10+ minute passive walk
# 2. Extract probes_<ts>.csv to host
# 3. Run the clustering recipe from § 5.2
python3 cluster_probes.py probes.csv
# 4. Output: cluster groups of MACs with shared SSID sets
# 5. (Optional) cross-reference with BLE scan from same time window for biometric correlation
Recipe C — Evil Portal engagement deliverable
Goal: produce a clean engagement-deliverable report from Evil Portal captures.
# 1. Mount SD card. Verify provenance.
sha256sum /mnt/sd/marauder/creds.txt > /tmp/creds_hash_2026-05-13.txt
# 2. Parse + deduplicate
python3 parse_creds.py /mnt/sd/marauder/creds.txt > /tmp/captures_parsed.csv
# 3. Manual review — drop bystanders, validate in-scope captures
# 4. Build engagement report (Markdown / Word per template)
# 5. Encrypt source + report; deliver via secure channel
# 6. Hash + encrypt source, securely delete original
10. Resources
Tools
- Wireshark: https://www.wireshark.org/
- tshark (Wireshark CLI): bundled with Wireshark
- hashcat: https://hashcat.net/hashcat/
- hcxtools (hcxpcapngtool): https://github.com/ZerBea/hcxtools
- aircrack-ng suite: https://www.aircrack-ng.org/
- bettercap: https://www.bettercap.org/
- scapy: https://scapy.readthedocs.io/
Wordlists
- SecLists (the catalogue): https://github.com/danielmiessler/SecLists
- rockyou.txt: included in Kali; available as standalone download
- CrackStation human-passwords-only list: https://crackstation.net/
Rules / masks
- hashcat best64 rules: included in hashcat distribution at
rules/best64.rule - hashcat OneRuleToRuleThemAll: https://github.com/NotSoSecure/password_cracking_rules
hashcat docs
- Hashcat wiki: https://hashcat.net/wiki/
- Mode 22000 reference: https://hashcat.net/wiki/doku.php?id=cracking_wpawpa2
GPU rental for crackers without high-end GPUs
- RunPod: https://www.runpod.io/
- Vast.ai: https://vast.ai/
Forward references in this series
- Operational handling of captured material (chain-of-custody full): Vol 11 § 7
- SD-card-side data layout (where the captures live before extraction): Vol 8
- Per-capture-type context (what’s in the pcap to begin with): Vols 4 + 6
This is Volume 9 of a twelve-volume series. Next: Vol 10 covers the build toolchain (PlatformIO setup), building from source for a specific board, adding a custom attack, forking strategy, and the web flasher.