Skip to content

Releases: tworjaga/ESP32Gotchi

v1.1.0 - Architecture Overhaul & Bug Fix Release

31 Mar 17:35
0681e79

Choose a tag to compare

v1.1.0 — Architecture Overhaul & Bug Fix Release

This release addresses eight bugs found during a full firmware audit — two of which could cause device lock-up or silent data loss under normal use. No new features. Flash it, move one wire, and it works correctly.


⚠️ Hardware Change Required

Move the button wire from IO0 to IO4.

GPIO0 is the ESP32 boot-mode strapping pin. If it reads LOW when the chip samples strapping pins after a reset (~50 ms post-boot), the ROM enters serial Download Mode instead of starting your firmware — the screen stays black and the device appears bricked until power-cycled. The long-press restart triggers on release, so most users never hit this, but the failure mode is real and reproducible. GPIO4 has no strapping function. One wire. That's it.


Memory Architecture Redesign

The two most consequential bugs were both memory layout problems.

hs_slot_t embedded raw[4][1600] inline. Each handshake slot was 6 430 bytes. With 32 slots, g_hs[] alone consumed 205 KB — nearly the entire user DRAM budget after the Wi-Fi stack. Slots now store four pool-block indices instead. Raw frame bytes live in a dedicated static pool and are released after the PCAP is written. Slot metadata is now ~40 bytes.

The write queue allocated 51 440 bytes and copied frame data three times per capture. write_item_t was a full value-copy of hs_slot_t. The queue now carries a single uint8_t slot index (8 bytes total queue storage). task_write reads g_hs[] directly.

promisc_cb called malloc() on every captured frame. In a busy RF environment this means thousands of variable-size allocations per second. After hours of operation the heap fragments until allocations silently fail and the sniffer goes blind. All packet storage is now handled by two static pools of 32 × 1 600 B blocks, allocated once at boot. Runtime heap allocations: zero.


Bug Fixes

Task priority inversiontask_hop was priority 3, below task_proc at 5. In a dense RF environment the packet queue never drains, task_proc monopolises Core 0, and the channel hopper freezes on a single channel. task_hop is now priority 6 (highest on Core 0). task_write raised from 2 to 4.

Unnecessary mutex on the hot pathg_ap_mutex was acquired on every beacon and data frame to protect a write-write race that cannot occur (task_proc is the only writer of g_aps[]). Removed.

O(N) AP scan — linear memcmp over up to 100 entries, called thousands of times per second. Replaced with a 256-bucket open-addressing hash table. AP lookup is now O(1) average.

EAPOL slot-exhaustion DoS — 32 spoofed EAPOL frames with random source MACs exhaust all tracking slots instantly, blinding the device for 30 seconds, repeating indefinitely. New slot creation is now rate-limited to one per 100 ms. MAX_HS_SLOTS reduced to 16, HS_EXPIRE_MS halved to 15 s.


What Changed at a Glance

v1.0.0 v1.1.0
Button pin GPIO0 ⚠️ GPIO4
task_hop priority 3 6
task_write priority 2 4
Runtime heap allocations per-packet 0
hs_slot_t size 6 430 B ~40 B
Write queue allocation 51 440 B 8 B
AP lookup O(N) O(1)
HS slot timeout 30 s 15 s
Max HS slots 32 16

Full source and wiring instructions in the README. Compiled and tested on ESP32-WROOM-32 @ 240 MHz, arduino-esp32 2.0.x.

First release v1.0.0

22 Mar 12:26
c488f5c

Choose a tag to compare

v1.0.0 — Initial Release

First public release of ESP32Gotchi.

Firmware features:

  • Passive WPA/WPA2 4-way handshake capture via ESP32 promiscuous mode
  • IEEE 802.11-2020 compliant EAPOL parser (messages 1-4)
  • Standard libpcap output, opens directly in Wireshark
  • Channel hopping across 1-11 (2.4 GHz), 200 ms dwell
  • FreeRTOS: 4 tasks, dual-core, dedicated SD write task
  • SSD1306 OLED status display
  • LED feedback state machine
  • SD retry, space check, watchdog

Hardware: ESP32 DevKit V1 + SSD1306 OLED + MicroSD SPI module. ~10 EUR total.

For authorised security research only.