Logo Search packages:      
Sourcecode: aircrack-ng version File versions

aircrack-ng.c

/*
 *  802.11 WEP / WPA-PSK Key Cracker
 *
 *  Copyright (C) 2006,2007 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
 */

#include <sys/types.h>
#include <sys/termios.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <getopt.h>
#include <ctype.h>
#include <err.h>

#include "version.h"
#include "crypto.h"
#include "pcap.h"
#include "uniqueiv.c"
#include "aircrack-ptw-lib.h"
#include "aircrack-ng.h"

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_ivb;              /* lock access to ivbuf array   */
pthread_mutex_t mx_apl;              /* lock write access to ap LL   */
pthread_mutex_t mx_eof;              /* lock write access to nb_eof  */
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;

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
};

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 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 <amode> : force attack mode (1/WEP, 2/WPA-PSK)\n"
"      -e <essid> : target selection: network identifier\n"
"      -b <bssid> : target selection: access point's MAC"
"%s"
"      -q         : enable quiet mode (no status output)\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 <mask>  : debug - specify mask of the key (A1:XX:CF:YY)\n"
"      -m <maddr> : MAC address to filter usable packets\n"
"      -n <nbits> : WEP key length :  64/128/152/256/512\n"
"      -i <index> : WEP key index (1 to 4), default: any\n"
"      -f <fudge> : bruteforce fudge factor,  default: 2\n"
"      -k <korek> : disable one attack method  (1 to 17)\n"
"      -x or -x0  : disable last keybytes bruteforce\n"
"      -x1        : enable last keybyte bruteforcing (default)\n"
"      -x2        : enable last two keybytes bruteforcing"
"%s"
"      -y         : experimental single bruteforce mode\n"
"      -z         : PTW attack\n"
"      -s         : show ASCII version of the key\n"
"\n"
"  WEP and WPA-PSK cracking options:\n"
"\n"
"      -w <words> : path to a dictionary file (multiple\n"
"                    dictionnaries can be specified.\n"
"                    See manpage for more information)\n"
/*"      -r <table> : path to a WPA PMK table\n" */
"\n"
"      --help     : Displays this usage screen\n"
"\n";

char * progname;

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 );
}

/* fread isn't atomic, sadly */

int atomic_read( read_buf *rb, int fd, int len, void *buf )
{
      int n;

      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 );
}

static int is_arp(void *wh, int len)
{
        int arpsize = 8 + 8 + 10*2;

      /* XXX check if broadcast to increase probability of correctness in some
       * cases?
       */
      if (wh) {}

        if (len == arpsize || len == 54)
                return 1;

        return 0;
}

static void *get_da(unsigned char *wh)
{
        if (wh[1] & IEEE80211_FC1_DIR_FROMDS)
                return wh + 4;
        else
                return wh + 4 + 6*2;
}

static void *get_sa(unsigned char *wh)
{
        if (wh[1] & IEEE80211_FC1_DIR_FROMDS)
                return wh + 4 + 6*2;
        else
                return wh + 4 + 6;
}

static int known_clear(void *clear, unsigned char *wh, int len)
{
        unsigned char *ptr = clear;

        /* IP */
        if (!is_arp(wh, len)) {
                unsigned short iplen = htons(len - 8);

//                printf("Assuming IP %d\n", len);

                len = sizeof(S_LLC_SNAP_IP) - 1;
                memcpy(ptr, S_LLC_SNAP_IP, len);
                ptr += len;
#if 1
                //version=4; header_length=20; services=0
                len = 2;
                memcpy(ptr, "\x45\x00", len);
                ptr += len;

                //ip total length
                memcpy(ptr, &iplen, len);
                ptr += len;

#if 0
            /* XXX IP ID is not always 0.  Can't use IP packets for PTW,
             * unless they are our own.  Can we use them for 40-bit keys
             * though [only 3+5 bytes of keystream needed]?  Or for
             * calculating only the first 9 bytes of the key?  -sorbo.
             */
                //ID=0
                len=2;
                memcpy(ptr, "\x00\x00", len);
                ptr += len;

                //ip flags=don't fragment
                len=2;
                memcpy(ptr, "\x40\x00", len);
                ptr += len;
#endif
#endif
                len = ptr - ((unsigned char*)clear);
                return len;
        }
//        printf("Assuming ARP %d\n", len);

        /* arp */
        len = sizeof(S_LLC_SNAP_ARP) - 1;
        memcpy(ptr, S_LLC_SNAP_ARP, len);
        ptr += len;

        /* arp hdr */
        len = 6;
        memcpy(ptr, "\x00\x01\x08\x00\x06\x04", len);
        ptr += len;

        /* type of arp */
        len = 2;
        if (memcmp(get_da(wh), "\xff\xff\xff\xff\xff\xff", 6) == 0)
                memcpy(ptr, "\x00\x01", len);
        else
                memcpy(ptr, "\x00\x02", len);
        ptr += len;

        /* src mac */
        len = 6;
        memcpy(ptr, get_sa(wh), len);
        ptr += len;

        len = ptr - ((unsigned char*)clear);
        return len;
}

