Politician 1.0.0
WiFi Auditing Library for ESP32
Loading...
Searching...
No Matches
PoliticianTypes.h
Go to the documentation of this file.
1#pragma once
2#include <stdint.h>
3#include "politician_compat.h"
4
5#ifndef POLITICIAN_NO_STD_FUNCTION
6#include <functional>
7#endif
8
9namespace politician {
10
11// ─── Compile-Time Feature Gates ──────────────────────────────────────────────
12// Define these before including Politician.h or via build flags (e.g. -DNAME)
13// #define POLITICIAN_NO_DB // Strip 14KB OUI Database (Vendor lookups)
14// #define POLITICIAN_NO_PCAPNG // Strip PCAPNG serialization logic
15// #define POLITICIAN_NO_HC22000 // Strip Hashcat mode 22000 formatter
16// #define POLITICIAN_NO_LOGGING // Strip all internal Serial _log() output
17// #define POLITICIAN_NO_STD_FUNCTION // Use raw fn pointers instead of std::function (saves ~2KB, no lambda captures)
18
19// ─── Capture Types ────────────────────────────────────────────────────────────
20#define CAP_PMKID 0x01 // PMKID fishing (fake association)
21#define CAP_EAPOL 0x02 // Passive EAPOL (natural client reconnection)
22#define CAP_EAPOL_CSA 0x03 // EAPOL triggered by CSA beacon injection
23#define CAP_EAPOL_HALF 0x04 // M2-only capture (no anonce) — active attack pivot triggered
24#define CAP_EAPOL_GROUP 0x05 // Non-pairwise EAPOL-Key (GTK rotation)
25#define CAP_SAE 0x06 // WPA3 SAE (Simultaneous Authentication of Equals) Commit/Confirm frame
26
27// ─── Attack Selection Bits ────────────────────────────────────────────────────
28#define ATTACK_PMKID 0x01 // PMKID fishing
29#define ATTACK_CSA 0x02 // CSA beacon injection
30#define ATTACK_PASSIVE 0x04 // Passive EAPOL capture
31#define ATTACK_DEAUTH 0x08 // Classic Reason 7 Deauthentication
32#define ATTACK_STIMULATE 0x10 // Zero-delay QoS Null Client Stimulation
33#define ATTACK_ALL 0x1F
34
35// ─── Capture Filters ──────────────────────────────────────────────────────────
36// NOTE: Logging High-Frequency Intel (like Beacons) via standard SPI (SD.h) will
37// create massive blocking delays (20-50ms per flush) that destroy the hopper's
38// attack loop. If you enable LOG_FILTER_BEACONS or LOG_FILTER_ALL, you MUST
39// use a board wired for SDMMC (4-bit DMA) for non-blocking background writes.
40#define LOG_FILTER_HANDSHAKES 0x01 // EAPOLs, PMKIDs (Crackable info, SPI Safe)
41#define LOG_FILTER_PROBES 0x02 // Probe Requests & Responses (Scouting, SPI Safe)
42#define LOG_FILTER_BEACONS 0x04 // Beacons (Network Mapping, SDMMC ONLY!)
43#define LOG_FILTER_PROBE_REQ 0x08 // Probe Requests as raw EPBs (Client Device History, SPI Safe)
44#define LOG_FILTER_MGMT_DISRUPT 0x10 // Deauth/Disassoc frames as raw EPBs (Attack Detection, SPI Safe)
45#define LOG_FILTER_ALL 0xFF // Everything (SDMMC ONLY!)
46
47// ─── Logging Callback ─────────────────────────────────────────────────────────
48#ifndef POLITICIAN_NO_STD_FUNCTION
49using LogCb = std::function<void(const char *msg)>;
50#else
51typedef void (*LogCb)(const char *msg);
52#endif
53
54// ─── Callbacks ────────────────────────────────────────────────────────────────
55struct ApRecord;
56struct HandshakeRecord;
59struct DisruptRecord;
60
61typedef void (*ApFoundCb)(const ApRecord &ap);
62typedef int (*TargetScoreCb)(const ApRecord &ap, const char *vendor); // Returns a priority score for autoTarget
63typedef void (*PacketCb)(const uint8_t *payload, uint16_t len, int8_t rssi, uint8_t channel, uint32_t ts_usec);
64typedef void (*EapolCb)(const HandshakeRecord &rec);
65typedef void (*IdentityCb)(const EapIdentityRecord &rec);
66typedef void (*ProbeRequestCb)(const ProbeRequestRecord &rec);
67typedef void (*DisruptCb)(const DisruptRecord &rec);
68
69// ─── Error Codes ──────────────────────────────────────────────────────────────
78
79/**
80 * @brief Configuration for the Politician engine.
81 */
82struct Config {
83 uint16_t hop_dwell_ms = 200; // Time per channel
84 bool smart_hopping = true; // Dynamic channel dwell time based on traffic
85 uint16_t hop_min_dwell_ms = 50; // Minimum dwell if no traffic is seen
86 uint16_t hop_max_dwell_ms = 400; // Maximum dwell if traffic is active
87 uint32_t m1_lock_ms = 800; // How long to stay on channel after seeing M1
88 uint32_t fish_timeout_ms = 2000; // Time for PMKID association
89 uint8_t fish_max_retries = 2; // PMKID retries before giving up or CSA
90 uint32_t csa_wait_ms = 4000; // How long to wait for reconnect after CSA
91 uint8_t csa_beacon_count = 8; // Number of CSA beacons to burst
92 uint8_t deauth_burst_count = 16; // Number of classic Deauth frames to send
93 uint16_t probe_aggr_interval_s = 30; // Seconds to wait between attacking same AP
94 uint32_t session_timeout_ms = 60000; // How long orphaned handshakes live in RAM
95 bool capture_half_handshakes = false; // Save M2-only captures and pivot to active attack
96 bool skip_immune_networks = true; // Ignore Pure WPA3 / PMF Required networks
97 uint8_t csa_deauth_count = 15; // Number of standard deauths to append
98 uint8_t capture_filter = LOG_FILTER_HANDSHAKES | LOG_FILTER_PROBES; // Exclude Beacons by default to save SD storage
99 int8_t min_rssi = -100; // Ignore APs with signal weaker than this (dBm)
100 uint32_t ap_expiry_ms = 300000; // Evict APs not seen for this long (0 = never expire)
101 bool unicast_deauth = true; // Send deauth to known client MAC instead of broadcast
102 uint32_t probe_hidden_interval_ms = 0; // How often to probe hidden APs for SSID (0 = disabled, opt-in)
103 uint8_t deauth_reason = 7; // 802.11 reason code for deauth frames (7=Class 3 from non-assoc)
104 bool deauth_reason_cycling = true; // Cycle through effective reason codes during burst (fuzzing)
105 bool capture_group_keys = false; // Fire eapolCb with CAP_EAPOL_GROUP on GTK rotation frames
106 uint8_t min_beacon_count = 0; // Min times AP must be seen before attack/apFoundCb (0 = no minimum)
107 uint8_t max_total_attempts = 0; // Permanently skip BSSID after this many failed attacks (0 = unlimited)
108 uint8_t sta_filter[6] = {}; // Only record EAPOL sessions from this client MAC (zero = no filter)
109 char ssid_filter[33] = {}; // Only cache APs matching this SSID (empty = no filter)
110 bool ssid_filter_exact = true; // True = exact SSID match, false = substring match
111 uint8_t enc_filter_mask = 0xFF; // Bitmask of enc types to cache: bit0=open,1=WEP,2=WPA,3=WPA2/3,4=Ent
112 bool require_active_clients = false; // Skip attack initiation if no active clients seen on AP
113 const char* soft_ap_ssid = nullptr; // Custom SSID for the engine's soft AP (nullptr = use default hidden AP)
114};
115
116// ─── AP Record ────────────────────────────────────────────────────────────────
117/** @brief Snapshot of a discovered Access Point from the internal cache. Populated by getAp(), getApByBssid(), and the ApFoundCb callback. */
118struct ApRecord {
119 uint8_t bssid[6];
120 char ssid[33];
121 uint8_t ssid_len;
122 uint8_t channel;
123 int8_t rssi;
124 uint8_t enc; // 0=open, 1=WEP, 2=WPA, 3=WPA2/WPA3, 4=Enterprise
125 bool wps_enabled; // WPS IE detected in beacon/probe-response
126 bool pmf_capable; // MFPC bit set in RSN Capabilities (PMF supported)
127 bool pmf_required; // MFPR bit set in RSN Capabilities (PMF mandatory)
128 uint8_t total_attempts; // Number of failed attack attempts recorded
129 bool captured; // True if BSSID is on the captured or ignore list
130 bool ft_capable; // 802.11r FT AKM advertised (FT-PSK or FT-EAP)
131 uint32_t first_seen_ms; // millis() timestamp when this AP was first observed
132 uint32_t last_seen_ms; // millis() timestamp of the most recent beacon or probe response
133 char country[3]; // ISO 3166-1 alpha-2 country code from IE 7 (e.g. "US"), empty if absent
134 uint16_t beacon_interval; // Advertised beacon interval in TUs (1 TU = 1024 µs), 0 if unknown
135 uint8_t max_rate_mbps; // Highest legacy data rate from Supported Rates IEs (Mbps), 0 if unknown
136 bool is_hidden; // True if AP broadcasts an empty SSID (hidden network)
137 uint16_t sta_count; // Connected client count from BSS Load IE (if present)
138 uint8_t chan_util; // Channel utilization from BSS Load IE (0-255)
139 uint8_t venue_group; // 802.11u Venue Group (e.g., 2=Education, 10=Residential)
140 uint8_t venue_type; // 802.11u Venue Type (e.g., 8=University, 1=Coffee Shop)
141 uint8_t network_type; // 802.11u Access Network Type (1=Free Public, 2=Chargeable, etc.)
142};
143
144// ─── Frame Stats ──────────────────────────────────────────────────────────────
145/** @brief Cumulative frame and capture counters for the engine session. Accessible via getStats(), reset with resetStats(). */
146struct Stats {
147 uint32_t total;
148 uint32_t mgmt;
149 uint32_t ctrl;
150 uint32_t data;
151 uint32_t eapol;
152 uint32_t pmkid_found;
153 uint32_t sae_found;
154 uint32_t beacons;
155 uint32_t captures;
156 uint32_t failed_pmkid; // PMKID retries exhausted without capture
157 uint32_t failed_csa; // CSA/Deauth wait expired without EAPOL
158 volatile uint32_t dropped; // Frames dropped due to ringbuffer overflow
159 uint32_t rb_max; // Max observed ringbuffer usage (bytes)
160 uint16_t channel_frames[200]; // Frames received per channel, indexed by channel number (e.g. ch1=index1, ch36=index36). Index 0 unused.
161};
162
163// ─── Handshake Record ─────────────────────────────────────────────────────────
164/** @brief A captured handshake or PMKID record delivered to the EapolCb callback. The @p type field identifies the capture path; fields not relevant to that path are zeroed. */
166 uint8_t type; // CAP_PMKID / CAP_EAPOL / ...
167 uint8_t channel;
168 int8_t rssi;
169 uint8_t bssid[6];
170 uint8_t sta[6];
171 char ssid[33];
172 uint8_t ssid_len;
173 uint8_t enc; // 0=open, 1=WEP, 2=WPA, 3=WPA2/WPA3, 4=Enterprise
174 // PMKID path
175 uint8_t pmkid[16];
176 // EAPOL path
177 uint8_t anonce[32];
178 uint8_t snonce[32];
179 uint8_t mic[16];
180 union {
181 uint8_t eapol_m2[256];
182 uint8_t sae_data[256];
183 };
184 uint8_t eapol_m3[256];
185 uint8_t eapol_m4[256];
186 union {
187 uint16_t eapol_m2_len;
188 uint16_t sae_len;
189 };
190 uint16_t eapol_m3_len;
191 uint16_t eapol_m4_len;
195 bool has_m3;
196 bool has_m4;
197 bool is_full; // True if this is a complete 4-way sequence or full SAE exchange
198 uint8_t sae_seq; // SAE Auth Sequence (1=Commit, 2=Confirm)
199};
200
201// ─── Disconnection Strategy ───────────────────────────────────────────────────
202enum DisconnectStrategy : uint8_t {
203 STRATEGY_AUTO_FALLBACK = 0, // CSA first, fallback to Deauth halfway through wait window
204 STRATEGY_SIMULTANEOUS = 1, // CSA and Deauth simultaneously (Legacy behavior)
205};
206
207// ─── Attack Result ────────────────────────────────────────────────────────────
208enum AttackResult : uint8_t {
209 RESULT_PMKID_EXHAUSTED = 1, // All PMKID retries failed, no PMKID captured
210 RESULT_CSA_EXPIRED = 2, // CSA/Deauth wait window closed, no EAPOL captured
211};
212
213/** @brief Identifies the AP and failure reason for a failed attack, delivered to the AttackResultCb callback. */
215 uint8_t bssid[6];
216 char ssid[33];
217 uint8_t ssid_len;
219};
220
221typedef void (*AttackResultCb)(const AttackResultRecord &rec);
222typedef void (*ClientFoundCb)(const uint8_t *bssid, const uint8_t *sta, int8_t rssi);
223
224/**
225 * @brief Fired when a second BSSID advertising the same SSID is observed on the same channel.
226 * This indicates a potential evil twin or rogue AP. Both the known AP and the newcomer are included.
227 */
229 uint8_t known_bssid[6]; // BSSID of the first AP already cached with this SSID
230 uint8_t rogue_bssid[6]; // BSSID of the newly observed AP sharing the same SSID
231 char ssid[33]; // The shared SSID
232 uint8_t ssid_len;
233 uint8_t channel; // Channel on which the conflict was detected
234 int8_t rssi; // Signal strength of the rogue AP (dBm)
235};
236
237#ifndef POLITICIAN_NO_STD_FUNCTION
238using RogueApCb = std::function<void(const RogueApRecord &rec)>; // Fired when an evil twin / rogue AP is detected
239#else
240typedef void (*RogueApCb)(const RogueApRecord &rec); // Fired when an evil twin / rogue AP is detected
241#endif
242
243// ─── 802.1X Enterprise Identity Record ─────────────────────────────────────────
244/** @brief A harvested 802.1X Enterprise plaintext identity, delivered to the IdentityCb callback. */
246 uint8_t bssid[6]; // Access Point MAC
247 uint8_t client[6]; // Enterprise Client MAC
248 char identity[65]; // The Plaintext Identity / Email Address
249 uint8_t channel;
250 int8_t rssi;
251};
252
253// ─── Probe Request Record ─────────────────────────────────────────────────────
254/** @brief A probe request frame observed on the air, delivered to the ProbeRequestCb callback. */
256 uint8_t client[6]; // Probing device MAC
257 uint8_t channel;
258 int8_t rssi;
259 char ssid[33]; // Requested SSID (empty = wildcard probe)
260 uint8_t ssid_len;
261 bool rand_mac; // True if locally administered bit is set (iOS/Android MAC randomization)
262};
263
264// ─── Disruption Record ────────────────────────────────────────────────────────
265/** @brief A deauthentication or disassociation frame observed on the air, delivered to the DisruptCb callback. */
267 uint8_t src[6]; // Frame source MAC
268 uint8_t dst[6]; // Frame destination MAC
269 uint8_t bssid[6]; // BSSID (addr3)
270 uint16_t reason; // 802.11 reason code
271 uint8_t subtype; // MGMT_SUB_DEAUTH (0xC0) or MGMT_SUB_DISASSOC (0xA0)
272 uint8_t channel;
273 int8_t rssi;
274 bool rand_mac; // True if source MAC has locally administered bit set (randomized)
275};
276
277// ─── Device Fingerprint ───────────────────────────────────────────────────────
278
279// match_flags bits (reported in DeviceRecord)
280#define FP_MATCH_OUI 0x01
281#define FP_MATCH_PROBE_SSID 0x02
282#define FP_MATCH_HT_CAP 0x04
283#define FP_MATCH_RATES 0x08
284#define FP_MATCH_IE_FLAGS 0x10
285
286// ie_flags / ie_flags_mask bits (in DeviceFingerprint)
287#define FP_IEF_NO_HT 0x01 // IE 45 (HT Capabilities) absent
288#define FP_IEF_NO_EXT_CAP 0x02 // IE 127 (Extended Capabilities) absent
289#define FP_IEF_HAS_WMM 0x04 // WMM vendor IE (00:50:F2:01) present
290#define FP_IEF_HAS_WPS 0x08 // WPS vendor IE (00:50:F2:04) present
291
292/** @brief One fingerprint entry in the built-in or user-defined database. */
294 const char* vendor;
295 const char* model;
296 uint8_t oui[3];
297 const char* probeSsid;
298 uint8_t confidence;
299 // IE-based signals — zero values mean "don't check this signal"
300 uint8_t ht_cap_info[2]; // expected HT Capabilities Info bytes 0–1
301 uint8_t ht_cap_mask[2]; // bitmask: which bits of ht_cap_info to compare
302 uint8_t rate_sig[4]; // first 4 bytes of Supported Rates IE
303 uint8_t ie_flags; // expected IE presence flags (FP_IEF_*)
304 uint8_t ie_flags_mask; // which ie_flags bits to check
305};
306
307/** @brief A matched device, delivered to the DeviceFoundCb callback. */
309 uint8_t mac[6];
310 char vendor[32];
311 char model[32];
312 uint8_t channel;
313 int8_t rssi;
314 uint8_t confidence;
315 uint8_t match_flags;
316};
317
318} // namespace politician
#define LOG_FILTER_HANDSHAKES
#define LOG_FILTER_PROBES
void(* EapolCb)(const HandshakeRecord &rec)
uint16_t channel_frames[200]
const char * soft_ap_ssid
uint32_t probe_hidden_interval_ms
void(* AttackResultCb)(const AttackResultRecord &rec)
int(* TargetScoreCb)(const ApRecord &ap, const char *vendor)
void(* ProbeRequestCb)(const ProbeRequestRecord &rec)
uint16_t probe_aggr_interval_s
void(* ApFoundCb)(const ApRecord &ap)
void(* IdentityCb)(const EapIdentityRecord &rec)
void(* ClientFoundCb)(const uint8_t *bssid, const uint8_t *sta, int8_t rssi)
std::function< void(const char *msg)> LogCb
void(* PacketCb)(const uint8_t *payload, uint16_t len, int8_t rssi, uint8_t channel, uint32_t ts_usec)
volatile uint32_t dropped
std::function< void(const RogueApRecord &rec)> RogueApCb
void(* DisruptCb)(const DisruptRecord &rec)
Snapshot of a discovered Access Point from the internal cache.
Identifies the AP and failure reason for a failed attack, delivered to the AttackResultCb callback.
Configuration for the Politician engine.
One fingerprint entry in the built-in or user-defined database.
A matched device, delivered to the DeviceFoundCb callback.
A deauthentication or disassociation frame observed on the air, delivered to the DisruptCb callback.
A harvested 802.1X Enterprise plaintext identity, delivered to the IdentityCb callback.
A captured handshake or PMKID record delivered to the EapolCb callback.
A probe request frame observed on the air, delivered to the ProbeRequestCb callback.
Fired when a second BSSID advertising the same SSID is observed on the same channel.
Cumulative frame and capture counters for the engine session.