The Adversary
Advanced WiFi Security Testing Tool
Features •
Hardware •
Installation •
Usage •
FAQ •
Development •
Legal
[!WARNING]
Adversary is currently in ALPHA — actively developed and built for stability, but still incomplete. Expect missing or unfinished features and occasional breaking changes between releases (backward compatibility is kept where possible). Use at your own risk.
Legal Disclaimer
Adversary is for educational and research purposes only. Unauthorized access to networks is illegal. By using this tool, you agree to the terms in the DISCLAIMER.
[!NOTE]
To reach every 2.4 GHz AP, the radio is pinned to the full 1-14 channel domain and will scan and transmit on channels 12-14 regardless of your location. Those channels are not licensed for transmission everywhere (e.g. the US allows 1-11). Operate only within your engagement's legal authorization.
Features
The main menu is a carousel: Wireless, BLE, Infrared, RFID, HID,
and Radio (Sub-GHz / 2.4 GHz, shown when the multi-radio cap is attached), plus
Modules (live peripheral inventory + hot-swap re-scan), Server (dashboard),
Settings, and About.
Scanner — security, signal, channel | Per-network actions | Packet sniffer |
Handshake Auto Hunt | Evil Twin — captive portal | Wardriving — GPS mapping |
Captures browser | Capture details — cracked | BLE scanner |
Sub-GHz band sweep | Sub-GHz OOK — capture/replay | 2.4 GHz spectrum |
IR TV-B-Gone | RFID audit | BadUSB — USB HID |
Modules — live inventory | Settings | |
Wireless (WiFi)
- Scanner - Discover networks with security type, signal strength, and channel info; context action menu per network.
- AP Proximity Tracker - Hunt an access point by beacon signal strength: a live meter with a closer/farther direction (labelled signal, not distance), launched from the scanner, working on hidden or idle APs.
- Packet Sniffer - Raw 802.11 frame capture with channel hopping and filtering.
- Handshake Capture - WPA/WPA2/WPA3 handshake acquisition (4-way, PMKID, partial EAPOL) in three modes: Manual, Auto Hunt (autonomous multi-target hunting + whitelist, with a Deauth / PMKID / Both capture strategy), and Clientless PMKID (solicits a PMKID directly from an AP that has no connected clients).
- Deauthentication - Targeted or mass 802.11 deauth frames.
- Evil Twin - Rogue AP with captive-portal credential harvesting; deauth or block individual connected clients from the clients list.
- Karma AP - Auto-responds to any client probe request.
- Beacon Spam / Probe Flood - Fake-network flooding and probe-request saturation.
- Wardriving - GPS-integrated mapping of WiFi and BLE observations, with CSV/KML export and WiGLE upload.
- Traffic Proxy - Real-time DNS/HTTP/HTTPS metadata capture from Evil Twin victims.
- Captures Browser - Manage Handshakes/Packets/Credentials, with cloud-cracking status and a bulk "Sync all new" action across every configured cracking service.
BLE (Bluetooth Low Energy)
- BLE Scanner - Real-time discovery and RSSI tracking of BLE peripherals, with a proximity tracker to hunt a chosen device by signal (live meter + closer/farther direction).
- Apple Attack - Proximity-pairing popup spam for Apple devices.
- BadBLE - BLE HID keyboard emulation, including a DuckyScript interpreter for scripted keystroke injection over BLE.
- Identity Spoof - BLE identity/address spoofing.
- BLE Spam - Proximity pairing notification flooding (Apple, Android, Windows).
HID (USB keystroke/mouse injection)
- BadUSB - Native USB-HID DuckyScript keyboard injection on the Cardputer (ESP32-S3 USB-OTG); built-in scripts plus SD-loaded custom scripts, with US/ES keyboard layout support.
- Mouse Jiggler - Periodic small mouse movements to defeat idle-lock/screensaver timers.
- Not available on M5StickC Plus2 (no native USB-OTG).
Custom BadUSB scripts: drop DuckyScript .txt files into /adversary/badusb/ on the SD
card. The firmware creates that folder on first run and lists each file with an "SD" badge
alongside the built-in scripts. One script per .txt file, standard DuckyScript syntax.
Radio — Sub-GHz & 2.4 GHz (multi-radio cap)
Requires the CC1101/NRF24 expansion cap; the Radio entry is greyed out when no cap is detected.
- Sub-GHz Band Sweep - CC1101 RSSI read across the 315 / 433.92 / 868.35 / 915 MHz presets while you hold a remote's button, with a peak-held bar per band and the strongest highlighted — tells you which band an unknown remote transmits on before you try to capture it. Reads energy, not modulation (independent of OOK vs FSK).
- Sub-GHz OOK Capture & Replay - CC1101-based raw OOK capture and replay across 315 / 433.92 / 868.35 / 915 MHz (e.g. simple remotes and sensors), with a pulse-train preview of the captured signal.
- Sub-GHz FSK Capture & Replay - CC1101 FSK demodulated capture (2-FSK / GFSK / MSK) for constant-amplitude remotes the OOK envelope-slicer can't see, chosen from a table of common modem presets (deviation / data rate / RX bandwidth), stored so a captured signal replays under its own configuration. Constant-amplitude modulation carries no envelope, so unknown deviation/data-rate is a preset search, not a read — and rolling-code targets won't actuate on replay (this is not an SDR).
- Sub-GHz Jamming - CC1101 carrier-wave or modulated-noise transmission on the selected band preset to hold a channel busy against a fixed-code receiver. Hold-to-jam (emits only while the key is held) behind an interference-warning gate — authorized testing only.
- 2.4 GHz Spectrum Analyzer - NRF24-based channel sweep (received-power detection) across the 2.4 GHz band for activity/interference mapping.
Infrared
- IR TV-B-Gone - High-power universal IR blast to turn off TVs (NA/EU code databases, arrow-key region toggle).
- IR Record & Replay - Learn a remote's IR frame (NEC/RC5/raw — decoded or raw timing train) via the cap's IR receiver, persist it to SD, and replay it, with a pulse preview of the capture.
RFID
- RFID Audit - MFRC522-based (13.56 MHz, I2C) NFC/RFID tag reading and dumping.
- RFID Write / Clone - Restore a saved
.nfc dump onto a MIFARE Classic 1K card: all data blocks with the recovered keys, plus optional UID cloning on magic cards (Gen2/CUID direct-write and Gen1a backdoor). Reports the detected card type and every block outcome.
- Magic card detection - Flags UID-rewritable (Gen1a) cards via a backdoor probe.
Modules
- Module inventory & hot-swap re-scan - A live view of which peripherals are attached right now (Sub-GHz/2.4 GHz cap, RFID reader, GPS) with a Re-scan action, so a module seated after boot is detected without a reboot — its greyed-out menu tile un-greys as soon as the re-scan finds it. Also surfaces the cap-detection override. Seat the module while the radio bus is idle, then Re-scan.
Cloud Cracking & Sync
- WPA-SEC - Upload
.pcap handshakes for cloud cracking; status tracking (uploaded/cracked) per capture.
- pwncrack.org - Second cracking service, consumes the
.hc22000 (.22000) files handshake capture already writes.
- WiGLE - Upload wardriving CSVs for community wireless mapping.
- All uploads go over a certificate-validated TLS connection (Mozilla root-CA bundle, no
setInsecure()), heap-paced to avoid OOM on large uploads.
Server / Dashboard Mode
- Serves a web dashboard from the SD card for browser-based review of captures and status. The device's access point is WPA2-protected with an auto-generated per-device key (shown on the Server screen, overridable in Settings), and the dashboard itself adds path-traversal protection and HTTP auth enabled by default.
User Interface
- Theme System - Customizable color schemes.
- Toast Notifications - Real-time operation feedback.
- Status Bar - Battery, SD card, WiFi status, and connected module display.
- Footer Hints - Context-sensitive key mapping guides.
Feature maturity
The Adversary is in alpha. Everything builds and runs, but features differ in how much
on-hardware mileage they have. This split is a guide, not a guarantee:
Stable — field-tested
Scanner · Packet Sniffer · Handshake Capture (4-way / PMKID / EAPOL) + Auto Hunt · Deauth ·
Evil Twin + captive portal + Traffic Proxy · Karma · Beacon Spam / Probe Flood · Wardriving +
WiGLE · Captures Browser · Cloud sync (WPA-SEC / pwncrack) · Web Dashboard · BadUSB · Mouse
Jiggler · IR TV-B-Gone · IR Record & Replay · BLE Scanner · Apple/BLE Spam · RFID Audit ·
RFID Write / Clone · AP / BLE Proximity Trackers · Evil Twin client deauth / block.
Experimental — works, but hardware verification is still in progress
Sub-GHz OOK replay (transmit) · Sub-GHz FSK capture/replay · Sub-GHz Jamming · 2.4 GHz Spectrum
Analyzer · BadBLE (reflash re-pair loop fixed via fresh per-session identity, pending on-device
confirmation) · BLE Identity Spoof.
How it compares
The Adversary is a newer, deliberately-engineered entrant in a category led by Bruce and
ESP32 Marauder. It doesn't try to out-feature them on raw breadth — it competes on rigor,
honesty, and Cardputer-native polish.
Reasons to choose it
- Sub-GHz FSK, not just OOK — demodulated 2-FSK/GFSK/MSK capture for constant-amplitude
remotes the OOK envelope-slicer can't see, plus a modulation-independent band sweep.
- Multi-service cloud cracking — one "Sync all new" pushes every not-yet-synced handshake
to WPA-SEC and pwncrack in a single action, with per-service status per capture.
- Uploads you can trust — all cloud traffic goes over certificate-validated TLS with an
embedded Mozilla root-CA bundle (no
setInsecure()).
- Built like production software — 770+ host-native unit tests, architecture decision records,
a 3-target CI matrix, and reproducible pinned builds. The engineering is the differentiator.
- MIT licensed — friendlier for downstream and commercial reuse than AGPL alternatives.
Reasons to look elsewhere
- No 5 GHz. Like every ESP32-S3 firmware, The Adversary is 2.4 GHz only. If you need 5 GHz
scanning/deauth, use dual-band hardware (RTL8720DN/BW16, or an ESP32-C5 board) instead.
- It's alpha, and young. The incumbents have larger communities, more device coverage, and
years of field mileage. If you need battle-tested stability today, start there.
Hardware
Supported Devices
| Device | Status | Notes |
|--------|--------|-------|
| M5Stack Cardputer (ESP32-S3) | ✅ Primary | Full keyboard, SD card slot, 240x135 display, native USB-OTG (BadUSB/Mouse Jiggler) |
| M5StickC Plus2 (ESP32-PICO-D4) | ⚠️ Secondary | Builds and is exercised in CI; active development and hardware testing target the Cardputer. No USB-OTG, so BadUSB/Mouse Jiggler are unavailable there. |
[!NOTE]
The architecture is designed to support both boards via the HAL, but active development and hardware testing target the Cardputer.
Requirements
- SD Card: 8GB+ Class 10 (FAT32 formatted)
- Battery: Fully charged for portable operation
- USB-C Cable: For flashing and serial monitoring
Optional external modules
Most features run on a bare Cardputer. These need extra hardware:
| Feature | Requires | Attaches via |
|---------|----------|--------------|
| Radio — Sub-GHz OOK capture/replay, 2.4 GHz analyzer | CC1101 + NRF24 multi-radio expansion cap | Top expansion header |
| IR Record & Replay | multi-radio cap (IR receiver) — the built-in Cardputer IR emitter is transmit-only | Top expansion header |
| Wardriving GPS coordinates | M5Stack GNSS/LoRa cap (onboard GPS), or a Grove-port GPS module (AT6668/ATGM336H-class NMEA) | Expansion header, or Grove port (UART) |
| RFID Audit | MFRC522 NFC/RFID reader (13.56 MHz, I2C) | Grove port (I2C) |
| BadUSB / Mouse Jiggler | none — native USB-OTG | Cardputer only (no external module) |
[!IMPORTANT]
GPS source, and the RFID conflict. GPS works either from the M5Stack GNSS/LoRa cap
(its onboard GPS — the cap's LoRa radio itself is not supported) or from a Grove-port GPS
module; the cap path takes priority when both are present. Either way, when a GPS module is
detected the RFID reader is disabled for that detection pass — and a Grove-port GPS
additionally shares the reader's Grove pins (G1/G2). Modules attached after boot are picked up
by the Modules → Re-scan action (no reboot needed); seat them while the radio bus is idle.
Everything else — WiFi, BLE, IR TV-B-Gone (built-in emitter), HID, Server — needs no
external hardware.
Installation
The fastest path is the web flasher — flash
from the browser, no tools. Or download a prebuilt release and flash it yourself.
Building from source (Option C) is only needed for development or an unreleased change.
Option A — One-click web flasher (Cardputer)
Open the web flasher in desktop Chrome, Edge,
or Opera, connect the Cardputer over USB-C, and click Connect & Flash. It writes the
latest release's factory image over Web Serial — no PlatformIO, no esptool, no clone.
[!NOTE]
Web Serial is Chromium-only (Chrome/Edge/Opera on desktop). On Firefox, Safari, or
mobile, use Option B or C.
Option B — Flash a prebuilt release (Cardputer)
Every version tag publishes ready-to-flash binaries on the
Releases page. Download the assets for
the latest tag:
| Asset | Use it for |
|-------|-----------|
| adversary-cardputer-<tag>-factory.bin | A fresh flash of a blank or bricked device — a complete image (bootloader + partitions + app) written to offset 0x0. Use with an ESP web flasher, M5Burner (search the catalog, or add as "User Custom"), or esptool. |
| adversary-cardputer-<tag>-app.bin | An over-the-air, app-only install from M5Launcher (bmorcelli) via a direct URL — writes just the app to the OTA slot. |
| SHA256SUMS.txt | Verify the download before flashing: sha256sum -c SHA256SUMS.txt. |
With esptool (factory image, ESP32-S3):
esptool --chip esp32s3 write-flash 0x0 adversary-cardputer-<tag>-factory.bin
With M5Burner: search for Adversary in the
M5Burner catalog and burn it directly — no manual file
handling. (Or add the -factory.bin as a User Custom firmware, the pre-catalog path.)
With M5Launcher: point it at the -app.bin release URL to install over OTA.
[!NOTE]
Prebuilt binaries are published for the Cardputer only. For the M5StickC Plus2, build
from source (Option C).
Option C — Build from source
Prerequisites
- PlatformIO (VS Code extension or CLI)
- USB-C cable
- SD Card (FAT32 formatted)
Build & Flash
# Clone the repository
git clone https://github.com/Isonimus/adversary.git
cd adversary
# Build for Cardputer
pio run -e cardputer
# Flash to device
pio run -e cardputer -t upload
# Monitor serial output (optional)
pio device monitor -b 115200
For M5StickC Plus2
pio run -e m5stick -t upload
First Boot
- Insert FAT32-formatted SD card
- Power on device
- Wait for splash screen initialization
- Settings will be created automatically at
/adversary/config/settings.json
Usage
Navigation
- ESC (
` key): Access menu / Cancel operation / Back
- ENTER: Select / Confirm
- ↑/↓ or ;/.: Navigate lists
- Number keys (1-9): Quick menu selection
- Fn + S: Screenshot — saves the current screen as a BMP to
/adversary/screenshots/ (any screen)
Tutorial: capture your first handshake
Only test networks you own or are explicitly authorized to assess. See the DISCLAIMER.
End to end, from a blank card to a crackable capture:
- Prep the card. Insert a FAT32-formatted SD card and power on. The device creates
/adversary/ on first boot.
- (Optional, for cloud cracking) Add a WPA-SEC key. Register at
wpa-sec.stanev.org, then either type the key in
Settings → WPA-SEC API Key, or drop it as
/adversary/config/wpasec.txt on the card
(imported and deleted on next boot).
- Find a target. From the main carousel open Wireless → Scan Networks. Scroll with
; / .; press s to sort by signal.
- Start the capture. Press
ENTER on your target → Handshake. Enable Auto Deauth
(kicks a client so it reconnects and completes the 4-way handshake), then ENTER to start.
- Wait for success. The screen shows progress and reports SUCCESS on a complete capture
(or TIMEOUT — move closer or raise the timeout and retry). The handshake auto-saves to
/adversary/captures/handshakes/ as both .pcap and hashcat .22000.
- Hands-off alternative: toggle Auto Hunt to scan, target, and capture across many
networks autonomously; press
h to view captures, w to whitelist one.
- Check and crack. Open Wireless → Captures. A
[4WAY] / [PMKID] / [EAPOL] badge
shows the type; a coloured dot shows cloud status (red = not uploaded, orange = uploaded,
green = cracked). Press "Sync all new" to upload to every configured service.
- (Handy) Press Fn + S at any point to save a screenshot to
/adversary/screenshots/.
That's the core loop: scan → handshake → sync → crack.
Menu Structure
The main screen is a carousel; press ENTER on a section to open its submenu.
Main Carousel
├── Wireless
│ ├── Scan Networks - WiFi reconnaissance
│ ├── Packet Sniffer - Raw frame capture
│ ├── Deauth Attack - Client disconnection
│ ├── Beacon Spam - Fake network flooding
│ ├── Probe Flood - Probe request saturation
│ ├── Handshake Capture - WPA handshake acquisition (Manual / Auto Hunt / Clientless PMKID)
│ ├── Evil Twin - Rogue AP + credential capture
│ ├── Karma AP - Probe request auto-response
│ ├── Wardriving - GPS network mapping (requires GPS module)
│ ├── Captures - View/manage Handshakes/Packets/Credentials
│ └── Whitelist - Auto Hunt exclusions
├── BLE
│ ├── BLE Scanner - Peripheral discovery
│ ├── Apple Attack - Proximity-pairing popup spam
│ ├── BadBLE (HID) - BLE keyboard emulation + DuckyScript
│ ├── Identity Spoof - BLE address/identity spoofing
│ └── BLE Spam - Pairing notification flooding
├── Infrared
│ ├── TV-B-Gone - Universal IR power-off blast
│ └── Record / Replay - Learn & replay an IR remote (requires cap IR RX)
├── RFID
│ └── RFID Dashboard - NFC/RFID read, audit & write/clone (requires MFRC522 I2C reader)
├── HID
│ ├── BadUSB (HID) - USB keystroke injection (Cardputer only)
│ └── Mouse Jiggler - Anti-idle-lock mouse movement (Cardputer only)
├── Radio - Sub-GHz OOK capture/replay + 2.4 GHz analyzer (requires multi-radio cap)
├── Server - Web dashboard (served from SD card)
├── Settings - Configuration options
└── About
Screen-by-Screen Guide
Scanner
- Navigate:
;/. to scroll through networks
- Sort:
s key to cycle (Signal → Channel → SSID)
- Select:
ENTER for action menu
- Actions: Deauth, Handshake, Evil Twin, Probe Flood, Info
- Exit:
` (ESC) to return to menu
Handshake Capture
Reached from Wireless -> Handshake, which offers three modes:
Manual Capture (single target):
- Select a target from the scanner (the Target row opens the scanner, or launch
Handshake straight from a scanned network)
- Set options: Auto Deauth, Deauth Count, Timeout
- Navigate to START CAPTURE and press
ENTER
- Wait for SUCCESS or TIMEOUT
- Handshake auto-saves to SD card
Auto Hunt (autonomous, multi-target):
- Open Wireless -> Handshake -> Auto Hunt
- Press
ENTER to start autonomous hunting
- Device scans, targets, and captures automatically
- Press
` to stop at any time
- Press
h to view the handshake list during the hunt
- Press
w to whitelist the current target
The capture strategy (Deauth / PMKID / Both) is set on the Auto Hunt config form: PMKID
and Both can solicit client-less APs that a deauth-only pass cannot reach.
Clientless PMKID (no connected client required):
- Launch Clientless PMKID from the scanner's action menu on a chosen AP
- The device injects an association to solicit the AP's PMKID directly, with no deauth
- Works against an AP that has no associated clients
- A solicited PMKID saves and uploads (pwncrack) like any other capture
Handshake List (during Auto Hunt):
- Press
h to enter list view
- Navigate with
;/. keys
- Press
d to delete selected handshake
- Confirm with
y or cancel with n
- Type badges show:
[4WAY], [PMKID], or [EAPOL]
- Press
` to return to hunt
Captures Browser
- Navigate categories: Handshakes / Packets / Credentials
- Browse files:
;/. to scroll
- Type badges: Visual indicators for handshake types
- WPA-SEC status: Colored dots (Red=Not uploaded, Orange=Uploaded, Green=Cracked)
- View details:
ENTER on file
- Delete:
d key (with confirmation)
Settings
- WiFi Configuration: Connect device to internet for WPA-SEC
- WPA-SEC API Key: Enter your API key for cloud cracking
- Theme Selection: Choose color scheme
- Auto Hunt Options: Configure autonomous capture behavior
- Whitelist Management: View/edit excluded networks
- System Info: Firmware version, storage, battery
Cracking Service API Keys (WPA-SEC / pwncrack / WiGLE)
Each cloud service (WPA-SEC handshake cracking, pwncrack.org handshake
cracking, WiGLE wardriving upload) needs its own API key, set up either way:
-
On-device entry — Settings → tap the service's key field (shows
"Not Set" until configured) → type the key on the physical keyboard.
-
SD-card auto-import (no typing required) — register for the service,
then drop a plain-text file containing just the key at:
/adversary/config/wpasec.txt
/adversary/config/pwncrack.txt
/adversary/config/wigle.txt
On the next boot the device imports the key into settings.json and
deletes the file (so a plaintext key doesn't linger on the card).
Registration:
Once a key is set, Captures → "Sync all new" uploads every not-yet-synced
handshake to every service that has a key configured, and status (per
capture, per service) shows as colored dots in the Captures screen.
SD Card Structure
/adversary/
├── config/
│ ├── settings.json - User preferences (incl. imported API keys)
│ ├── whitelist.json - Auto Hunt exclusions
│ ├── wpasec.txt - (optional, one-time) WPA-SEC key import
│ ├── pwncrack.txt - (optional, one-time) pwncrack key import
│ └── wigle.txt - (optional, one-time) WiGLE key import
├── badusb/
│ └── *.txt - Custom DuckyScript files (BadUSB/BadBLE)
├── captures/
│ ├── handshakes/
│ │ └── *.pcap, *.22000 - Captured handshakes (pcap + hashcat format)
│ ├── packets/
│ │ └── *.pcap - Raw packet captures
│ └── credentials/
│ └── *.json - Evil Twin credentials
├── dashboard/
│ └── index.html, ... - Web dashboard (Server mode); deploy with
│ scripts/deploy_dashboard.sh (see Development)
├── screenshots/
│ └── shot_NNN.bmp - Screen captures (Fn + S)
└── logs/
└── system.log - Debug/activity logs
FAQ
Q: What's the difference between Auto Hunt and Manual mode?
A: Manual mode targets a single network until success/timeout. Auto Hunt autonomously scans, selects targets, captures handshakes, and moves to the next target indefinitely.
Q: How do I use WPA-SEC integration?
A: Register at wpa-sec.stanev.org, then either type your API key into Settings on-device, or drop it as a text file at /adversary/config/wpasec.txt on the SD card — the device imports it on next boot and deletes the file. See Cracking Service API Keys above.
Q: What do the type badges mean (4WAY/PMKID/EAPOL)?
A: [4WAY] = Complete 4-way handshake (most reliable), [EAPOL] = Partial handshake (2-3 messages, still crackable), [PMKID] = PMKID-based capture (efficient, WPA2 only).
Q: How do I add networks to the whitelist?
A: During Auto Hunt, press w on any target to whitelist it. Or manage manually in Settings → Whitelist Management.
Q: What's the difference between Karma AP and Evil Twin?
A: Karma responds to ANY probe request (useful for reconnaissance). Evil Twin impersonates a SPECIFIC network to capture credentials via captive portal.
Q: Why isn't my handshake cracking?
A: Ensure it's a [4WAY] or [EAPOL] type. Check WPA-SEC upload status in Captures screen. Weak passwords may take time; dictionary quality matters.
Troubleshooting
SD Card Not Recognized
- Ensure FAT32 format (not exFAT or NTFS)
- Try a different/smaller card (8-32GB recommended)
- Check for physical damage to card or slot
SD Card Works on Direct USB Flash but Not via M5Launcher
Some cards — more often larger ones (16GB+) — mount fine when you flash The Adversary
directly over USB, yet fail every time the firmware is launched from M5Launcher. This is a
card quirk, not a firmware bug. M5Launcher hands control over with a warm reset, and the
Cardputer ADV has no way to power-cycle the SD card's power rail across that reset; some
cards latch into a state where they report as present but refuse to re-initialize until
they get a genuine power cycle. A direct USB flash works because that is a cold power-on.
Fixes, easiest first:
- Reseat the card — physically remove and reinsert it (its only power cycle), then boot.
- Flash The Adversary directly over USB onto that card instead of launching via M5Launcher.
- Use a card that tolerates the warm reset — in testing an 8GB card mounted first try where a 16GB did not.
Handshake Capture Failures
- Verify target is WPA/WPA2 (not WPA3-only or Open)
- Enable Auto Deauth if no clients reconnecting
- Increase timeout if network has few clients
- Check signal strength (closer to AP helps)
WPA-SEC API Issues
- Verify API key is correct (check for typos)
- Ensure WiFi is connected for uploads
- Check internet connectivity
- Per-capture upload/crack status lives in
/adversary/captures/handshakes/manifest.bin; if status looks wrong, Settings → Rebuild Index resyncs it against the files on the card
Theme Not Persisting
- SD card may be full or corrupted
- Settings file may have write errors
- Check
/adversary/config/settings.json exists
Serial Output for Debugging
pio device monitor -b 115200
Look for error messages, crash logs, or module initialization failures.
Development
Project Structure
/adversary
├── src/
│ ├── config/ - Configuration headers
│ ├── core/ - State machine, events
│ ├── hal/ - Hardware abstraction
│ ├── modules/ - Feature modules
│ │ ├── attack/ - Attack implementations
│ │ ├── capture/ - Handshake capture logic
│ │ ├── network/ - WPA-SEC, WiFi connection
│ │ ├── pcap/ - PCAP file generation
│ │ ├── sniffer/ - Packet capture
│ │ └── storage/ - Settings, registry
│ ├── ui/ - User interface
│ │ ├── screens/ - Screen implementations
│ │ ├── components/ - Reusable UI components
│ │ └── theme.h - Color schemes
│ └── utils/ - Utility functions
├── test/ - Unit tests
│ ├── common/ - Test mocks (Arduino, ESP32)
│ └── test_*/ - Individual test suites
├── adr/ - Architecture decision records
└── slices/ - Feature slice specs (decision records)
Running Tests
# Run all native tests
pio test -e native
# Run specific test
pio test -e native -f test_handshake_capture
# View test coverage
pio test -e native --verbose
Deploying the dashboard
The web dashboard is served directly off the SD card from /adversary/dashboard/.
Its source lives in dashboard_dev/, and nothing syncs the two automatically —
editing dashboard_dev/ has no effect on the device until the files are copied
onto the card. Pop the SD into a card reader and run:
# <sd_mount_path> is where the card is mounted, e.g. /media/$USER/CARDPUTER
scripts/deploy_dashboard.sh <sd_mount_path>
The script copies every asset, verifies each file's size on the card matches the
source (a truncated or 0-byte write renders as a blank dashboard), and flushes
the card before reporting success.
Code Standards
- Language: C++17
- Framework: Arduino (ESP32)
- Build System: PlatformIO
- Testing: Unity test framework
- Style: See
CLAUDE.md for guidelines
Contributing
See CONTRIBUTING.md for setup, coding standards, and the PR
workflow, and CODE_OF_CONDUCT.md for community expectations.
Community
Documentation
- CLAUDE.md - Architecture and development guidelines
- CONTRIBUTING.md - How to build, test, and submit changes
- SECURITY.md - How to report a firmware vulnerability
- CHANGELOG.md - Notable shipped changes (historical)
- adr/ & slices/ - Architecture decisions and feature slices (decision records)
License
This project is licensed under the MIT License - see LICENSE for details.
Acknowledgments
- Inspired by ESP32 WiFi security research community
- M5Stack for excellent hardware platforms
- WPA-SEC for handshake cracking infrastructure
- ESP32 and Arduino communities