A sophisticated WiFi auditing library for ESP32 microcontrollers

Politician is an embedded C++ library designed for WiFi security auditing on ESP32 platforms. It provides a clean, modern API for capturing WPA/WPA2/WPA3 handshakes and harvesting enterprise credentials using advanced 802.11 protocol techniques.
📚 Full API Documentation
Key Capabilities
- PMKID Capture: Extract PMKIDs from association responses without client disconnection
- CSA (Channel Switch Announcement) Injection: Modern alternative to deauthentication attacks
- Enterprise Credential Harvesting: Capture EAP-Identity frames from 802.1X networks
- Hidden Network Discovery: Automatic SSID decloaking via probe response interception
- Client Stimulation: Wake sleeping mobile devices using QoS Null Data frames
- WPA3/PMF Detection: Intelligent filtering to skip Protected Management Frame-enabled networks
- Export Formats: PCAPNG and Hashcat HC22000 output support
Architecture
The library is built around a non-blocking state machine that manages channel hopping, target selection, attack execution, and capture processing. All operations are contained within the politician namespace.
Core Components
| Component | Description |
Politician | Main engine class managing the audit lifecycle |
PoliticianFormat | PCAPNG and Hashcat export utilities |
PoliticianStorage | Optional SD card logging and NVS persistence |
PoliticianTypes | Core data structures and enumerations |
Attack Modes
Traditional deauthentication attacks are ineffective against modern WPA3 and WPA2 networks with Protected Management Frames (PMF/802.11w). Politician implements modern alternatives:
| Mode | Description | Effectiveness |
ATTACK_PMKID | Extract PMKID via dummy authentication | Works on all WPA2/WPA3-Transition |
ATTACK_CSA | Channel Switch Announcement injection | Bypasses PMF protections |
ATTACK_DEAUTH | Legacy deauthentication (Reason 7) | WPA2 without PMF only |
ATTACK_STIMULATE | QoS Null Data for sleeping clients | Non-intrusive client wake-up |
ATTACK_PASSIVE | Listen-only mode | Zero transmission |
ATTACK_ALL | Enable all active attack vectors | Maximum aggression |
Installation
PlatformIO
Add to your platformio.ini:
[env:myboard]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
Politician
Or clone directly into your project's lib/ directory:
cd lib/
git clone https://github.com/0ldev/Politician.git
Arduino IDE
- Download the library as a ZIP file
- In Arduino IDE: Sketch → Include Library → Add .ZIP Library
- Select the downloaded ZIP file
Quick Start
Basic Handshake Capture
#include <Arduino.h>
Serial.printf(
"\n[✓] Captured handshake: %s\n", rec.
ssid);
Serial.printf("HC22000: %s\n", toHC22000(rec).c_str());
}
}
}
#define LOG_FILTER_HANDSHAKES
#define LOG_FILTER_PROBES
The core WiFi handshake capturing engine.
Error begin(const Config &cfg=Config())
Initializes the WiFi driver in promiscuous mode.
void onHandshake(const HandshakeRecord &rec)
Configuration for the Politician engine.
API Reference
Politician Class
The main engine class. Must call tick() in your main loop.
Initialization
Initialize the engine with configuration options.
Configuration Structure
uint16_t hop_dwell_ms;
uint8_t hop_interval;
uint8_t attack_retries;
uint16_t pmkid_timeout_ms;
bool capture_half_handshakes;
uint8_t capture_filter;
};
Callbacks
void setEapolCallback(EapolCb callback);
void setIdentityCallback(IdentityCb callback);
void setApCallback(ApCb callback);
void setTargetFilter(TargetFilterCb filter);
void setPacketLogger(PacketCb logger);
Attack Control
void setAttackMask(uint8_t mask);
void addIgnoreBssid(const uint8_t* bssid);
Attack Mode Constants
#define ATTACK_PASSIVE 0x00
#define ATTACK_PMKID 0x01
#define ATTACK_CSA 0x02
#define ATTACK_DEAUTH 0x04
#define ATTACK_STIMULATE 0x08
#define ATTACK_ALL 0xFF
Capture Filter Constants
#define LOG_FILTER_NONE 0x00
#define LOG_FILTER_HANDSHAKES 0x01
#define LOG_FILTER_PROBES 0x02
#define LOG_FILTER_BEACONS 0x04
#define LOG_FILTER_ALL 0xFF
Data Structures
HandshakeRecord
uint8_t bssid[6];
uint8_t client[6];
char ssid[33];
uint8_t enc;
uint8_t channel;
int8_t rssi;
uint8_t eapol_m1[256];
uint8_t eapol_m2[256];
uint16_t m1_len;
uint16_t m2_len;
bool is_complete;
};
IdentityRecord
struct IdentityRecord {
uint8_t bssid[6];
uint8_t client[6];
char ssid[33];
char identity[128];
int8_t rssi;
};
ApRecord
uint8_t bssid[6];
char ssid[33];
uint8_t enc;
uint8_t channel;
int8_t rssi;
bool pmf_required;
};
Format Utilities
Storage Utilities (Optional)
Requires #include <PoliticianStorage.h>.
PcapngFileLogger::append(fs::FS& fs, const char* path,
PcapngFileLogger::appendPacket(fs::FS& fs, const char* path,
const uint8_t* payload, uint16_t len,
int8_t rssi, uint32_t timestamp);
WigleCsvLogger::append(fs::FS& fs, const char* path,
const ApRecord& ap,
float lat,
float lon);
EnterpriseCsvLogger::append(fs::FS& fs, const char* path,
const IdentityRecord& rec);
Usage Examples
Targeted Network Auditing
Use callbacks to filter networks by signal strength, encryption type, or SSID pattern:
if (ap.
rssi < -70)
return false;
if (ap.
enc < 3)
return false;
if (strstr(ap.
ssid,
"CORP-") !=
nullptr)
return false;
return true;
});
Selective Attack Modes
Custom Channel Selection (Optional)
By default, the library hops through all standard channels. You can optionally restrict to specific channels:
const uint8_t channels_24[] = {1, 6, 11};
engine.setChannelList(channels_24, 3);
const uint8_t channels_5ghz[] = {36, 40, 44, 48, 149, 153, 157, 161, 165};
engine.setChannelList(channels_5ghz, 9);
const uint8_t channels_dual[] = {1, 6, 11, 36, 40, 44, 149, 153, 157};
engine.setChannelList(channels_dual, 9);
engine.setChannelList(
nullptr, 0);
Enterprise Credential Harvesting
void onIdentity(const IdentityRecord &rec) {
Serial.printf("[802.1X] %s → %s\n", rec.ssid, rec.identity);
EnterpriseCsvLogger::append(SD, "/identities.csv", rec);
}
engine.setIdentityCallback(onIdentity);
cfg.hop_dwell_ms = 800;
}
Persistent Storage
The core library is decoupled from filesystem dependencies. Optionally include PoliticianStorage.h for SD card logging:
#include <SD.h>
PcapngFileLogger::append(SD, "/captures.pcapng", rec);
}
void onPacket(const uint8_t* payload, uint16_t len, int8_t rssi, uint32_t ts) {
PcapngFileLogger::appendPacket(SD, "/intel.pcapng", payload, len, rssi, ts);
}
SD.begin();
engine.setPacketLogger(onPacket);
}
⚠️ Logging Performance Warning
Beacon logging (LOG_FILTER_BEACONS) can generate 500+ writes/second. Standard SPI SD card writes are blocking and will freeze the engine. For high-volume logging, use ESP32 boards with native SDMMC (4-bit) hardware support and DMA.
GPS Integration (Wigle.net)
Combine with a GPS module for wardriving datasets:
#include <TinyGPS++.h>
TinyGPSPlus gps;
if (gps.location.isValid()) {
WigleCsvLogger::append(SD, "/wardrive.csv", ap,
gps.location.lat(),
gps.location.lng());
}
}
Advanced Features
Half-Handshakes and Smart Pivot
When cfg.capture_half_handshakes = true, the engine saves M2-only frames (incomplete handshakes). These can still be cracked by modern tools like Hashcat.
When an M2-only handshake is captured, the engine automatically executes a Smart Pivot:
- Marks the network as a "Hot Target" with active clients
- Immediately launches CSA/Deauth attacks on the client
- Captures the complete 4-way handshake on reconnection
Hidden Network Discovery
Probe Response frames triggered by deauth bursts automatically reveal hidden SSIDs. The engine caches these with zero configuration required.
PMF/WPA3 Detection
RSNE (Robust Security Network Element) parsing automatically identifies networks with PMF Required. These are skipped to save time, but WPA3 Transition Mode networks (PMF Capable but not Required) are still targeted.
Examples
The library includes complete examples demonstrating various use cases:
| Example | Description |
ExportFormats | HC22000 and PCAPNG format conversion |
TargetedAuditing | Network filtering with callbacks |
EnterpriseAuditing | 802.1X identity harvesting |
StorageAndNVS | SD card PCAPNG logging and NVS persistence |
WigleIntegration | GPS wardriving with Wigle CSV export |
DynamicControl | Runtime attack mode switching |
AutoEnterpriseHunter | Automatic enterprise network targeting |
SerialStreaming | Real-time packet streaming over USB |
StressTest | Performance and memory testing |
See the examples/ directory for complete source code.
Documentation
Full API documentation is automatically generated and published to GitHub Pages.
The documentation includes:
- Complete API reference for all classes and methods
- Data structure specifications
- Usage examples and code snippets
- Architecture overview
To generate documentation locally:
Then open docs/html/index.html in your browser.
Hardware Requirements
- Platform: ESP32, ESP32-S2, ESP32-S3, ESP32-C3 (2.4GHz), ESP32-C6 (2.4GHz + 5GHz)
- Framework: Arduino or ESP-IDF
- Memory: Minimum 4MB flash recommended
- WiFi Bands:
- All ESP32 variants: 2.4GHz (channels 1-14)
- ESP32-C6: Also supports 5GHz (channels 36-165)
- Optional: SD card module for persistent logging
- Optional: GPS module for Wigle integration
5GHz Support
On ESP32-C6, the library automatically supports 5GHz bands - no code changes required. All capture techniques (PMKID, handshakes, enterprise identities) work identically on both 2.4GHz and 5GHz.
Note: Not all 5GHz channels are legal worldwide. DFS channels (52-144) may have regulatory restrictions in your region.
Performance Considerations
- Channel Hopping: Default 300ms dwell time balances discovery speed vs. capture reliability
- Memory: Core engine uses ~45KB RAM. Storage helpers are opt-in
- CPU: Non-blocking state machine keeps
loop() responsive
- Half-Handshakes: Enable for better capture rate on fast-hopping scenarios
Troubleshooting
No handshakes captured:
- Verify WiFi is enabled and promiscuous mode works
- Increase
hop_dwell_ms for slow-reconnecting devices
- Check if target networks use PMF Required (will be auto-skipped)
- Try
ATTACK_ALL mask for maximum aggression
SD card writes fail:
- Ensure SD.begin() succeeds before logging
- Check file permissions and available space
- Disable
LOG_FILTER_BEACONS if using SPI SD cards
Enterprise identities not captured:
- Increase
hop_dwell_ms to 800-1200ms for EAP exchanges
- Use
ATTACK_PASSIVE or ATTACK_STIMULATE only
- Aggressive attacks may interrupt EAP authentication
Legal & Ethical Use
This library is intended for:
- ✅ Authorized penetration testing
- ✅ Security research in controlled environments
- ✅ Educational purposes with permission
- ✅ Auditing your own networks
Unauthorized access to networks you do not own or have permission to test is illegal under laws such as the Computer Fraud and Abuse Act (CFAA) in the United States and similar legislation worldwide.
The authors and contributors assume no liability for misuse of this software.
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests/examples for new features
- Submit a pull request
License
MIT License - see [LICENSE](LICENSE) for details.
Acknowledgments
Special thanks to justcallmekoko for inspiring this project and the broader hardware hacking community through the ESP32 Marauder project. Years of learning from Marauder's innovative approaches to WiFi security research have been invaluable.
Built on ESP32 WiFi driver capabilities and inspired by modern WiFi security research and responsible disclosure practices.