
Modern WiFi auditing library for ESP32 using advanced 802.11 techniques. Captures WPA/WPA2/WPA3 handshakes via PMKID extraction and CSA injection (bypasses PMF). Harvests enterprise credentials, supports dual-band (2.4GHz/5GHz on ESP32-C6), exports to PCAPNG/Hashcat. Clean C++ API with 9 examples.
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.
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.
| Component | Description |
|---|---|
Politician | Main engine class managing the audit lifecycle |
PoliticianFormat | PCAPNG capture serialization; auxiliary HC22000 text export |
PoliticianStorage | Optional SD card logging and NVS persistence |
PoliticianStress | Decoupled DoS/disruption payload delivery (opt-in) |
PoliticianTypes | Core data structures and enumerations |
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 |
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
Clone the repository into your project's components/ directory:
cd components/
git clone https://github.com/0ldev/Politician.git
Create a components/Politician/CMakeLists.txt component descriptor:
idf_component_register(
SRCS
"src/Politician.cpp"
"src/PoliticianFormat.cpp"
"src/PoliticianStress.cpp"
INCLUDE_DIRS "src"
)
PoliticianStorage.h is not available under ESP-IDF — it emits a #error at compile time if included outside Arduino. Use ESP-IDF's VFS and nvs_flash APIs directly for any persistence you need.
#include <Arduino.h>
#include <SD.h>
#include <Politician.h>
#include <PoliticianStorage.h>
using namespace politician;
using namespace politician::storage;
Politician engine;
void onHandshake(const HandshakeRecord &rec) {
Serial.printf("\n[✓] Captured: %s ch%d rssi=%d type=%d\n",
rec.ssid, rec.channel, rec.rssi, rec.type);
// Primary output: PCAPNG — open in Wireshark or convert with hcxpcapngtool
PcapngFileLogger::append(SD, "/captures.pcapng", rec);
}
void setup() {
Serial.begin(115200);
SD.begin();
engine.setEapolCallback(onHandshake);
Config cfg;
engine.begin(cfg);
engine.setAttackMask(ATTACK_ALL);
}
void loop() {
engine.tick();
}
Under ESP-IDF, begin() calls esp_wifi_init() internally but expects NVS and the default event loop to already be initialized. Call those before begin(), then drive the engine from a FreeRTOS task.
#include <nvs_flash.h>
#include <esp_event.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <Politician.h>
using namespace politician;
static Politician engine;
static void on_handshake(const HandshakeRecord &rec) {
printf("[+] Captured: %s ch%d rssi=%d type=%d\n",
rec.ssid, rec.channel, rec.rssi, rec.type);
}
static void audit_task(void *) {
Config cfg;
engine.setEapolCallback(on_handshake);
if (engine.begin(cfg) != OK) {
printf("[!] WiFi init failed\n");
vTaskDelete(nullptr);
return;
}
engine.setAttackMask(ATTACK_ALL);
for (;;) {
engine.tick();
vTaskDelay(pdMS_TO_TICKS(1));
}
}
extern "C" void app_main(void) {
nvs_flash_init();
esp_event_loop_create_default();
xTaskCreate(audit_task, "politician", 8192, nullptr, 5, nullptr);
}
The main engine class. Must call tick() in your main loop.
Error begin(const Config& cfg = Config());
Initialize the engine. Returns OK on success or an Error code on failure. Must be called before any other method.