Files
cute-handshake-capture/handshake-capture-c6
drjones 8121137b68 handshake-capture-c6 v1.0.4: persist captured BSSIDs, PCAP EAPOL recount
- /cap_bssids.txt append on save; handshakeLoadPersistedBssids after SD mount
- Boot order: SD then load file then first WiFi scan (reds match SD)
- Pre-save walk of in-memory PCAP counting EAPOL-Key frames
- SD_AppendLine / SD_ForEachLine; drop g_sd_ready clear on write fail
- README + MUST_DO updates

Made-with: Cursor
2026-03-23 09:35:18 -07:00
..

Handshake Capture - ESP32-C6 1.47" LCD

Production-oriented WiFi 4-way handshake capture for Waveshare ESP32-C6-LCD-1.47.

Firmware version: HANDSHAKE_FIRMWARE_VERSION in HandshakeCapture.h (also printed on serial at boot).

Review backlog: prioritized fixes from a full firmware pass → MUST_DO_IMPROVEMENTS.md.

Features

  • SD required for capture: No card, or open/write failure → pending PCAP is discarded and the slot freed (no infinite pending). Hot-insert: sketch retries SD_Init() before each capture round.
  • SD storage: Saves only complete 4-way handshakes as .pcap (LINKTYPE_IEEE802_11): 4way_<ssid>_<ms>_s<n>.pcap. Filenames are FAT-sanitized. No PMKID-only or partial EAPOL dumps.
  • Auto-deauth: Bursts toward mapped clients to provoke a full 4-way.
  • Display: Green = targetable 2.4 GHz WPA/WPA2/WPA3 AP, gray = shown but skipped, red = 4-way saved to SD.
  • No web UI: Capture-only device.
  • WPA / WPA2 / WPA3 PSK / mixed (when the core reports them). Skips Open, WEP, WPA2-Enterprise.
  • 2.4 GHz only capture sweep: channels 1-14 are targeted. Secure APs seen on 5/6 GHz stay visible in the list but are marked 5G+ and skipped.
  • BSSID cache: Captured BSSIDs stay red across rescans and across reboots: each successful save appends that APs BSSID to /cap_bssids.txt (one line AA:BB:…:FF). On boot (after SD mounts), that file is merged into RAM so the device does not re-target APs already marked good.
  • Pre-save PCAP check: Before writing a .pcap, the firmware walks the in-memory PCAP and counts EAPOL-Key frames (type 3, same LLC/SNAP rules as live capture). If the count is below four, the buffer is discarded (no file, no BSSID append). This does not verify MIC, nonces, or distinct M1M4 — that still requires offline tools / knowing the passphrase.
  • Shared SPI protection: LCD flushes and SD filesystem calls now serialize on one bus lock; SD writes also pause LVGL updates for the duration of the transaction.

Convert: hcxpcapngtool / Wireshark / aircrack-ng expect PCAP with EAPOL-Key frames; a full 4-way is included in each saved file (plus one target beacon when available).

“Partial” captures — whats actually possible

  • Not mergeable across random reconnects: EAPOL messages from different 4-way runs (different nonces / MIC context) usually cannot be stitched into one crackable handshake. Tools need a coherent set for that AP↔STA association attempt.
  • Within one visit, frames can trickle in: While tuned to a channel, the device keeps one PCAP buffer per target AP. If the client reconnects several times during the same session, all EAPOL frames append until either four are seen (then SD save) or the channel round ends without four (buffer dropped — no file).
  • EAPOL counting is still heuristic: Live path stops after four matching frames; the PCAP recount before SD write catches obvious buffer/counter mismatch. It still does not cryptographically validate the 4-way (MIC / replay / message order) — use Wireshark or hcxpcapngtool on a PC for that.
  • Fewer than four frames: Some attacks (e.g. PMKID in message 1, or classic M1+M2 with beacon) need fewer frames, but this firmware only saves on four so every file aims to be a clean full 4-way for your earlier requirement.

Hardware

  • Waveshare ESP32-C6-LCD-1.47 (non-touch, ST7789)
  • TF card in onboard slot

Build & Flash

Requires LVGL and lv_conf from the ESP32-C6-LCD-1.47-Demo:

cd "/path/to/4 way handshake"
arduino-cli compile \
  -b 'esp32:esp32:esp32c6:PartitionScheme=huge_app' \
  --build-path /tmp/arduino-build-handshake-c6 \
  --libraries "ESP32-C6-LCD-1.47-Demo/Arduino/libraries" \
  handshake-capture-c6
arduino-cli upload \
  -p /dev/cu.usbmodem* \
  -b 'esp32:esp32:esp32c6:PartitionScheme=huge_app' \
  --input-dir /tmp/arduino-build-handshake-c6

Use arduino-cli board list to find the correct port.

For bench builds, set HANDSHAKE_DEBUG 1 in HandshakeCapture.h to restore verbose serial logs. USE_SOFTAP defaults to 0; only turn it on for lab experiments where you explicitly want WIFI_AP_STA.

Flow

  1. Boot → scan → display networks (green targetable, gray skipped)
  2. Channel sweep + up to 2 WPA APs at a time on that channel; map clients → deauth burst → listen (several rounds per visit)
  3. PCAP grows in RAM; SD write only when 4 EAPOL-Key frames are seen for that AP
  4. On save → mark red; refill slots with other networks on the same channel, then next channel until everyone captured or timed out
  5. If a visit ends without 4 EAPOL for an AP, that buffer is discarded (no partial PCAP); the next sweep can try again
  6. Mid-capture rescans are intentionally not exposed in the UI; if you add one later, stop capture first and clear active slots before rebuilding networks[]

Production checklist

Item Notes
Flash layout Prefer PartitionScheme=huge_app (~40% of that partition at v1.0.0); default default partition is too small (~96% full).
SD FAT-formatted microSD; capture is gated on SD_IsReady() (successful SD_Init), not raw cardType() (unreliable after WiFi on shared SPI).
Serial 115200 — boot line shows handshake-capture-c6 vX.Y.Z.
Legal / authorization Only deploy on networks you own or have explicit written permission to test. Unauthorized interception or disruption is illegal in many jurisdictions.

Release discipline

  1. Bump HANDSHAKE_FIRMWARE_VERSION in HandshakeCapture.h for any field release.
  2. Rebuild with the same arduino-cli FQBN and partition scheme you ship.
  3. Run a short on-bench test: scan → capture → confirm .pcap opens in Wireshark and shows four EAPOL-Key exchanges for the target BSSID.