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
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include "SD_Card.h"
|
||||
#include "LVGL_Driver.h"
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
// ─── Internal prototypes ───
|
||||
@@ -15,6 +16,11 @@ static bool addClientToSlot(CaptureSlot* slot, const uint8_t* mac);
|
||||
static int getNextChannelSweep();
|
||||
static void sanitizeFilenameForFat(String& path);
|
||||
static void discardSlotCapture(CaptureSlot* s, int slot_index);
|
||||
static bool parsePersistedBssidLine(const char* s, uint8_t mac[6]);
|
||||
static void formatBssidHexLine(const uint8_t* bssid, char* out, size_t cap);
|
||||
static bool framePayloadIsEapolKey(const uint8_t* payload, uint16_t len);
|
||||
static unsigned countEapolKeyFramesInPcap(const uint8_t* buf, size_t sz);
|
||||
static void persistBssidLineCallback(const char* line, void* user);
|
||||
|
||||
// ─── Shared state ───
|
||||
|
||||
@@ -63,6 +69,76 @@ static void markBssidCaptured(const uint8_t* bssid) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool parsePersistedBssidLine(const char* s, uint8_t mac[6]) {
|
||||
if (s == nullptr) return false;
|
||||
unsigned a, b, c, d, e, f;
|
||||
if (sscanf(s, " %x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f) != 6) return false;
|
||||
mac[0] = (uint8_t)a;
|
||||
mac[1] = (uint8_t)b;
|
||||
mac[2] = (uint8_t)c;
|
||||
mac[3] = (uint8_t)d;
|
||||
mac[4] = (uint8_t)e;
|
||||
mac[5] = (uint8_t)f;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void formatBssidHexLine(const uint8_t* bssid, char* out, size_t cap) {
|
||||
snprintf(out, cap, "%02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
|
||||
}
|
||||
|
||||
static bool framePayloadIsEapolKey(const uint8_t* payload, uint16_t len) {
|
||||
if (len < 24) return false;
|
||||
uint8_t frame_type = payload[0];
|
||||
bool is_qos = (frame_type == 0x88);
|
||||
bool is_data = (frame_type == 0x08) || is_qos;
|
||||
if (!is_data) return false;
|
||||
bool to_ds = (payload[1] & 0x01) != 0;
|
||||
bool from_ds = (payload[1] & 0x02) != 0;
|
||||
uint16_t mhl = 24;
|
||||
if (to_ds && from_ds) mhl += 6;
|
||||
if (is_qos) mhl += 2;
|
||||
if ((payload[1] & 0x40) != 0 || len < mhl + 8 + 4) return false;
|
||||
if (payload[mhl] != 0xAA || payload[mhl + 1] != 0xAA || payload[mhl + 2] != 0x03) return false;
|
||||
if (payload[mhl + 6] != 0x88 || payload[mhl + 7] != 0x8E) return false;
|
||||
uint8_t eapol_type = payload[mhl + 9];
|
||||
return eapol_type == 3;
|
||||
}
|
||||
|
||||
static uint32_t pcapRdU32(const uint8_t* p) {
|
||||
return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
|
||||
}
|
||||
|
||||
static unsigned countEapolKeyFramesInPcap(const uint8_t* buf, size_t sz) {
|
||||
if (sz < sizeof(pcap_global_header_t)) return 0;
|
||||
size_t off = sizeof(pcap_global_header_t);
|
||||
unsigned n = 0;
|
||||
while (off + sizeof(pcap_record_header_t) <= sz) {
|
||||
uint32_t incl = pcapRdU32(buf + off + 8);
|
||||
off += sizeof(pcap_record_header_t);
|
||||
if (incl > PCAP_MAX_SIZE || off + incl > sz) break;
|
||||
if (incl >= 24 && framePayloadIsEapolKey(buf + off, (uint16_t)incl)) n++;
|
||||
off += incl;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void persistBssidLineCallback(const char* line, void* user) {
|
||||
(void)user;
|
||||
uint8_t mac[6];
|
||||
if (!parsePersistedBssidLine(line, mac)) return;
|
||||
markBssidCaptured(mac);
|
||||
}
|
||||
|
||||
void handshakeLoadPersistedBssids() {
|
||||
if (!SD_IsReady()) return;
|
||||
if (!SD_ForEachLine(HANDSHAKE_CAPTURED_BSSID_FILE, persistBssidLineCallback, nullptr)) {
|
||||
HANDSHAKE_LOGLN("[PERSIST] cap_bssids read failed");
|
||||
} else {
|
||||
HANDSHAKE_LOGF("[PERSIST] loaded BSSID cache from %s\n", HANDSHAKE_CAPTURED_BSSID_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
static void sanitizeFilenameForFat(String& path) {
|
||||
for (unsigned i = 0; i < path.length(); i++) {
|
||||
char c = path[i];
|
||||
@@ -149,6 +225,16 @@ void handshakeCaptureProcessPending() {
|
||||
filename.replace(" ", "_");
|
||||
sanitizeFilenameForFat(filename);
|
||||
|
||||
unsigned eapolInPcap = countEapolKeyFramesInPcap(s->pcap_buffer, s->pcap_size);
|
||||
if (eapolInPcap < HANDSHAKE_EAPOL_FRAMES) {
|
||||
HANDSHAKE_LOGF("[VALIDATE] PCAP has %u EAPOL-Key (need %d) — discard\n",
|
||||
eapolInPcap, HANDSHAKE_EAPOL_FRAMES);
|
||||
Ui_SetWifiStatus("Bad PCAP");
|
||||
pending_save_slots[i] = -1;
|
||||
discardSlotCapture(s, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ok = SD_WriteFileAtomic(filename.c_str(), s->pcap_buffer, s->pcap_size);
|
||||
if (ok) {
|
||||
HANDSHAKE_LOGF("Saved 4-way %s (%d bytes)\n", filename.c_str(), (int)s->pcap_size);
|
||||
@@ -161,6 +247,11 @@ void handshakeCaptureProcessPending() {
|
||||
if (ok) {
|
||||
pending_save_slots[i] = -1;
|
||||
markBssidCaptured(s->bssid);
|
||||
char pline[24];
|
||||
formatBssidHexLine(s->bssid, pline, sizeof(pline));
|
||||
if (!SD_AppendLine(HANDSHAKE_CAPTURED_BSSID_FILE, pline)) {
|
||||
HANDSHAKE_LOGLN("[PERSIST] append BSSID failed (RAM cache still set)");
|
||||
}
|
||||
if (s->network_index >= 0 && s->network_index < MAX_NETWORKS) {
|
||||
networks[s->network_index].handshake_captured = true;
|
||||
Ui_SetNetworkColor(s->network_index, lv_palette_main(LV_PALETTE_RED));
|
||||
|
||||
Reference in New Issue
Block a user