void read_thread( void *arg )
{
      int fd, n, z, fmt;
      int eof_notified = 0;
      read_buf rb;

      uchar bssid[6];
      uchar stmac[6];
      uchar *buffer;
      uchar *h80211;
      uchar *p;

      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 ) );

      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 )
      {
            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 )
            {
                  fprintf( stderr, "This file is not a regular "
                        "802.11 (wireless) capture.\n" );
                  goto read_fail;
            }
      } else if (opt.do_ptw)
            errx(1, "Can't do PTW with IV files for now\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( fmt == FORMAT_IVS )
            {
                  /* read one IV */

                  while( ! atomic_read( &rb, fd, 1, buffer ) )
                        eof_wait( &eof_notified );

                  if( buffer[0] != 0xFF )
                  {
                        /* new access point MAC */

                        bssid[0] = buffer[0];

                        while( ! atomic_read( &rb, fd, 5, bssid + 1 ) )
                              eof_wait( &eof_notified );
                  }

                  while( ! atomic_read( &rb, fd, 5, buffer ) )
                        eof_wait( &eof_notified );
            }
            else
            {
                  while( ! atomic_read( &rb, fd, sizeof( pkh ), &pkh ) )
                        eof_wait( &eof_notified );

                  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 );

                  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;
                  }
            }

            /* 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;
                        case  1: memcpy( bssid, h80211 +  4, 6 ); break;
                        case  2: memcpy( bssid, h80211 + 10, 6 ); break;
                        default: memcpy( bssid, h80211 +  4, 6 ); break;
                  }
            }

            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 (opt.do_ptw == 1)
                  {
                        ap_cur->ptw = PTW_newattackstate();
                        if (!ap_cur->ptw) {
                              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;
            }

            /* 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] != 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 + 24;
                        int dlen = pkh.caplen - (body-h80211) - 4 -4;
                        unsigned char clear[2048];
                        int clearsize, i;

                        /* calculate keystream */
                        clearsize = known_clear(clear, h80211, dlen);
                        if (clearsize < 16)
                              goto unlock_mx_apl;
                        for (i = 0; i < 16; i++)
                              clear[i] ^= body[4+i];

                        if (PTW_addsession(ap_cur->ptw, body, clear))
                              ap_cur->nb_ivs++;

                        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;
                  }
            }

            /* 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 |= 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 |= 8;

                  /* copy the key descriptor version */

                  st_cur->wpa.keyver = h80211[z + 6] & 7;
            }

            if( st_cur->wpa.state == 15 )
            {
                  /* 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 );
      }

      read_fail:

      kill( 0, SIGTERM );
      _exit( FAILURE );
}

/* timing routine */

float chrono( struct timeval *start, int reset )
{
      float delta;
      struct timeval current;

      gettimeofday( &current, 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];

      while( 1 )
      {
            if( safe_read( mc_pipe[cid][0], (void *) &B,
                  sizeof( int ) ) != sizeof( int ) )
            {
                  perror( "read failed" );
                  kill( 0, SIGTERM );
                  _exit( FAILURE );
            }

            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 )
            {
                  pthread_mutex_lock( &mx_ivb );

                  memcpy( K, &wep.ivbuf[xv], 3 );
                  memcpy( S,  R, 256 );
                  memcpy( Si, R, 256 );

                  for( i = j = 0; i < q; i++ )
                  {
                        jj[i] = j = ( j + S[i] + K[i % (3 + opt.keylen)] ) & 0xFF;
                        SWAP( S[i], S[j] );
                  }

                  i = q; do { i--; SWAP(Si[i],Si[jj[i]]); }
                  while( i != 0 );

                  o1 = wep.ivbuf[xv + 3] ^ 0xAA; io1 = Si[o1]; S1 = S[1];
                  o2 = wep.ivbuf[xv + 4] ^ 0xAA; io2 = Si[o2]; S2 = S[2];

                  pthread_mutex_unlock( &mx_ivb );


                  Sq = S[q]; dq = Sq + jj[q - 1];

                  if( S2 == 0 )
                  {
                        if( ( S1 == 2 ) && ( o1 == 2 ) )
                        {
                              Kq = 1 - dq; votes[A_neg][Kq]++;
                              Kq = 2 - dq; votes[A_neg][Kq]++;
                        }
                        else if( o2 == 0 )
                        {
                              Kq = 2 - dq; votes[A_neg][Kq]++;
                        }
                  }
                  else
                  {
                        if( ( o2 == 0 ) && ( Sq == 0 ) )
                        {
                              Kq = 2 - dq; votes[A_u15][Kq]++;
                        }
                  }

                  if( ( S1 == 1 ) && ( o1 == S2 ) )
                  {
                        Kq = 1 - dq; votes[A_neg][Kq]++;
                        Kq = 2 - dq; votes[A_neg][Kq]++;
                  }

                  if( ( S1 == 0 ) && ( S[0] == 1 ) && ( o1 == 1 ) )
                  {
                        Kq = 0 - dq; votes[A_neg][Kq]++;
                        Kq = 1 - dq; votes[A_neg][Kq]++;
                  }

                  if( S1 == q )
                  {
                        if( o1 == q )
                        {
                              Kq = Si[0] - dq; votes[A_s13][Kq]++;
                        }
                        else if( ( ( 1 - q - o1 ) & 0xFF ) == 0 )
                        {
                              Kq = io1 - dq; votes[A_u13_1][Kq]++;
                        }
                        else if( io1 < q )
                        {
                              jq = Si[( io1 - q ) & 0xFF];

                              if( jq != 1 )
                              {
                                    Kq = jq - dq; votes[A_u5_1][Kq]++;
                              }
                        }
                  }

                  if( ( io1 == 2 ) && ( S[q] == 1 ) )
                  {
                        Kq = 1 - dq; votes[A_u5_2][Kq]++;
                  }

                  if( S[q] == q )
                  {
                        if( ( S1 == 0 ) && ( o1 == q ) )
                        {
                              Kq = 1 - dq; votes[A_u13_2][Kq]++;
                        }
                        else if( ( ( ( 1 - q - S1 ) & 0xFF ) == 0 ) && ( o1 == S1 ) )
                        {
                              Kq = 1 - dq; votes[A_u13_3][Kq]++;
                        }
                        else if( ( S1 >= ( ( -q ) & 0xFF ) )
                              && ( ( ( q + S1 - io1 ) & 0xFF ) == 0 ) )
                        {
                              Kq = 1 - dq; votes[A_u5_3][Kq]++;
                        }
                  }

                  if( ( S1 < q ) && ( ( ( S1 + S[S1] - q ) & 0xFF ) == 0 )  &&
                        ( io1 != 1 ) && ( io1 != S[S1] ) )
                  {
                        Kq = io1 - dq; votes[A_s5_1][Kq]++;
                  }

                  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]++;
                              }
                        }
                        else if( o2 == ( ( 2 - S2 ) & 0xFF ) )
                        {
                              jq = io2;

                              if( ( jq != 1 ) && ( jq != 2 ) )
                              {
                                    Kq = jq - dq; votes[A_s5_3][Kq]++;
                              }
                        }
                  }

                  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]++;
                              }
                        }
                  }

                  if( S1 == 2 )
                  {
                        if( q == 4 )
                        {
                              if( o2 == 0 )
                              {
                                    Kq = Si[0] - dq; votes[A_4_s13][Kq]++;
                              }
                              else
                              {
                                    if( ( jj[1] == 2 ) && ( io2 == 0 ) )
                                    {
                                          Kq = Si[254] - dq; votes[A_4_u5_1][Kq]++;
                                    }
                                    if( ( jj[1] == 2 ) && ( io2 == 2 ) )
                                    {
                                          Kq = Si[255] - dq; votes[A_4_u5_2][Kq]++;
                                    }
                              }
                        }
                        else if( ( q > 4 ) && ( ( S[4] + 2 ) == q ) &&
                              ( io2 != 1 ) && ( io2 != 4 ) )
                        {
                              Kq = io2 - dq; votes[A_u5_4][Kq]++;
                        }
                  }
            }

            /* 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, int keylimit )
{
      float delta;
      struct winsize ws;
      int i, et_h, et_m, et_s;
      static int is_cleared = 0;

      if( ioctl( 0, TIOCGWINSZ, &ws ) < 0 )
      {
            ws.ws_row = 25;
            ws.ws_col = 80;
      }

      if( (chrono( &t_stats, 0 ) < 1.51 || wepkey_crack_success) && force == 0 )
            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( 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/%d keys (got %ld IVs)\33[K",
                  (ws.ws_col - 44) / 2, et_h, et_m, et_s, prod, keylimit, 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 ) / 9;

            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)
{
      int nb_ascii = 0;
      int i, n;

      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, 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( 100 * nb_ascii > 75 * opt.keylen )
      {
            printf( "(ASCII: " );

            for( i = 0; i < opt.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" );
}

/* 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);
//    printf("%02X:%02X:%02X:%02X:%02X\n", wepkey[0],wepkey[1],wepkey[2],wepkey[3],wepkey[4]);

      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 ) )
      {
            pthread_mutex_lock( &mx_ivb );

            /* one buffer to rule them all */

            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 );
}

