handshake-capture-c6: production SD gating (SD_IsReady), v1.0.1

- Gate capture on SD_IsReady() after successful SD_Init; avoid false
  'insert SD' when SD.cardType() lies after WiFi on shared SPI with LCD
- SD_Init: LCD CS high, SD.end() on empty card; HandshakeCapture save path
  retries SD_Init before discard
- FAT filename sanitize, discard deadlocks, WPA3 scan labels, docs (README,
  PRODUCTION, IMPROVEMENTS), firmware version 1.0.1

Made-with: Cursor
This commit is contained in:
drjones
2026-03-21 01:12:12 -07:00
parent 4bef28bd83
commit 804e71e175
11 changed files with 512 additions and 153 deletions

View File

@@ -1,15 +1,26 @@
# Handshake Capture - ESP32-C6 1.47" LCD
Automatic WiFi 4-way handshake capture for Waveshare ESP32-C6-LCD-1.47.
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).
## Features
- **SD card storage**: Saves `.pcap` files to TF card (not SPIFFS)
- **Auto-deauth**: Aggressive 150ms deauth interval to force handshakes
- **Display**: Networks in **green** = not captured, **red** = captured
- **No web interface**: Capture-only device
- **WPA/WPA2 only**: Skips Open/WEP networks
- **BSSID cache**: Captured networks stay red across rescans
- **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** = pending, **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.
- **BSSID cache:** Captured BSSIDs stay red across rescans.
**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).
- **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 is a clean full 4-way for your earlier requirement.
## Hardware
@@ -41,7 +52,22 @@ Use `arduino-cli board list` to find the correct port.
## Flow
1. Boot → scan → display networks (green)
2. Pick first uncaptured WPA/WPA2 network
3. Set channel, deauth every 150ms, capture EAPOL
4. On full handshake → save to SD, mark red, next network
5. When all done → rescan, repeat
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
## 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.