Implement 4-phase capture architecture: observe, target, capture
- Phase 2 (Observation): passive client mapping from data frame headers, ClientInfo array per slot (up to 8 clients), 5s observation window - Phase 3 (Targeting): unicast deauth burst to each discovered client instead of broadcast, reason code 7, 5 frames per client - Phase 4 (Capture): timeout + retry loop cycles back to observation to refresh stale client list (2 cycles within 30s channel timeout) - Fix EAPOL detection: compute LLC/SNAP offset from QoS vs non-QoS header length, verify AA-AA-03 SNAP prefix, skip protected frames - Concurrency: portMUX spinlock for callback/main-loop shared state, no dynamic alloc in callback, pre-allocated 4KB PCAP buffer per slot - Phase-aware LCD status display (mapping → capturing → EAPOL count) Made-with: Cursor
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* WiFi Handshake Capture - ESP32-C6 1.47" LCD
|
||||
* Automatically scans, deauths, and captures handshakes to SD card.
|
||||
* Multi-target capture: up to 3 networks per channel, deauth all, capture all.
|
||||
* Display: green = not captured, red = captured.
|
||||
*/
|
||||
|
||||
@@ -18,8 +18,7 @@ enum CaptureState {
|
||||
|
||||
CaptureState captureState = STATE_SCANNING;
|
||||
unsigned long capture_start_time = 0;
|
||||
const unsigned long CAPTURE_TIMEOUT_MS = 25000;
|
||||
const unsigned long DEAUTH_INTERVAL_MS = 150;
|
||||
const unsigned long CHANNEL_TIMEOUT_MS = 30000;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
@@ -40,41 +39,63 @@ void setup() {
|
||||
|
||||
void loop() {
|
||||
Timer_Loop();
|
||||
handshakeCaptureProcessPending();
|
||||
handshakeCaptureLoop();
|
||||
|
||||
switch (captureState) {
|
||||
case STATE_SCANNING: {
|
||||
int idx = -1;
|
||||
for (int i = 0; i < 20; i++) {
|
||||
if (networks[i].ssid.isEmpty()) break;
|
||||
if (!networks[i].handshake_captured && isCaptureable(i)) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx >= 0) {
|
||||
setTarget(idx);
|
||||
captureState = STATE_CAPTURING;
|
||||
capture_start_time = millis();
|
||||
startCapture(true);
|
||||
Ui_SetWifiStatus("Capturing...");
|
||||
} else {
|
||||
if (getCaptureableCount() == 0) {
|
||||
Ui_SetWifiStatus("Rescan");
|
||||
WiFiScanner_Refresh();
|
||||
delay(500);
|
||||
break;
|
||||
}
|
||||
startMultiCapture();
|
||||
if (is_capturing) {
|
||||
captureState = STATE_CAPTURING;
|
||||
capture_start_time = millis();
|
||||
Ui_SetWifiStatus("Mapping clients");
|
||||
} else {
|
||||
Ui_SetWifiStatus("No targets");
|
||||
delay(1000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case STATE_CAPTURING: {
|
||||
int idx = getCurrentTargetIndex();
|
||||
if (isHandshakeCaptured(idx)) {
|
||||
Ui_SetWifiStatus("Got handshake");
|
||||
bool any_active = false;
|
||||
for (int i = 0; i < MAX_SLOTS; i++) {
|
||||
if (slots[i].active) {
|
||||
any_active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Phase-aware status display
|
||||
static CapturePhase last_shown_phase = PHASE_CAPTURING;
|
||||
if (capturePhase != last_shown_phase) {
|
||||
Ui_SetWifiStatus(capturePhase == PHASE_OBSERVING ? "Mapping clients" : "Capturing...");
|
||||
last_shown_phase = capturePhase;
|
||||
}
|
||||
|
||||
static int last_eapol = -1;
|
||||
if (capturePhase == PHASE_CAPTURING && latest_eapol_count != last_eapol) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "EAPOL %d/2", latest_eapol_count);
|
||||
Ui_SetWifiStatus(buf);
|
||||
last_eapol = latest_eapol_count;
|
||||
}
|
||||
|
||||
if (!any_active && getCaptureableCount() == 0) {
|
||||
Ui_SetWifiStatus("Done");
|
||||
stopCapture();
|
||||
captureState = STATE_SCANNING;
|
||||
delay(2000);
|
||||
} else if (idx >= 0 && millis() - capture_start_time > CAPTURE_TIMEOUT_MS) {
|
||||
Ui_SetWifiStatus("Timeout");
|
||||
} else if (!any_active) {
|
||||
stopCapture();
|
||||
captureState = STATE_SCANNING;
|
||||
} else if (millis() - capture_start_time > CHANNEL_TIMEOUT_MS) {
|
||||
Ui_SetWifiStatus("Ch timeout");
|
||||
stopCapture();
|
||||
captureState = STATE_SCANNING;
|
||||
delay(2000);
|
||||
|
||||
Reference in New Issue
Block a user