/* 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;
      static int k = 0;

      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, 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, 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. */

                  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; tsel<opt.nbcpu && !wepkey_crack_success; ++tsel)
                              {
                                    if (bf_nkeys[(tsel+k) % opt.nbcpu]>16)
                                    {
                                          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;
                  }
            }
      }

      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, 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, 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, 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;
      size_t nthread = (size_t)arg;
      uchar wepkey[64];

      inner_bruteforcer_thread_start:

      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
            bf_nkeys[nthread]--;

      /* 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);
            }
      }

      goto inner_bruteforcer_thread_start;

}

/* derive the PMK from the passphrase and the essid */

void calc_pmk( char *key, char *essid, uchar pmk[40] )
{
      int i, j, slen;
      uchar buffer[65];
      sha1_context ctx_ipad;
      sha1_context ctx_opad;
      sha1_context sha1_ctx;

      slen = strlen( essid ) + 4;

      /* setup the inner and outer contexts */

      memset( buffer, 0, sizeof( buffer ) );
      strncpy( (char *) buffer, key, sizeof( buffer ) - 1 );

      for( i = 0; i < 64; i++ )
            buffer[i] ^= 0x36;

      sha1_starts( &ctx_ipad );
      sha1_update( &ctx_ipad, buffer, 64 );

      for( i = 0; i < 64; i++ )
            buffer[i] ^= 0x6A;

      sha1_starts( &ctx_opad );
      sha1_update( &ctx_opad, buffer, 64 );

      /* iterate HMAC-SHA1 over itself 8192 times */

      essid[slen - 1] = '\1';
      hmac_sha1( (uchar *) key, strlen( key ),
            (uchar *) essid, slen, pmk );
      memcpy( buffer, pmk, 20 );

      for( i = 1; i < 4096; i++ )
      {
            memcpy( &sha1_ctx, &ctx_ipad, sizeof( sha1_ctx ) );
            sha1_update( &sha1_ctx, buffer, 20 );
            sha1_finish( &sha1_ctx, buffer );

            memcpy( &sha1_ctx, &ctx_opad, sizeof( sha1_ctx ) );
            sha1_update( &sha1_ctx, buffer, 20 );
            sha1_finish( &sha1_ctx, buffer );

            for( j = 0; j < 20; j++ )
                  pmk[j] ^= buffer[j];
      }

      essid[slen - 1] = '\2';
      hmac_sha1( (uchar *) key, strlen( key ),
            (uchar *) essid, slen, pmk + 20 );
      memcpy( buffer, pmk + 20, 20 );

      for( i = 1; i < 4096; i++ )
      {
            memcpy( &sha1_ctx, &ctx_ipad, sizeof( sha1_ctx ) );
            sha1_update( &sha1_ctx, buffer, 20 );
            sha1_finish( &sha1_ctx, buffer );

            memcpy( &sha1_ctx, &ctx_opad, sizeof( sha1_ctx ) );
            sha1_update( &sha1_ctx, buffer, 20 );
            sha1_finish( &sha1_ctx, buffer );

            for( j = 0; j < 20; j++ )
                  pmk[j + 20] ^= buffer[j];
      }
}

