/* * 802.11 WEP / WPA-PSK Key Cracker * * Copyright (C) 2006, 2007, 2008, 2009 Thomas d'Otreppe * Copyright (C) 2004, 2005 Christophe Devine * * Advanced WEP attacks developed by KoreK * WPA-PSK attack code developed by Joshua Wright * SHA1 MMX assembly code written by Simon Marechal * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "version.h" #include "crypto.h" #include "pcap.h" #include "uniqueiv.h" #include "aircrack-ng.h" #include "sha1-sse2.h" #include "osdep/byteorder.h" #include "common.h" #ifdef HAVE_SQLITE #include sqlite3 *db; #endif extern int get_nb_cpus(); static uchar ZERO[32] = "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00"; /* stats global data */ struct timeval t_begin; /* time at start of attack */ struct timeval t_stats; /* time since last update */ struct timeval t_kprev; /* time at start of window */ long long int nb_kprev; /* last # of keys tried */ long long int nb_tried; /* total # of keys tried */ /* IPC global data */ struct AP_info *ap_1st; /* first item in linked list */ pthread_mutex_t mx_apl; /* lock write access to ap LL */ pthread_mutex_t mx_eof; /* lock write access to nb_eof */ pthread_mutex_t mx_ivb; /* lock access to ivbuf array */ pthread_cond_t cv_eof; /* read EOF condition variable */ int nb_eof = 0; /* # of threads who reached eof */ long nb_pkt = 0; /* # of packets read so far */ int mc_pipe[256][2]; /* master->child control pipe */ int cm_pipe[256][2]; /* child->master results pipe */ int bf_pipe[256][2]; /* bruteforcer 'queue' pipe */ int bf_nkeys[256]; uchar bf_wepkey[64]; int wepkey_crack_success = 0; int close_aircrack = 0; int id=0; pthread_t tid[MAX_THREADS]; struct WPA_data wpa_data[MAX_THREADS]; int wpa_wordlists_done = 0; static pthread_mutex_t mx_nb = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t mx_wpastats = PTHREAD_MUTEX_INITIALIZER; #define GOT_IV 0x00000001 #define USE_IV 0x00000002 #define K01_IV 0x00000010 #define K02_IV 0x00000020 #define K03_IV 0x00000040 #define K04_IV 0x00000080 #define K05_IV 0x00000100 #define K06_IV 0x00000200 #define K07_IV 0x00000400 #define K08_IV 0x00000800 #define K09_IV 0x00001000 #define K10_IV 0x00002000 #define K11_IV 0x00004000 #define K12_IV 0x00008000 #define K13_IV 0x00010000 #define K14_IV 0x00020000 #define K15_IV 0x00040000 #define K16_IV 0x00080000 #define K17_IV 0x00100000 typedef struct { int off1; int off2; void *buf1; void *buf2; } read_buf; int K_COEFF[N_ATTACKS] = { 15, 13, 12, 12, 12, 5, 5, 5, 3, 4, 3, 4, 3, 13, 4, 4, -20 }; int PTW_DEFAULTWEIGHT[1] = { 256 }; int PTW_DEFAULTBF[PTW_KEYHSBYTES] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const uchar R[256] = { 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 }; char usage[] = "\n" " %s - (C) 2006, 2007, 2008, 2009 Thomas d\'Otreppe\n" " Original work: Christophe Devine\n" " http://www.aircrack-ng.org\n" "\n" " usage: aircrack-ng [options] <.cap / .ivs file(s)>\n" "\n" " Common options:\n" "\n" " -a : force attack mode (1/WEP, 2/WPA-PSK)\n" " -e : target selection: network identifier\n" " -b : target selection: access point's MAC\n" " -p : # of CPU to use (default: all CPUs)\n" " -q : enable quiet mode (no status output)\n" " -C : merge the given APs to a virtual one\n" " -l : write key to file\n" "\n" " Static WEP cracking options:\n" "\n" " -c : search alpha-numeric characters only\n" " -t : search binary coded decimal chr only\n" " -h : search the numeric key for Fritz!BOX\n" " -d : use masking of the key (A1:XX:CF:YY)\n" " -m : MAC address to filter usable packets\n" " -n : WEP key length : 64/128/152/256/512\n" " -i : WEP key index (1 to 4), default: any\n" " -f : bruteforce fudge factor, default: 2\n" " -k : disable one attack method (1 to 17)\n" " -x or -x0 : disable bruteforce for last keybytes\n" " -x1 : last keybyte bruteforcing (default)\n" " -x2 : enable last 2 keybytes bruteforcing" "%s" " -y : experimental single bruteforce mode\n" " -K : use only old KoreK attacks (pre-PTW)\n" " -s : show the key in ASCII while cracking\n" " -M : specify maximum number of IVs to use\n" " -D : WEP decloak, skips broken keystreams\n" " -P : PTW debug: 1: disable Klein, 2: PTW\n" " -1 : run only 1 try to crack key with PTW\n" "\n" " WEP and WPA-PSK cracking options:\n" "\n" " -w : path to wordlist(s) filename(s)\n" #ifdef HAVE_SQLITE " -r : path to airolib-ng database\n" " (Cannot be used with -w)\n" #endif "\n" " --help : Displays this usage screen\n" "\n"; char * progname; int intr_read = 0; int safe_write( int fd, void *buf, size_t len ); void clean_exit(int ret) { struct AP_info *ap_cur; struct AP_info *ap_prv; struct AP_info *ap_next; int i=0; // int j=0, k=0, attack=0; int child_pid; char tmpbuf[128]; memset(tmpbuf, 0, 128); if(ret && !opt.is_quiet) { printf("\nQuitting aircrack-ng...\n"); fflush(stdout); } close_aircrack = 1; for( i = 0; i < opt.nbcpu; i++ ) { #ifdef CYGWIN close( mc_pipe[i][1] ); close( bf_pipe[i][1] ); #else safe_write( mc_pipe[i][1], (void *) "EXIT\r", 5 ); safe_write( bf_pipe[i][1], (void *) tmpbuf, 64 ); #endif } if( opt.amode != 2 ) { for(i=0; iivbuf != NULL ) { free(ap_cur->ivbuf); ap_cur->ivbuf = NULL; } uniqueiv_wipe( ap_cur->uiv_root ); if( ap_cur->ptw_clean != NULL ) { if( ap_cur->ptw_clean->allsessions != NULL ) { free(ap_cur->ptw_clean->allsessions); ap_cur->ptw_clean->allsessions=NULL; } free(ap_cur->ptw_clean); ap_cur->ptw_clean = NULL; } if( ap_cur->ptw_vague != NULL ) { if( ap_cur->ptw_vague->allsessions != NULL ) { free(ap_cur->ptw_vague->allsessions); ap_cur->ptw_vague->allsessions = NULL; } free(ap_cur->ptw_vague); ap_cur->ptw_vague = NULL; } ap_prv = ap_cur; ap_cur = ap_cur->next; } ap_cur = ap_1st; while( ap_cur != NULL ) { ap_next = ap_cur->next; if( ap_cur != NULL ) free(ap_cur); ap_cur = ap_next; } // attack = A_s5_1; // printf("Please wait for evaluation...\n"); // for(i=0; i<(256*256*256); i++) // { // if((all_ivs[i].used & GOT_IV) && !(all_ivs[i].used & USE_IV)) // j++; // // if((all_ivs[i].used & GOT_IV) && (all_ivs[i].used & (1<<(attack+4)) ) ) // { // printf("IV %02X:%02X:%02X used for %d\n", (i/(256*256)), ((i&0xFFFF)/(256)), (i&0xFF), attack); // k++; // } // } // // printf("%d unused IVs\n", j); // printf("%d used IVs for %d\n", k, attack); child_pid=fork(); if(child_pid==-1) { /* do error stuff here */ } if(child_pid!=0) { /* The parent process exits here. */ exit(0); } _exit(ret); } void sighandler( int signum ) { #if ((defined(__INTEL_COMPILER) || defined(__ICC)) && defined(DO_PGO_DUMP)) _PGOPTI_Prof_Dump(); #endif signal( signum, sighandler ); if( signum == SIGQUIT ) clean_exit( SUCCESS ); // _exit( SUCCESS ); if( signum == SIGTERM ) clean_exit( FAILURE ); // _exit( FAILURE ); if( signum == SIGINT ) { #if ((defined(__INTEL_COMPILER) || defined(__ICC)) && defined(DO_PGO_DUMP)) clean_exit( FAILURE ); // _exit( FAILURE ); #else /* if(intr_read > 0)*/ clean_exit( FAILURE ); /* else intr_read++;*/ #endif } if( signum == SIGWINCH ) printf( "\33[2J\n" ); } void eof_wait( int *eof_notified ) { if( *eof_notified == 0 ) { *eof_notified = 1; /* tell the master thread we reached EOF */ pthread_mutex_lock( &mx_eof ); nb_eof++; pthread_cond_broadcast( &cv_eof ); pthread_mutex_unlock( &mx_eof ); } usleep( 100000 ); } inline int wpa_send_passphrase(char *key, struct WPA_data* data, int lock) { pthread_mutex_lock(&data->mutex); if ((data->back+1) % data->nkeys == data->front) { if (lock != 0) { // wait until there's room in the queue pthread_cond_wait(&data->cond, &data->mutex); } else { pthread_mutex_unlock(&data->mutex); return 0; // full queue! } } // put one key in the buffer: memcpy(data->key_buffer + data->back*128, key, 128); data->back = (data->back+1) % data->nkeys; pthread_mutex_unlock(&data->mutex); return 1; } inline int wpa_receive_passphrase(char *key, struct WPA_data* data) { pthread_mutex_lock(&data->mutex); if (data->front==data->back) { pthread_mutex_unlock(&data->mutex); return 0; // empty queue! } // get one key from the buffer: memcpy(key, data->key_buffer + data->front*128, 128); data->front = (data->front+1) % data->nkeys; // signal that there's now room in the queue for more keys pthread_cond_signal(&data->cond); pthread_mutex_unlock(&data->mutex); return 1; } int checkbssids(char *bssidlist) { int first = 1; int i = 0; char *list, *tmp; int nbBSSID = 0; if(bssidlist == NULL) return -1; #define IS_X(x) ((x) == 'X' || (x) == 'x') #define VALID_CHAR(x) ((IS_X(x)) || hexCharToInt(x) > -1) #define VALID_SEP(arg) ( ((arg) == '_') || ((arg) == '-') || ((arg) == ':') ) list = strdup(bssidlist); do { tmp = strsep(&list, ","); if (tmp == NULL) break; ++nbBSSID; if(strlen(tmp) != 17) return -1; //first byte if(!VALID_CHAR(tmp[ 0])) return -1; if(!VALID_CHAR(tmp[ 1])) return -1; if(!VALID_SEP( tmp[ 2])) return -1; //second byte if(!VALID_CHAR(tmp[ 3])) return -1; if(!VALID_CHAR(tmp[ 4])) return -1; if(!VALID_SEP( tmp[ 5])) return -1; //third byte if(!VALID_CHAR(tmp[ 6])) return -1; if(!VALID_CHAR(tmp[ 7])) return -1; if(!VALID_SEP( tmp[ 8])) return -1; //fourth byte if(!VALID_CHAR(tmp[ 9])) return -1; if(!VALID_CHAR(tmp[10])) return -1; if(!VALID_SEP( tmp[11])) return -1; //fifth byte if(!VALID_CHAR(tmp[12])) return -1; if(!VALID_CHAR(tmp[13])) return -1; if(!VALID_SEP( tmp[14])) return -1; //sixth byte if(!VALID_CHAR(tmp[15])) return -1; if(!VALID_CHAR(tmp[16])) return -1; if(first) { for(i=0; i< 17; i++) if( IS_X(tmp[i])) return -1; opt.firstbssid = (unsigned char *) malloc(sizeof(unsigned char)); getmac(tmp, 1, opt.firstbssid); first = 0; } } while(list); // Success return nbBSSID; } int mergebssids(char * bssidlist, unsigned char * bssid) { struct mergeBSSID * list_prev; struct mergeBSSID * list_cur; char * mac = NULL; char * list = NULL; char * tmp = NULL; char * tmp2 = NULL; int next, i, found; // Do not convert if equal to first bssid if (memcmp(opt.firstbssid, bssid, 6) == 0) return 1; list_prev = NULL; list_cur = opt.bssid_list_1st; while (list_cur != NULL) { if (memcmp(list_cur->bssid, bssid, 6) == 0) { if (list_cur->convert) memcpy(bssid, opt.firstbssid, 6); return list_cur->convert; } list_prev = list_cur; list_cur = list_cur->next; } // Not found, check if it has to be converted mac = (char *) malloc(18); if (!mac) { perror( "malloc failed" ); return -1; } snprintf(mac, 18, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); mac[17] = 0; tmp2 = list = strdup(bssidlist); // skip first element (because it doesn't have to be converted // It already has the good value tmp = strsep(&list, ","); next = found = 0; do { next=0; tmp = strsep(&list, ","); if (tmp == NULL) break; // Length already checked, no need to check it again for( i = 0; i < 17; ++i) { if((IS_X(tmp[i]) || VALID_SEP(tmp[i]))) continue; if(toupper((int)tmp[i]) != (int)mac[i]) { // Not found next = 1; break; } } if(next == 0) { found = 1; break; } } while (list); // Free memory if(mac != NULL) free(mac); if(tmp2 != NULL) free(tmp2); // Add the result to the list list_cur = (struct mergeBSSID *) malloc(sizeof(struct mergeBSSID)); if (!list_cur) { perror( "malloc failed" ); return -1; } list_cur->convert = found; list_cur->next = NULL; memcpy(list_cur->bssid, bssid, 6); if (opt.bssid_list_1st == NULL) opt.bssid_list_1st = list_cur; else list_prev->next = list_cur; // Do not forget to convert if it was successful if (list_cur->convert) memcpy(bssid, opt.firstbssid, 6); #undef VALID_CHAR #undef VALID_SEP #undef IS_X return list_cur->convert; } /* fread isn't atomic, sadly */ int atomic_read( read_buf *rb, int fd, int len, void *buf ) { int n; if( close_aircrack ) return( CLOSE_IT ); if( rb->buf1 == NULL ) { rb->buf1 = malloc( 65536 ); rb->buf2 = malloc( 65536 ); if( rb->buf1 == NULL || rb->buf2 == NULL ) return( 0 ); rb->off1 = 0; rb->off2 = 0; } if( len > 65536 - rb->off1 ) { rb->off2 -= rb->off1; memcpy( rb->buf2, rb->buf1 + rb->off1, rb->off2 ); memcpy( rb->buf1, rb->buf2, rb->off2 ); rb->off1 = 0; } if( rb->off2 - rb->off1 >= len ) { memcpy( buf, rb->buf1 + rb->off1, len ); rb->off1 += len; return( 1 ); } else { n = read( fd, rb->buf1 + rb->off2, 65536 - rb->off2 ); if( n <= 0 ) return( 0 ); rb->off2 += n; if( rb->off2 - rb->off1 >= len ) { memcpy( buf, rb->buf1 + rb->off1, len ); rb->off1 += len; return( 1 ); } } return( 0 ); } void read_thread( void *arg ) { int fd, n, z, fmt; int eof_notified = 0; read_buf rb; // int ret=0; uchar bssid[6]; uchar dest[6]; uchar stmac[6]; uchar *buffer; uchar *h80211; uchar *p; int weight[16]; struct ivs2_pkthdr ivs2; struct ivs2_filehdr fivs2; struct pcap_pkthdr pkh; struct pcap_file_header pfh; struct AP_info *ap_prv, *ap_cur; struct ST_info *st_prv, *st_cur; signal( SIGINT, sighandler); memset( &rb, 0, sizeof( rb ) ); ap_cur = NULL; memset(&pfh, 0, sizeof(struct pcap_file_header)); if( ( buffer = (uchar *) malloc( 65536 ) ) == NULL ) { /* there is no buffer */ perror( "malloc failed" ); goto read_fail; } h80211 = buffer; if( ! opt.is_quiet ) printf( "Opening %s\n", (char *) arg ); if( strcmp( arg, "-" ) == 0 ) fd = 0; else { if( ( fd = open( (char *) arg, O_RDONLY | O_BINARY ) ) < 0 ) { perror( "open failed" ); goto read_fail; } } if( ! atomic_read( &rb, fd, 4, &pfh ) ) { perror( "read(file header) failed" ); goto read_fail; } fmt = FORMAT_IVS; if( memcmp( &pfh, IVSONLY_MAGIC, 4 ) != 0 && memcmp( &pfh, IVS2_MAGIC, 4 ) != 0) { fmt = FORMAT_CAP; if( pfh.magic != TCPDUMP_MAGIC && pfh.magic != TCPDUMP_CIGAM ) { fprintf( stderr, "Unsupported file format " "(not a pcap or IVs file).\n" ); goto read_fail; } /* read the rest of the pcap file header */ if( ! atomic_read( &rb, fd, 20, (uchar *) &pfh + 4 ) ) { perror( "read(file header) failed" ); goto read_fail; } /* take care of endian issues and check the link type */ if( pfh.magic == TCPDUMP_CIGAM ) SWAP32( pfh.linktype ); if( pfh.linktype != LINKTYPE_IEEE802_11 && pfh.linktype != LINKTYPE_PRISM_HEADER && pfh.linktype != LINKTYPE_RADIOTAP_HDR && pfh.linktype != LINKTYPE_PPI_HDR) { fprintf( stderr, "This file is not a regular " "802.11 (wireless) capture.\n" ); goto read_fail; } } else { if( opt.wep_decloak ) { errx(1, "Can't use decloak wep mode with ivs\n"); /* XXX */ } if (memcmp( &pfh, IVS2_MAGIC, 4 ) == 0) { fmt = FORMAT_IVS2; if( ! atomic_read( &rb, fd, sizeof(struct ivs2_filehdr), (uchar *) &fivs2 ) ) { perror( "read(file header) failed" ); goto read_fail; } if(fivs2.version > IVS2_VERSION) { printf( "Error, wrong %s version: %d. Supported up to version %d.\n", IVS2_EXTENSION, fivs2.version, IVS2_VERSION ); goto read_fail; } } else if (opt.do_ptw) errx(1, "Can't do PTW with old IVS files, recapture without --ivs or use airodump-ng >= 1.0\n"); /* XXX */ } /* avoid blocking on reading the file */ if( fcntl( fd, F_SETFL, O_NONBLOCK ) < 0 ) { perror( "fcntl(O_NONBLOCK) failed" ); goto read_fail; } while( 1 ) { if( close_aircrack ) break; if( fmt == FORMAT_IVS ) { /* read one IV */ while( ! atomic_read( &rb, fd, 1, buffer ) ) eof_wait( &eof_notified ); if( close_aircrack ) break; if( buffer[0] != 0xFF ) { /* new access point MAC */ bssid[0] = buffer[0]; while( ! atomic_read( &rb, fd, 5, bssid + 1 ) ) eof_wait( &eof_notified ); if( close_aircrack ) break; } while( ! atomic_read( &rb, fd, 5, buffer ) ) eof_wait( &eof_notified ); if( close_aircrack ) break; } else if( fmt == FORMAT_IVS2 ) { while( ! atomic_read( &rb, fd, sizeof( struct ivs2_pkthdr ), &ivs2 ) ) eof_wait( &eof_notified ); if( close_aircrack ) break; if(ivs2.flags & IVS2_BSSID) { while( ! atomic_read( &rb, fd, 6, bssid ) ) eof_wait( &eof_notified ); if( close_aircrack ) break; ivs2.len -= 6; } while( ! atomic_read( &rb, fd, ivs2.len, buffer ) ) eof_wait( &eof_notified ); if( close_aircrack ) break; } else { while( ! atomic_read( &rb, fd, sizeof( pkh ), &pkh ) ) eof_wait( &eof_notified ); if( close_aircrack ) break; if( pfh.magic == TCPDUMP_CIGAM ) SWAP32( pkh.caplen ); if( pkh.caplen <= 0 || pkh.caplen > 65535 ) { fprintf( stderr, "\nInvalid packet capture length %d - " "corrupted file?\n", pkh.caplen ); eof_wait( &eof_notified ); _exit( FAILURE ); } while( ! atomic_read( &rb, fd, pkh.caplen, buffer ) ) eof_wait( &eof_notified ); if( close_aircrack ) break; h80211 = buffer; if( pfh.linktype == LINKTYPE_PRISM_HEADER ) { /* remove the prism header */ if( h80211[7] == 0x40 ) n = 64; else { n = *(int *)( h80211 + 4 ); if( pfh.magic == TCPDUMP_CIGAM ) SWAP32( n ); } if( n < 8 || n >= (int) pkh.caplen ) continue; h80211 += n; pkh.caplen -= n; } if( pfh.linktype == LINKTYPE_RADIOTAP_HDR ) { /* remove the radiotap header */ n = *(unsigned short *)( h80211 + 2 ); if( n <= 0 || n >= (int) pkh.caplen ) continue; h80211 += n; pkh.caplen -= n; } if( pfh.linktype == LINKTYPE_PPI_HDR ) { /* Remove the PPI header */ n = le16_to_cpu(*(unsigned short *)( h80211 + 2)); if( n <= 0 || n>= (int) pkh.caplen ) continue; /* for a while Kismet logged broken PPI headers */ if ( n == 24 && le16_to_cpu(*(unsigned short *)(h80211 + 8)) == 2 ) n = 32; if( n <= 0 || n>= (int) pkh.caplen ) continue; h80211 += n; pkh.caplen -= n; } } /* prevent concurrent access on the linked list */ pthread_mutex_lock( &mx_apl ); nb_pkt++; if( fmt == FORMAT_CAP ) { /* skip packets smaller than a 802.11 header */ if( pkh.caplen < 24 ) goto unlock_mx_apl; /* skip (uninteresting) control frames */ if( ( h80211[0] & 0x0C ) == 0x04 ) goto unlock_mx_apl; /* locate the access point's MAC address */ switch( h80211[1] & 3 ) { case 0: memcpy( bssid, h80211 + 16, 6 ); break; //Adhoc case 1: memcpy( bssid, h80211 + 4, 6 ); break; //ToDS case 2: memcpy( bssid, h80211 + 10, 6 ); break; //FromDS case 3: memcpy( bssid, h80211 + 10, 6 ); break; //WDS -> Transmitter taken as BSSID } switch( h80211[1] & 3 ) { case 0: memcpy( dest, h80211 + 4, 6 ); break; //Adhoc case 1: memcpy( dest, h80211 + 16, 6 ); break; //ToDS case 2: memcpy( dest, h80211 + 4, 6 ); break; //FromDS case 3: memcpy( dest, h80211 + 16, 6 ); break; //WDS -> Transmitter taken as BSSID } //skip corrupted keystreams in wep decloak mode if(opt.wep_decloak) { if(dest[0] == 0x01) goto unlock_mx_apl; } } if(opt.bssidmerge) mergebssids(opt.bssidmerge, bssid); if( memcmp( bssid, BROADCAST, 6 ) == 0 ) /* probe request or such - skip the packet */ goto unlock_mx_apl; if( memcmp( bssid, opt.bssid, 6 ) != 0 ) goto unlock_mx_apl; if( memcmp( opt.maddr, ZERO, 6 ) != 0 && memcmp( opt.maddr, BROADCAST, 6 ) != 0 ) { /* apply the MAC filter */ if( memcmp( opt.maddr, h80211 + 4, 6 ) != 0 && memcmp( opt.maddr, h80211 + 10, 6 ) != 0 && memcmp( opt.maddr, h80211 + 16, 6 ) != 0 ) goto unlock_mx_apl; } /* search the linked list */ ap_prv = NULL; ap_cur = ap_1st; while( ap_cur != NULL ) { if( ! memcmp( ap_cur->bssid, bssid, 6 ) ) break; ap_prv = ap_cur; ap_cur = ap_cur->next; } /* if it's a new access point, add it */ if( ap_cur == NULL ) { if( ! ( ap_cur = (struct AP_info *) malloc( sizeof( struct AP_info ) ) ) ) { perror( "malloc failed" ); break; } memset( ap_cur, 0, sizeof( struct AP_info ) ); if( ap_1st == NULL ) ap_1st = ap_cur; else ap_prv->next = ap_cur; memcpy( ap_cur->bssid, bssid, 6 ); ap_cur->crypt = -1; if (opt.do_ptw == 1) { ap_cur->ptw_clean = PTW_newattackstate(); if (!ap_cur->ptw_clean) { perror("PTW_newattackstate()"); free(ap_cur); ap_cur = NULL; break; } ap_cur->ptw_vague = PTW_newattackstate(); if (!ap_cur->ptw_vague) { perror("PTW_newattackstate()"); free(ap_cur); ap_cur = NULL; break; } } } if( fmt == FORMAT_IVS ) { ap_cur->crypt = 2; add_wep_iv: /* check for uniqueness first */ if( ap_cur->nb_ivs == 0 ) ap_cur->uiv_root = uniqueiv_init(); if( uniqueiv_check( ap_cur->uiv_root, buffer ) == 0 ) { /* add the IV & first two encrypted bytes */ n = ap_cur->nb_ivs * 5; if( n + 5 > ap_cur->ivbuf_size ) { /* enlarge the IVs buffer */ ap_cur->ivbuf_size += 131072; ap_cur->ivbuf = (uchar *) realloc( ap_cur->ivbuf, ap_cur->ivbuf_size ); if( ap_cur->ivbuf == NULL ) { perror( "realloc failed" ); break; } } memcpy( ap_cur->ivbuf + n, buffer, 5 ); uniqueiv_mark( ap_cur->uiv_root, buffer ); ap_cur->nb_ivs++; } goto unlock_mx_apl; } if( fmt == FORMAT_IVS2 ) { if(ivs2.flags & IVS2_ESSID) { memcpy( ap_cur->essid, buffer, ivs2.len); } else if(ivs2.flags & IVS2_XOR) { ap_cur->crypt = 2; if (opt.do_ptw) { int clearsize; clearsize = ivs2.len; if (clearsize < opt.keylen+3) goto unlock_mx_apl; if (PTW_addsession(ap_cur->ptw_clean, buffer, buffer+4, PTW_DEFAULTWEIGHT, 1)) ap_cur->nb_ivs_clean++; if (PTW_addsession(ap_cur->ptw_vague, buffer, buffer+4, PTW_DEFAULTWEIGHT, 1)) ap_cur->nb_ivs_vague++; goto unlock_mx_apl; } buffer[3] = buffer[4]; buffer[4] = buffer[5]; buffer[3] ^= 0xAA; buffer[4] ^= 0xAA; /* check for uniqueness first */ if( ap_cur->nb_ivs == 0 ) ap_cur->uiv_root = uniqueiv_init(); if( uniqueiv_check( ap_cur->uiv_root, buffer ) == 0 ) { /* add the IV & first two encrypted bytes */ n = ap_cur->nb_ivs * 5; if( n + 5 > ap_cur->ivbuf_size ) { /* enlarge the IVs buffer */ ap_cur->ivbuf_size += 131072; ap_cur->ivbuf = (uchar *) realloc( ap_cur->ivbuf, ap_cur->ivbuf_size ); if( ap_cur->ivbuf == NULL ) { perror( "realloc failed" ); break; } } memcpy( ap_cur->ivbuf + n, buffer, 5 ); uniqueiv_mark( ap_cur->uiv_root, buffer ); ap_cur->nb_ivs++; // all_ivs[256*256*buffer[0] + 256*buffer[1] + buffer[2]].used |= GOT_IV; } } else if(ivs2.flags & IVS2_PTW) { ap_cur->crypt = 2; if (opt.do_ptw) { int clearsize; clearsize = ivs2.len; if (buffer[5] < opt.keylen) goto unlock_mx_apl; if( clearsize < (6 + buffer[4]*32 + 16*(signed)sizeof(int)) ) goto unlock_mx_apl; memcpy(weight, buffer+clearsize-15*sizeof(int), 16*sizeof(int)); // printf("weight 1: %d, weight 2: %d\n", weight[0], weight[1]); if (PTW_addsession(ap_cur->ptw_vague, buffer, buffer+6, weight, buffer[4])) ap_cur->nb_ivs_vague++; goto unlock_mx_apl; } buffer[3] = buffer[6]; buffer[4] = buffer[7]; buffer[3] ^= 0xAA; buffer[4] ^= 0xAA; /* check for uniqueness first */ if( ap_cur->nb_ivs == 0 ) ap_cur->uiv_root = uniqueiv_init(); if( uniqueiv_check( ap_cur->uiv_root, buffer ) == 0 ) { /* add the IV & first two encrypted bytes */ n = ap_cur->nb_ivs * 5; if( n + 5 > ap_cur->ivbuf_size ) { /* enlarge the IVs buffer */ ap_cur->ivbuf_size += 131072; ap_cur->ivbuf = (uchar *) realloc( ap_cur->ivbuf, ap_cur->ivbuf_size ); if( ap_cur->ivbuf == NULL ) { perror( "realloc failed" ); break; } } memcpy( ap_cur->ivbuf + n, buffer, 5 ); uniqueiv_mark( ap_cur->uiv_root, buffer ); ap_cur->nb_ivs++; } } else if(ivs2.flags & IVS2_WPA) { ap_cur->crypt = 3; memcpy( &ap_cur->wpa, buffer, sizeof( struct WPA_hdsk ) ); } goto unlock_mx_apl; } /* locate the station MAC in the 802.11 header */ st_cur = NULL; switch( h80211[1] & 3 ) { case 0: memcpy( stmac, h80211 + 10, 6 ); break; case 1: memcpy( stmac, h80211 + 10, 6 ); break; case 2: /* reject broadcast MACs */ if( (h80211[4]%2) != 0 ) goto skip_station; memcpy( stmac, h80211 + 4, 6 ); break; default: goto skip_station; break; } st_prv = NULL; st_cur = ap_cur->st_1st; while( st_cur != NULL ) { if( ! memcmp( st_cur->stmac, stmac, 6 ) ) break; st_prv = st_cur; st_cur = st_cur->next; } /* if it's a new supplicant, add it */ if( st_cur == NULL ) { if( ! ( st_cur = (struct ST_info *) malloc( sizeof( struct ST_info ) ) ) ) { perror( "malloc failed" ); break; } memset( st_cur, 0, sizeof( struct ST_info ) ); if( ap_cur->st_1st == NULL ) ap_cur->st_1st = st_cur; else st_prv->next = st_cur; memcpy( st_cur->stmac, stmac, 6 ); } skip_station: /* packet parsing: Beacon or Probe Response */ if( h80211[0] == 0x80 || h80211[0] == 0x50 ) { if( ap_cur->crypt < 0 ) ap_cur->crypt = ( h80211[34] & 0x10 ) >> 4; p = h80211 + 36; while( p < h80211 + pkh.caplen ) { if( p + 2 + p[1] > h80211 + pkh.caplen ) break; if( p[0] == 0x00 && p[1] > 0 && p[2] != '\0' ) { /* found a non-cloaked ESSID */ n = ( p[1] > 32 ) ? 32 : p[1]; memset( ap_cur->essid, 0, 33 ); memcpy( ap_cur->essid, p + 2, n ); } p += 2 + p[1]; } } /* packet parsing: Association Request */ if( h80211[0] == 0x00 ) { p = h80211 + 28; while( p < h80211 + pkh.caplen ) { if( p + 2 + p[1] > h80211 + pkh.caplen ) break; if( p[0] == 0x00 && p[1] > 0 && p[2] != '\0' ) { n = ( p[1] > 32 ) ? 32 : p[1]; memset( ap_cur->essid, 0, 33 ); memcpy( ap_cur->essid, p + 2, n ); } p += 2 + p[1]; } } /* packet parsing: Association Response */ if( h80211[0] == 0x10 ) { /* reset the WPA handshake state */ if( st_cur != NULL ) st_cur->wpa.state = 0; } /* check if data */ if( ( h80211[0] & 0x0C ) != 0x08 ) goto unlock_mx_apl; /* check minimum size */ z = ( ( h80211[1] & 3 ) != 3 ) ? 24 : 30; if ( ( h80211[0] & 0x80 ) == 0x80 ) z+=2; /* 802.11e QoS */ if( z + 16 > (int) pkh.caplen ) goto unlock_mx_apl; /* check the SNAP header to see if data is encrypted */ if( h80211[z] != h80211[z + 1] || h80211[z + 2] != 0x03 ) { ap_cur->crypt = 2; /* encryption = WEP */ /* check the extended IV flag */ if( ( h80211[z + 3] & 0x20 ) != 0 ) /* encryption = WPA */ ap_cur->crypt = 3; /* check the WEP key index */ if( opt.index != 0 && ( h80211[z + 3] >> 6 ) != opt.index - 1 ) goto unlock_mx_apl; if (opt.do_ptw) { unsigned char *body = h80211 + z; int dlen = pkh.caplen - (body-h80211) - 4 -4; unsigned char clear[2048]; int clearsize, i, j, k; int weight[16]; if((h80211[1] & 0x03) == 0x03) //30byte header { body += 6; dlen -=6; } memset(weight, 0, sizeof(weight)); memset(clear, 0, sizeof(clear)); /* calculate keystream */ k = known_clear(clear, &clearsize, weight, h80211, dlen); if (clearsize < (opt.keylen+3)) goto unlock_mx_apl; for (j=0; jptw_clean, body, clear, weight, k)) ap_cur->nb_ivs_clean++; } if (PTW_addsession(ap_cur->ptw_vague, body, clear, weight, k)) ap_cur->nb_ivs_vague++; goto unlock_mx_apl; } /* save the IV & first two output bytes */ memcpy( buffer , h80211 + z , 3 ); memcpy( buffer + 3, h80211 + z + 4, 2 ); /* Special handling for spanning-tree packets */ if ( memcmp( h80211 + 4, SPANTREE, 6 ) == 0 || memcmp( h80211 + 16, SPANTREE, 6 ) == 0 ) { buffer[3] = (buffer[3] ^ 0x42) ^ 0xAA; buffer[4] = (buffer[4] ^ 0x42) ^ 0xAA; } goto add_wep_iv; } if( ap_cur->crypt < 0 ) ap_cur->crypt = 0; /* no encryption */ /* if ethertype == IPv4, find the LAN address */ z += 6; if( z + 20 < (int) pkh.caplen ) { if( h80211[z] == 0x08 && h80211[z + 1] == 0x00 && ( h80211[1] & 3 ) == 0x01 ) memcpy( ap_cur->lanip, &h80211[z + 14], 4 ); if( h80211[z] == 0x08 && h80211[z + 1] == 0x06 ) memcpy( ap_cur->lanip, &h80211[z + 16], 4 ); } /* check ethertype == EAPOL */ if( h80211[z] != 0x88 || h80211[z + 1] != 0x8E ) goto unlock_mx_apl; z += 2; ap_cur->eapol = 1; /* type == 3 (key), desc. == 254 (WPA) or 2 (RSN) */ if( h80211[z + 1] != 0x03 || ( h80211[z + 4] != 0xFE && h80211[z + 4] != 0x02 ) ) goto unlock_mx_apl; ap_cur->eapol = 0; ap_cur->crypt = 3; /* set WPA */ if( st_cur == NULL ) { pthread_mutex_unlock( &mx_apl ); continue; } /* frame 1: Pairwise == 1, Install == 0, Ack == 1, MIC == 0 */ if( ( h80211[z + 6] & 0x08 ) != 0 && ( h80211[z + 6] & 0x40 ) == 0 && ( h80211[z + 6] & 0x80 ) != 0 && ( h80211[z + 5] & 0x01 ) == 0 ) { memcpy( st_cur->wpa.anonce, &h80211[z + 17], 32 ); /* authenticator nonce set */ st_cur->wpa.state = 1; } /* frame 2 or 4: Pairwise == 1, Install == 0, Ack == 0, MIC == 1 */ if( ( h80211[z + 6] & 0x08 ) != 0 && ( h80211[z + 6] & 0x40 ) == 0 && ( h80211[z + 6] & 0x80 ) == 0 && ( h80211[z + 5] & 0x01 ) != 0 ) { if( memcmp( &h80211[z + 17], ZERO, 32 ) != 0 ) { memcpy( st_cur->wpa.snonce, &h80211[z + 17], 32 ); /* supplicant nonce set */ st_cur->wpa.state |= 2; } if( (st_cur->wpa.state & 4) != 4 ) { /* copy the MIC & eapol frame */ st_cur->wpa.eapol_size = ( h80211[z + 2] << 8 ) + h80211[z + 3] + 4; memcpy( st_cur->wpa.keymic, &h80211[z + 81], 16 ); memcpy( st_cur->wpa.eapol, &h80211[z], st_cur->wpa.eapol_size ); memset( st_cur->wpa.eapol + 81, 0, 16 ); /* eapol frame & keymic set */ st_cur->wpa.state |= 4; /* copy the key descriptor version */ st_cur->wpa.keyver = h80211[z + 6] & 7; } } /* frame 3: Pairwise == 1, Install == 1, Ack == 1, MIC == 1 */ if( ( h80211[z + 6] & 0x08 ) != 0 && ( h80211[z + 6] & 0x40 ) != 0 && ( h80211[z + 6] & 0x80 ) != 0 && ( h80211[z + 5] & 0x01 ) != 0 ) { if( memcmp( &h80211[z + 17], ZERO, 32 ) != 0 ) { memcpy( st_cur->wpa.anonce, &h80211[z + 17], 32 ); /* authenticator nonce set */ st_cur->wpa.state |= 1; } if( (st_cur->wpa.state & 4) != 4 ) { /* copy the MIC & eapol frame */ st_cur->wpa.eapol_size = ( h80211[z + 2] << 8 ) + h80211[z + 3] + 4; memcpy( st_cur->wpa.keymic, &h80211[z + 81], 16 ); memcpy( st_cur->wpa.eapol, &h80211[z], st_cur->wpa.eapol_size ); memset( st_cur->wpa.eapol + 81, 0, 16 ); /* eapol frame & keymic set */ st_cur->wpa.state |= 4; /* copy the key descriptor version */ st_cur->wpa.keyver = h80211[z + 6] & 7; } } if( st_cur->wpa.state == 7 ) { /* got one valid handshake */ memcpy( st_cur->wpa.stmac, stmac, 6 ); memcpy( &ap_cur->wpa, &st_cur->wpa, sizeof( struct WPA_hdsk ) ); } unlock_mx_apl: pthread_mutex_unlock( &mx_apl ); if( ap_cur != NULL ) { if( ( ap_cur->nb_ivs >= opt.max_ivs) || ( ap_cur->nb_ivs_clean >= opt.max_ivs ) || ( ap_cur->nb_ivs_vague >= opt.max_ivs ) ) { eof_wait( &eof_notified ); return; } } } read_fail: if(rb.buf1 != NULL) { free(rb.buf1); rb.buf1=NULL; } if(rb.buf2 != NULL) { free(rb.buf2); rb.buf2=NULL; } if(buffer != NULL) { free(buffer); buffer=NULL; } if(close_aircrack) return; //everything is going down kill( 0, SIGTERM ); _exit( FAILURE ); } void check_thread( void *arg ) { int fd, n, z, fmt; read_buf rb; // int ret=0; uchar bssid[6]; uchar dest[6]; uchar stmac[6]; uchar *buffer; uchar *h80211; uchar *p; int weight[16]; struct ivs2_pkthdr ivs2; struct ivs2_filehdr fivs2; struct pcap_pkthdr pkh; struct pcap_file_header pfh; struct AP_info *ap_prv, *ap_cur; struct ST_info *st_prv, *st_cur; memset( &rb, 0, sizeof( rb ) ); ap_cur = NULL; if( ( buffer = (uchar *) malloc( 65536 ) ) == NULL ) { /* there is no buffer */ perror( "malloc failed" ); goto read_fail; } h80211 = buffer; if( ! opt.is_quiet ) printf( "Opening %s\n", (char *) arg ); if( strcmp( arg, "-" ) == 0 ) fd = 0; else { if( ( fd = open( (char *) arg, O_RDONLY | O_BINARY ) ) < 0 ) { perror( "open failed" ); goto read_fail; } } if( ! atomic_read( &rb, fd, 4, &pfh ) ) { perror( "read(file header) failed" ); goto read_fail; } fmt = FORMAT_IVS; if( memcmp( &pfh, IVSONLY_MAGIC, 4 ) != 0 && memcmp( &pfh, IVS2_MAGIC, 4 ) != 0) { fmt = FORMAT_CAP; if( pfh.magic != TCPDUMP_MAGIC && pfh.magic != TCPDUMP_CIGAM ) { fprintf( stderr, "Unsupported file format " "(not a pcap or IVs file).\n" ); goto read_fail; } /* read the rest of the pcap file header */ if( ! atomic_read( &rb, fd, 20, (uchar *) &pfh + 4 ) ) { perror( "read(file header) failed" ); goto read_fail; } /* take care of endian issues and check the link type */ if( pfh.magic == TCPDUMP_CIGAM ) SWAP32( pfh.linktype ); if( pfh.linktype != LINKTYPE_IEEE802_11 && pfh.linktype != LINKTYPE_PRISM_HEADER && pfh.linktype != LINKTYPE_RADIOTAP_HDR && pfh.linktype != LINKTYPE_PPI_HDR ) { fprintf( stderr, "This file is not a regular " "802.11 (wireless) capture.\n" ); goto read_fail; } } else { if( opt.wep_decloak ) { errx(1, "Can't use decloak wep mode with ivs\n"); /* XXX */ } if (memcmp( &pfh, IVS2_MAGIC, 4 ) == 0) { fmt = FORMAT_IVS2; if( ! atomic_read( &rb, fd, sizeof(struct ivs2_filehdr), (uchar *) &fivs2 ) ) { perror( "read(file header) failed" ); goto read_fail; } if(fivs2.version > IVS2_VERSION) { printf( "Error, wrong %s version: %d. Supported up to version %d.\n", IVS2_EXTENSION, fivs2.version, IVS2_VERSION ); goto read_fail; } } else if (opt.do_ptw) errx(1, "Can't do PTW with old IVS files, recapture without --ivs or use airodump-ng >= 1.0\n"); /* XXX */ } /* avoid blocking on reading the file */ if( fcntl( fd, F_SETFL, O_NONBLOCK ) < 0 ) { perror( "fcntl(O_NONBLOCK) failed" ); goto read_fail; } while( 1 ) { if(close_aircrack) break; if( fmt == FORMAT_IVS ) { /* read one IV */ while( ! atomic_read( &rb, fd, 1, buffer ) ) goto read_fail; if( buffer[0] != 0xFF ) { /* new access point MAC */ bssid[0] = buffer[0]; while( ! atomic_read( &rb, fd, 5, bssid + 1 ) ) goto read_fail; } while( ! atomic_read( &rb, fd, 5, buffer ) ) goto read_fail; } else if( fmt == FORMAT_IVS2 ) { while( ! atomic_read( &rb, fd, sizeof( struct ivs2_pkthdr ), &ivs2 ) ) goto read_fail; if(ivs2.flags & IVS2_BSSID) { while( ! atomic_read( &rb, fd, 6, bssid ) ) goto read_fail; ivs2.len -= 6; } while( ! atomic_read( &rb, fd, ivs2.len, buffer ) ) goto read_fail; } else { while( ! atomic_read( &rb, fd, sizeof( pkh ), &pkh ) ) goto read_fail; if( pfh.magic == TCPDUMP_CIGAM ) SWAP32( pkh.caplen ); if( pkh.caplen <= 0 || pkh.caplen > 65535 ) { fprintf( stderr, "\nInvalid packet capture length %d - " "corrupted file?\n", pkh.caplen ); goto read_fail; _exit( FAILURE ); } while( ! atomic_read( &rb, fd, pkh.caplen, buffer ) ) goto read_fail; h80211 = buffer; if( pfh.linktype == LINKTYPE_PRISM_HEADER ) { /* remove the prism header */ if( h80211[7] == 0x40 ) n = 64; else { n = *(int *)( h80211 + 4 ); if( pfh.magic == TCPDUMP_CIGAM ) SWAP32( n ); } if( n < 8 || n >= (int) pkh.caplen ) continue; h80211 += n; pkh.caplen -= n; } if( pfh.linktype == LINKTYPE_RADIOTAP_HDR ) { /* remove the radiotap header */ n = *(unsigned short *)( h80211 + 2 ); if( n <= 0 || n >= (int) pkh.caplen ) continue; h80211 += n; pkh.caplen -= n; } if( pfh.linktype == LINKTYPE_PPI_HDR ) { /* Remove the PPI header */ n = le16_to_cpu(*(unsigned short *)( h80211 + 2)); if( n <= 0 || n>= (int) pkh.caplen ) continue; /* for a whole Kismet logged broken PPI headers */ if ( n == 24 && le16_to_cpu(*(unsigned short *)(h80211 + 8)) == 2 ) n = 32; if( n <= 0 || n>= (int) pkh.caplen ) continue; h80211 += n; pkh.caplen -= n; } } /* prevent concurrent access on the linked list */ pthread_mutex_lock( &mx_apl ); nb_pkt++; if( fmt == FORMAT_CAP ) { /* skip packets smaller than a 802.11 header */ if( pkh.caplen < 24 ) goto unlock_mx_apl; /* skip (uninteresting) control frames */ if( ( h80211[0] & 0x0C ) == 0x04 ) goto unlock_mx_apl; /* locate the access point's MAC address */ switch( h80211[1] & 3 ) { case 0: memcpy( bssid, h80211 + 16, 6 ); break; //Adhoc case 1: memcpy( bssid, h80211 + 4, 6 ); break; //ToDS case 2: memcpy( bssid, h80211 + 10, 6 ); break; //FromDS case 3: memcpy( bssid, h80211 + 10, 6 ); break; //WDS -> Transmitter taken as BSSID } switch( h80211[1] & 3 ) { case 0: memcpy( dest, h80211 + 4, 6 ); break; //Adhoc case 1: memcpy( dest, h80211 + 16, 6 ); break; //ToDS case 2: memcpy( dest, h80211 + 4, 6 ); break; //FromDS case 3: memcpy( dest, h80211 + 16, 6 ); break; //WDS -> Transmitter taken as BSSID } //skip corrupted keystreams in wep decloak mode if(opt.wep_decloak) { if(dest[0] == 0x01) goto unlock_mx_apl; } } if(opt.bssidmerge) mergebssids(opt.bssidmerge, bssid); if( memcmp( bssid, BROADCAST, 6 ) == 0 ) /* probe request or such - skip the packet */ goto unlock_mx_apl; if( memcmp( opt.maddr, ZERO, 6 ) != 0 && memcmp( opt.maddr, BROADCAST, 6 ) != 0 ) { /* apply the MAC filter */ if( memcmp( opt.maddr, h80211 + 4, 6 ) != 0 && memcmp( opt.maddr, h80211 + 10, 6 ) != 0 && memcmp( opt.maddr, h80211 + 16, 6 ) != 0 ) goto unlock_mx_apl; } /* search the linked list */ ap_prv = NULL; ap_cur = ap_1st; while( ap_cur != NULL ) { if( ! memcmp( ap_cur->bssid, bssid, 6 ) ) break; ap_prv = ap_cur; ap_cur = ap_cur->next; } /* if it's a new access point, add it */ if( ap_cur == NULL ) { if( ! ( ap_cur = (struct AP_info *) malloc( sizeof( struct AP_info ) ) ) ) { perror( "malloc failed" ); break; } memset( ap_cur, 0, sizeof( struct AP_info ) ); if( ap_1st == NULL ) ap_1st = ap_cur; else ap_prv->next = ap_cur; memcpy( ap_cur->bssid, bssid, 6 ); ap_cur->crypt = -1; } if( fmt == FORMAT_IVS ) { ap_cur->crypt = 2; add_wep_iv: /* check for uniqueness first */ if( ap_cur->nb_ivs == 0 ) ap_cur->uiv_root = uniqueiv_init(); if( uniqueiv_check( ap_cur->uiv_root, buffer ) == 0 ) { uniqueiv_mark( ap_cur->uiv_root, buffer ); ap_cur->nb_ivs++; } goto unlock_mx_apl; } if( fmt == FORMAT_IVS2 ) { if(ivs2.flags & IVS2_ESSID) { memcpy( ap_cur->essid, buffer, ivs2.len); if(opt.essid_set && ! strcmp( opt.essid, ap_cur->essid ) ) memcpy( opt.bssid, ap_cur->bssid, 6 ); } else if(ivs2.flags & IVS2_XOR) { ap_cur->crypt = 2; if (opt.do_ptw) { int clearsize; clearsize = ivs2.len; if (clearsize < opt.keylen+3) goto unlock_mx_apl; } if( ap_cur->nb_ivs == 0 ) ap_cur->uiv_root = uniqueiv_init(); if( uniqueiv_check( ap_cur->uiv_root, buffer ) == 0 ) { uniqueiv_mark( ap_cur->uiv_root, buffer ); ap_cur->nb_ivs++; } } else if(ivs2.flags & IVS2_PTW) { ap_cur->crypt = 2; if (opt.do_ptw) { int clearsize; clearsize = ivs2.len; if (buffer[5] < opt.keylen) goto unlock_mx_apl; if( clearsize < (6 + buffer[4]*32 + 16*(signed)sizeof(int)) ) goto unlock_mx_apl; } if( ap_cur->nb_ivs == 0 ) ap_cur->uiv_root = uniqueiv_init(); if( uniqueiv_check( ap_cur->uiv_root, buffer ) == 0 ) { uniqueiv_mark( ap_cur->uiv_root, buffer ); ap_cur->nb_ivs++; } } else if(ivs2.flags & IVS2_WPA) { ap_cur->crypt = 3; memcpy( &ap_cur->wpa, buffer, sizeof( struct WPA_hdsk ) ); } goto unlock_mx_apl; } /* locate the station MAC in the 802.11 header */ st_cur = NULL; switch( h80211[1] & 3 ) { case 0: memcpy( stmac, h80211 + 10, 6 ); break; case 1: memcpy( stmac, h80211 + 10, 6 ); break; case 2: /* reject broadcast MACs */ if( (h80211[4]%2) != 0 ) goto skip_station; memcpy( stmac, h80211 + 4, 6 ); break; default: goto skip_station; break; } st_prv = NULL; st_cur = ap_cur->st_1st; while( st_cur != NULL ) { if( ! memcmp( st_cur->stmac, stmac, 6 ) ) break; st_prv = st_cur; st_cur = st_cur->next; } /* if it's a new supplicant, add it */ if( st_cur == NULL ) { if( ! ( st_cur = (struct ST_info *) malloc( sizeof( struct ST_info ) ) ) ) { perror( "malloc failed" ); break; } memset( st_cur, 0, sizeof( struct ST_info ) ); if( ap_cur->st_1st == NULL ) ap_cur->st_1st = st_cur; else st_prv->next = st_cur; memcpy( st_cur->stmac, stmac, 6 ); } skip_station: /* packet parsing: Beacon or Probe Response */ if( h80211[0] == 0x80 || h80211[0] == 0x50 ) { if( ap_cur->crypt < 0 ) ap_cur->crypt = ( h80211[34] & 0x10 ) >> 4; p = h80211 + 36; while( p < h80211 + pkh.caplen ) { if( p + 2 + p[1] > h80211 + pkh.caplen ) break; if( p[0] == 0x00 && p[1] > 0 && p[2] != '\0' ) { /* found a non-cloaked ESSID */ n = ( p[1] > 32 ) ? 32 : p[1]; memset( ap_cur->essid, 0, 33 ); memcpy( ap_cur->essid, p + 2, n ); if(opt.essid_set && ! strcmp( opt.essid, ap_cur->essid ) ) memcpy( opt.bssid, ap_cur->bssid, 6 ); } p += 2 + p[1]; } } /* packet parsing: Association Request */ if( h80211[0] == 0x00 ) { p = h80211 + 28; while( p < h80211 + pkh.caplen ) { if( p + 2 + p[1] > h80211 + pkh.caplen ) break; if( p[0] == 0x00 && p[1] > 0 && p[2] != '\0' ) { n = ( p[1] > 32 ) ? 32 : p[1]; memset( ap_cur->essid, 0, 33 ); memcpy( ap_cur->essid, p + 2, n ); if(opt.essid_set && ! strcmp( opt.essid, ap_cur->essid ) ) memcpy( opt.bssid, ap_cur->bssid, 6 ); } p += 2 + p[1]; } /* reset the WPA handshake state */ if( st_cur != NULL ) st_cur->wpa.state = 0; } /* packet parsing: Association Response */ if( h80211[0] == 0x10 ) { /* reset the WPA handshake state */ if( st_cur != NULL ) st_cur->wpa.state = 0; } /* check if data */ if( ( h80211[0] & 0x0C ) != 0x08 ) goto unlock_mx_apl; /* check minimum size */ z = ( ( h80211[1] & 3 ) != 3 ) ? 24 : 30; if ( ( h80211[0] & 0x80 ) == 0x80 ) z+=2; /* 802.11e QoS */ if( z + 16 > (int) pkh.caplen ) goto unlock_mx_apl; /* check the SNAP header to see if data is encrypted */ if( h80211[z] != h80211[z + 1] || h80211[z + 2] != 0x03 ) { ap_cur->crypt = 2; /* encryption = WEP */ /* check the extended IV flag */ if( ( h80211[z + 3] & 0x20 ) != 0 ) /* encryption = WPA */ ap_cur->crypt = 3; /* check the WEP key index */ if( opt.index != 0 && ( h80211[z + 3] >> 6 ) != opt.index - 1 ) goto unlock_mx_apl; if (opt.do_ptw) { unsigned char *body = h80211 + z; int dlen = pkh.caplen - (body-h80211) - 4 -4; unsigned char clear[2048]; int clearsize, k; if((h80211[1] & 0x03) == 0x03) //30byte header { body += 6; dlen -=6; } /* calculate keystream */ k = known_clear(clear, &clearsize, weight, h80211, dlen); if (clearsize < (opt.keylen+3)) goto unlock_mx_apl; } /* save the IV & first two output bytes */ memcpy( buffer , h80211 + z , 3 ); goto add_wep_iv; } if( ap_cur->crypt < 0 ) ap_cur->crypt = 0; /* no encryption */ /* if ethertype == IPv4, find the LAN address */ z += 6; if( z + 20 < (int) pkh.caplen ) { if( h80211[z] == 0x08 && h80211[z + 1] == 0x00 && ( h80211[1] & 3 ) == 0x01 ) memcpy( ap_cur->lanip, &h80211[z + 14], 4 ); if( h80211[z] == 0x08 && h80211[z + 1] == 0x06 ) memcpy( ap_cur->lanip, &h80211[z + 16], 4 ); } /* check ethertype == EAPOL */ if( h80211[z] != 0x88 || h80211[z + 1] != 0x8E ) goto unlock_mx_apl; z += 2; ap_cur->eapol = 1; /* type == 3 (key), desc. == 254 (WPA) or 2 (RSN) */ if( h80211[z + 1] != 0x03 || ( h80211[z + 4] != 0xFE && h80211[z + 4] != 0x02 ) ) goto unlock_mx_apl; ap_cur->eapol = 0; ap_cur->crypt = 3; /* set WPA */ if( st_cur == NULL ) { pthread_mutex_unlock( &mx_apl ); continue; } /* frame 1: Pairwise == 1, Install == 0, Ack == 1, MIC == 0 */ if( ( h80211[z + 6] & 0x08 ) != 0 && ( h80211[z + 6] & 0x40 ) == 0 && ( h80211[z + 6] & 0x80 ) != 0 && ( h80211[z + 5] & 0x01 ) == 0 ) { memcpy( st_cur->wpa.anonce, &h80211[z + 17], 32 ); /* authenticator nonce set */ st_cur->wpa.state = 1; } /* frame 2 or 4: Pairwise == 1, Install == 0, Ack == 0, MIC == 1 */ if( ( h80211[z + 6] & 0x08 ) != 0 && ( h80211[z + 6] & 0x40 ) == 0 && ( h80211[z + 6] & 0x80 ) == 0 && ( h80211[z + 5] & 0x01 ) != 0 ) { if( memcmp( &h80211[z + 17], ZERO, 32 ) != 0 ) { memcpy( st_cur->wpa.snonce, &h80211[z + 17], 32 ); /* supplicant nonce set */ st_cur->wpa.state |= 2; } if( (st_cur->wpa.state & 4) != 4 ) { /* copy the MIC & eapol frame */ st_cur->wpa.eapol_size = ( h80211[z + 2] << 8 ) + h80211[z + 3] + 4; memcpy( st_cur->wpa.keymic, &h80211[z + 81], 16 ); memcpy( st_cur->wpa.eapol, &h80211[z], st_cur->wpa.eapol_size ); memset( st_cur->wpa.eapol + 81, 0, 16 ); /* eapol frame & keymic set */ st_cur->wpa.state |= 4; /* copy the key descriptor version */ st_cur->wpa.keyver = h80211[z + 6] & 7; } } /* frame 3: Pairwise == 1, Install == 1, Ack == 1, MIC == 1 */ if( ( h80211[z + 6] & 0x08 ) != 0 && ( h80211[z + 6] & 0x40 ) != 0 && ( h80211[z + 6] & 0x80 ) != 0 && ( h80211[z + 5] & 0x01 ) != 0 ) { if( memcmp( &h80211[z + 17], ZERO, 32 ) != 0 ) { memcpy( st_cur->wpa.anonce, &h80211[z + 17], 32 ); /* authenticator nonce set */ st_cur->wpa.state |= 1; } if( (st_cur->wpa.state & 4) != 4 ) { /* copy the MIC & eapol frame */ st_cur->wpa.eapol_size = ( h80211[z + 2] << 8 ) + h80211[z + 3] + 4; memcpy( st_cur->wpa.keymic, &h80211[z + 81], 16 ); memcpy( st_cur->wpa.eapol, &h80211[z], st_cur->wpa.eapol_size ); memset( st_cur->wpa.eapol + 81, 0, 16 ); /* eapol frame & keymic set */ st_cur->wpa.state |= 4; /* copy the key descriptor version */ st_cur->wpa.keyver = h80211[z + 6] & 7; } } if( st_cur->wpa.state == 7 ) { /* got one valid handshake */ memcpy( st_cur->wpa.stmac, stmac, 6 ); memcpy( &ap_cur->wpa, &st_cur->wpa, sizeof( struct WPA_hdsk ) ); } unlock_mx_apl: pthread_mutex_unlock( &mx_apl ); if( ap_cur != NULL ) if( ap_cur->nb_ivs >= opt.max_ivs ) break; } read_fail: if(rb.buf1 != NULL) { free(rb.buf1); rb.buf1 = NULL; } if(rb.buf2 != NULL) { free(rb.buf2); rb.buf2 = NULL; } if(buffer != NULL) { free(buffer); buffer = NULL; } return; } /* timing routine */ float chrono( struct timeval *start, int reset ) { float delta; struct timeval current; gettimeofday( ¤t, NULL ); delta = ( current.tv_sec - start->tv_sec ) + (float) ( current.tv_usec - start->tv_usec ) / 1000000; if( reset ) gettimeofday( start, NULL ); return( delta ); } /* signal-safe I/O routines */ int safe_read( int fd, void *buf, size_t len ) { int n; size_t sum = 0; char *off = (char *) buf; while( sum < len ) { if( ! ( n = read( fd, (void *) off, len - sum ) ) ) { return( 0 ); } if( n < 0 && errno == EINTR ) continue; if( n < 0 ) return( n ); sum += n; off += n; } return( sum ); } int safe_write( int fd, void *buf, size_t len ) { int n; size_t sum = 0; char *off = (char *) buf; while( sum < len ) { if( ( n = write( fd, (void *) off, len - sum ) ) < 0 ) { if( errno == EINTR ) continue; return( n ); } sum += n; off += n; } return( sum ); } /* each thread computes the votes over a subset of the IVs */ int crack_wep_thread( void *arg ) { long xv, min, max; uchar jj[256]; uchar S[256], Si[256]; uchar K[64]; uchar io1, o1, io2, o2; uchar Sq, dq, Kq, jq, q; uchar S1, S2, J2, t2; int i, j, B, cid = (long) arg; int votes[N_ATTACKS][256]; //first: first S-Box Setup; first2:first round with new key; oldB: old B value int first=1, first2=1, oldB=0, oldq=0; memcpy( S, R, 256 ); memcpy( Si, R, 256 ); while( 1 ) { if(!first) oldB=B; if( safe_read( mc_pipe[cid][0], (void *) &B, sizeof( int ) ) != sizeof( int ) ) { perror( "read failed" ); kill( 0, SIGTERM ); _exit( FAILURE ); } if( close_aircrack ) break; first2=1; min = 5 * ( ( ( cid ) * wep.nb_ivs ) / opt.nbcpu ); max = 5 * ( ( ( 1 + cid ) * wep.nb_ivs ) / opt.nbcpu ); q = 3 + B; memcpy( K + 3, wep.key, B ); memset( votes, 0, sizeof( votes ) ); /* START: KoreK attacks */ for( xv = min; xv < max; xv += 5 ) { if(!first) { for(i=0; i= ( ( -q ) & 0xFF ) ) && ( ( ( q + S1 - io1 ) & 0xFF ) == 0 ) ) { Kq = 1 - dq; votes[A_u5_3][Kq]++; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= USE_IV; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= 1 << (4+A_u5_3); } } if( ( S1 < q ) && ( ( ( S1 + S[S1] - q ) & 0xFF ) == 0 ) && ( io1 != 1 ) && ( io1 != S[S1] ) ) { Kq = io1 - dq; votes[A_s5_1][Kq]++; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= USE_IV; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= 1 << (4+A_s5_1); } if( ( S1 > q ) && ( ( ( S2 + S1 - q ) & 0xFF ) == 0 ) ) { if( o2 == S1 ) { jq = Si[(S1 - S2) & 0xFF]; if( ( jq != 1 ) && ( jq != 2 ) ) { Kq = jq - dq; votes[A_s5_2][Kq]++; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= USE_IV; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= 1 << (4+A_s5_2); } } else if( o2 == ( ( 2 - S2 ) & 0xFF ) ) { jq = io2; if( ( jq != 1 ) && ( jq != 2 ) ) { Kq = jq - dq; votes[A_s5_3][Kq]++; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= USE_IV; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= 1 << (4+A_s5_3); } } } if( ( S[1] != 2 ) && ( S[2] != 0 ) ) { J2 = S[1] + S[2]; if( J2 < q ) { t2 = S[J2] + S[2]; if( ( t2 == q ) && ( io2 != 1 ) && ( io2 != 2 ) && ( io2 != J2 ) ) { Kq = io2 - dq; votes[A_s3][Kq]++; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= USE_IV; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= 1 << (4+A_s3); } } } if( S1 == 2 ) { if( q == 4 ) { if( o2 == 0 ) { Kq = Si[0] - dq; votes[A_4_s13][Kq]++; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= USE_IV; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= 1 << (4+A_4_s13); } else { if( ( jj[1] == 2 ) && ( io2 == 0 ) ) { Kq = Si[254] - dq; votes[A_4_u5_1][Kq]++; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= USE_IV; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= 1 << (4+A_4_u5_1); } if( ( jj[1] == 2 ) && ( io2 == 2 ) ) { Kq = Si[255] - dq; votes[A_4_u5_2][Kq]++; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= USE_IV; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= 1 << (4+A_4_u5_2); } } } else if( ( q > 4 ) && ( ( S[4] + 2 ) == q ) && ( io2 != 1 ) && ( io2 != 4 ) ) { Kq = io2 - dq; votes[A_u5_4][Kq]++; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= USE_IV; // all_ivs[256*256*K[0] + 256*K[1] + K[2]].used |= 1 << (4+A_u5_4); } } if( close_aircrack ) break; } if( close_aircrack ) break; /* END: KoreK attacks */ if( safe_write( cm_pipe[cid][1], votes, sizeof( votes ) ) != sizeof( votes ) ) { perror( "write failed" ); kill( 0, SIGTERM ); _exit( FAILURE ); } } return( 0 ); } /* display the current votes */ void show_wep_stats( int B, int force, PTW_tableentry table[PTW_KEYHSBYTES][PTW_n], int choices[KEYHSBYTES], int depth[KEYHSBYTES], int prod ) { float delta; struct winsize ws; int i, et_h, et_m, et_s; static int is_cleared = 0; if( (chrono( &t_stats, 0 ) < 1.51 || wepkey_crack_success) && force == 0 ) return; if( ioctl( 0, TIOCGWINSZ, &ws ) < 0 ) { ws.ws_row = 25; ws.ws_col = 80; } chrono( &t_stats, 1 ); delta = chrono( &t_begin, 0 ); et_h = delta / 3600; et_m = ( delta - et_h * 3600 ) / 60; et_s = delta - et_h * 3600 - et_m * 60; if( is_cleared == 0 ) { is_cleared++; if( opt.l33t ) printf( "\33[40m" ); printf( "\33[2J" ); } if( opt.l33t ) printf( "\33[34;1m" ); printf( "\33[2;%dH%s\n\n", (ws.ws_col - 12) / 2, progname ); if( opt.l33t ) printf( "\33[33;1m" ); if(table) printf( "\33[5;%dH[%02d:%02d:%02d] Tested %d keys (got %ld IVs)\33[K", (ws.ws_col - 44) / 2, et_h, et_m, et_s, prod, opt.ap->nb_ivs ); else printf( "\33[5;%dH[%02d:%02d:%02d] Tested %lld keys (got %ld IVs)\33[K", (ws.ws_col - 44) / 2, et_h, et_m, et_s, nb_tried, wep.nb_ivs_now ); if( opt.l33t ) printf( "\33[32;22m" ); printf( "\33[7;4HKB depth byte(vote)\n" ); for( i = 0; i <= B; i++ ) { int j, k = ( ws.ws_col - 20 ) / 11; if(!table) { if( opt.l33t ) printf( " %2d \33[1m%3d\33[22m/%3d ", i, wep.depth[i], wep.fudge[i] ); else printf( " %2d %3d/%3d ", i, wep.depth[i], wep.fudge[i] ); } else printf( " %2d %3d/%3d ", i, depth[i], choices[i] ); if(table) { for( j = depth[i]; j < k + depth[i]; j++ ) { if( j >= 256 ) break; if( opt.l33t ) printf( "\33[1m%02X\33[22m(%4d) ", table[i][j].b, table[i][j].votes ); else printf( "%02X(%4d) ", table[i][j].b, table[i][j].votes ); } } else { for( j = wep.depth[i]; j < k + wep.depth[i]; j++ ) { if( j >= 256 ) break; if( wep.poll[i][j].val == 32767 ) { if( opt.l33t ) printf( "\33[1m%02X\33[22m(+inf) ", wep.poll[i][j].idx ); else printf( "%02X(+inf) ", wep.poll[i][j].idx ); } else { if( opt.l33t ) printf( "\33[1m%02X\33[22m(%4d) ", wep.poll[i][j].idx, wep.poll[i][j].val ); else printf( "%02X(%4d) ", wep.poll[i][j].idx, wep.poll[i][j].val ); } } } if (opt.showASCII && !table) if(wep.poll[i][wep.depth[i]].idx>=ASCII_LOW_T && wep.poll[i][wep.depth[i]].idx<=ASCII_HIGH_T) if(wep.poll[i][wep.depth[i]].val>=ASCII_VOTE_STRENGTH_T || ASCII_DISREGARD_STRENGTH ) printf( " %c",wep.poll[i][wep.depth[i]].idx ); printf( "\n" ); } if( B < opt.keylen - 1 ) printf( "\33[J" ); printf( "\n" ); } static void key_found(unsigned char *wepkey, int keylen, int B) { FILE * keyFile; int i, n; int nb_ascii = 0; for( i = 0; i < keylen; i++ ) if( wepkey[i] == 0 || ( wepkey[i] >= 32 && wepkey[i] < 127 ) ) nb_ascii++; wepkey_crack_success = 1; memcpy(bf_wepkey, wepkey, keylen); if( opt.is_quiet ) printf( "KEY FOUND! [ " ); else { if (B != -1) show_wep_stats( B - 1, 1, NULL, NULL, NULL, 0 ); if( opt.l33t ) printf( "\33[31;1m" ); n = ( 80 - 14 - keylen * 3 ) / 2; if( 100 * nb_ascii > 75 * keylen ) n -= ( keylen + 4 ) / 2; if( n <= 0 ) n = 0; printf( "\33[K\33[%dCKEY FOUND! [ ", n ); } for( i = 0; i < keylen - 1; i++ ) printf( "%02X:", wepkey[i] ); printf( "%02X ] ", wepkey[i] ); if( nb_ascii == keylen ) { printf( "(ASCII: " ); for( i = 0; i < keylen; i++ ) printf( "%c", ( ( wepkey[i] > 31 && wepkey[i] < 127 ) || wepkey[i] > 160 ) ? wepkey[i] : '.' ); printf( " )" ); } if( opt.l33t ) printf( "\33[32;22m" ); printf( "\n\tDecrypted correctly: %d%%\n", opt.probability ); printf( "\n" ); // Write the key to a file if (opt.logKeyToFile != NULL) { keyFile = fopen(opt.logKeyToFile, "w"); if (keyFile != NULL) { for( i = 0; i < keylen; i++ ) fprintf(keyFile, "%02X", wepkey[i]); fclose(keyFile); } } } /* test if the current WEP key is valid */ int check_wep_key( uchar *wepkey, int B, int keylen ) { uchar x1, x2; unsigned long xv; int i, j, n, bad, tests; uchar K[64]; uchar S[256]; if (keylen<=0) keylen = opt.keylen; nb_tried++; bad = 0; memcpy( K + 3, wepkey, keylen ); tests = 32; // printf("keylen: %d\n", keylen); // if(keylen==13) // printf("%02X:%02X:%02X:%02X:%02X\n", wepkey[8],wepkey[9],wepkey[10],wepkey[11],wepkey[12]); if(opt.dict) tests = wep.nb_ivs; if(tests < TEST_MIN_IVS) tests=TEST_MIN_IVS; if(tests > TEST_MAX_IVS) tests=TEST_MAX_IVS; for( n = 0; n < tests; n++ ) { /* xv = 5 * ( rand() % wep.nb_ivs ); */ xv = 5 * n; pthread_mutex_lock( &mx_ivb ); memcpy( K, &wep.ivbuf[xv], 3 ); memcpy( S, R, 256 ); for( i = j = 0; i < 256; i++ ) { j = ( j + S[i] + K[i % (3 + keylen)]) & 0xFF; SWAP( S[i], S[j] ); } i = 1; j = ( 0 + S[i] ) & 0xFF; SWAP(S[i], S[j]); x1 = wep.ivbuf[xv + 3] ^ S[(S[i] + S[j]) & 0xFF]; i = 2; j = ( j + S[i] ) & 0xFF; SWAP(S[i], S[j]); x2 = wep.ivbuf[xv + 4] ^ S[(S[i] + S[j]) & 0xFF]; pthread_mutex_unlock( &mx_ivb ); // printf("xv: %li x1: %02X x2: %02X\n", (xv/5), x1, x2); if( ( x1 != 0xAA || x2 != 0xAA ) && ( x1 != 0xE0 || x2 != 0xE0 ) && ( x1 != 0x42 || x2 != 0x42 ) && ( x1 != 0x02 || x2 != 0xAA ) ) //llc sub layer management bad++; if( bad > ((tests*opt.probability)/100) ) return( FAILURE ); } opt.probability = (((tests-bad)*100)/tests); key_found(wepkey, keylen, B); return( SUCCESS ); } /* routine used to sort the votes */ int cmp_votes( const void *bs1, const void *bs2 ) { if( ((vote *) bs1)->val < ((vote *) bs2)->val ) return( 1 ); if( ((vote *) bs1)->val > ((vote *) bs2)->val ) return( -1 ); return( 0 ); } /* sum up the votes and sort them */ int calc_poll( int B ) { int i, n, cid, *vi; int votes[N_ATTACKS][256]; memset(&opt.votes, '\0', sizeof(opt.votes)); /* send the current keybyte # to each thread */ for( cid = 0; cid < opt.nbcpu; cid++ ) { n = sizeof( int ); if( safe_write( mc_pipe[cid][1], &B, n ) != n ) { perror( "write failed" ); kill( 0, SIGTERM ); _exit( FAILURE ); } } /* collect the votes, multiply by the korek coeffs */ for( i = 0; i < 256; i++ ) { wep.poll[B][i].idx = i; wep.poll[B][i].val = 0; } for( cid = 0; cid < opt.nbcpu; cid++ ) { n = sizeof( votes ); if( safe_read( cm_pipe[cid][0], votes, n ) != n ) { perror( "read failed" ); kill( 0, SIGTERM ); _exit( FAILURE ); } for( n = 0, vi = (int *) votes; n < N_ATTACKS; n++ ) for( i = 0; i < 256; i++, vi++ ) { wep.poll[B][i].val += *vi * K_COEFF[n]; if(K_COEFF[n]) opt.votes[n] += *vi; } } /* set votes to the max if the keybyte is user-defined */ if( opt.debug_row[B] ) wep.poll[B][opt.debug[B]].val = 32767; /* if option is set, restrict keyspace to alpha-numeric */ if( opt.is_alnum ) { for( i = 1; i < 32; i++ ) wep.poll[B][i].val = -1; for( i = 127; i < 256; i++ ) wep.poll[B][i].val = -1; } if( opt.is_fritz ) { for( i = 0; i < 48; i++ ) wep.poll[B][i].val = -1; for( i = 58; i < 256; i++ ) wep.poll[B][i].val = -1; } /* if option is set, restrict keyspace to BCD hex digits */ if( opt.is_bcdonly ) { for( i = 1; i < 256; i++ ) if( i > 0x99 || ( i & 0x0F ) > 0x09 ) wep.poll[B][i].val = -1; } /* sort the votes, highest ones first */ qsort( wep.poll[B], 256, sizeof( vote ), cmp_votes ); return( SUCCESS ); } int update_ivbuf( void ) { int n; struct AP_info *ap_cur; /* 1st pass: compute the total number of available IVs */ wep.nb_ivs_now = 0; wep.nb_aps = 0; ap_cur = ap_1st; while( ap_cur != NULL ) { if( ap_cur->crypt == 2 && ap_cur->target ) { wep.nb_ivs_now += ap_cur->nb_ivs; wep.nb_aps++; } ap_cur = ap_cur->next; } /* 2nd pass: create the main IVs buffer if necessary */ if( wep.nb_ivs == 0 || ( opt.keylen == 5 && wep.nb_ivs_now - wep.nb_ivs > 20000 ) || ( opt.keylen >= 13 && wep.nb_ivs_now - wep.nb_ivs > 40000 ) ) { /* one buffer to rule them all */ pthread_mutex_lock( &mx_ivb ); if( wep.ivbuf != NULL ) { free( wep.ivbuf ); wep.ivbuf = NULL; } wep.nb_ivs = 0; ap_cur = ap_1st; while( ap_cur != NULL ) { if( ap_cur->crypt == 2 && ap_cur->target ) { n = ap_cur->nb_ivs; if( ( wep.ivbuf = realloc( wep.ivbuf, ( wep.nb_ivs + n ) * 5 ) ) == NULL ) { pthread_mutex_unlock( &mx_ivb ); perror( "realloc failed" ); kill( 0, SIGTERM ); _exit( FAILURE ); } memcpy( wep.ivbuf + wep.nb_ivs * 5, ap_cur->ivbuf, 5 * n ); wep.nb_ivs += n; } ap_cur = ap_cur->next; } pthread_mutex_unlock( &mx_ivb ); return( RESTART ); } return( SUCCESS ); } /* * It will remove votes for a specific keybyte (and remove from the requested current value) * Return 0 on success, another value on failure */ int remove_votes(int keybyte, unsigned char value) { int i; int found = 0; for (i=0; i < 256; i++) { if (wep.poll[keybyte][i].idx == (int)value) { found = 1; //wep.poll[keybyte][i].val = 0; // Update wep.key } if (found) { // Put the value at the end with NO votes if (i== 255) { wep.poll[keybyte][i].idx = (int)value; wep.poll[keybyte][i].val = 0; } else { wep.poll[keybyte][i].idx = wep.poll[keybyte][i + 1].idx; wep.poll[keybyte][i].val = wep.poll[keybyte][i + 1].val; if (i == 0) { // Also update wep key if it's the first value to remove wep.key[keybyte] = wep.poll[keybyte][i].idx; } } } } return 0; } /* standard attack mode: */ /* this routine gathers and sorts the votes, then recurses until it * * reaches B == keylen. It also stops when the current keybyte vote * * is lower than the highest vote divided by the fudge factor. */ int do_wep_crack1( int B ) { int i, j, l, m, tsel, charread, askchange; int remove_keybyte_nr, remove_keybyte_value; //int a,b; static int k = 0; char user_guess[4]; askchange = 1; get_ivs: switch( update_ivbuf() ) { case FAILURE: return( FAILURE ); case RESTART: return( RESTART ); default: break; } if( ( wep.nb_ivs_now < 256 && opt.debug[0] == 0 ) || ( wep.nb_ivs_now < 32 && opt.debug[0] != 0 ) ) { if( ! opt.no_stdin ) { printf( "Not enough IVs available. You need about 250.000 IVs to crack\n" "40-bit WEP, and more than 800.000 IVs to crack a 104-bit key.\n" ); kill( 0, SIGTERM ); _exit( FAILURE ); } else { printf( "Read %ld packets, got %ld IVs...\r", nb_pkt, wep.nb_ivs_now ); fflush( stdout ); sleep( 1 ); goto get_ivs; } } /* if last keybyte reached, check if the key is valid */ if( B == opt.keylen ) { if( ! opt.is_quiet ) show_wep_stats( B - 1, 0, NULL, NULL, NULL, 0 ); return( check_wep_key( wep.key, B, 0 ) ); } /* now compute the poll resultst for keybyte B */ if( calc_poll( B ) != SUCCESS ) return( FAILURE ); /* fudge threshold = higest vote divided by fudge factor */ for( wep.fudge[B] = 1; wep.fudge[B] < 256; wep.fudge[B]++ ) if( (float) wep.poll[B][wep.fudge[B]].val < (float) wep.poll[B][0].val / opt.ffact ) break; /* try the most likely n votes, where n is the fudge threshold */ for( wep.depth[B] = 0; wep.depth[B] < wep.fudge[B]; ( wep.depth[B] )++ ) { switch( update_ivbuf() ) { case FAILURE: return( FAILURE ); case RESTART: return( RESTART ); default: break; } wep.key[B] = wep.poll[B][wep.depth[B]].idx; if( ! opt.is_quiet ) { show_wep_stats( B, 0, NULL, NULL, NULL, 0 ); } if( B == 4 && opt.keylen == 13 ) { /* even when cracking 104-bit WEP, * * check if the 40-bit key matches */ /* opt.keylen = 5; many functions use keylen. it is dangerous to do this in a multithreaded process */ if( check_wep_key( wep.key, B, 5 ) == SUCCESS ) { opt.keylen = 5; return( SUCCESS ); } /* opt.keylen = 13; */ } if( B + opt.do_brute + 1 == opt.keylen && opt.do_brute ) { /* as noted by Simon Marechal, it's more efficient * to just bruteforce the last two keybytes. */ /* Ask for removing votes here 1. Input keybyte. Use enter when it's done => Bruteforce will start 2. Input value to remove votes from: 00 -> FF or Enter to cancel remove 3. Remove votes 4. Redraw 5. Go back to 1 */ if (opt.visual_inspection == 1) { while(1) { // Show the current stat show_wep_stats( B, 1, NULL, NULL, NULL, 0 ); // Inputting user value until it hits enter or give a valid value printf("On which keybyte do you want to remove votes (Hit Enter when done)? "); memset(user_guess, 0, 4); charread = readLine(user_guess, 3); // Break if 'Enter' key was hit if (user_guess[0] == 0 || charread == 0) break; // If it's not a number, reask // Check if inputted value is correct (from 0 to and inferior to opt.keylen) remove_keybyte_nr = atoi(user_guess); if (isdigit((int)user_guess[0]) == 0 || remove_keybyte_nr < 0 || remove_keybyte_nr >= opt.keylen) continue; // It's a number for sure and the number is correct // Now ask which value should be removed printf("From which keybyte value do you want to remove the votes (Hit Enter to cancel)? "); memset(user_guess, 0, 4); charread = readLine(user_guess, 3); // Break if enter was hit if (user_guess[0] == 0 || charread == 0) continue; remove_keybyte_value = hexToInt(user_guess, charread); // Check if inputted value is correct (hexa). Value range: 00 - FF if (remove_keybyte_value < 0 || remove_keybyte_value > 255) continue; // If correct, remove and redraw remove_votes(remove_keybyte_nr, (unsigned char)remove_keybyte_value); } } if (opt.nbcpu==1 || opt.do_mt_brute==0) { if (opt.do_brute==4) { for( l = 0; l < 256; l++) { wep.key[opt.brutebytes[0]] = l; for( m = 0; m < 256; m++ ) { wep.key[opt.brutebytes[1]] = m; for( i = 0; i < 256; i++ ) { wep.key[opt.brutebytes[2]] = i; for( j = 0; j < 256; j++ ) { wep.key[opt.brutebytes[3]] = j; if (check_wep_key( wep.key, B + 1, 0 ) == SUCCESS) return SUCCESS; } } } } } else if (opt.do_brute==3) { for( m = 0; m < 256; m++ ) { wep.key[opt.brutebytes[0]] = m; for( i = 0; i < 256; i++ ) { wep.key[opt.brutebytes[1]] = i; for( j = 0; j < 256; j++ ) { wep.key[opt.brutebytes[2]] = j; if (check_wep_key( wep.key, B + 1, 0 ) == SUCCESS) return SUCCESS; } } } } else if (opt.do_brute==2) { for( i = 0; i < 256; i++ ) { wep.key[opt.brutebytes[0]] = i; for( j = 0; j < 256; j++ ) { wep.key[opt.brutebytes[1]] = j; if (check_wep_key( wep.key, B + 1, 0 ) == SUCCESS) return SUCCESS; } } } else { for( i = 0; i < 256; i++ ) { wep.key[opt.brutebytes[0]] = i; if (check_wep_key( wep.key, B + 1, 0 ) == SUCCESS) return SUCCESS; } } } else { /* multithreaded bruteforcing of the last 2 keybytes */ k = (k+1) % opt.nbcpu; do { for(tsel=0; tsel16) { usleep(1); continue; } else { /* write our current key to the pipe so it'll have its last 2 bytes bruteforced */ bf_nkeys[(tsel+k) % opt.nbcpu]++; if (safe_write(bf_pipe[(tsel+k) % opt.nbcpu][1], (void *) wep.key, 64) != 64) { perror( "write pmk failed" ); kill( 0, SIGTERM ); _exit( FAILURE ); } break; } } } while (tsel>=opt.nbcpu && !wepkey_crack_success); if (wepkey_crack_success) { memcpy(wep.key, bf_wepkey, opt.keylen); return(SUCCESS); } } } else { switch( do_wep_crack1( B + 1 ) ) { case SUCCESS: return( SUCCESS ); case RESTART: return( RESTART ); default: break; } } } //if we are going to fail on the root byte, check again if there are still threads bruting, if so wait and check again. if(B==0) { for(i=0; i0 && !wepkey_crack_success) usleep(1); } if (wepkey_crack_success) { memcpy(wep.key, bf_wepkey, opt.keylen); return(SUCCESS); } } return( FAILURE ); } /* experimental single bruteforce attack */ int do_wep_crack2( int B ) { int i, j; switch( update_ivbuf() ) { case FAILURE: return( FAILURE ); case RESTART: return( RESTART ); default: break; } if( wep.nb_ivs_now / opt.keylen < 60000 ) { printf( "Not enough IVs available. This option is only meant to be used\n" "if the standard attack method fails with more than %d IVs.\n", opt.keylen * 60000 ); kill( 0, SIGTERM ); _exit( FAILURE ); } for( i = 0; i <= B; i++ ) { if( calc_poll( i ) != SUCCESS ) return( FAILURE ); wep.key[i] = wep.poll[i][0].idx; wep.fudge[i] = 1; wep.depth[i] = 0; if( ! opt.is_quiet ) show_wep_stats( i, 0, NULL, NULL, NULL, 0 ); } for( wep.fudge[B] = 1; wep.fudge[B] < 256; wep.fudge[B]++ ) if( (float) wep.poll[B][wep.fudge[B]].val < (float) wep.poll[B][0].val / opt.ffact ) break; for( wep.depth[B] = 0; wep.depth[B] < wep.fudge[B]; wep.depth[B]++ ) { switch( update_ivbuf() ) { case FAILURE: return( FAILURE ); case RESTART: return( RESTART ); default: break; } wep.key[B] = wep.poll[B][wep.depth[B]].idx; if( ! opt.is_quiet ) show_wep_stats( B, 0, NULL, NULL, NULL, 0 ); for( i = B + 1; i < opt.keylen - 2; i++ ) { if( calc_poll( i ) != SUCCESS ) return( FAILURE ); wep.key[i] = wep.poll[i][0].idx; wep.fudge[i] = 1; wep.depth[i] = 0; if( ! opt.is_quiet ) show_wep_stats( i, 0, NULL, NULL, NULL, 0 ); } for( i = 0; i < 256; i++ ) { wep.key[opt.keylen - 2] = i; for( j = 0; j < 256; j++ ) { wep.key[opt.keylen - 1] = j; if( check_wep_key( wep.key, opt.keylen - 2, 0 ) == SUCCESS ) return( SUCCESS ); } } } return( FAILURE ); } int inner_bruteforcer_thread(void *arg) { int i, j, k, l, reduce=0; size_t nthread = (size_t)arg; uchar wepkey[64]; int ret=0; inner_bruteforcer_thread_start: reduce=0; if( close_aircrack ) return(ret); if (wepkey_crack_success) return(SUCCESS); /* we get the key for which we'll bruteforce the last 2 bytes from the pipe */ if( safe_read( bf_pipe[nthread][0], (void *) wepkey, 64) != 64) { perror( "read failed" ); kill( 0, SIGTERM ); _exit( FAILURE ); } else reduce=1; if( close_aircrack ) return(ret); /* now we test the 256*256 keys... if we succeed we'll save it and exit the thread */ if (opt.do_brute==4) { for( l = 0; l < 256; l++ ) { wepkey[opt.brutebytes[0]] = l; for( k = 0; k < 256; k++ ) { wepkey[opt.brutebytes[1]] = k; for( i = 0; i < 256; i++ ) { wepkey[opt.brutebytes[2]] = i; for( j = 0; j < 256; j++ ) { wepkey[opt.brutebytes[3]] = j; if( check_wep_key( wepkey, opt.keylen - 2, 0 ) == SUCCESS ) return(SUCCESS); } } } } } else if (opt.do_brute==3) { for( k = 0; k < 256; k++ ) { wepkey[opt.brutebytes[0]] = k; for( i = 0; i < 256; i++ ) { wepkey[opt.brutebytes[1]] = i; for( j = 0; j < 256; j++ ) { wepkey[opt.brutebytes[2]] = j; if( check_wep_key( wepkey, opt.keylen - 2, 0 ) == SUCCESS ) return(SUCCESS); } } } } else if (opt.do_brute==2) { for( i = 0; i < 256; i++ ) { wepkey[opt.brutebytes[0]] = i; for( j = 0; j < 256; j++ ) { wepkey[opt.brutebytes[1]] = j; if( check_wep_key( wepkey, opt.keylen - 2, 0 ) == SUCCESS ) return(SUCCESS); } } } else { for( j = 0; j < 256; j++ ) { wepkey[opt.brutebytes[0]] = j; if( check_wep_key( wepkey, opt.keylen - 2, 0 ) == SUCCESS ) return(SUCCESS); } } if(reduce) bf_nkeys[nthread]--; goto inner_bruteforcer_thread_start; } /* display the current wpa key info, matrix-like */ void show_wpa_stats( char *key, int keylen, uchar pmk[32], uchar ptk[64], uchar mic[16], int force ) { float delta; int i, et_h, et_m, et_s; char tmpbuf[28]; if (chrono( &t_stats, 0 ) < 0.15 && force == 0) return; if (force != 0) pthread_mutex_lock(&mx_wpastats); // if forced, wait until we can lock else if (pthread_mutex_trylock(&mx_wpastats) != 0) // if not forced, just try return; chrono( &t_stats, 1 ); delta = chrono( &t_begin, 0 ); et_h = delta / 3600; et_m = ( delta - et_h * 3600 ) / 60; et_s = delta - et_h * 3600 - et_m * 60; if( ( delta = chrono( &t_kprev, 0 ) ) >= 6 ) { int delta0; delta0 = delta; t_kprev.tv_sec += 3; delta = chrono( &t_kprev, 0 ); nb_kprev *= delta / delta0; } if( opt.l33t ) printf( "\33[33;1m" ); printf( "\33[5;20H[%02d:%02d:%02d] %lld keys tested " "(%2.2f k/s)", et_h, et_m, et_s, nb_tried, (float) nb_kprev / delta); memset( tmpbuf, ' ', sizeof( tmpbuf ) ); memcpy( tmpbuf, key, keylen > 27 ? 27 : keylen ); tmpbuf[27] = '\0'; if( opt.l33t ) printf( "\33[37;1m" ); printf( "\33[8;24HCurrent passphrase: %s\n", tmpbuf ); if( opt.l33t ) printf( "\33[32;22m" ); printf( "\33[11;7HMaster Key : " ); if( opt.l33t ) printf( "\33[32;1m" ); for( i = 0; i < 32; i++ ) { if( i == 16 ) printf( "\n\33[23C" ); printf( "%02X ", pmk[i] ); } if( opt.l33t ) printf( "\33[32;22m" ); printf( "\33[14;7HTransient Key : " ); if( opt.l33t ) printf( "\33[32;1m" ); for( i = 0; i < 64; i++ ) { if( i > 0 && i % 16 == 0 ) printf( "\n\33[23C" ); printf( "%02X ", ptk[i] ); } if( opt.l33t ) printf( "\33[32;22m" ); printf( "\33[19;7HEAPOL HMAC : " ); if( opt.l33t ) printf( "\33[32;1m" ); for( i = 0; i < 16; i++ ) printf( "%02X ", mic[i] ); printf( "\n" ); pthread_mutex_unlock(&mx_wpastats); } int crack_wpa_thread( void *arg ) { FILE * keyFile; char essid[36]; char key[4][128]; uchar pmk[4][128]; uchar pke[100]; uchar ptk[4][80]; uchar mic[4][20]; struct WPA_data* data; struct AP_info* ap; int thread; int ret=0; int i, j, len, slen; int nparallel = 1; #if defined(__i386__) || defined(__x86_64__) // Check for SSE2, with SSE2 the algorithm works with 4 keys if (shasse2_cpuid()>=2) nparallel = 4; #endif data = (struct WPA_data*)arg; ap = data->ap; thread = data->thread; strncpy(essid, ap->essid, 36); /* pre-compute the key expansion buffer */ memcpy( pke, "Pairwise key expansion", 23 ); if( memcmp( ap->wpa.stmac, ap->bssid, 6 ) < 0 ) { memcpy( pke + 23, ap->wpa.stmac, 6 ); memcpy( pke + 29, ap->bssid, 6 ); } else { memcpy( pke + 23, ap->bssid, 6 ); memcpy( pke + 29, ap->wpa.stmac, 6 ); } if( memcmp( ap->wpa.snonce, ap->wpa.anonce, 32 ) < 0 ) { memcpy( pke + 35, ap->wpa.snonce, 32 ); memcpy( pke + 67, ap->wpa.anonce, 32 ); } else { memcpy( pke + 35, ap->wpa.anonce, 32 ); memcpy( pke + 67, ap->wpa.snonce, 32 ); } /* receive the essid */ slen = strlen(essid) + 4; while( 1 ) { if (close_aircrack) pthread_exit(&ret); /* receive passphrases */ for(j=0; jwpa.keyver == 1) HMAC(EVP_md5(), ptk[j], 16, ap->wpa.eapol, ap->wpa.eapol_size, mic[j], NULL); else HMAC(EVP_sha1(), ptk[j], 16, ap->wpa.eapol, ap->wpa.eapol_size, mic[j], NULL); if (memcmp( mic[j], ap->wpa.keymic, 16 ) == 0) { // to stop do_wpa_crack, we close the dictionary if(opt.dict != NULL) { if (!opt.stdin_dict) fclose(opt.dict); opt.dict = NULL; } for( i = 0; i < opt.nbcpu; i++ ) { // we make sure do_wpa_crack doesn't block before exiting, // now that we're not consuming passphrases here any longer pthread_mutex_lock(&wpa_data[i].mutex); pthread_cond_signal(&wpa_data[i].cond); pthread_mutex_unlock(&wpa_data[i].mutex); } memcpy(data->key, key[j], sizeof(data->key)); if (opt.is_quiet) return SUCCESS; pthread_mutex_lock(&mx_nb); nb_tried += 4; nb_kprev += 4; pthread_mutex_unlock(&mx_nb); len = strlen(key[j]); if (len > 64 ) len = 64; if (len < 8) len = 8; show_wpa_stats( key[j], len, pmk[j], ptk[j], mic[j], 1 ); if (opt.l33t) printf( "\33[31;1m" ); printf("\33[8;%dH\33[2KKEY FOUND! [ %s ]\33[11B\n", ( 80 - 15 - (int) len ) / 2, key[j] ); if (opt.l33t) printf( "\33[32;22m" ); // Write the key to a file if (opt.logKeyToFile != NULL) { keyFile = fopen(opt.logKeyToFile, "w"); if (keyFile != NULL) { fprintf(keyFile, "%s", key[j]); fclose(keyFile); } } return SUCCESS; } } pthread_mutex_lock(&mx_nb); nb_tried += 4; nb_kprev += 4; pthread_mutex_unlock(&mx_nb); if (!opt.is_quiet) { len = strlen(key[0]); if (len > 64 ) len = 64; if (len < 8) len = 8; show_wpa_stats(key[0], len, pmk[0], ptk[0], mic[0], 0); } } } /** * Open a specific dictionnary * nb: index of the dictionnary * return 0 on success and FAILURE if it failed */ int next_dict(int nb) { if(opt.dict != NULL) { if(!opt.stdin_dict) fclose(opt.dict); opt.dict = NULL; } opt.nbdict = nb; if(opt.dicts[opt.nbdict] == NULL) return( FAILURE ); while(opt.nbdict < MAX_DICTS && opt.dicts[opt.nbdict] != NULL) { if( strcmp( opt.dicts[opt.nbdict], "-" ) == 0 ) { opt.stdin_dict = 1; if( ( opt.dict = fdopen( fileno(stdin) , "r" ) ) == NULL ) { perror( "fopen(dictionary) failed" ); opt.nbdict++; continue; } opt.no_stdin = 1; } else { opt.stdin_dict = 0; if( ( opt.dict = fopen( opt.dicts[opt.nbdict], "r" ) ) == NULL ) { perror( "fopen(dictionary) failed" ); opt.nbdict++; continue; } fseek(opt.dict, 0L, SEEK_END); if ( ftell( opt.dict ) <= 0L ) { fclose( opt.dict ); opt.dict = NULL; printf( "Empty dictionary\n" ); opt.nbdict++; continue; } rewind( opt.dict ); } break; } if(opt.nbdict >= MAX_DICTS || opt.dicts[opt.nbdict] == NULL) return( FAILURE ); return( 0 ); } #ifdef HAVE_SQLITE int sql_wpacallback(void* arg, int ccount, char** values, char** columnnames ) { struct AP_info *ap = (struct AP_info*)arg; unsigned char ptk[80]; unsigned char mic[20]; FILE * keyFile; if(ccount) {} //XXX if(columnnames) {} //XXX calc_mic(ap, (unsigned char*) values[0], ptk, mic); if( memcmp( mic, ap->wpa.keymic, 16 ) == 0 ) { // Write the key to a file if (opt.logKeyToFile != NULL) { keyFile = fopen(opt.logKeyToFile, "w"); if (keyFile != NULL) { fprintf(keyFile, "%s", values[1]); fclose(keyFile); } } if( opt.is_quiet ) { printf( "KEY FOUND! [ %s ]\n", values[1] ); return 1; } show_wpa_stats( values[1], strlen(values[1]), (unsigned char*)(values[0]), ptk, mic, 1 ); if( opt.l33t ) printf( "\33[31;1m" ); printf( "\33[8;%dH\33[2KKEY FOUND! [ %s ]\33[11B\n", ( 80 - 15 - (int) strlen(values[1])) / 2, values[1] ); if( opt.l33t ) printf( "\33[32;22m" ); // abort the query return 1; } nb_tried++; nb_kprev++; if( ! opt.is_quiet ) show_wpa_stats( values[1], strlen(values[1]), (unsigned char*)(values[0]), ptk, mic, 0 ); return 0; } #endif int do_wpa_crack() { int i, j, cid, num_cpus, res; char key1[128]; i = 0; res = 0; opt.amode = 2; num_cpus = opt.nbcpu; if( ! opt.is_quiet ) { if( opt.l33t ) printf( "\33[37;40m" ); printf( "\33[2J" ); if( opt.l33t ) printf( "\33[34;1m" ); printf("\33[2;34H%s",progname); } cid = 0; while( num_cpus > 0 ) { /* read a couple of keys (skip those < 8 chars) */ if(opt.dict == NULL) return( FAILURE ); do { memset(key1, 0, sizeof(key1)); if (fgets(key1, sizeof(key1), opt.dict) == NULL) { if( opt.l33t ) printf( "\33[32;22m" ); /* printf( "\nPassphrase not in dictionary %s \n", opt.dicts[opt.nbdict] );*/ if(next_dict(opt.nbdict+1) != 0) { /* no more words, but we still have to wait for the cracking threads */ num_cpus = cid; //goto collect_and_test; return( FAILURE ); } else continue; } i = strlen( key1 ); if( i < 8 ) continue; if( i > 64 ) i = 64; while(i>0 && (key1[i-1]=='\r' || key1[i-1]=='\n')) i--; if (i==0) continue; key1[i] = '\0'; for(j=0; j 2 || strlen(hex) == 0) { rtn = 1; break; } if(sscanf(hex, "%x", &dec) == 0 ) { rtn = 1; break; } (*key)[i] = dec; hex = strsep(&tmp, ":"); i++; } if(rtn) { continue; } } else { if( fgets( *key, keysize, opt.dict ) == NULL ) { if( opt.l33t ) printf( "\33[32;22m" ); // printf( "\nPassphrase not in dictionary \"%s\" \n", opt.dicts[opt.nbdict] ); if(next_dict(opt.nbdict+1) != 0) { free(tmp); tmp = NULL; return( FAILURE ); } else { continue; } } i=strlen(*key); if( i <= 2 ) continue; if( (*key)[i - 1] == '\n' ) (*key)[--i] = '\0'; if( (*key)[i - 1] == '\r' ) (*key)[--i] = '\0'; if( i <= 0 ) continue; } break; } free(tmp); tmp = NULL; return( SUCCESS ); } int set_dicts(char* optargs) { int len; char *optarg; opt.nbdict = 0; optarg = strsep(&optargs, ","); for(len=0; len 0) { show_wep_stats(opt.keylen - 1, 1, NULL, NULL, NULL, 0); gettimeofday( &t_last, NULL); } } for(i=0; i<=opt.keylen; i++) { wep.key[i] = (uchar)key[i]; } if(check_wep_key(wep.key, opt.keylen, 0) == SUCCESS) return( SUCCESS ); } } static int crack_wep_ptw(struct AP_info *ap_cur) { int (* all)[256]; int i, j, len = 0; opt.ap = ap_cur; all = malloc(256*32*sizeof(int)); if (all == NULL) { return FAILURE; } //initial setup (complete keyspace) for (i = 0; i < 32; i++) { for (j = 0; j < 256; j++) { all[i][j] = 1; } } //setting restricted keyspace for (i = 0; i < 32; i++) { for (j = 0; j < 256; j++) { if( (opt.is_alnum && (j<32 || j>=128) ) || (opt.is_fritz && (j<48 || j>=58)) || (opt.is_bcdonly && ( j > 0x99 || ( j & 0x0F ) > 0x09 )) ) all[i][j] = 0; } } //if debug is specified, force a specific value. for (i=0; i<32; i++) { for (j = 0; j < 256; j++) { if(opt.debug_row[i] == 1 && opt.debug[i] != j) all[i][j] = 0; else if(opt.debug_row[i] == 1 && opt.debug[i] == j) all[i][j] = 1; } } if(ap_cur->nb_ivs_clean > 99) { ap_cur->nb_ivs = ap_cur->nb_ivs_clean; //first try without bruteforcing, using only "clean" keystreams if(opt.keylen != 13) { if(PTW_computeKey(ap_cur->ptw_clean, wep.key, opt.keylen, (KEYLIMIT*opt.ffact), PTW_DEFAULTBF, all, opt.ptw_attack) == 1) len = opt.keylen; } else { /* try 1000 40bit keys first, to find the key "instantly" and you don't need to wait for 104bit to fail */ if(PTW_computeKey(ap_cur->ptw_clean, wep.key, 5, 1000, PTW_DEFAULTBF, all, opt.ptw_attack) == 1) len = 5; else if(PTW_computeKey(ap_cur->ptw_clean, wep.key, 13, (KEYLIMIT*opt.ffact), PTW_DEFAULTBF, all, opt.ptw_attack) == 1) len = 13; else if(PTW_computeKey(ap_cur->ptw_clean, wep.key, 5, (KEYLIMIT*opt.ffact)/3, PTW_DEFAULTBF, all, opt.ptw_attack) == 1) len = 5; } } if(!len) { ap_cur->nb_ivs = ap_cur->nb_ivs_vague; //in case its not found, try bruteforcing the id field and include "vague" keystreams PTW_DEFAULTBF[10]=1; PTW_DEFAULTBF[11]=1; // PTW_DEFAULTBF[12]=1; if(opt.keylen != 13) { if(PTW_computeKey(ap_cur->ptw_vague, wep.key, opt.keylen, (KEYLIMIT*opt.ffact), PTW_DEFAULTBF, all, opt.ptw_attack) == 1) len = opt.keylen; } else { /* try 1000 40bit keys first, to find the key "instantly" and you don't need to wait for 104bit to fail */ if(PTW_computeKey(ap_cur->ptw_vague, wep.key, 5, 1000, PTW_DEFAULTBF, all, opt.ptw_attack) == 1) len = 5; else if(PTW_computeKey(ap_cur->ptw_vague, wep.key, 13, (KEYLIMIT*opt.ffact), PTW_DEFAULTBF, all, opt.ptw_attack) == 1) len = 13; else if(PTW_computeKey(ap_cur->ptw_vague, wep.key, 5, (KEYLIMIT*opt.ffact)/10, PTW_DEFAULTBF, all, opt.ptw_attack) == 1) len = 5; } } if (!len) return FAILURE; opt.probability = 100; key_found(wep.key, len, -1); return SUCCESS; } int main( int argc, char *argv[] ) { int i, n, ret, option, j, ret1, nbMergeBSSID, unused; int cpu_count, showhelp, z, zz, forceptw; char *s, buf[128]; struct AP_info *ap_cur; int old=0; char essid[33]; #ifdef HAVE_SQLITE int rc; char *zErrMsg = 0; char looper[4] = {'|','/','-','\\'}; int looperc = 0; int waited = 0; char *sqlformat = "SELECT pmk.PMK, passwd.passwd FROM pmk INNER JOIN passwd ON passwd.passwd_id = pmk.passwd_id INNER JOIN essid ON essid.essid_id = pmk.essid_id WHERE essid.essid = '%q'"; char *sql; #endif ret = FAILURE; showhelp = 0; // Start a new process group, we are perhaps going to call kill(0, ...) later setsid(); progname = getVersion("Aircrack-ng", _MAJ, _MIN, _SUB_MIN, _REVISION, _BETA, _RC); memset( &opt, 0, sizeof( opt ) ); srand( time( NULL ) ); // Get number of CPU (return -1 if failed). cpu_count = get_nb_cpus(); opt.nbcpu = 1; if (cpu_count > 1) { opt.nbcpu = cpu_count; } j=0; /* check the arguments */ opt.nbdict = 0; opt.amode = 0; opt.do_brute = 1; opt.do_mt_brute = 1; opt.showASCII = 0; opt.probability = 51; opt.next_ptw_try= 0; opt.do_ptw = 1; opt.max_ivs = INT_MAX; opt.visual_inspection = 0; opt.firstbssid = NULL; opt.bssid_list_1st = NULL; opt.bssidmerge = NULL; opt.oneshot = 0; opt.logKeyToFile = NULL; /* all_ivs = malloc( (256*256*256) * sizeof(used_iv)); memset(all_ivs, 0, (256*256*256)*sizeof(used_iv)); */ forceptw = 0; while( 1 ) { int option_index = 0; static struct option long_options[] = { {"bssid", 1, 0, 'b'}, {"debug", 1, 0, 'd'}, {"combine", 0, 0, 'C'}, {"help", 0, 0, 'H'}, {"wep-decloak", 0, 0, 'D'}, {"ptw-debug", 0, 0, 'P'}, {"visual-inspection", 0, 0, 'V'}, {"oneshot", 0, 0, '1'}, {"cpu-detect", 0, 0, 'u'}, {0, 0, 0, 0 } }; option = getopt_long( argc, argv, "r:a:e:b:p:qcthd:l:m:n:i:f:k:x::Xysw:0HKC:M:DP:zV1", long_options, &option_index ); if( option < 0 ) break; switch( option ) { case ':' : printf("\"%s --help\" for help.\n", argv[0]); return( 1 ); case '?' : printf("\"%s --help\" for help.\n", argv[0]); return( 1 ); case 'u' : printf("Nb CPU detected: %d ", cpu_count); #if defined(__i386__) || defined(__x86_64__) unused = shasse2_cpuid(); if (unused == 1) { printf(" (MMX available)"); } if (unused >= 2) { printf(" (SSE2 available)"); } #endif printf("\n"); return( 0 ); case 'V' : if (forceptw) { printf("Visual inspection can only be used with KoreK\n"); printf("Use \"%s --help\" for help.\n", argv[0]); return FAILURE; } opt.visual_inspection = 1; opt.do_ptw = 0; break; case 'a' : ret1 = sscanf( optarg, "%d", &opt.amode ); if ( strcasecmp( optarg, "wep" ) == 0 ) opt.amode = 1; else if ( strcasecmp( optarg, "wpa" ) == 0 ) opt.amode = 2; if( opt.amode != 1 && opt.amode != 2 ) { printf( "Invalid attack mode. [1,2] or [wep,wpa]\n" ); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } break; case 'e' : memset( opt.essid, 0, sizeof( opt.essid ) ); strncpy( opt.essid, optarg, sizeof( opt.essid ) - 1 ); opt.essid_set = 1; break; case 'b' : if (getmac(optarg, 1, opt.bssid) != 0) { printf( "Invalid BSSID (not a MAC).\n" ); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } opt.bssid_set = 1; break; case 'p' : if( sscanf( optarg, "%d", &opt.nbcpu ) != 1 || opt.nbcpu < 1 || opt.nbcpu > MAX_THREADS) { printf( "Invalid number of processes (recommended: %d)\n", cpu_count ); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } break; case 'q' : opt.is_quiet = 1; break; case 'c' : opt.is_alnum = 1; break; case 'D' : opt.wep_decloak = 1; break; case 'h' : opt.is_fritz = 1; break; case 't' : opt.is_bcdonly = 1; break; case '1' : opt.oneshot = 1; break; case 'd' : i = 0 ; n = 0; s = optarg; while( s[i] != '\0' ) { if (s[i] == 'x') s[i] = 'X'; if (s[i] == 'y') s[i] = 'Y'; if ( s[i] == '-' || s[i] == ':' || s[i] == ' ') i++; else s[n++] = s[i++]; } s[n] = '\0' ; buf[0] = s[0]; buf[1] = s[1]; buf[2] = '\0'; i = 0; j = 0; while( ( sscanf( buf, "%x", &n ) == 1 ) || ( buf[0] == 'X' && buf[1] == 'X' ) || ( buf[0] == 'Y' && buf[1] == 'Y' )) { if ( buf[0] == 'X' && buf[1] == 'X' ) { opt.debug_row[i++] = 0 ; } else if ( buf[0] == 'Y' && buf[1] == 'Y' ) { opt.brutebytes[j++] = i++; } else { if ( n < 0 || n > 255 ) { printf( "Invalid debug key.\n" ); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } opt.debug[i] = n ; opt.debug_row[i++] = 1; } if( i >= 64 ) break; s += 2; buf[0] = s[0]; buf[1] = s[1]; } break; case 'm' : if ( getmac(optarg, 1, opt.maddr) != 0) { printf( "Invalid MAC address filter.\n" ); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } break; case 'n' : if( sscanf( optarg, "%d", &opt.keylen ) != 1 || ( opt.keylen != 64 && opt.keylen != 128 && opt.keylen != 152 && opt.keylen != 256 && opt.keylen != 512 ) ) { printf( "Invalid WEP key length. [64,128,152,256,512]\n" ); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } opt.keylen = ( opt.keylen / 8 ) - 3; break; case 'i' : if( sscanf( optarg, "%d", &opt.index ) != 1 || opt.index < 1 || opt.index > 4 ) { printf( "Invalid WEP key index. [1-4]\n" ); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } break; case 'f' : if( sscanf( optarg, "%f", &opt.ffact ) != 1 || opt.ffact < 1 ) { printf( "Invalid fudge factor. [>=1]\n" ); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } break; case 'k' : if( sscanf( optarg, "%d", &opt.korek ) != 1 || opt.korek < 1 || opt.korek > N_ATTACKS ) { printf( "Invalid KoreK attack strategy. [1-%d]\n", N_ATTACKS ); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } K_COEFF[(opt.korek) - 1] = 0; break; case 'l' : opt.logKeyToFile = (char *)calloc(1, strlen(optarg) + 1); if (opt.logKeyToFile == NULL) { printf("Error allocating memory\n"); return( FAILURE ); } strncpy(opt.logKeyToFile, optarg, strlen(optarg)); break; case 'M' : if( sscanf( optarg, "%d", &opt.max_ivs) != 1 || opt.max_ivs < 1) { printf( "Invalid number of max. ivs [>1]\n"); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } K_COEFF[(opt.korek) - 1] = 0; break; case 'P' : if( sscanf( optarg, "%d", &opt.ptw_attack) != 1 || opt.ptw_attack < 0 || opt.ptw_attack > 2) { printf( "Invalid number for ptw debug [0-2]\n"); printf("\"%s --help\" for help.\n", argv[0]); return( FAILURE ); } break; case 'x' : opt.do_brute = 0; if (optarg) { if (sscanf(optarg, "%d", &opt.do_brute)!=1 || opt.do_brute<0 || opt.do_brute>4) { printf("Invalid option -x%s. [0-4]\n", optarg); printf("\"%s --help\" for help.\n", argv[0]); return FAILURE; } } break; case 'X' : opt.do_mt_brute = 0; break; case 'y' : opt.do_testy = 1; break; case 'K' : opt.do_ptw = 0; break; case 's' : opt.showASCII = 1; break; case 'w' : if(set_dicts(optarg) != 0) { printf("\"%s --help\" for help.\n", argv[0]); return FAILURE; } break; case 'r' : #ifdef HAVE_SQLITE if(sqlite3_open(optarg, &db)) { fprintf(stderr, "Database error: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); return FAILURE; } #else fprintf(stderr, "Error: Aircrack-ng wasn't compiled with sqlite support\n"); return FAILURE; #endif break; case '0' : opt.l33t = 1; break; case 'H' : showhelp = 1; goto usage; break; case 'C' : nbMergeBSSID = checkbssids(optarg); if(nbMergeBSSID < 1) { printf("Invalid bssids (-C).\n\"%s --help\" for help.\n", argv[0]); return FAILURE; } // Useless to merge BSSID if only one element if (nbMergeBSSID == 1) printf("Merging BSSID disabled, only one BSSID specified\n"); else opt.bssidmerge = optarg; break; case 'z' : /* only for backwards compatibility - PTW used by default */ if (opt.visual_inspection) { printf("Visual inspection can only be used with KoreK\n"); printf("Use \"%s --help\" for help.\n", argv[0]); return FAILURE; } forceptw = 1; break; default : goto usage; } } if( argc - optind < 1 ) { if(argc == 1) { usage: printf (usage, progname, ( cpu_count > 1 || cpu_count == -1) ? "\n -X : disable bruteforce multithreading\n" : "\n"); // If the user requested help, exit directly. if (showhelp == 1) exit(0); } // Missing parameters if( argc - optind == 0) { printf("No file to crack specified.\n"); } if(argc > 1) { printf("\"%s --help\" for help.\n", argv[0]); } return( ret ); } if( opt.amode == 2 && opt.dict == NULL ) { nodict: printf( "Please specify a dictionary (option -w).\n" ); goto exit_main; } if( (! opt.essid_set && ! opt.bssid_set) && ( opt.is_quiet || opt.no_stdin ) ) { printf( "Please specify an ESSID or BSSID.\n" ); goto exit_main; } /* start one thread per input file */ signal( SIGINT, sighandler ); signal( SIGQUIT, sighandler ); signal( SIGTERM, sighandler ); signal( SIGALRM, SIG_IGN ); pthread_mutex_init( &mx_apl, NULL ); pthread_mutex_init( &mx_ivb, NULL ); pthread_mutex_init( &mx_eof, NULL ); pthread_cond_init( &cv_eof, NULL ); ap_1st = NULL; old = optind; n = argc - optind; id = 0; if( !opt.bssid_set ) { do { if( strcmp( argv[optind], "-" ) == 0 ) opt.no_stdin = 1; if( pthread_create( &(tid[id]), NULL, (void *) check_thread, (void *) argv[optind] ) != 0 ) { perror( "pthread_create failed" ); goto exit_main; } usleep( 131071 ); id++; if(id >= MAX_THREADS) { if(! opt.is_quiet) printf("Only using the first %d files, ignoring the rest.\n", MAX_THREADS); break; } } while( ++optind < argc ); /* wait until each thread reaches EOF */ if( ! opt.is_quiet ) { printf( "Reading packets, please wait...\r" ); fflush( stdout ); } // #ifndef DO_PGO_DUMP // signal( SIGINT, SIG_DFL ); /* we want sigint to stop and dump pgo data */ // #endif intr_read=1; for(i=0; iessid, 32); for(zz=0;zz<32;zz++) { if( (essid[zz] > 0 && essid[zz] < 32) || (essid[zz] > 126) ) essid[zz]='?'; } printf( "%4d %02X:%02X:%02X:%02X:%02X:%02X %-24s ", i, ap_cur->bssid[0], ap_cur->bssid[1], ap_cur->bssid[2], ap_cur->bssid[3], ap_cur->bssid[4], ap_cur->bssid[5], essid ); if( ap_cur->eapol ) printf( "EAPOL+" ); switch( ap_cur->crypt ) { case 0: printf( "None (%d.%d.%d.%d)\n", ap_cur->lanip[0], ap_cur->lanip[1], ap_cur->lanip[2], ap_cur->lanip[3] ); break; case 1: printf( "No data - WEP or WPA\n" ); break; case 2: printf( "WEP (%ld IVs)\n", ap_cur->nb_ivs ); break; case 3: printf( "WPA (%d handshake)\n", ap_cur->wpa.state == 7 ); break; default: printf( "Unknown\n" ); break; } i++; ap_cur = ap_cur->next; } printf( "\n" ); if( ap_1st->next != NULL ) { do { printf( "Index number of target network ? " ); fflush( stdout ); ret1 = 0; while(!ret1) ret1 = scanf( "%127s", buf ); if( ( z = atoi( buf ) ) < 1 ) continue; i = 1; ap_cur = ap_1st; while( ap_cur != NULL && i < z ) { i++; ap_cur = ap_cur->next; } } while( z < 0 || ap_cur == NULL ); } else { printf( "Choosing first network as target.\n" ); ap_cur = ap_1st; } printf( "\n" ); memcpy( opt.bssid, ap_cur->bssid, 6 ); opt.bssid_set = 1; /* Disable PTW if dictionnary used in WEP */ if (ap_cur->crypt == 2 && opt.dict != NULL) { opt.do_ptw = 0; } } ap_1st = NULL; optind = old; id=0; } nb_eof=0; signal( SIGINT, sighandler ); do { if( strcmp( argv[optind], "-" ) == 0 ) opt.no_stdin = 1; if( pthread_create( &(tid[id]), NULL, (void *) read_thread, (void *) argv[optind] ) != 0 ) { perror( "pthread_create failed" ); goto exit_main; } id++; usleep( 131071 ); if(id >= MAX_THREADS) break; } while( ++optind < argc ); nb_pkt=0; /* wait until each thread reaches EOF */ intr_read=0; pthread_mutex_lock( &mx_eof ); if( ! opt.is_quiet ) { printf( "Reading packets, please wait...\r" ); fflush( stdout ); } while( nb_eof < n && ! intr_read ) pthread_cond_wait( &cv_eof, &mx_eof ); pthread_mutex_unlock( &mx_eof ); intr_read=1; // if( ! opt.is_quiet && ! opt.no_stdin ) // printf( "\33[KRead %ld packets.\n\n", nb_pkt ); // #ifndef DO_PGO_DUMP // signal( SIGINT, SIG_DFL ); /* we want sigint to stop and dump pgo data */ // #endif /* mark the targeted access point(s) */ ap_cur = ap_1st; while( ap_cur != NULL ) { if( memcmp( opt.maddr, BROADCAST, 6 ) == 0 || ( opt.bssid_set && ! memcmp( opt.bssid, ap_cur->bssid, 6 ) ) || ( opt.essid_set && ! strcmp( opt.essid, ap_cur->essid ) ) ) ap_cur->target = 1; ap_cur = ap_cur->next; } ap_cur = ap_1st; while( ap_cur != NULL ) { if( ap_cur->target ) break; ap_cur = ap_cur->next; } if( ap_cur == NULL ) { printf( "No matching network found - check your %s.\n", ( opt.essid_set ) ? "essid" : "bssid" ); goto exit_main; } if( ap_cur->crypt < 2 ) { switch( ap_cur->crypt ) { case 0: printf( "Target network doesn't seem encrypted.\n" ); break; default: printf( "Got no data packets from target network!\n" ); break; } goto exit_main; } /* create the cracker<->master communication pipes */ for( i = 0; i < opt.nbcpu; i++ ) { unused = pipe( mc_pipe[i] ); unused = pipe( cm_pipe[i] ); if (opt.amode<=1 && opt.nbcpu>1 && opt.do_brute && opt.do_mt_brute) { unused = pipe(bf_pipe[i]); bf_nkeys[i] = 0; } } /* launch the attack */ nb_tried = 0; nb_kprev = 0; chrono( &t_begin, 1 ); chrono( &t_stats, 1 ); chrono( &t_kprev, 1 ); signal( SIGWINCH, sighandler ); if( opt.amode == 1 ) goto crack_wep; if( opt.amode == 2 ) goto crack_wpa; if( ap_cur->crypt == 2 ) { crack_wep: /* Default key length: 128 bits */ if( opt.keylen == 0 ) opt.keylen = 13; if(j + opt.do_brute > 4) { printf( "Bruteforcing more then 4 bytes will take too long, aborting!" ); goto exit_main; } for( i=0; inb_ivs_vague - (ap_cur->nb_ivs_vague % PTW_TRY_STEP); do { if(ap_cur->nb_ivs_vague >= opt.next_ptw_try) { if(!opt.is_quiet) printf("Starting PTW attack with %ld ivs.\n", ap_cur->nb_ivs_vague); ret = crack_wep_ptw(ap_cur); if( opt.oneshot == 1 && ret == FAILURE ) { printf( " Attack failed. Possible reasons:\n\n" " * Out of luck: you must capture more IVs. Usually, 104-bit WEP\n" " can be cracked with about 80.000 IVs, sometimes more.\n\n" " * Try to raise the fudge factor (-f).\n"); ret=0; } if(ret) { opt.next_ptw_try += PTW_TRY_STEP; printf("Failed. Next try with %d IVs.\n", opt.next_ptw_try); } } if(ret) usleep(10000); }while(ret != 0); } else if(opt.dict != NULL) { ret = crack_wep_dict(); } else { for( i = 0; i < opt.nbcpu; i++ ) { /* start one thread per cpu */ if (opt.amode<=1 && opt.nbcpu>1 && opt.do_brute && opt.do_mt_brute) { if (pthread_create( &(tid[id]), NULL, (void *) inner_bruteforcer_thread, (void *) (long) i ) != 0) { perror( "pthread_create failed" ); goto exit_main; } id++; } if( pthread_create( &(tid[id]), NULL, (void *) crack_wep_thread, (void *) (long) i ) != 0 ) { perror( "pthread_create failed" ); goto exit_main; } id++; } if( ! opt.do_testy ) { do { ret = do_wep_crack1( 0 ); } while( ret == RESTART ); if( ret == FAILURE ) { printf( " Attack failed. Possible reasons:\n\n" " * Out of luck: you must capture more IVs. Usually, 104-bit WEP\n" " can be cracked with about one million IVs, sometimes more.\n\n" " * If all votes seem equal, or if there are many negative votes,\n" " then the capture file is corrupted, or the key is not static.\n\n" " * A false positive prevented the key from being found. Try to\n" " disable each korek attack (-k 1 .. 17), raise the fudge factor\n" " (-f)" ); if (opt.do_testy) printf( "and try the experimental bruteforce attacks (-y)." ); printf( "\n" ); } } else { for( i = opt.keylen - 3; i < opt.keylen - 2; i++ ) { do { ret = do_wep_crack2( i ); } while( ret == RESTART ); if( ret == SUCCESS ) break; } if( ret == FAILURE ) { printf( " Attack failed. Possible reasons:\n\n" " * Out of luck: you must capture more IVs. Usually, 104-bit WEP\n" " can be cracked with about one million IVs, sometimes more.\n\n" " * If all votes seem equal, or if there are many negative votes,\n" " then the capture file is corrupted, or the key is not static.\n\n" " * A false positive prevented the key from being found. Try to\n" " disable each korek attack (-k 1 .. 17), raise the fudge factor\n" " (-f)" ); if (opt.do_testy) printf( "or try the standard attack mode instead (no -y option)." ); printf( "\n" ); } } } } if( ap_cur->crypt == 3 ) { crack_wpa: #ifdef HAVE_SQLITE if (opt.dict == NULL && db == NULL) goto nodict; #else if ( opt.dict == NULL ) goto nodict; #endif ap_cur = ap_1st; while( ap_cur != NULL ) { if( ap_cur->target && ap_cur->wpa.state == 7 ) break; ap_cur = ap_cur->next; } if( ap_cur == NULL ) { printf( "No valid WPA handshakes found.\n" ); goto exit_main; } if( memcmp( ap_cur->essid, ZERO, 32 ) == 0 && ! opt.essid_set ) { printf( "An ESSID is required. Try option -e.\n" ); goto exit_main; } if( opt.essid_set && ap_cur->essid[0] == '\0' ) { memset( ap_cur->essid, 0, sizeof( ap_cur->essid ) ); strncpy( ap_cur->essid, opt.essid, sizeof( ap_cur->essid ) - 1 ); } #ifdef HAVE_SQLITE if (db == NULL) { #endif for( i = 0; i < opt.nbcpu; i++ ) { /* start one thread per cpu */ wpa_data[i].ap = ap_cur; wpa_data[i].thread = i; wpa_data[i].nkeys = 17; wpa_data[i].key_buffer = (char*) malloc(wpa_data[i].nkeys * 128); wpa_data[i].front = 0; wpa_data[i].back = 0; memset(wpa_data[i].key, 0, sizeof(wpa_data[i].key)); pthread_cond_init(&wpa_data[i].cond, NULL); pthread_mutex_init(&wpa_data[i].mutex, NULL); if( pthread_create( &(tid[id]), NULL, (void *) crack_wpa_thread, (void *) &(wpa_data[i]) ) != 0 ) { perror( "pthread_create failed" ); goto exit_main; } #ifdef pthread_setaffinity_np // set affinity to one processor cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(i, &cpuset); pthread_setaffinity_np(tid[id], sizeof(cpu_set_t), &cpuset); #endif id++; } ret = do_wpa_crack(); // we feed keys to the cracking threads wpa_wordlists_done = 1; // we tell the threads that they shouldn't expect more words (don't wait for parallel crack) for( i = 0; i < opt.nbcpu; i++ ) // we wait for the cracking threads to end pthread_join(tid[--id], NULL); for( i = 0; i < opt.nbcpu; i++ ) { if (wpa_data[i].key[0] != 0) { ret = SUCCESS; break; } } if (ret==SUCCESS) { if( opt.is_quiet ) { printf( "KEY FOUND! [ %s ]\n", wpa_data[i].key ); return( SUCCESS ); } if( opt.l33t ) printf( "\33[31;1m" ); printf( "\33[8;%dH\33[2KKEY FOUND! [ %s ]\33[11B\n", ( 80 - 15 - (int) strlen(wpa_data[i].key) ) / 2, wpa_data[i].key ); if( opt.l33t ) printf( "\33[32;22m" ); return( SUCCESS ); } else printf( "\nPassphrase not in dictionary \n" ); printf("\n"); #ifdef HAVE_SQLITE } else { if( ! opt.is_quiet ) { if( opt.l33t ) printf( "\33[37;40m" ); printf( "\33[2J" ); if( opt.l33t ) printf( "\33[34;1m" ); printf("\33[2;34H%s",progname); } sql = sqlite3_mprintf(sqlformat,ap_cur->essid); while (1) { rc = sqlite3_exec(db,sql,sql_wpacallback,ap_cur,&zErrMsg); if (rc == SQLITE_LOCKED || rc == SQLITE_BUSY) { fprintf(stdout,"Database is locked or busy. Waiting %is ... %1c \r",++waited, looper[looperc]); fflush(stdout); looperc = (looperc+1) % sizeof(looper); sleep(1); } else { if (rc != SQLITE_OK && rc != SQLITE_ABORT ) { fprintf(stderr, "SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); } if (waited != 0) printf("\n\n"); break; } } sqlite3_free(sql); } #endif } exit_main: #ifdef HAVE_SQLITE if (db != NULL) { sqlite3_close(db); } #endif #if ((defined(__INTEL_COMPILER) || defined(__ICC)) && defined(DO_PGO_DUMP)) _PGOPTI_Prof_Dump(); #endif if( ! opt.is_quiet ) printf( "\n" ); fflush( stdout ); // if( ret == SUCCESS ) kill( 0, SIGQUIT ); // if( ret == FAILURE ) kill( 0, SIGTERM ); clean_exit(ret); _exit( ret ); }