Files
cute-handshake-capture/handshake-capture-c6/HandshakeCapture.h
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

122 lines
3.2 KiB
C

#pragma once
#include <Arduino.h>
#include <WiFi.h>
#include "esp_wifi.h"
#include <SD.h>
/** Semantic version (Serial banner + support). */
#define HANDSHAKE_FIRMWARE_VERSION "1.0.4"
#ifndef HANDSHAKE_DEBUG
#define HANDSHAKE_DEBUG 0
#endif
#ifndef USE_SOFTAP
#define USE_SOFTAP 0
#endif
#define HANDSHAKE_MIN_CHANNEL 1
#define HANDSHAKE_MAX_CHANNEL 14
#define HANDSHAKE_OBSERVE_DURATION_MS 8000UL
#define HANDSHAKE_CAPTURE_TIMEOUT_MS 20000UL
#define HANDSHAKE_CHANNEL_TIMEOUT_MS 150000UL
#define HANDSHAKE_DEAUTH_BURST_COUNT 5
#define HANDSHAKE_DEAUTH_BURST_DELAY_MS 2
#define HANDSHAKE_MAX_OBSERVE_CYCLES 5
#define HANDSHAKE_DEAUTH_GAP_AFTER_CLIENT_MS 80
#define HANDSHAKE_DEAUTH_GAP_AFTER_SLOT_MS 120
#if HANDSHAKE_DEBUG
#define HANDSHAKE_LOGF(...) Serial.printf(__VA_ARGS__)
#define HANDSHAKE_LOGLN(msg) Serial.println(msg)
#else
#define HANDSHAKE_LOGF(...) do { } while (0)
#define HANDSHAKE_LOGLN(msg) do { } while (0)
#endif
/** Heuristic threshold only; frames are not validated as distinct 4-way steps. */
#define HANDSHAKE_EAPOL_FRAMES 4
/** SD file: one line per BSSID `AA:BB:CC:DD:EE:FF` — loaded on boot so restarts skip re-capture. */
#define HANDSHAKE_CAPTURED_BSSID_FILE "/cap_bssids.txt"
// Two APs at once: less on-air contention, more time per target before rotating.
#define MAX_SLOTS 2
#define MAX_NETWORKS 20
#define MAX_CLIENTS_PER_SLOT 8
#define PCAP_MAX_SIZE 4096
typedef struct {
uint32_t magic_number;
uint16_t version_major;
uint16_t version_minor;
int32_t thiszone;
uint32_t sigfigs;
uint32_t snaplen;
uint32_t network;
} __attribute__((packed)) pcap_global_header_t;
typedef struct {
uint32_t ts_sec;
uint32_t ts_usec;
uint32_t incl_len;
uint32_t orig_len;
} __attribute__((packed)) pcap_record_header_t;
typedef struct {
String ssid;
uint8_t bssid[6];
int ch;
int rssi;
String encryption;
bool handshake_captured;
} WifiNetwork;
typedef struct {
uint8_t mac[6];
uint32_t last_seen;
} ClientInfo;
typedef struct {
uint8_t bssid[6];
char ssid[33];
int network_index;
bool beacon_captured;
uint8_t eapol_count;
uint8_t pcap_buffer[PCAP_MAX_SIZE];
size_t pcap_size;
bool active;
ClientInfo clients[MAX_CLIENTS_PER_SLOT];
uint8_t client_count;
} CaptureSlot;
// Phase 3 (deauth burst) is transient — no dedicated state needed
enum CapturePhase : uint8_t {
PHASE_OBSERVING, // Phase 2: passive client mapping (RX only)
PHASE_CAPTURING // Phase 4: EAPOL capture (RX only)
};
extern WifiNetwork networks[MAX_NETWORKS];
extern CaptureSlot slots[MAX_SLOTS];
extern volatile int pending_save_slots[MAX_SLOTS];
extern volatile uint8_t latest_eapol_count[MAX_SLOTS];
extern bool is_capturing;
extern int current_channel;
extern CapturePhase capturePhase;
void handshakeCaptureInit();
/** Call after SD_Init() succeeds — merges file into RAM BSSID cache (survives reboot). */
void handshakeLoadPersistedBssids();
void handshakeCaptureProcessPending();
void refillSlots();
bool wasBssidCaptured(const uint8_t* bssid);
void scanNetworksSortedByRSSI();
void startMultiCapture();
void stopCapture();
bool isSupportedCaptureAuth(const String& encryption);
bool isSupportedCaptureChannel(int channel);
bool isCaptureable(int index);
void handshakeCaptureLoop();
int getCaptureableCount();