/* each thread computes two pairwise master keys at a time */

int crack_wpa_thread( void *arg )
{
      char  essid[36];
      char  key1[128], key2[128];
      uchar pmk1[128], pmk2[128];
        int len1, len2;

      #ifdef __i386__

      uchar k_ipad[128], ctx_ipad[40];
      uchar k_opad[128], ctx_opad[40];
      uchar buffer[128], sha1_ctx[40];
      uchar wrkbuf[640];
      uint i, *u, *v, *w;
      #endif

      int slen, cid = (long) arg;

      /* receive the essid */

      memset( essid, 0, sizeof( essid ) );

      if( safe_read( mc_pipe[cid][0], (void *) essid, 32 ) != 32 )
      {
            perror( "read failed" );
            kill( 0, SIGTERM );
            _exit( FAILURE );
      }

      slen = strlen( essid ) + 4;

      while( 1 )
      {
            /* receive two passphrases */

            memset( key1, 0, sizeof( key1 ) );
            memset( key2, 0, sizeof( key2 ) );

            if( safe_read( mc_pipe[cid][0], (void *) key1, 128 ) != 128 ||
                  safe_read( mc_pipe[cid][0], (void *) key2, 128 ) != 128 )
            {
                  perror( "read passphrase failed" );
                  kill( 0, SIGTERM );
                  _exit( FAILURE );
            }

            key1[127] = '\0';
            key2[127] = '\0';

                len1 = strlen( key1 );
                len2 = strlen( key1 );
                if(len1 > 64 ) len1 = 64;
                if(len2 > 64 ) len2 = 64;

                if(len1 < 8) len1 = 8;
                if(len2 < 8) len2 = 8;
            #ifdef __i386__

            /* MMX available, so compute two PMKs in a single row */

            memset( k_ipad, 0, sizeof( k_ipad ) );
            memset( k_opad, 0, sizeof( k_opad ) );

            memcpy( k_ipad, key1, len1 );
            memcpy( k_opad, key1, len1 );

            memcpy( k_ipad + 64, key2, len2 );
            memcpy( k_opad + 64, key2, len2 );

            u = (uint *) ( k_ipad      );
            v = (uint *) ( k_ipad + 64 );
            w = (uint *) buffer;

            for( i = 0; i < 16; i++ )
            {
                  /* interleave the data */

                  *w++ = *u++ ^ 0x36363636;
                  *w++ = *v++ ^ 0x36363636;
            }

            shammx_init( ctx_ipad );
            shammx_data( ctx_ipad, buffer, wrkbuf );

            u = (uint *) ( k_opad      );
            v = (uint *) ( k_opad + 64 );
            w = (uint *) buffer;

            for( i = 0; i < 16; i++ )
            {
                  *w++ = *u++ ^ 0x5C5C5C5C;
                  *w++ = *v++ ^ 0x5C5C5C5C;
            }

            shammx_init( ctx_opad );
            shammx_data( ctx_opad, buffer, wrkbuf );

            memset( buffer, 0, sizeof( buffer ) );

            /* use the buffer, luke */

            buffer[ 40] = buffer[ 44] = 0x80;
            buffer[122] = buffer[126] = 0x02;
            buffer[123] = buffer[127] = 0xA0;

            essid[slen - 1] = '\1';

            hmac_sha1( (uchar *) key1, len1,
                  (uchar *) essid, slen,  pmk1 );

            hmac_sha1( (uchar *) key2, len2,
                  (uchar *) essid, slen,  pmk2 );

            u = (uint *) pmk1;
            v = (uint *) pmk2;
            w = (uint *) buffer;

            *w++ = *u++; *w++ = *v++;
            *w++ = *u++; *w++ = *v++;
            *w++ = *u++; *w++ = *v++;
            *w++ = *u++; *w++ = *v++;
            *w++ = *u++; *w++ = *v++;

            for( i = 1; i < 4096; i++ )
            {
                  memcpy( sha1_ctx, ctx_ipad, 40 );
                  shammx_data( sha1_ctx, buffer, wrkbuf );
                  shammx_ends( sha1_ctx, buffer );

                  memcpy( sha1_ctx, ctx_opad, 40 );
                  shammx_data( sha1_ctx, buffer, wrkbuf );
                  shammx_ends( sha1_ctx, buffer );

                  u = (uint *) pmk1;
                  v = (uint *) pmk2;
                  w = (uint *) buffer;

                  /* de-interleave the digests */

                  *u++ ^= *w++; *v++ ^= *w++;
                  *u++ ^= *w++; *v++ ^= *w++;
                  *u++ ^= *w++; *v++ ^= *w++;
                  *u++ ^= *w++; *v++ ^= *w++;
                  *u++ ^= *w++; *v++ ^= *w++;
            }

            essid[slen - 1] = '\2';

            hmac_sha1( (uchar *) key1, len1,
                  (uchar *) essid, slen,  pmk1 + 20 );

            hmac_sha1( (uchar *) key2, len2,
                  (uchar *) essid, slen,  pmk2 + 20 );

            u = (uint *) ( pmk1 + 20 );
            v = (uint *) ( pmk2 + 20 );
            w = (uint *) buffer;

            *w++ = *u++; *w++ = *v++;
            *w++ = *u++; *w++ = *v++;
            *w++ = *u++; *w++ = *v++;
            *w++ = *u++; *w++ = *v++;
            *w++ = *u++; *w++ = *v++;

            for( i = 1; i < 4096; i++ )
            {
                  memcpy( sha1_ctx, ctx_ipad, 40 );
                  shammx_data( sha1_ctx, buffer, wrkbuf );
                  shammx_ends( sha1_ctx, buffer );

                  memcpy( sha1_ctx, ctx_opad, 40 );
                  shammx_data( sha1_ctx, buffer, wrkbuf );
                  shammx_ends( sha1_ctx, buffer );

                  u = (uint *) ( pmk1 + 20 );
                  v = (uint *) ( pmk2 + 20 );
                  w = (uint *) buffer;

                  *u++ ^= *w++; *v++ ^= *w++;
                  *u++ ^= *w++; *v++ ^= *w++;
                  *u++ ^= *w++; *v++ ^= *w++;
            }

            #else

            /* not x86, use the generic SHA-1 C code */

            calc_pmk( key1, essid, pmk1 );
            calc_pmk( key2, essid, pmk2 );
            #endif

            /* send the passphrase & master keys */

            if( safe_write( cm_pipe[cid][1], (void *) key1, 128 ) != 128 ||
                  safe_write( cm_pipe[cid][1], (void *) key2, 128 ) != 128 ||
                  safe_write( cm_pipe[cid][1], (void *) pmk1,  32 ) !=  32 ||
                  safe_write( cm_pipe[cid][1], (void *) pmk2,  32 ) !=  32 )
            {
                  perror( "write pmk failed" );
                  kill( 0, SIGTERM );
                  _exit( FAILURE );
            }
      }
}

