Esempio n. 1
0
File: test_pmk.c Progetto: 0x0d/lrc
int main(int argc, char **argv)
{
    if (argc < 1) return 1;

    static unsigned char expected[PLEN] =
             "\x1d\x4d\xf5\x5d\xd8\xd9\x13\xf5\x54\x0d\x05\x3c\xdb\x57\x83\x53"
             "\xd0\x6c\x0f\xb3\x50\x71\x10\xee\x48\xda\xce\x2b\x60\xf6\xd0\xd4"
             "\xc2\x24\x39\x9f\xe8\x1d\x1e\x80";
    static char key[KLEN] =
             "\x6E\x9C\x7A\x91\x9F\xB8\xAE\x93\xC1\xAB\x80\x3C\x09\x00";
    static char essid[8] = "T3st1ng";


    unsigned char pmk[PLEN]; 

    printf("Calc try\n");
    calc_pmk( key, essid, pmk );
    hexdump(pmk, PLEN);
    printf("-----------------\n");

    printf("Expected\n");
    hexdump(expected, PLEN);
    printf("-----------------\n");


}
// sql function. takes ESSID and PASSWD, gives PMK
void sql_calcpmk(sqlite3_context* context, int argc, sqlite3_value** values) {
	unsigned char pmk[40];
	char* passwd = (char*)sqlite3_value_blob(values[1]);
	char* essid = (char*)sqlite3_value_blob(values[0]);
	if (argc < 2 || passwd == 0 || essid == 0) {
		sqlite3_result_error(context, "SQL function PMK() called with invalid arguments.\n", -1);
		return;
	}
	calc_pmk(passwd,essid,pmk);
	sqlite3_result_blob(context,pmk,32,SQLITE_TRANSIENT);
}
Esempio n. 3
0
void prof_pmk(char *essid)
{
  TIME_STRUCT p1,p2;

  char key[16][128];
  unsigned char pmk_sol[16][40];
  unsigned char pmk_fast[16][40];

  int i,j;
  for(i=0;i<16;i++)
    {
      strcpy(key[i],"atest");
      key[i][0]+=i;
    }

  p1 = t_start();
  for(i=0;i<16;i++)
    calc_pmk(key[i],essid,pmk_sol[i]); //key값과 essid로부터 pmk 값을 계산함
  t_end(&p1);

  p2 = t_start();
  calc_16pmk(key,essid,pmk_fast);
  t_end(&p2);

  //diff
  for(i=0;i<16;i++)
    {
      if(memcmp(pmk_sol[i],pmk_fast[i],sizeof(pmk_sol[i])) != 0)
	{
	  printf("* %d wrong case (key:%s)\n",i,key[i]);
	  dump_key("pmk_sol",pmk_sol[i],sizeof(pmk_sol[i]));
	  dump_key("pmk_fst",pmk_fast[i],sizeof(pmk_fast[i]));	  
	}
    }  
  printf("original : %0.2lf ms\n",t_get(p1)/1000);
  printf("simd ver : %0.2lf ms\n",t_get(p2)/1000);
  printf("performance : x%0.2lf\n",t_get(p1)/t_get(p2));
}
Esempio n. 4
0
void* crack_cpu_thread(void *arg)
{
  char essid[32];
  char key[128];
  uchar pmk[40];
  uchar pke[100];
  uchar ptk[80];
  uchar mic[20];
  
  ck_td_struct* ck_td_arg = (ck_td_struct*)arg;
  wpa_hdsk* phdsk = ck_td_arg->phdsk;
  int cpu_core_id = ck_td_arg->cpu_core_id;
  float* calc_speed = ck_td_arg->calc_speed;
  char* final_key = ck_td_arg->final_key;
  char* final_key_flag = ck_td_arg->final_key_flag;
  memset(essid, 0, sizeof(essid));
  memcpy(essid, ck_td_arg->essid, 32);
  
  pthread_t tid;
  tid = pthread_self();
  
  int i = 0;
  unsigned long cnt = 0;
  int cnt_int = 250;
  struct timeval tnow;
  struct timeval tlast;
  int flag = 0;
  pwd_range range;
  unsigned long cur_key_digit;
  
  // set cpu affinity
  if (ck_td_arg->set_affinity)
  {
    cpu_set_t set;
    CPU_ZERO(&set);
    CPU_SET(cpu_core_id, &set);
    flag = pthread_setaffinity_np(tid, sizeof(cpu_set_t), &set);
    if (flag)
      printf("thread %u set setaffinity failed: %s\n", (unsigned)tid, strerror(flag));
  }
  
  // do the calculation
  while (1)
  {
    // get the password range
    range = fetch_pwd('c', NULL, NULL);
    if (range.start == -1)
      break;
      
    // loop through each key in range
    for (cur_key_digit = range.start; cur_key_digit <= range.end; ++cur_key_digit)
    {    
      // calculate the calculation speed
      if (cnt == 0)
        gettimeofday(&tlast, NULL);
      else if (cnt%cnt_int == 0)
      {
        gettimeofday(&tnow, NULL);
        calc_speed[cpu_core_id] = 1.0*cnt_int/(tnow.tv_sec-tlast.tv_sec+(tnow.tv_usec-tlast.tv_usec)*0.000001);
        gettimeofday(&tlast, NULL);
      }
      cnt++;
      
      // reset variables
      memset(key, 0, sizeof(key));
      memset(pmk, 0, sizeof(pmk));
      memset(pke, 0, sizeof(pke));
      memset(ptk, 0, sizeof(ptk));
      memset(mic, 0, sizeof(mic));      
      
      // convert the key from digit to string
      sprintf(key, "%08lu", cur_key_digit);
      
      // calculate the PMK
      calc_pmk(key, essid, pmk);
      
      // pre-compute the key expansion buffer
      memcpy(pke, "Pairwise key expansion", 23);
      if (memcmp(phdsk->smac, phdsk->amac, 6) < 0)
      {
        memcpy(pke+23, phdsk->smac, 6);
        memcpy(pke+29, phdsk->amac, 6);
      }
      else
      {
        memcpy(pke+23, phdsk->amac, 6);
        memcpy(pke+29, phdsk->smac, 6);
      }
      
      if (memcmp(phdsk->snonce, phdsk->anonce, 32) < 0)
      {
        memcpy(pke+35, phdsk->snonce, 32);
        memcpy(pke+67, phdsk->anonce, 32);
      }
      else
      {
        memcpy(pke+35, phdsk->anonce, 32);
        memcpy(pke+67, phdsk->snonce, 32);
      }
      
      // calculate the PTK
      for (i=0; i<4; i++)
			{
				pke[99] = i;
				HMAC(EVP_sha1(), pmk, 32, pke, 100, ptk + i*20, NULL);
			}
			
			// calculate the MIC
			if (phdsk->keyver == 1)
				HMAC(EVP_md5(), ptk, 16, phdsk->eapol, phdsk->eapol_size, mic, NULL);
			else
				HMAC(EVP_sha1(), ptk, 16, phdsk->eapol, phdsk->eapol_size, mic, NULL);
				
			// check if MIC agrees
			if (memcmp(mic, phdsk->keymic, 16) == 0)
			{
			  memcpy(final_key, key, strlen(key));
			  *final_key_flag = 1;
			  break;
			}
    }
    
    // check if the final key is found
    if (*final_key_flag)
      break;
  }
  
  calc_speed[cpu_core_id] = -1; // this indicates the thread is returned
  return NULL;
}
Esempio n. 5
0
int main( int argc, char *argv[] )
{
    time_t tt;
    uint magic;
    char *s, buf[128];
    FILE *f_in, *f_out, *f_bad=NULL;
    unsigned long crc;
    int i = 0, n, linktype;
    uint z;
    uchar ZERO[32], *h80211;
    uchar bssid[6], stmac[6];

    struct WPA_ST_info *st_1st;
    struct WPA_ST_info *st_cur;
    struct WPA_ST_info *st_prv;
    struct pcap_file_header pfh;
    struct pcap_pkthdr pkh;

    #ifdef USE_GCRYPT
        // Disable secure memory.
        gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
        // Tell Libgcrypt that initialization has completed.
        gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    #endif

    /* parse the arguments */

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

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

        int option = getopt_long( argc, argv, "lb:k:e:p:w:H",
                        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 'l' :

                opt.no_convert = 1;
                break;

            case 'b' :

                i = 0;
                s = optarg;

                while( sscanf( s, "%x", &n ) == 1 )
                {
                    if( n < 0 || n > 255 )
                    {
                        printf( "Invalid BSSID (not a MAC).\n" );
			    		printf("\"%s --help\" for help.\n", argv[0]);
                        return( 1 );
                    }

                    opt.bssid[i] = n;

                    if( ++i >= 6 ) break;

                    if( ! ( s = strchr( s, ':' ) ) )
                        break;

                    s++;
                }

                if( i != 6 )
                {
                    printf( "Invalid BSSID (not a MAC).\n" );
		    		printf("\"%s --help\" for help.\n", argv[0]);
                    return( 1 );
                }

                break;

            case 'k' :

                if( opt.crypt != CRYPT_NONE )
                {
                    printf( "Encryption key already specified.\n" );
                    printf("\"%s --help\" for help.\n", argv[0]);
                    return( 1 );
                }

                opt.crypt = CRYPT_WPA;

                i = 0;
                s = optarg;

                buf[0] = s[0];
                buf[1] = s[1];
                buf[2] = '\0';

                while( sscanf( buf, "%x", &n ) == 1 )
                {
                    if( n < 0 || n > 255 )
                    {
                        printf( "Invalid WPA PMK.\n" );
                        printf("\"%s --help\" for help.\n", argv[0]);
                        return( 1 );
                    }

                    opt.pmk[i++] = n;
                    if( i >= 32 ) break;

                    s += 2;

                    if( s[0] == ':' || s[0] == '-' )
                        s++;

                    if( s[0] == '\0' || s[1] == '\0' )
                        break;

                    buf[0] = s[0];
                    buf[1] = s[1];
                }

                if( i != 32 )
                {
                    printf( "Invalid WPA PMK.\n" );
		    		printf("\"%s --help\" for help.\n", argv[0]);
                    return( 1 );
                }

                break;

            case 'e' :

				if ( opt.essid[0])
				{
					printf( "ESSID already specified.\n" );
		    		printf("\"%s --help\" for help.\n", argv[0]);
                    return( 1 );
				}

                memset(  opt.essid, 0, sizeof( opt.essid ) );
                strncpy( opt.essid, optarg, sizeof( opt.essid ) - 1 );
                break;

            case 'p' :

                if( opt.crypt != CRYPT_NONE )
                {
                    printf( "Encryption key already specified.\n" );
		    		printf("\"%s --help\" for help.\n", argv[0]);
                    return( 1 );
                }

                opt.crypt = CRYPT_WPA;

                memset(  opt.passphrase, 0, sizeof( opt.passphrase ) );
                strncpy( opt.passphrase, optarg, sizeof( opt.passphrase ) - 1 );
                break;

            case 'w' :

                if( opt.crypt != CRYPT_NONE )
                {
                    printf( "Encryption key already specified.\n" );
		    		printf("\"%s --help\" for help.\n", argv[0]);
                    return( 1 );
                }

                opt.crypt = CRYPT_WEP;

                i = 0;
                s = optarg;

                buf[0] = s[0];
                buf[1] = s[1];
                buf[2] = '\0';

                while( sscanf( buf, "%x", &n ) == 1 )
                {
                    if( n < 0 || n > 255 )
                    {
                        printf( "Invalid WEP key.\n" );
			    		printf("\"%s --help\" for help.\n", argv[0]);
                        return( 1 );
                    }

                    opt.wepkey[i++] = n;

                    if( i >= 64 ) break;

                    s += 2;

                    if( s[0] == ':' || s[0] == '-' )
                        s++;

                    if( s[0] == '\0' || s[1] == '\0' )
                        break;

                    buf[0] = s[0];
                    buf[1] = s[1];
                }

                if( i != 5 && i != 13 && i != 16 && i != 29 && i != 61 )
                {
                    printf( "Invalid WEP key length. [5,13,16,29,61]\n" );
		    		printf("\"%s --help\" for help.\n", argv[0]);
                    return( 1 );
                }

                opt.weplen = i;

                break;

            case 'H' :

            	printf( usage, getVersion("Airdecap-ng", _MAJ, _MIN, _SUB_MIN, _REVISION, _BETA, _RC));
            	return( 1 );

            default : goto usage;
        }
    }

    if( argc - optind != 1 )
    {
    	if(argc == 1)
    	{
usage:
	        printf( usage, getVersion("Airdecap-ng", _MAJ, _MIN, _SUB_MIN, _REVISION, _BETA, _RC));
	    }
		if( argc - optind == 0)
	    {
	    	printf("No file to decrypt specified.\n");
	    }
	    if(argc > 1)
	    {
    		printf("\"%s --help\" for help.\n", argv[0]);
	    }
        return( 1 );
    }

    if( opt.crypt == CRYPT_WPA )
    {
        if( opt.passphrase[0] != '\0' )
        {
            /* compute the Pairwise Master Key */

            if( opt.essid[0] == '\0' )
            {
                printf( "You must also specify the ESSID (-e).\n" );
	    		printf("\"%s --help\" for help.\n", argv[0]);
                return( 1 );
            }

            calc_pmk( opt.passphrase, opt.essid, opt.pmk );
        }
    }

    /* open the input and output pcap files */

    if( ( f_in = fopen( argv[optind], "rb" ) ) == NULL )
    {
        perror( "fopen failed\n" );
        printf( "Could not open \"%s\".\n", argv[optind] );
        return( 1 );
    }

    n = sizeof( pfh );

    if( fread( &pfh, 1, n, f_in ) != (size_t) n )
    {
        perror( "fread(pcap file header) failed" );
        return( 1 );
    }

    if( pfh.magic != TCPDUMP_MAGIC &&
        pfh.magic != TCPDUMP_CIGAM )
    {
        printf( "\"%s\" isn't a pcap file (expected "
                "TCPDUMP_MAGIC).\n", argv[optind] );
        return( 1 );
    }

    if( ( magic = pfh.magic ) == TCPDUMP_CIGAM )
        SWAP32( pfh.linktype );

    if( pfh.linktype != LINKTYPE_IEEE802_11 &&
        pfh.linktype != LINKTYPE_PRISM_HEADER &&
        pfh.linktype != LINKTYPE_RADIOTAP_HDR &&
		pfh.linktype != LINKTYPE_PPI_HDR )
    {
        printf( "\"%s\" isn't a regular 802.11 "
                "(wireless) capture.\n", argv[optind] );
        return( 1 );
    }

    linktype = pfh.linktype;

    n = strlen( argv[optind] );

    if( n > 4 && ( n + 5 < (int) sizeof( buffer ) ) &&
        argv[optind][n - 4] == '.' )
    {
        memcpy( buffer , argv[optind], n - 4 );
        memcpy( buffer2, argv[optind], n - 4 );
        memcpy( buffer  + n - 4, "-dec", 4 );
        memcpy( buffer2 + n - 4, "-bad", 4 );
        memcpy( buffer  + n, argv[optind] + n - 4, 5 );
        memcpy( buffer2 + n, argv[optind] + n - 4, 5 );
    }
    else
    {
        if( n > 5 && ( n + 6 < (int) sizeof( buffer ) ) &&
            argv[optind][n - 5] == '.' )
        {
            memcpy( buffer , argv[optind], n - 5 );
            memcpy( buffer2, argv[optind], n - 5 );
            memcpy( buffer  + n - 5, "-dec", 4 );
            memcpy( buffer2 + n - 5, "-bad", 4 );
            memcpy( buffer  + n - 1, argv[optind] + n - 5, 6 );
            memcpy( buffer2 + n - 1, argv[optind] + n - 5, 6 );
        }
        else
        {
            memset( buffer , 0, sizeof( buffer ) );
            memset( buffer2, 0, sizeof( buffer ) );
            snprintf( (char *) buffer , sizeof( buffer ) - 1,
                      "%s-dec", argv[optind] );
            snprintf( (char *) buffer2, sizeof( buffer ) - 1,
                      "%s-bad", argv[optind] );
        }
    }

    if( opt.crypt == CRYPT_WEP && opt.no_convert == 1 )
    {
        opt.store_bad=1;
    }

    if( ( f_out = fopen( (char *) buffer, "wb+" ) ) == NULL )
    {
        perror( "fopen failed" );
        printf( "Could not create \"%s\".\n", buffer );
        return( 1 );
    }

    if(opt.store_bad)
    {
        if( ( f_bad = fopen( (char *) buffer2, "wb+" ) ) == NULL )
        {
            perror( "fopen failed" );
            printf( "Could not create \"%s\".\n", buffer2 );
            return( 1 );
        }
    }

    pfh.magic           = TCPDUMP_MAGIC;
    pfh.version_major   = PCAP_VERSION_MAJOR;
    pfh.version_minor   = PCAP_VERSION_MINOR;
    pfh.thiszone        = 0;
    pfh.sigfigs         = 0;
    pfh.snaplen         = 65535;
    pfh.linktype        = ( opt.no_convert ) ?
                            LINKTYPE_IEEE802_11 :
                            LINKTYPE_ETHERNET;

    n = sizeof( pfh );

    if( fwrite( &pfh, 1, n, f_out ) != (size_t) n )
    {
        perror( "fwrite(pcap file header) failed" );
        return( 1 );
    }

    if(opt.store_bad)
    {
        if( fwrite( &pfh, 1, n, f_bad ) != (size_t) n )
        {
            perror( "fwrite(pcap file header) failed" );
            return( 1 );
        }
    }

    /* loop reading and deciphering the packets */

    memset( &stats, 0, sizeof( stats ) );
    tt = time( NULL );
    st_1st = NULL;

    while( 1 )
    {
        if( time( NULL ) - tt > 0 )
        {
            /* update the status line every second */

            printf( "\33[KRead %ld packets...\r", stats.nb_read );
            fflush( stdout );
            tt = time( NULL );
        }

        /* read one packet */

        n = sizeof( pkh );

        if( fread( &pkh, 1, n, f_in ) != (size_t) n )
            break;

        if( magic == TCPDUMP_CIGAM ) {
            SWAP32( pkh.caplen );
            SWAP32( pkh.len );
        }

        n = pkh.caplen;

        if( n <= 0 || n > 65535 )
        {
            printf( "Corrupted file? Invalid packet length %d.\n", n );
            break;
        }

        if( fread( buffer, 1, n, f_in ) != (size_t) n )
            break;

        stats.nb_read++;

        h80211 = buffer;

        if( linktype == LINKTYPE_PRISM_HEADER )
        {
            /* remove the prism header */

            if( h80211[7] == 0x40 )
                n = 64; /* prism54 */
            else
            {
                n = *(int *)( h80211 + 4 );

                if( magic == TCPDUMP_CIGAM )
                    SWAP32( n );
            }

            if( n < 8 || n >= (int) pkh.caplen )
                continue;

            h80211 += n; pkh.caplen -= n;
        }

        if( linktype == LINKTYPE_RADIOTAP_HDR )
        {
            /* remove the radiotap header */

            n = *(unsigned short *)( h80211 + 2 );

            if( n <= 0 || n >= (int) pkh.caplen )
                continue;

            h80211 += n; pkh.caplen -= n;
        }

		if( linktype == LINKTYPE_PPI_HDR )
		{
			/* Remove the PPI header */

			n = le16_to_cpu(*(unsigned short *)( h80211 + 2));

			if( n <= 0 || n>= (int) pkh.caplen )
				continue;

			/* for a while Kismet logged broken PPI headers */
			if ( n == 24 && le16_to_cpu(*(unsigned short *)(h80211 + 8)) == 2 )
				n = 32;

			if( n <= 0 || n>= (int) pkh.caplen )
				continue;

			h80211 += n; pkh.caplen -= n;
		}

        /* remove the FCS if present (madwifi) */

        if( check_crc_buf( h80211, pkh.caplen - 4 ) == 1 )
        {
            pkh.len    -= 4;
            pkh.caplen -= 4;
        }

        /* check if data */

        if( ( h80211[0] & 0x0C ) != 0x08 )
            continue;

        /* check minimum size */

        z = ( ( h80211[1] & 3 ) != 3 ) ? 24 : 30;

        if( z + 16 > pkh.caplen )
            continue;

        /* check QoS header */
        if ( GET_SUBTYPE(h80211[0]) == IEEE80211_FC0_SUBTYPE_QOS ) {
            z += 2;
        }

        /* check the BSSID */

        switch( h80211[1] & 3 )
        {
            case  0: memcpy( bssid, h80211 + 16, 6 ); break;  //Adhoc
            case  1: memcpy( bssid, h80211 +  4, 6 ); break;  //ToDS
            case  2: memcpy( bssid, h80211 + 10, 6 ); break;  //FromDS
            case  3: memcpy( bssid, h80211 + 10, 6 ); break;  //WDS -> Transmitter taken as BSSID
        }

        if( memcmp( opt.bssid, ZERO, 6 ) != 0 )
            if( memcmp( opt.bssid, bssid, 6 ) != 0 )
                continue;

        /* locate the station's MAC address */

        switch( h80211[1] & 3 )
        {
            case  1: memcpy( stmac, h80211 + 10, 6 ); break;
            case  2: memcpy( stmac, h80211 +  4, 6 ); break;
            case  3: memcpy( stmac, h80211 + 10, 6 ); break;
            default: continue;
        }

        st_prv = NULL;
        st_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 station, add it */

        if( st_cur == NULL )
        {
            if( ! ( st_cur = (struct WPA_ST_info *) malloc(
                             sizeof( struct WPA_ST_info ) ) ) )
            {
                perror( "malloc failed" );
                break;
            }

            memset( st_cur, 0, sizeof( struct WPA_ST_info ) );

            if( st_1st == NULL )
                st_1st = st_cur;
            else
                st_prv->next = st_cur;

            memcpy( st_cur->stmac, stmac, 6 );
            memcpy( st_cur->bssid, bssid, 6 );
        }

        /* check if we haven't already processed this packet */

        crc = calc_crc_buf( h80211 + z, pkh.caplen - z );

        if( ( h80211[1] & 3 ) == 2 )
        {
            if( st_cur->t_crc == crc )
                continue;

            st_cur->t_crc = crc;
        }
        else
        {
            if( st_cur->f_crc == crc )
                continue;

            st_cur->f_crc = crc;
        }

        /* check the SNAP header to see if data is encrypted *
         * as unencrypted data begins with AA AA 03 00 00 00 */

        if( h80211[z] != h80211[z + 1] || h80211[z + 2] != 0x03 )
        {
            /* check the extended IV flag */

            if( ( h80211[z + 3] & 0x20 ) == 0 )
            {
                uchar K[64];

                stats.nb_wep++;

                if( opt.crypt != CRYPT_WEP )
                    continue;

                memcpy( K, h80211 + z, 3 );
                memcpy( K + 3, opt.wepkey, opt.weplen );

                if(opt.store_bad)
                    memcpy(buffer2, h80211, pkh.caplen);

                if( decrypt_wep( h80211 + z + 4, pkh.caplen - z - 4,
                                 K, 3 + opt.weplen ) == 0 )
                {
                    if(opt.store_bad)
                    {
                        stats.nb_bad++;
                        memcpy(h80211, buffer2, pkh.caplen);
                        if( write_packet( f_bad, &pkh, h80211 ) != 0 )
                            break;
                    }
                    continue;
                }

                /* WEP data packet was successfully decrypted, *
                 * remove the WEP IV & ICV and write the data  */

                pkh.len    -= 8;
                pkh.caplen -= 8;

                memmove( h80211 + z, h80211 + z + 4, pkh.caplen - z );

                stats.nb_unwep++;

                h80211[1] &= 0xBF;

                if( write_packet( f_out, &pkh, h80211 ) != 0 )
                    break;
            }
            else
            {
                stats.nb_wpa++;

                if( opt.crypt != CRYPT_WPA )
                    continue;

                /* if the PTK is valid, try to decrypt */

                if( st_cur == NULL || ! st_cur->valid_ptk )
                    continue;

                if( st_cur->keyver == 1 )
                {
                    if( decrypt_tkip( h80211, pkh.caplen,
                                      st_cur->ptk + 32 ) == 0 )
                        continue;

                    pkh.len    -= 20;
                    pkh.caplen -= 20;
                }
                else
                {
                    if( decrypt_ccmp( h80211, pkh.caplen,
                                      st_cur->ptk + 32 ) == 0 )
                        continue;

                    pkh.len    -= 16;
                    pkh.caplen -= 16;
                }

                /* WPA data packet was successfully decrypted, *
                 * remove the WPA Ext.IV & MIC, write the data */

                /* can overlap */
                memmove( h80211 + z, h80211 + z + 8, pkh.caplen - z );

                stats.nb_unwpa++;

                h80211[1] &= 0xBF;

                if( write_packet( f_out, &pkh, h80211 ) != 0 )
                    break;
            }
        }
        else
        {
            /* check ethertype == EAPOL */

            z += 6;

            if( h80211[z] != 0x88 || h80211[z + 1] != 0x8E )
            {
                stats.nb_plain++;

                if( opt.crypt != CRYPT_NONE )
                    continue;

                if( write_packet( f_out, &pkh, h80211 ) != 0 )
                    break;
				else
					continue;
            }

            z += 2;

            /* type == 3 (key), desc. == 254 (WPA) or 2 (RSN) */

            if( h80211[z + 1] != 0x03 ||
                ( h80211[z + 4] != 0xFE && h80211[z + 4] != 0x02 ) )
                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 )
            {
                /* set authenticator nonce */

                memcpy( st_cur->anonce, &h80211[z + 17], 32 );
            }

            /* 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 )
                {
                    /* set supplicant nonce */

                    memcpy( st_cur->snonce, &h80211[z + 17], 32 );
                }

                /* copy the MIC & eapol frame */

                st_cur->eapol_size = ( h80211[z + 2] << 8 )
                                   +   h80211[z + 3] + 4;

                if (pkh.len - z < st_cur->eapol_size  || st_cur->eapol_size == 0 ||
                    st_cur->eapol_size > sizeof(st_cur->eapol))
                {
                        // Ignore the packet trying to crash us.
                        st_cur->eapol_size = 0;
                        continue;
                }

                memcpy( st_cur->keymic, &h80211[z + 81], 16 );
                memcpy( st_cur->eapol, &h80211[z], st_cur->eapol_size );
                memset( st_cur->eapol + 81, 0, 16 );

                /* copy the key descriptor version */

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

            /* frame 3: Pairwise == 1, Install == 1, Ack == 1, MIC == 1 */

            if( ( h80211[z + 6] & 0x08 ) != 0 &&
                ( h80211[z + 6] & 0x40 ) != 0 &&
                ( h80211[z + 6] & 0x80 ) != 0 &&
                ( h80211[z + 5] & 0x01 ) != 0 )
            {
                if( memcmp( &h80211[z + 17], ZERO, 32 ) != 0 )
                {
                    /* set authenticator nonce */

                    memcpy( st_cur->anonce, &h80211[z + 17], 32 );
                }

                /* copy the MIC & eapol frame */

                st_cur->eapol_size = ( h80211[z + 2] << 8 )
                                   +   h80211[z + 3] + 4;

                if (pkh.len - z < st_cur->eapol_size  || st_cur->eapol_size == 0 ||
                    st_cur->eapol_size > sizeof(st_cur->eapol))
                {
                    // Ignore the packet trying to crash us.
                    st_cur->eapol_size = 0;
                    continue;
                 }

                memcpy( st_cur->keymic, &h80211[z + 81], 16 );
                memcpy( st_cur->eapol, &h80211[z], st_cur->eapol_size );
                memset( st_cur->eapol + 81, 0, 16 );

                /* copy the key descriptor version */

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

            st_cur->valid_ptk = calc_ptk( st_cur, opt.pmk );
        }
    }

    fclose( f_in  );
    fclose( f_out );
    if(opt.store_bad)
        fclose( f_bad );

    /* write some statistics */

    printf( "\33[KTotal number of packets read      % 8ld\n"
                 "Total number of WEP data packets  % 8ld\n"
                 "Total number of WPA data packets  % 8ld\n"
                 "Number of plaintext data packets  % 8ld\n"
                 "Number of decrypted WEP  packets  % 8ld\n"
                 "Number of corrupted WEP  packets  % 8ld\n"
                 "Number of decrypted WPA  packets  % 8ld\n",
            stats.nb_read, stats.nb_wep, stats.nb_wpa,
            stats.nb_plain, stats.nb_unwep, stats.nb_bad, stats.nb_unwpa );

    return( 0 );
}