I have liked the idea behind Pwnagotchi for years: a little Raspberry Pi that watches WiFi traffic, collects WPA handshake material and pulls faces while it works. It is equal parts security project and needy electronic pet.
I wanted to see how much of that idea I could squeeze into something cheaper and simpler. No Linux installation, no Pi Zero and no display HAT. Just an ESP32 development board, a tiny OLED and whatever jumper wires were closest to the soldering iron.
My parts came to roughly £10. By the end of the weekend, the board could watch my 2.4 GHz lab network, recognise the frames involved in a WPA2 connection, save useful packets as PCAP files and serve those files from a private local download page. It also had a 16 by 16 pixel face that bounced when it caught something.
I called it EVIL-GOTCHI. Subtle was never really an option.
Two boards, four wires
The physical build is almost suspiciously small. I used a generic ESP32 Dev Module and a 0.96-inch SSD1306 OLED. The ESP32 provides the processor, WiFi radio and flash storage. The OLED provides 128 by 64 pixels of extremely serious operational feedback.
ESP32 Dev Module
The ordinary 30-pin version. Its built-in BOOT button became the mode switch, so I did not need another control.
SSD1306 OLED
A small I2C display. I2C is a simple way for small electronics to talk over two signal wires.
USB power
A phone charger works on the bench. A power bank makes the finished board portable.
| OLED | ESP32 | Job |
|---|---|---|
| GND | GND | Ground |
| VCC | 3V3 | 3.3-volt power |
| SCL | GPIO 22 | I2C clock |
| SDA | GPIO 21 | I2C data |
That is the whole circuit. The display library is Adafruit SSD1306 with Adafruit GFX underneath it, and the firmware is an Arduino sketch built for the ESP32. The hardware was the easy part. Making the radio, storage and screen cooperate without tripping over one another was where the project became interesting.
What a handshake actually is
When a device joins a WPA2 network, the device and access point perform a four-way handshake. It is a short exchange that lets both sides derive fresh encryption keys without sending the WiFi password through the air.
Those packets can still be observed. Capturing them does not reveal the password and it does not mean the network has been broken. It creates material that can be checked offline against password guesses, which is why a long, unique WiFi passphrase still matters.
EVIL-GOTCHI puts the ESP32 radio into promiscuous mode. Despite the slightly alarming name, that simply means the radio listens to nearby WiFi frames instead of accepting only traffic addressed to itself. The firmware looks for three useful kinds of frame.
It cycles through channels 1, 6 and 11, the three non-overlapping channels commonly used on 2.4 GHz WiFi. That was enough for my own setup, but it is also a deliberate limitation. A network on another 2.4 GHz channel can be missed, and this ESP32 build does not cover 5 GHz at all.
The tiny traffic queue that saved it
The WiFi callback runs inside the radio driver’s own task. That is the worst possible place to pause while a file is written to flash. If the callback takes too long, more packets arrive while the processor is busy and useful data can disappear.
My solution is a 24-slot ring buffer. Think of it as a tiny circular waiting room. The radio copies an interesting frame into the next free slot and gets straight back to listening. The normal Arduino loop empties those slots later and writes them to LittleFS, the small filesystem living in the ESP32’s onboard flash.
Each access point gets its own PCAP file. PCAP is a standard packet-capture format understood by tools such as Wireshark, so I can move the file to a computer and inspect exactly what the board recorded. The prototype stores the beacon plus up to eight EAPOL frames for each access point, enough room for the four-part exchange and a few repeats.
The active part stays inside the lab
A handshake appears naturally whenever a device connects or reconnects. Waiting for that is passive and slow. My prototype also has an active test mode that asks devices on my lab network to reconnect, giving the sniffer another chance to observe the exchange.
That action interrupts a live connection and can become a denial-of-service attack when abused. Protected Management Frames, often called PMF or 802.11w, are designed to stop forged disconnect messages and are required by WPA3. So the earlier idea that a directed frame is impossible for a modern device to ignore is not true. Security has moved on, as it should.
I have deliberately left the frame-injection routine, access credentials and full attack-capable sketch out of this public post. They are not needed to explain the build, and publishing a copy-and-run disruption tool would turn an engineering write-up into something much less responsible.
One button, two personalities
In hunt mode, the display shows the current channel, how many access points the board has worked through and how many handshakes it has recognised. The total persists across restarts in the ESP32’s non-volatile storage.
Pressing BOOT switches to download mode. The radio stops hunting, the queue is flushed to flash and the ESP32 creates its own local WPA2-protected WiFi network. A small web page then lists the saved captures for download. Pressing BOOT again returns it to hunt mode.
The download service is local to the board and has no internet route. I am not publishing its credentials here. For the next firmware revision, I want to replace the prototype’s fixed password with a random one shown on the OLED at startup. Losing a pocket-sized capture device should not also hand somebody the key to its files.
The face was non-negotiable
The OLED could have displayed three numbers and called it a day. Instead, I spent an unreasonable amount of time animating a 16 by 16 face.
It blinks every four seconds. If nothing is happening, it gives a small bounce every ten seconds. When a handshake is recognised, it switches to an excited six-second wiggle with a proper curved hop. The access point name appears on the status line, while the counters remain visible beside it.
None of that improves packet capture. All of it improves EVIL-GOTCHI.
What worked, and what still needs fixing
The good bit is that the architecture held together. One inexpensive board managed the radio, display, flash storage, persistent counter and local web server. The ring buffer kept slow storage away from time-sensitive packet handling, and the BOOT button gave the device two clear modes without adding more hardware.
The limitations are equally clear. It only watches 2.4 GHz and currently hops across three channels. Flash is limited, the capture files are not encrypted at rest, and active reconnection attempts will not work against properly configured PMF clients. The little board is a learning tool, not a replacement for professional WiFi test equipment.
Next on the list is a proper enclosure, random download credentials, encrypted capture storage and a passive-only option that never transmits test frames. I also want a reset control for the saved count without wiping anything else.
The first weekend proved the idea. Roughly £10 of hardware can teach a surprising amount about radio callbacks, packet formats, flash storage and the protections built into modern WiFi. It can also pull a very pleased face when the code finally works.
Worth every wire.
Zombie