/* 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];

      #ifdef __i386__
      __asm__( "emms" );                   /* clean up the fp regs */
      #endif

      if( chrono( &t_stats, 0 ) < 0.08 && force == 0 )
            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 )
      {
            t_kprev.tv_sec += 3;
            nb_kprev /= 2;
      }

      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;7HTranscient 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" );
}

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 dictionnary\n" );
                        opt.nbdict++;
                        continue;
                  }

                  rewind( opt.dict );
            }
            break;
      }

      if(opt.nbdict >= MAX_DICTS || opt.dicts[opt.nbdict] == NULL)
          return( FAILURE );

      return( 0 );
}

int do_wpa_crack( struct AP_info *ap )
{
      int i, j, cid, len1, len2;
      char key1[128], key2[128];

      uchar pke[100];
      uchar pmk1[40], ptk1[80];
      uchar pmk2[40], ptk2[80];
      uchar mic1[20], mic2[20];

        i=0;

      /* send the ESSID to each thread */

      for( cid = 0; cid < opt.nbcpu; cid++ )
      {
            if( safe_write( mc_pipe[cid][1], (void *) ap->essid, 32 ) != 32 )
            {
                  perror( "write essid failed" );
                  kill( 0, SIGTERM );
                  _exit( FAILURE );
            }
      }

      /* 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 );
      }

      memset( key1, 0, sizeof( key1 ) );
      memset( key2, 0, sizeof( key1 ) );

      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);
      }

      while( 1 )
      {
            for( cid = 0; cid < opt.nbcpu; cid++ )
            {
                  /* read a couple of keys (skip those < 8 chars) */

                  if(opt.dict == NULL)
                  {
                        printf( "\nPassphrase not in dictionnary \n" );
                        return( FAILURE );
                  }

                  do
                  {
                        if( fgets( key1, sizeof( key1 ), opt.dict ) == NULL )
                        {
                              if( opt.l33t )
                                    printf( "\33[32;22m" );

                              printf( "\nPassphrase not in dictionnary %s \n", opt.dicts[opt.nbdict] );
                              if(next_dict(opt.nbdict+1) != 0)
                              {
                                    return( FAILURE );
                              }
                              else
                              {
                                    continue;
                              }
                        }

                        i = strlen( key1 );
                                if( i < 8 ) continue;
                                if( i > 64 ) i = 64;

                        if( key1[i - 1] == '\n' ) key1[--i] = '\0';
                        if( key1[i - 1] == '\r' ) key1[--i] = '\0';
                        if( key1[i - 1] == '\n' ) key1[--i] = '\0';
                        if( key1[i - 1] == '\r' ) key1[--i] = '\0';

                                for(j=0; j<i; j++)
                                    if(!isascii(key1[j]) || key1[j] < 32) i=0;
                  }
                  while( i < 8 );

                  do
                  {
                        if( fgets( key2, sizeof( key2 ), opt.dict ) == NULL )
                        {
                              if(next_dict(opt.nbdict+1) != 0)
                              {
                                    break;
                              }
                              else
                              {
                                    continue;
                              }
                        }

                        i = strlen( key2 );

                                if( i < 8 ) continue;
                                if( i > 64 ) i = 64;

                        if( key2[i - 1] == '\n' ) key2[--i] = '\0';
                        if( key2[i - 1] == '\r' ) key2[--i] = '\0';
                        if( key2[i - 1] == '\n' ) key2[--i] = '\0';
                        if( key2[i - 1] == '\r' ) key2[--i] = '\0';

                                for(j=0; j<i; j++)
                                    if(!isascii(key2[j]) || key2[j] < 32 ) i=0;
                  }
                  while( i < 8 );

                  /* send the keys */

                  if( safe_write( mc_pipe[cid][1], (void *) key1, 128 ) != 128 ||
                        safe_write( mc_pipe[cid][1], (void *) key2, 128 ) != 128 )
                  {
                        perror( "write passphrase failed" );
                        return( FAILURE );
                  }
            }

            for( cid = 0; cid < opt.nbcpu; cid++ )
            {
                  /* collect and test the master keys */

                  if( safe_read( cm_pipe[cid][0], (void *) key1, 128 ) != 128 ||
                        safe_read( cm_pipe[cid][0], (void *) key2, 128 ) != 128 ||
                        safe_read( cm_pipe[cid][0], (void *) pmk1,  32 ) !=  32 ||
                        safe_read( cm_pipe[cid][0], (void *) pmk2,  32 ) !=  32 )
                  {
                        perror( "read pmk failed" );
                        return( FAILURE );
                  }

                  len1 = strlen( key1 );
                  len2 = strlen( key2 );

                        if( len1 < 8 ) len1=8;
                        if( len1 > 64 ) len1 = 64;

                        if( len2 < 8 ) len2=8;
                        if( len2 > 64 ) len2 = 64;

                  /* compute the pairwise transient key and the frame MIC */

                  for( i = 0; i < 4; i++ )
                  {
                        pke[99] = i;
                        hmac_sha1( pmk1, 32, pke, 100, ptk1 + i * 20 );
                        hmac_sha1( pmk2, 32, pke, 100, ptk2 + i * 20 );
                  }

                  if( ap->wpa.keyver == 1 )
                  {
                        hmac_md5( ptk1, 16, ap->wpa.eapol, ap->wpa.eapol_size, mic1 );
                        hmac_md5( ptk2, 16, ap->wpa.eapol, ap->wpa.eapol_size, mic2 );
                  }
                  else
                  {
                        hmac_sha1( ptk1, 16, ap->wpa.eapol, ap->wpa.eapol_size, mic1 );
                        hmac_sha1( ptk2, 16, ap->wpa.eapol, ap->wpa.eapol_size, mic2 );
                  }

                  if( memcmp( mic1, ap->wpa.keymic, 16 ) == 0 )
                  {
                        memcpy( key2, key1, 128 );
                        memcpy( pmk2, pmk1,  32 );
                        memcpy( ptk2, ptk1,  64 );
                        memcpy( mic2, mic1,  16 );
                  }

                  if( memcmp( mic2, ap->wpa.keymic, 16 ) == 0 )
                  {
                        if( opt.is_quiet )
                        {
                              printf( "KEY FOUND! [ %s ]\n", key2 );
                              return( SUCCESS );
                        }

                        show_wpa_stats( key2, len1, pmk2, ptk2, mic2, 1 );

                        if( opt.l33t )
                              printf( "\33[31;1m" );

                        printf( "\33[8;%dH\33[2KKEY FOUND! [ %s ]\33[11B\n",
                              ( 80 - 15 - (int) len1 ) / 2, key2 );

                        if( opt.l33t )
                              printf( "\33[32;22m" );

                        return( SUCCESS );
                  }

                  nb_tried += 2;
                  nb_kprev += 2;

                  if( ! opt.is_quiet )
                        show_wpa_stats( key1, len1, pmk1, ptk1, mic1, 0 );
            }
      }

      return( FAILURE );
}

