Politician 1.0.0
WiFi Auditing Library for ESP32
Loading...
Searching...
No Matches
PoliticianFormat.cpp
Go to the documentation of this file.
1#include "PoliticianFormat.h"
2
3namespace politician {
4namespace format {
5
6static void appendHex(String& str, const uint8_t* data, size_t len) {
7 char buf[3];
8 for (size_t i = 0; i < len; i++) {
9 sprintf(buf, "%02x", data[i]);
10 str += buf;
11 }
12}
13
14String toHC22000(const HandshakeRecord& rec) {
15 String out = "WPA*";
16
17 if (rec.type == CAP_PMKID) {
18 out += "01*";
19 appendHex(out, rec.pmkid, 16);
20 out += "*";
21 } else {
22 out += "02*";
23 appendHex(out, rec.mic, 16);
24 out += "*";
25 }
26
27 appendHex(out, rec.bssid, 6);
28 out += "*";
29 appendHex(out, rec.sta, 6);
30 out += "*";
31 appendHex(out, (const uint8_t*)rec.ssid, rec.ssid_len);
32 out += "*";
33
34 if (rec.type == CAP_PMKID) {
35 out += "**";
36 } else {
37 appendHex(out, rec.anonce, 32);
38 out += "*";
39 appendHex(out, rec.eapol_m2, rec.eapol_m2_len);
40 out += "*";
41 }
42
43 return out;
44}
45
46size_t writePcapngGlobalHeader(uint8_t* buffer) {
47 size_t offset = 0;
48
49 // 1. Section Header Block (SHB)
50 uint32_t shb_type = 0x0A0D0D0A;
51 uint32_t shb_len = 28;
52 uint32_t magic = 0x1A2B3C4D;
53 uint16_t v_major = 1;
54 uint16_t v_minor = 0;
55 int64_t section_len = -1;
56
57 memcpy(buffer + offset, &shb_type, 4); offset += 4;
58 memcpy(buffer + offset, &shb_len, 4); offset += 4;
59 memcpy(buffer + offset, &magic, 4); offset += 4;
60 memcpy(buffer + offset, &v_major, 2); offset += 2;
61 memcpy(buffer + offset, &v_minor, 2); offset += 2;
62 memcpy(buffer + offset, &section_len, 8); offset += 8;
63 memcpy(buffer + offset, &shb_len, 4); offset += 4;
64
65 // 2. Interface Description Block (IDB)
66 uint32_t idb_type = 0x00000001;
67 uint32_t idb_len = 20;
68 uint16_t link_type = 127; // IEEE 802.11 radiotap
69 uint16_t reserved = 0;
70 uint32_t snaplen = 65535;
71
72 memcpy(buffer + offset, &idb_type, 4); offset += 4;
73 memcpy(buffer + offset, &idb_len, 4); offset += 4;
74 memcpy(buffer + offset, &link_type, 2); offset += 2;
75 memcpy(buffer + offset, &reserved, 2); offset += 2;
76 memcpy(buffer + offset, &snaplen, 4); offset += 4;
77 memcpy(buffer + offset, &idb_len, 4); offset += 4;
78
79 return offset;
80}
81
82size_t writePcapngPacket(const uint8_t* payload, size_t payload_len, int8_t rssi, uint32_t ts_usec, uint8_t* buffer, size_t max_len) {
83 uint8_t radiotap[8] = { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 };
84 uint32_t cap_len = payload_len + 8;
85 uint32_t pkt_len = payload_len + 8;
86 uint32_t aligned_len = (cap_len + 3) & ~3;
87 uint32_t padding = aligned_len - cap_len;
88 uint32_t block_len = 32 + aligned_len;
89
90 if (block_len > max_len) return 0;
91
92 size_t offset = 0;
93 uint32_t epb_type = 0x00000006;
94 uint32_t interface_id = 0;
95 uint32_t ts_high = 0;
96 uint32_t ts_low = ts_usec;
97
98 memcpy(buffer + offset, &epb_type, 4); offset += 4;
99 memcpy(buffer + offset, &block_len, 4); offset += 4;
100 memcpy(buffer + offset, &interface_id, 4); offset += 4;
101 memcpy(buffer + offset, &ts_high, 4); offset += 4;
102 memcpy(buffer + offset, &ts_low, 4); offset += 4;
103 memcpy(buffer + offset, &cap_len, 4); offset += 4;
104 memcpy(buffer + offset, &pkt_len, 4); offset += 4;
105
106 memcpy(buffer + offset, radiotap, 8); offset += 8;
107 memcpy(buffer + offset, payload, payload_len); offset += payload_len;
108
109 if (padding > 0) {
110 uint32_t zero = 0;
111 memcpy(buffer + offset, &zero, padding); offset += padding;
112 }
113
114 memcpy(buffer + offset, &block_len, 4); offset += 4;
115
116 return offset;
117}
118
119size_t writePcapngRecord(const HandshakeRecord& rec, uint8_t* buffer, size_t max_len) {
120 size_t offset = 0;
121 uint8_t pkt[512];
122 uint32_t ts = millis() * 1000;
123
124 // Packet 1: Beacon
125 {
126 size_t p = 0;
127 // MAC Header (24 bytes): Frame Control(2), Dur(2), DA(6), SA(6), BSSID(6), Seq(2)
128 pkt[p++] = 0x80; pkt[p++] = 0x00; pkt[p++] = 0x00; pkt[p++] = 0x00; // Type Mgmt / Subtype Beacon
129 for (int i=0; i<6; i++) pkt[p++] = 0xFF; // Broadcast DA
130 memcpy(pkt + p, rec.bssid, 6); p += 6; // SA
131 memcpy(pkt + p, rec.bssid, 6); p += 6; // BSSID
132 pkt[p++] = 0x00; pkt[p++] = 0x00; // Seq
133 // Fixed params (12 bytes)
134 memset(pkt + p, 0, 8); p += 8; // Timestamp
135 pkt[p++] = 0x64; pkt[p++] = 0x00; // Beacon Interval (100)
136 pkt[p++] = 0x11; pkt[p++] = 0x04; // Capabilities
137 // Tagged params
138 pkt[p++] = 0x00; pkt[p++] = rec.ssid_len; // SSID Tag
139 memcpy(pkt + p, rec.ssid, rec.ssid_len); p += rec.ssid_len;
140 pkt[p++] = 0x03; pkt[p++] = 0x01; pkt[p++] = rec.channel; // Channel Tag
141
142 size_t w = writePcapngPacket(pkt, p, -50, ts++, buffer + offset, max_len - offset);
143 if (w == 0) return offset;
144 offset += w;
145 }
146
147 if (rec.type == CAP_PMKID) {
148 // Packet 2: EAPOL M1 containing PMKID in Key Data
149 size_t p = 0;
150 pkt[p++] = 0x08; pkt[p++] = 0x02; pkt[p++] = 0x00; pkt[p++] = 0x00; // Data / QoS Data, FromDS=1
151 memcpy(pkt + p, rec.sta, 6); p += 6; // DA
152 memcpy(pkt + p, rec.bssid, 6); p += 6; // SA
153 memcpy(pkt + p, rec.bssid, 6); p += 6; // BSSID
154 pkt[p++] = 0x00; pkt[p++] = 0x00; // Seq
155 pkt[p++] = 0x00; pkt[p++] = 0x00; // QoS Control
156
157 // LLC SNAP
158 uint8_t snap[8] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8E };
159 memcpy(pkt + p, snap, 8); p += 8;
160
161 // EAPOL Version 1, Type 3 (Key)
162 pkt[p++] = 0x01; pkt[p++] = 0x03;
163
164 uint16_t eapol_len = 95 + 22; // Key Frame + 22 bytes Key Data (PMKID)
165 pkt[p++] = (eapol_len >> 8); pkt[p++] = (eapol_len & 0xFF);
166
167 // EAPOL Key Frame (95 bytes without Key Data)
168 uint8_t eapolPayload[95] = {0};
169 eapolPayload[0] = 0x02; // Descriptor Type
170 eapolPayload[1] = 0x00; eapolPayload[2] = 0x8A; // Key Info (Pairwise, Ack)
171 eapolPayload[5] = 0x00; eapolPayload[6] = 0x00; eapolPayload[7] = 0x00; eapolPayload[8] = 0x00;
172 eapolPayload[9] = 0x00; eapolPayload[10] = 0x00; eapolPayload[11] = 0x00; eapolPayload[12] = 0x01; // Replay Counter
173 // Remaining is zeros
174 eapolPayload[93] = 0x00; eapolPayload[94] = 0x16; // Key Data Len = 22
175
176 memcpy(pkt + p, eapolPayload, 95); p += 95;
177
178 // Key Data: PMKID = DD 14 00 0F AC 04 <16 bytes>
179 pkt[p++] = 0xDD; pkt[p++] = 0x14; pkt[p++] = 0x00; pkt[p++] = 0x0F; pkt[p++] = 0xAC; pkt[p++] = 0x04;
180 memcpy(pkt + p, rec.pmkid, 16); p += 16;
181
182 size_t w = writePcapngPacket(pkt, p, -50, ts++, buffer + offset, max_len - offset);
183 if (w == 0) return offset;
184 offset += w;
185
186 } else {
187 // CAP_EAPOL/EAPOL_CSA
188 // Packet 2: EAPOL M1 (AP -> STA)
189 {
190 size_t p = 0;
191 pkt[p++] = 0x08; pkt[p++] = 0x02; pkt[p++] = 0x00; pkt[p++] = 0x00; // Data / QoS Data, FromDS=1
192 memcpy(pkt + p, rec.sta, 6); p += 6; // DA
193 memcpy(pkt + p, rec.bssid, 6); p += 6; // SA
194 memcpy(pkt + p, rec.bssid, 6); p += 6; // BSSID
195 pkt[p++] = 0x00; pkt[p++] = 0x00; // Seq
196 pkt[p++] = 0x00; pkt[p++] = 0x00; // QoS Control
197
198 uint8_t snap[8] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8E };
199 memcpy(pkt + p, snap, 8); p += 8;
200
201 pkt[p++] = 0x01; pkt[p++] = 0x03;
202 uint16_t eapol_len = 95;
203 pkt[p++] = (eapol_len >> 8); pkt[p++] = (eapol_len & 0xFF);
204
205 uint8_t eapolPayload[95] = {0};
206 eapolPayload[0] = 0x02;
207 eapolPayload[1] = 0x00; eapolPayload[2] = 0x8A; // Key Info
208 eapolPayload[12] = 0x01; // Replay Counter
209 memcpy(&eapolPayload[13], rec.anonce, 32); // Anonce
210
211 memcpy(pkt + p, eapolPayload, 95); p += 95;
212
213 size_t w = writePcapngPacket(pkt, p, -50, ts++, buffer + offset, max_len - offset);
214 if (w == 0) return offset;
215 offset += w;
216 }
217
218 // Packet 3: EAPOL M2 (STA -> AP)
219 {
220 size_t p = 0;
221 pkt[p++] = 0x08; pkt[p++] = 0x01; pkt[p++] = 0x00; pkt[p++] = 0x00; // Data / QoS Data, ToDS=1
222 memcpy(pkt + p, rec.bssid, 6); p += 6; // DA
223 memcpy(pkt + p, rec.sta, 6); p += 6; // SA
224 memcpy(pkt + p, rec.bssid, 6); p += 6; // BSSID
225 pkt[p++] = 0x00; pkt[p++] = 0x00; // Seq
226 pkt[p++] = 0x00; pkt[p++] = 0x00; // QoS Control
227
228 uint8_t snap[8] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8E };
229 memcpy(pkt + p, snap, 8); p += 8;
230
231 uint16_t eapol_len = rec.eapol_m2_len > 4 ? rec.eapol_m2_len - 4 : 0;
232 if (eapol_len > 0) {
233 // EAPOL Version + Type usually part of m2
234 memcpy(pkt + p, rec.eapol_m2, rec.eapol_m2_len); p += rec.eapol_m2_len;
235 }
236
237 size_t w = writePcapngPacket(pkt, p, -50, ts++, buffer + offset, max_len - offset);
238 if (w == 0) return offset;
239 offset += w;
240 }
241 }
242
243 return offset;
244}
245
246} // namespace format
247} // namespace politician
#define CAP_PMKID
size_t writePcapngPacket(const uint8_t *payload, size_t payload_len, int8_t rssi, uint32_t ts_usec, uint8_t *buffer, size_t max_len)
Serializes a Raw 802.11 Frame into a PCAPNG Enhanced Packet Block.
String toHC22000(const HandshakeRecord &rec)
Converts a captured HandshakeRecord into the Hashcat 22000 (hc22000) text format.
size_t writePcapngRecord(const HandshakeRecord &rec, uint8_t *buffer, size_t max_len)
Serializes a HandshakeRecord into PCAPNG Enhanced Packet Blocks.
static void appendHex(String &str, const uint8_t *data, size_t len)
size_t writePcapngGlobalHeader(uint8_t *buffer)
Writes a PCAPNG Global Header (SHB + IDB).