int intr_read = 0;

void sighandler( int signum )
{
      #if ((defined(__INTEL_COMPILER) || defined(__ICC)) && defined(DO_PGO_DUMP))
      _PGOPTI_Prof_Dump();
      #endif
      signal( signum, sighandler );

      if( signum == SIGQUIT )
            _exit( SUCCESS );

      if( signum == SIGTERM )
            _exit( FAILURE );

      if( signum == SIGINT )
      #if ((defined(__INTEL_COMPILER) || defined(__ICC)) && defined(DO_PGO_DUMP))
            _exit( FAILURE );
      #else
      intr_read++;
      #endif

      if( signum == SIGWINCH )
            printf( "\33[2J\n" );
}

int next_key( char **key, int keysize )
{
      char *tmp, *tmp2;
      int i, rtn;
      unsigned int dec;
      char *hex;

      tmp2 = tmp = (char*) malloc(1024);

      while(1)
      {
            rtn = 0;
            tmp = tmp2;
            if(opt.dict == NULL)
            {
                  printf( "\nPassphrase not in dictionnary \n" );
                  free(tmp);
                  return( FAILURE );
            }

            if( opt.hexdict[opt.nbdict] )
            {
                  if( fgets( tmp, ((keysize*2)+(keysize-1)), opt.dict ) == NULL )
                  {
                        if( opt.l33t )
                              printf( "\33[32;22m" );

//                      printf( "\nPassphrase not in dictionnary \"%s\" \n", opt.dicts[opt.nbdict] );
                        if(next_dict(opt.nbdict+1) != 0)
                        {
                              free(tmp);
                              return( FAILURE );
                        }
                        else
                        {
                              continue;
                        }
                  }

                  i=strlen(tmp);

                  if( i <= 2 ) continue;

                  if( tmp[i - 1] == '\n' ) tmp[--i] = '\0';
                  if( tmp[i - 1] == '\r' ) tmp[--i] = '\0';
                  if( i <= 0 ) continue;

                  i=0;

                  hex = strsep(&tmp, ":");

                  while( i<keysize && hex != NULL )
                  {
                        if(strlen(hex) > 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 dictionnary \"%s\" \n", opt.dicts[opt.nbdict] );
                        if(next_dict(opt.nbdict+1) != 0)
                        {
                              free(tmp);
                              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);

      return( SUCCESS );
}

int set_dicts(char* optargs)
{
      int len;
      char *optarg;

      opt.nbdict = 0;
      optarg = strsep(&optargs, ",");

      for(len=0; len<MAX_DICTS; len++)
      {
            opt.dicts[len] = NULL;
      }

      while(optarg != NULL && opt.nbdict<MAX_DICTS)
      {
            len = strlen(optarg)+1;
            opt.dicts[opt.nbdict] = (char*)malloc(len * sizeof(char));
            if(opt.dicts[opt.nbdict] == NULL)
            {
                  perror("allocation failed!");
                  return( FAILURE );
            }
            if(strncasecmp(optarg, "h:", 2) == 0)
            {
                  strncpy(opt.dicts[opt.nbdict], optarg+2, len-2);
                  opt.hexdict[opt.nbdict] = 1;
            }
            else
            {
                  strncpy(opt.dicts[opt.nbdict], optarg, len);
                  opt.hexdict[opt.nbdict] = 0;
            }
            optarg = strsep(&optargs, ",");
            opt.nbdict++;
      }

      next_dict(0);

      while(next_dict(opt.nbdict+1) == 0) {}

      next_dict(0);

      return 0;
}

int crack_wep_dict()
{
      struct timeval t_last;
      struct timeval t_now;
      int i, origlen, keysize;
      char *key;

      key = (char*) malloc(sizeof(char) * (opt.keylen + 1));
      keysize = opt.keylen+1;

      update_ivbuf();

      if(wep.nb_ivs < TEST_MIN_IVS)
      {
            printf( "\nYou need to capture at least %d IVs!\n", TEST_MIN_IVS );
            return( FAILURE );
      }

      gettimeofday( &t_last, NULL );
      t_last.tv_sec--;

      while(1)
      {
            if( next_key( &key, keysize ) != SUCCESS) return( FAILURE );

            i = strlen( key );

            origlen = i;

            while(i<opt.keylen)
            {
                  key[i] = key[i - origlen];
                  i++;
            }

            key[i] = '\0';

            if( ! opt.is_quiet )
            {
                  gettimeofday( &t_now, NULL );
                  if( (t_now.tv_sec - t_last.tv_sec) > 0)
                  {
                        show_wep_stats(opt.keylen - 1, 1, NULL, NULL, NULL, 0, 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 len = 0;

      opt.ap = ap_cur;

      if(PTW_computeKey(ap_cur->ptw, wep.key, 13, (KEYLIMIT*opt.ffact)) == 1)
            len = 13;
      else if(PTW_computeKey(ap_cur->ptw, wep.key, 5, (KEYLIMIT*opt.ffact)/10) == 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, max_cpu, option, j, ret1, cpudetectfailed, unused, showhelp;
      char *s, buf[128];
      struct AP_info *ap_cur;

      ret = FAILURE;
      cpudetectfailed = 0;
      showhelp = 0;

      progname = getVersion("Aircrack-ng", _MAJ, _MIN, _SUB_MIN, _REVISION);

      memset( &opt, 0, sizeof( opt ) );

      srand( time( NULL ) );

      #ifdef _SC_NPROCESSORS_ONLN

      max_cpu   = sysconf(_SC_NPROCESSORS_ONLN);
      /* Fails on some archs */
      cpudetectfailed = ( max_cpu < 1 );
      if (cpudetectfailed)
            max_cpu = 1;
      opt.nbcpu = max_cpu;

      #else

      cpudetectfailed = 1;
      max_cpu   = 255;
      opt.nbcpu =   1;
      #endif
      j=0;
      /* check the arguments */

      opt.do_brute    = 1;
      opt.do_mt_brute = 1;
      opt.showASCII   = 0;
      opt.probability = 51;
        opt.next_ptw_try= 0;

      while( 1 )
      {

        int option_index = 0;

        static struct option long_options[] = {
            {"bssid",   1, 0, 'b'},
            {"debug",   1, 0, 'd'},
            {"help",    0, 0, 'H'},
            {0,         0, 0,  0 }
        };

            if ( max_cpu == 1 )
                  option = getopt_long( argc, argv, "a:e:b:qcthd:m:n:i:f:k:x::ysw:0Hz",
                        long_options, &option_index );
            else
                  option = getopt_long( argc, argv, "a:e:b:p:qcthd:m:n:i:f:k:x::Xysw:0Hz",
                        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 '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_cpu )
                        {
                              printf( "Invalid number of processes. [1-%d]\n", max_cpu );
                        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 'h' :

                        opt.is_fritz = 1;
                        break;

                  case 't' :

                        opt.is_bcdonly = 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 || opt.ffact > 32 )
                        {
                              printf( "Invalid fudge factor. [1-32]\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 '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 'z' :
                        opt.do_ptw = 1;
                        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 '0' :

                        opt.l33t = 1;
                        break;

                  case 'H' :

                        showhelp = 1;
                        goto usage;
                        break;

                  default : goto usage;
            }
      }

      if( argc - optind < 1 )
      {
            if(argc == 1)
            {
usage:
                  printf (usage, progname,
                        ( max_cpu == 1 && cpudetectfailed == 0) ? "\n" : "\n      -p <nbcpu> : # of CPU to use (by default, all CPUs)\n",
                        ( max_cpu == 1 && cpudetectfailed == 0) ? "\n" : "\n      -X         : disable bruteforce multithreading (SMP only)\n");

                  /* The user only asked for help */
                  if (showhelp == 1)
                        exit(0);
            }
            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_eof, NULL );
      pthread_mutex_init( &mx_ivb, NULL );
      pthread_cond_init(  &cv_eof, NULL );

      ap_1st = NULL;

      n = argc - optind;

      do
      {
            pthread_t tid;

            if( strcmp( argv[optind], "-" ) == 0 )
                  opt.no_stdin = 1;

            if( pthread_create( &tid, NULL, (void *) read_thread,
                  (void *) argv[optind] ) != 0 )
            {
                  perror( "pthread_create failed" );
                  goto exit_main;
            }

            usleep( 131071 );
      }
      while( ++optind < argc );

      /* wait until each thread reaches EOF */

      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 );

      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

      if( ap_1st == NULL )
      {
            printf( "No networks found, exiting.\n" );
            goto exit_main;
      }

      if( ! opt.essid_set && ! opt.bssid_set )
      {
            /* ask the user which network is to be cracked */

            printf( "   #  BSSID%14sESSID%21sEncryption\n\n", "", "" );

            i = 1;

            ap_cur = ap_1st;

            while( ap_cur != NULL )
            {
                  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],
                        ap_cur->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 == 15 );
                        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( ( n = atoi( buf ) ) < 1 )
                              continue;

                        i = 1; ap_cur = ap_1st;
                        while( ap_cur != NULL && i < n )
                              { i++; ap_cur = ap_cur->next; }
                  }
                  while( n < 0 || ap_cur == NULL );
            }
            else
            {
                  printf( "Choosing first network as target.\n" );
                  sleep( 2 );
                  ap_cur = ap_1st;
            }

            printf( "\n" );

            memcpy( opt.bssid, ap_cur->bssid,  6 );
            opt.bssid_set = 1;
      }

      /* 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:

            if( opt.keylen == 0 )
                  opt.keylen = 13;

            if(j + opt.do_brute > 4)
            {
                  printf( "Specified more then 4 bytes to bruteforce!" );
                  goto exit_main;
            }

            for( i=0; i<opt.do_brute; i++)
            {
                  opt.brutebytes[j+i] = opt.keylen -1 -i;
            }

            opt.do_brute += j;

            if( opt.ffact == 0 )
            {
                        if( opt.do_ptw ) opt.ffact = 2;
                        else
                        {
                            if( ! opt.do_testy )
                            {
                                if( opt.keylen == 5 )
                                    opt.ffact = 5;
                                else
                                    opt.ffact = 2;
                            }
                            else
                                opt.ffact = 30;
                        }
                }

            memset( &wep, 0, sizeof( wep ) );

            if (opt.do_ptw)
                {
                    if(opt.is_quiet)
                        printf("Attack will be restarted every %d captured ivs.\n", PTW_TRY_STEP);
                    opt.next_ptw_try = ap_cur->nb_ivs - (ap_cur->nb_ivs % PTW_TRY_STEP);
                    do
                    {
                        if(ap_cur->nb_ivs >= opt.next_ptw_try)
                        {
                            if(opt.is_quiet)
                                printf("Starting ptw attack with %ld ivs.\n", ap_cur->nb_ivs);
                            ret = crack_wep_ptw(ap_cur);
                            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 */

                        pthread_t tid;

                        if (opt.amode<=1 && opt.nbcpu>1 && opt.do_brute && opt.do_mt_brute)
                        {
                              if (pthread_create( &tid, NULL, (void *) inner_bruteforcer_thread,
                                    (void *) (long) i ) != 0)
                              {
                                    perror( "pthread_create failed" );
                                    goto exit_main;
                              }
                        }

                        if( pthread_create( &tid, NULL, (void *) crack_wep_thread,
                              (void *) (long) i ) != 0 )
                        {
                              perror( "pthread_create failed" );
                              goto exit_main;
                        }
                  }

                  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:

            if ( opt.dict == NULL )
                  goto nodict;

            ap_cur = ap_1st;

            while( ap_cur != NULL )
            {
                  if( ap_cur->target && ap_cur->wpa.state == 15 )
                        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 );
            }

            for( i = 0; i < opt.nbcpu; i++ )
            {
                  /* start one thread per cpu */

                  pthread_t tid;

                  if( pthread_create( &tid, NULL, (void *) crack_wpa_thread,
                        (void *) (long) i ) != 0 )
                  {
                        perror( "pthread_create failed" );
                        goto exit_main;
                  }
            }

            ret = do_wpa_crack( ap_cur );
      }

      exit_main:

      #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 );

      _exit( ret );
}

Generated by  Doxygen 1.6.0   Back to index