airdecap.c
上传用户:fubang
上传日期:2009-06-18
资源大小:2071k
文件大小:34k
源码类别:

其他

开发平台:

Unix_Linux

  1. /*
  2.  *  802.11 to Ethernet pcap translator
  3.  *
  4.  *  Copyright (C) 2004,2005  Christophe Devine
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20. #include <unistd.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <time.h>
  25. #include "crctable.h"
  26. #include "crypto.h"
  27. #include "pcap.h"
  28. #define CRYPT_NONE 0
  29. #define CRYPT_WEP  1
  30. #define CRYPT_WPA  2
  31. const short Sbox[2][256]=
  32. {
  33.     {
  34.         0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
  35.         0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
  36.         0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
  37.         0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
  38.         0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
  39.         0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
  40.         0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
  41.         0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
  42.         0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
  43.         0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
  44.         0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
  45.         0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
  46.         0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
  47.         0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
  48.         0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
  49.         0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
  50.         0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
  51.         0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
  52.         0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
  53.         0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
  54.         0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
  55.         0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
  56.         0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
  57.         0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
  58.         0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
  59.         0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
  60.         0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
  61.         0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
  62.         0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
  63.         0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
  64.         0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
  65.         0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A
  66.     },
  67.     {
  68.         0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
  69.         0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
  70.         0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
  71.         0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
  72.         0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
  73.         0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
  74.         0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
  75.         0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
  76.         0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
  77.         0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
  78.         0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
  79.         0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
  80.         0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
  81.         0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
  82.         0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
  83.         0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
  84.         0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
  85.         0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
  86.         0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
  87.         0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
  88.         0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
  89.         0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
  90.         0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
  91.         0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
  92.         0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
  93.         0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
  94.         0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
  95.         0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
  96.         0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
  97.         0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
  98.         0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
  99.         0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C
  100.     }
  101. };
  102. /* derive the PMK from the passphrase and the essid */
  103. void calc_pmk( char *key, char *essid, uchar pmk[40] )
  104. {
  105.     int i, j, slen;
  106.     uchar buffer[65];
  107.     sha1_context ctx_ipad;
  108.     sha1_context ctx_opad;
  109.     sha1_context sha1_ctx;
  110.     slen = strlen( essid ) + 4;
  111.     /* setup the inner and outer contexts */
  112.     memset( buffer, 0, sizeof( buffer ) );
  113.     strncpy( (char *) buffer, key, sizeof( buffer ) - 1 );
  114.     for( i = 0; i < 64; i++ )
  115.         buffer[i] ^= 0x36;
  116.     sha1_starts( &ctx_ipad );
  117.     sha1_update( &ctx_ipad, buffer, 64 );
  118.     for( i = 0; i < 64; i++ )
  119.         buffer[i] ^= 0x6A;
  120.     sha1_starts( &ctx_opad );
  121.     sha1_update( &ctx_opad, buffer, 64 );
  122.     /* iterate HMAC-SHA1 over itself 8192 times */
  123.     essid[slen - 1] = '1';
  124.     hmac_sha1( (uchar *) key, strlen( key ),
  125.                (uchar *) essid, slen, pmk );
  126.     memcpy( buffer, pmk, 20 );
  127.     for( i = 1; i < 4096; i++ )
  128.     {
  129.         memcpy( &sha1_ctx, &ctx_ipad, sizeof( sha1_ctx ) );
  130.         sha1_update( &sha1_ctx, buffer, 20 );
  131.         sha1_finish( &sha1_ctx, buffer );
  132.         memcpy( &sha1_ctx, &ctx_opad, sizeof( sha1_ctx ) );
  133.         sha1_update( &sha1_ctx, buffer, 20 );
  134.         sha1_finish( &sha1_ctx, buffer );
  135.         for( j = 0; j < 20; j++ )
  136.             pmk[j] ^= buffer[j];
  137.     }
  138.     essid[slen - 1] = '2';
  139.     hmac_sha1( (uchar *) key, strlen( key ),
  140.                (uchar *) essid, slen, pmk + 20 );
  141.     memcpy( buffer, pmk + 20, 20 );
  142.     for( i = 1; i < 4096; i++ )
  143.     {
  144.         memcpy( &sha1_ctx, &ctx_ipad, sizeof( sha1_ctx ) );
  145.         sha1_update( &sha1_ctx, buffer, 20 );
  146.         sha1_finish( &sha1_ctx, buffer );
  147.         memcpy( &sha1_ctx, &ctx_opad, sizeof( sha1_ctx ) );
  148.         sha1_update( &sha1_ctx, buffer, 20 );
  149.         sha1_finish( &sha1_ctx, buffer );
  150.         for( j = 0; j < 20; j++ )
  151.             pmk[j + 20] ^= buffer[j];
  152.     }
  153. }
  154. struct ST_info
  155. {
  156.     struct ST_info *next;       /* next supplicant              */
  157.     uchar stmac[6];             /* supplicant MAC               */
  158.     uchar bssid[6];             /* authenticator MAC            */
  159.     uchar snonce[32];           /* supplicant nonce             */
  160.     uchar anonce[32];           /* authenticator nonce          */
  161.     uchar keymic[20];           /* eapol frame MIC              */
  162.     uchar eapol[256];           /* eapol frame contents         */
  163.     uchar ptk[80];              /* pairwise transcient key      */
  164.     int eapol_size;             /* eapol frame size             */
  165.     unsigned long t_crc;        /* last ToDS   frame CRC        */
  166.     unsigned long f_crc;        /* last FromDS frame CRC        */
  167.     int keyver, valid_ptk;
  168. };
  169. /* derive the pairwise transcient keys from a bunch of stuff */
  170. int calc_ptk( struct ST_info *wpa, uchar pmk[32] )
  171. {
  172.     int i;
  173.     uchar pke[100];
  174.     uchar mic[20];
  175.     memcpy( pke, "Pairwise key expansion", 23 );
  176.     if( memcmp( wpa->stmac, wpa->bssid, 6 ) < 0 )
  177.     {
  178.         memcpy( pke + 23, wpa->stmac, 6 );
  179.         memcpy( pke + 29, wpa->bssid, 6 );
  180.     }
  181.     else
  182.     {
  183.         memcpy( pke + 23, wpa->bssid, 6 );
  184.         memcpy( pke + 29, wpa->stmac, 6 );
  185.     }
  186.     if( memcmp( wpa->snonce, wpa->anonce, 32 ) < 0 )
  187.     {
  188.         memcpy( pke + 35, wpa->snonce, 32 );
  189.         memcpy( pke + 67, wpa->anonce, 32 );
  190.     }
  191.     else
  192.     {
  193.         memcpy( pke + 35, wpa->anonce, 32 );
  194.         memcpy( pke + 67, wpa->snonce, 32 );
  195.     }
  196.     for( i = 0; i < 4; i++ )
  197.     {
  198.         pke[99] = i;
  199.         hmac_sha1( pmk, 32, pke, 100, wpa->ptk + i * 20 );
  200.     }
  201.     /* check the EAPOL frame MIC */
  202.     if( ( wpa->keyver & 0x07 ) == 1 )
  203.         hmac_md5(  wpa->ptk, 16, wpa->eapol, wpa->eapol_size, mic );
  204.     else
  205.         hmac_sha1( wpa->ptk, 16, wpa->eapol, wpa->eapol_size, mic );
  206.     return( memcmp( mic, wpa->keymic, 16 ) == 0 );
  207. }
  208. /* CRC checksum calculation routine */
  209. int calc_crc_buf( unsigned char *buf, int len )
  210. {
  211.     unsigned long crc = 0xFFFFFFFF;
  212.     for( ; len > 0; len--, buf++ )
  213.         crc = crc_tbl[(crc ^ *buf) & 0xFF] ^ ( crc >> 8 );
  214.     return( ~crc );
  215. }
  216. /* CRC checksum verification routine */
  217. int check_crc_buf( unsigned char *buf, int len )
  218. {
  219.     unsigned long crc = 0xFFFFFFFF;
  220.     for( ; len > 0; len--, buf++ )
  221.         crc = crc_tbl[(crc ^ *buf) & 0xFF] ^ ( crc >> 8 );
  222.     crc = ~crc;
  223.     return( ( ( crc       ) & 0xFF ) == buf[0] &&
  224.             ( ( crc >>  8 ) & 0xFF ) == buf[1] &&
  225.             ( ( crc >> 16 ) & 0xFF ) == buf[2] &&
  226.             ( ( crc >> 24 ) & 0xFF ) == buf[3] );
  227. }
  228. /* WEP (barebone RC4) decryption routine */
  229. int decrypt_wep( uchar *data, int len, uchar *key, int keylen )
  230. {
  231.     struct rc4_state S;
  232.     rc4_setup( &S, key, keylen );
  233.     rc4_crypt( &S, data, len );
  234.     return( check_crc_buf( data, len - 4 ) );
  235. }
  236. /* TKIP (RC4 + key mixing) decryption routine */
  237. #define ROTR1(x)      ((((x) >> 1) & 0x7FFF) ^ (((x) & 1) << 15))
  238. #define LO8(x)        ( (x) & 0x00FF )
  239. #define LO16(x)       ( (x) & 0xFFFF )
  240. #define HI8(x)        ( ((x) >>  8) & 0x00FF )
  241. #define HI16(x)       ( ((x) >> 16) & 0xFFFF )
  242. #define MK16(hi,lo)   ( (lo) ^ ( LO8(hi) << 8 ) )
  243. #define TK16(N)       MK16(TK1[2*(N)+1],TK1[2*(N)])
  244. #define _S_(x)        (Sbox[0][LO8(x)] ^ Sbox[1][HI8(x)])
  245. int decrypt_tkip( uchar *h80211, int caplen, uchar TK1[16] )
  246. {
  247.     int i, z;
  248.     uint IV32;
  249.     ushort IV16;
  250.     ushort PPK[6];
  251.     uchar K[16];
  252.     z = ( ( h80211[1] & 3 ) != 3 ) ? 24 : 30;
  253.     IV16 = MK16( h80211[z], h80211[z + 2] );
  254.     IV32 = ( h80211[z + 4]       ) | ( h80211[z + 5] <<  8 ) |
  255.            ( h80211[z + 6] << 16 ) | ( h80211[z + 7] << 24 );
  256.     PPK[0] = LO16( IV32 );
  257.     PPK[1] = HI16( IV32 );
  258.     PPK[2] = MK16( h80211[11], h80211[10] );
  259.     PPK[3] = MK16( h80211[13], h80211[12] );
  260.     PPK[4] = MK16( h80211[15], h80211[14] );
  261.     for( i = 0; i < 8; i++ )
  262.     {
  263.         PPK[0] += _S_( PPK[4] ^ TK16( (i & 1) + 0 ) );
  264.         PPK[1] += _S_( PPK[0] ^ TK16( (i & 1) + 2 ) );
  265.         PPK[2] += _S_( PPK[1] ^ TK16( (i & 1) + 4 ) );
  266.         PPK[3] += _S_( PPK[2] ^ TK16( (i & 1) + 6 ) );
  267.         PPK[4] += _S_( PPK[3] ^ TK16( (i & 1) + 0 ) ) + i;
  268.     }
  269.     PPK[5] = PPK[4] + IV16;
  270.     PPK[0] += _S_( PPK[5] ^ TK16(0) );
  271.     PPK[1] += _S_( PPK[0] ^ TK16(1) );
  272.     PPK[2] += _S_( PPK[1] ^ TK16(2) );
  273.     PPK[3] += _S_( PPK[2] ^ TK16(3) );
  274.     PPK[4] += _S_( PPK[3] ^ TK16(4) );
  275.     PPK[5] += _S_( PPK[4] ^ TK16(5) );
  276.     PPK[0] += ROTR1( PPK[5] ^ TK16(6) );
  277.     PPK[1] += ROTR1( PPK[0] ^ TK16(7) );
  278.     PPK[2] += ROTR1( PPK[1] );
  279.     PPK[3] += ROTR1( PPK[2] );
  280.     PPK[4] += ROTR1( PPK[3] );
  281.     PPK[5] += ROTR1( PPK[4] );
  282.     K[0] =   HI8( IV16 );
  283.     K[1] = ( HI8( IV16 ) | 0x20 ) & 0x7F;
  284.     K[2] =   LO8( IV16 );
  285.     K[3] =   LO8( (PPK[5] ^ TK16(0) ) >> 1);
  286.     for( i = 0; i < 6; i++ )
  287.     {
  288.         K[4 + ( 2 * i)] = LO8( PPK[i] );
  289.         K[5 + ( 2 * i)] = HI8( PPK[i] );
  290.     }
  291.     return( decrypt_wep( h80211 + z + 8, caplen - z - 8, K, 16 ) );
  292. }
  293. /* CCMP (AES-CTR-MAC) decryption routine */
  294. static inline void XOR( uchar *dst, uchar *src, int len )
  295. {
  296.     int i;
  297.     for( i = 0; i < len; i++ )
  298.         dst[i] ^= src[i];
  299. }
  300. int decrypt_ccmp( uchar *h80211, int caplen, uchar TK1[16] )
  301. {
  302.     int is_a4, i, n, z, blocks;
  303.     int data_len, last, offset;
  304.     uchar B0[16], B[16], MIC[16];
  305.     uchar PN[6], AAD[32];
  306.     aes_context aes_ctx;
  307.     is_a4 = ( h80211[0] & 3 ) == 3;
  308.     z = 24 + 6 * is_a4;
  309.     PN[0] = h80211[z + 7];
  310.     PN[1] = h80211[z + 6];
  311.     PN[2] = h80211[z + 5];
  312.     PN[3] = h80211[z + 4];
  313.     PN[4] = h80211[z + 1];
  314.     PN[5] = h80211[z + 0];
  315.     data_len = caplen - z - 8 - 8;
  316.     B0[0] = 0x59;
  317.     B0[1] = 0;
  318.     memcpy( B0 + 2, h80211 + 10, 6 );
  319.     memcpy( B0 + 8, PN, 6 );
  320.     B0[14] = ( data_len >> 8 ) & 0xFF;
  321.     B0[15] = ( data_len & 0xFF );
  322.     memset( AAD, 0, sizeof( AAD ) );
  323.     AAD[1] = 22 + 6 * is_a4;
  324.     AAD[2] = h80211[0] & 0x8F;
  325.     AAD[3] = h80211[1] & 0xC7;
  326.     memcpy( AAD + 4, h80211 + 4, 3 * 6 );
  327.     AAD[22] = h80211[22] & 0x0F;
  328.     if( is_a4 )
  329.         memcpy( AAD + 24, h80211 + 24, 6 );
  330.     aes_set_key( &aes_ctx, TK1, 128 );
  331.     aes_encrypt( &aes_ctx, B0, MIC );
  332.     XOR( MIC, AAD, 16 );
  333.     aes_encrypt( &aes_ctx, MIC, MIC );
  334.     XOR( MIC, AAD + 16, 16 );
  335.     aes_encrypt( &aes_ctx, MIC, MIC );
  336.     B0[0] &= 0x07;
  337.     B0[14] = B0[15] = 0;
  338.     aes_encrypt( &aes_ctx, B0, B );
  339.     XOR( h80211 + caplen - 8, B, 8 );
  340.     blocks = ( data_len + 16 - 1 ) / 16;
  341.     last = data_len % 16;
  342.     offset = z + 8;
  343.     for( i = 1; i <= blocks; i++ )
  344.     {
  345.         n = ( last > 0 && i == blocks ) ? last : 16;
  346.         B0[14] = ( i >> 8 ) & 0xFF;
  347.         B0[15] =   i & 0xFF;
  348.         aes_encrypt( &aes_ctx, B0, B );
  349.         XOR( h80211 + offset, B, n );
  350.         XOR( MIC, h80211 + offset, n );
  351.         aes_encrypt( &aes_ctx, MIC, MIC );
  352.         offset += n;
  353.     }
  354.     return( memcmp( h80211 + offset, MIC, 8 ) == 0 );
  355. }
  356. struct decap_stats
  357. {
  358.     unsigned long nb_read;      /* # of packets read       */
  359.     unsigned long nb_wep;       /* # of WEP data packets   */
  360.     unsigned long nb_wpa;       /* # of WPA data packets   */
  361.     unsigned long nb_plain;     /* # of plaintext packets  */
  362.     unsigned long nb_unwep;     /* # of decrypted WEP pkt  */
  363.     unsigned long nb_unwpa;     /* # of decrypted WPA pkt  */
  364. }
  365. stats;
  366. struct options
  367. {
  368.     int no_convert;
  369.     char essid[36];
  370.     char passphrase[65];
  371.     uchar bssid[6];
  372.     uchar pmk[40];
  373.     uchar wepkey[64];
  374.     int weplen, crypt;
  375. }
  376. opt;
  377. char usage[] =
  378. "n"
  379. "  airdecap %d.%d - (C) 2004,2005 Christophe Devinen"
  380. "n"
  381. "  usage: airdecap [options] <pcap file>n"
  382. "n"
  383. "      -l       : don't remove the 802.11 headern"
  384. "      -b bssid : access point MAC address filtern"
  385. "      -k pmk   : WPA Pairwise Master Key in hexn"
  386. "      -e essid : target network ascii identifiern"
  387. "      -p pass  : target network WPA passphrasen"
  388. "      -w key   : target network WEP key in hexn"
  389. "n"
  390. "  examples:n"
  391. "n"
  392. "  airdecap -b 00:09:5B:10:BC:5A open-network.capn"
  393. "  airdecap -w 11A3E229084349BC25D97E2939 wep.capn"
  394. "  airdecap -e my_essid -p my_passphrase tkip.capn"
  395. "n";
  396. uchar buffer[65536];
  397. /* this routine handles to 802.11 to Ethernet translation */
  398. int write_packet( FILE *f_out, struct pcap_pkthdr *pkh, uchar *h80211 )
  399. {
  400.     int n;
  401.     uchar arphdr[12];
  402.     if( opt.no_convert )
  403.     {
  404.         if( buffer != h80211 )
  405.             memcpy( buffer, h80211, pkh->caplen );
  406.     }
  407.     else
  408.     {
  409.         /* create the Ethernet link layer (MAC dst+src) */
  410.         switch( h80211[1] & 3 )
  411.         {
  412.             case  0:    /* To DS = 0, From DS = 0: DA, SA, BSSID */
  413.                 memcpy( arphdr + 0, h80211 +  4, 6 );
  414.                 memcpy( arphdr + 6, h80211 + 10, 6 );
  415.                 break;
  416.             case  1:    /* To DS = 1, From DS = 0: BSSID, SA, DA */
  417.                 memcpy( arphdr + 0, h80211 + 16, 6 );
  418.                 memcpy( arphdr + 6, h80211 + 10, 6 );
  419.                 break;
  420.             case  2:    /* To DS = 0, From DS = 1: DA, BSSID, SA */
  421.                 memcpy( arphdr + 0, h80211 +  4, 6 );
  422.                 memcpy( arphdr + 6, h80211 + 16, 6 );
  423.                 break;
  424.             default:    /* To DS = 1, From DS = 1: RA, TA, DA, SA */
  425.                 memcpy( arphdr + 0, h80211 + 16, 6 );
  426.                 memcpy( arphdr + 6, h80211 + 24, 6 );
  427.                 break;
  428.         }
  429.         /* remove the 802.11 + LLC header */
  430.         if( ( h80211[1] & 3 ) != 3 )
  431.         {
  432.             pkh->len    -= 24 + 6;
  433.             pkh->caplen -= 24 + 6;
  434.             memcpy( buffer + 12, h80211 + 30, pkh->caplen );
  435.         }
  436.         else
  437.         {
  438.             pkh->len    -= 30 + 6;
  439.             pkh->caplen -= 30 + 6;
  440.             memcpy( buffer + 12, h80211 + 36, pkh->caplen );
  441.         }
  442.         memcpy( buffer, arphdr, 12 );
  443.         pkh->len    += 12;
  444.         pkh->caplen += 12;
  445.     }
  446.     n = sizeof( struct pcap_pkthdr );
  447.     if( fwrite( pkh, 1, n, f_out ) != (size_t) n )
  448.     {
  449.         perror( "fwrite(packet header) failed" );
  450.         return( 1 );
  451.     }
  452.     n = pkh->caplen;
  453.     if( fwrite( buffer, 1, n, f_out ) != (size_t) n )
  454.     {
  455.         perror( "fwrite(packet data) failed" );
  456.         return( 1 );
  457.     }
  458.     return( 0 );
  459. }
  460. int main( int argc, char *argv[] )
  461. {
  462.     time_t tt;
  463.     uint magic;
  464.     char *s, buf[128];
  465.     FILE *f_in, *f_out;
  466.     unsigned long crc;
  467.     int i = 0, n, z, linktype;
  468.     uchar ZERO[32], *h80211;
  469.     uchar bssid[6], stmac[6];
  470.     struct ST_info *st_1st;
  471.     struct ST_info *st_cur;
  472.     struct ST_info *st_prv;
  473.     struct pcap_file_header pfh;
  474.     struct pcap_pkthdr pkh;    
  475.     /* parse the arguments */
  476.     memset( ZERO, 0, sizeof( ZERO ) );
  477.     memset( &opt, 0, sizeof( opt  ) );
  478.     while( 1 )
  479.     {
  480.         int option = getopt( argc, argv, "lb:k:e:p:w:" );
  481.         if( option < 0 ) break;
  482.         switch( option )
  483.         {
  484.             case 'l' :
  485.                 opt.no_convert = 1;
  486.                 break;
  487.             case 'b' :
  488.                 i = 0;
  489.                 s = optarg;
  490.                 while( sscanf( s, "%x", &n ) == 1 )
  491.                 {
  492.                     if( n < 0 || n > 255 )
  493.                     {
  494.                         printf( "Invalid BSSID (not a MAC).n" );
  495.                         return( 1 );
  496.                     }
  497.                     opt.bssid[i] = n;
  498.                     if( ++i > 6 ) break;
  499.                     if( ! ( s = strchr( s, ':' ) ) )
  500.                         break;
  501.                     s++;
  502.                 }
  503.                 if( i != 6 )
  504.                 {
  505.                     printf( "Invalid BSSID (not a MAC).n" );
  506.                     return( 1 );
  507.                 }
  508.                 break;
  509.             case 'k' :
  510.                 if( opt.crypt != CRYPT_NONE )
  511.                 {
  512.                     printf( "Encryption key already specified.n" );
  513.                     return( 1 );
  514.                 }
  515.                 opt.crypt = CRYPT_WPA;
  516.                 i = 0;
  517.                 s = optarg;
  518.                 buf[0] = s[0];
  519.                 buf[1] = s[1];
  520.                 buf[2] = '';
  521.                 while( sscanf( buf, "%x", &n ) == 1 )
  522.                 {
  523.                     if( n < 0 || n > 255 )
  524.                     {
  525.                         printf( "Invalid WPA PMK.n" );
  526.                         return( 1 );
  527.                     }
  528.                     opt.pmk[i++] = n;
  529.                     if( i >= 32 ) break;
  530.                     s += 2;
  531.                     if( s[0] == ':' || s[0] == '-' )
  532.                         s++;
  533.                     if( s[0] == '' || s[1] == '' )
  534.                         break;
  535.                     buf[0] = s[0];
  536.                     buf[1] = s[1];
  537.                 }
  538.                 if( i != 32 )
  539.                 {
  540.                     printf( "Invalid WPA PMK.n" );
  541.                     return( 1 );
  542.                 }
  543.                 break;
  544.             case 'e' :
  545.                 memset(  opt.essid, 0, sizeof( opt.essid ) );
  546.                 strncpy( opt.essid, optarg, sizeof( opt.essid ) - 1 );
  547.                 break;
  548.             case 'p' :
  549.                 if( opt.crypt != CRYPT_NONE )
  550.                 {
  551.                     printf( "Encryption key already specified.n" );
  552.                     return( 1 );
  553.                 }
  554.                 opt.crypt = CRYPT_WPA;
  555.                 memset(  opt.passphrase, 0, sizeof( opt.passphrase ) );
  556.                 strncpy( opt.passphrase, optarg, sizeof( opt.passphrase ) - 1 );
  557.                 break;
  558.             case 'w' :
  559.                 if( opt.crypt != CRYPT_NONE )
  560.                 {
  561.                     printf( "Encryption key already specified.n" );
  562.                     return( 1 );
  563.                 }
  564.                 opt.crypt = CRYPT_WEP;
  565.                 i = 0;
  566.                 s = optarg;
  567.                 buf[0] = s[0];
  568.                 buf[1] = s[1];
  569.                 buf[2] = '';
  570.                 while( sscanf( buf, "%x", &n ) == 1 )
  571.                 {
  572.                     if( n < 0 || n > 255 )
  573.                     {
  574.                         printf( "Invalid WEP key.n" );
  575.                         return( 1 );
  576.                     }
  577.                     opt.wepkey[i++] = n;
  578.                     if( i >= 64 ) break;
  579.                     s += 2;
  580.                     if( s[0] == ':' || s[0] == '-' )
  581.                         s++;
  582.                     if( s[0] == '' || s[1] == '' )
  583.                         break;
  584.                     buf[0] = s[0];
  585.                     buf[1] = s[1];
  586.                 }
  587.                 if( i != 5 && i != 13 && i != 16 && i != 29 && i != 61 )
  588.                 {
  589.                     printf( "Invalid WEP key length.n" );
  590.                     return( 1 );
  591.                 }
  592.                 opt.weplen = i;
  593.                 break;
  594.             default : goto usage;
  595.         }
  596.     }
  597.     if( argc - optind != 1 )
  598.     {
  599.     usage:
  600.         printf( usage, _MAJ, _MIN );
  601.         return( 1 );
  602.     }
  603.     if( opt.crypt == CRYPT_WPA )
  604.     {
  605.         if( opt.passphrase[0] != '' )
  606.         {
  607.             /* compute the Pairwise Master Key */
  608.             if( opt.essid[0] == '' )
  609.             {
  610.                 printf( "You must also specify the ESSID (-e).n" );
  611.                 return( 1 );
  612.             }
  613.             calc_pmk( opt.passphrase, opt.essid, opt.pmk );
  614.         }
  615.     }
  616.     /* open the input and output pcap files */
  617.     if( ( f_in = fopen( argv[optind], "rb" ) ) == NULL )
  618.     {
  619.         perror( "fopen failedn" );
  620.         printf( "Could not open "%s".n", argv[optind] );
  621.         return( 1 );
  622.     }
  623.     n = sizeof( pfh );
  624.     if( fread( &pfh, 1, n, f_in ) != (size_t) n )
  625.     {
  626.         perror( "fread(pcap file header) failed" );
  627.         return( 1 );
  628.     }
  629.     if( pfh.magic != TCPDUMP_MAGIC &&
  630.         pfh.magic != TCPDUMP_CIGAM )
  631.     {
  632.         printf( ""%s" isn't a pcap file (expected "
  633.                 "TCPDUMP_MAGIC).n", argv[optind] );
  634.         return( 1 );
  635.     }
  636.     if( ( magic = pfh.magic ) == TCPDUMP_CIGAM )
  637.         SWAP32( pfh.linktype );
  638.     if( pfh.linktype != LINKTYPE_IEEE802_11 &&
  639.         pfh.linktype != LINKTYPE_PRISM_HEADER &&
  640.         pfh.linktype != LINKTYPE_RADIOTAP_HDR )
  641.     {
  642.         printf( ""%s" isn't a regular 802.11 "
  643.                 "(wireless) capture.n", argv[optind] );
  644.         return( 1 );
  645.     }
  646.     linktype = pfh.linktype;
  647.     n = strlen( argv[optind] );
  648.     if( n > 4 && ( n + 5 < (int) sizeof( buffer ) ) &&
  649.         argv[optind][n - 4] == '.' )
  650.     {
  651.         memcpy( buffer, argv[optind], n - 4 );
  652.         memcpy( buffer + n - 4, "-dec", 4 );
  653.         memcpy( buffer + n, argv[optind] + n - 4, 5 );
  654.     }
  655.     else
  656.     {
  657.         if( n > 5 && ( n + 6 < (int) sizeof( buffer ) ) &&
  658.             argv[optind][n - 5] == '.' )
  659.         {
  660.             memcpy( buffer, argv[optind], n - 5 );
  661.             memcpy( buffer + n - 5, "-dec", 4 );
  662.             memcpy( buffer + n - 1, argv[optind] + n - 5, 6 );
  663.         }
  664.         else
  665.         {
  666.             memset( buffer, 0, sizeof( buffer ) );
  667.             snprintf( (char *) buffer, sizeof( buffer ) - 1,
  668.                       "%s-dec", argv[optind] );
  669.         }
  670.     }
  671.     if( ( f_out = fopen( (char *) buffer, "wb+" ) ) == NULL )
  672.     {
  673.         perror( "fopen failed" );
  674.         printf( "Could not create "%s".n", buffer );
  675.         return( 1 );
  676.     }
  677.     pfh.magic           = TCPDUMP_MAGIC;
  678.     pfh.version_major   = PCAP_VERSION_MAJOR;
  679.     pfh.version_minor   = PCAP_VERSION_MINOR;
  680.     pfh.thiszone        = 0;
  681.     pfh.sigfigs         = 0;
  682.     pfh.snaplen         = 65535;
  683.     pfh.linktype        = ( opt.no_convert ) ? 
  684.                             LINKTYPE_IEEE802_11 :
  685.                             LINKTYPE_ETHERNET;
  686.     n = sizeof( pfh );
  687.     if( fwrite( &pfh, 1, n, f_out ) != (size_t) n )
  688.     {
  689.         perror( "fwrite(pcap file header) failed" );
  690.         return( 1 );
  691.     }
  692.     /* loop reading and deciphering the packets */
  693.     memset( &stats, 0, sizeof( stats ) );
  694.     tt = time( NULL );
  695.     st_1st = NULL;
  696.     while( 1 )
  697.     {
  698.         if( time( NULL ) - tt > 0 )
  699.         {
  700.             /* update the status line every second */
  701.             printf( "33[KRead %ld packets...r", stats.nb_read );
  702.             fflush( stdout );
  703.             tt = time( NULL );
  704.         }
  705.         /* read one packet */
  706.         n = sizeof( pkh );
  707.         if( fread( &pkh, 1, n, f_in ) != (size_t) n )
  708.             break;
  709.         if( magic == TCPDUMP_CIGAM )
  710.             SWAP32( pkh.caplen );
  711.         n = pkh.caplen;
  712.         if( n <= 0 || n > 65535 )
  713.         {
  714.             printf( "Corrupted file? Invalid packet length %d.n", n );
  715.             break;
  716.         }
  717.         if( fread( buffer, 1, n, f_in ) != (size_t) n )
  718.             break;
  719.         stats.nb_read++;
  720.         h80211 = buffer;
  721.         if( linktype == LINKTYPE_PRISM_HEADER )
  722.         {
  723.             /* remove the prism header */
  724.             if( h80211[7] == 0x40 )
  725.                 n = 64; /* prism54 */
  726.             else
  727.             {
  728.                 n = *(int *)( h80211 + 4 );
  729.                 if( magic == TCPDUMP_CIGAM )
  730.                     SWAP32( n );
  731.             }
  732.             if( n < 8 || n >= (int) pkh.caplen )
  733.                 continue;
  734.             h80211 += n; pkh.caplen -= n;
  735.         }
  736.         if( linktype == LINKTYPE_RADIOTAP_HDR )
  737.         {
  738.             /* remove the radiotap header */
  739.             n = *(unsigned short *)( h80211 + 2 );
  740.             if( n <= 0 || n >= (int) pkh.caplen )
  741.                 continue;
  742.             h80211 += n; pkh.caplen -= n;
  743.         }
  744.         /* remove the FCS if present (madwifi) */
  745.         if( check_crc_buf( h80211, pkh.caplen - 4 ) == 1 )
  746.         {
  747.             pkh.len    -= 4;
  748.             pkh.caplen -= 4;
  749.         }
  750.         /* check if data */
  751.         if( ( h80211[0] & 0x0C ) != 0x08 )
  752.             continue;
  753.         /* check minimum size */
  754.         z = ( ( h80211[1] & 3 ) != 3 ) ? 24 : 30;
  755.         if( z + 16 > (int) pkh.caplen )
  756.             continue;
  757.         /* check the BSSID */
  758.         switch( h80211[0] & 3 )
  759.         {
  760.             case  0: memcpy( bssid, h80211 + 16, 6 ); break;
  761.             case  1: memcpy( bssid, h80211 +  4, 6 ); break;
  762.             case  2: memcpy( bssid, h80211 + 10, 6 ); break;
  763.             default: memcpy( bssid, h80211 +  4, 6 ); break;
  764.         }
  765.         if( memcmp( opt.bssid, ZERO, 6 ) != 0 )
  766.             if( memcmp( opt.bssid, bssid, 6 ) != 0 )
  767.                 continue;    
  768.         /* locate the station's MAC address */
  769.         switch( h80211[1] & 3 )
  770.         {
  771.             case  1: memcpy( stmac, h80211 + 10, 6 ); break;
  772.             case  2: memcpy( stmac, h80211 +  4, 6 ); break;
  773.             case  3: memcpy( stmac, h80211 + 10, 6 ); break;
  774.             default: continue;
  775.         }
  776.         st_prv = NULL;
  777.         st_cur = st_1st;
  778.         while( st_cur != NULL )
  779.         {
  780.             if( ! memcmp( st_cur->stmac, stmac, 6 ) )
  781.                 break;
  782.             st_prv = st_cur;
  783.             st_cur = st_cur->next;
  784.         }
  785.         /* if it's a new station, add it */
  786.         if( st_cur == NULL )
  787.         {
  788.             if( ! ( st_cur = (struct ST_info *) malloc(
  789.                              sizeof( struct ST_info ) ) ) )
  790.             {
  791.                 perror( "malloc failed" );
  792.                 break;
  793.             }
  794.             memset( st_cur, 0, sizeof( struct ST_info ) );
  795.             if( st_1st == NULL )
  796.                 st_1st = st_cur;
  797.             else
  798.                 st_prv->next = st_cur;
  799.             memcpy( st_cur->stmac, stmac, 6 );
  800.             memcpy( st_cur->bssid, bssid, 6 );
  801.         }
  802.         /* check if we haven't already processed this packet */
  803.         crc = calc_crc_buf( h80211 + z, pkh.caplen - z );
  804.         if( ( h80211[1] & 3 ) == 2 )
  805.         {
  806.             if( st_cur->t_crc == crc )
  807.                 continue;
  808.             st_cur->t_crc = crc;
  809.         }
  810.         else
  811.         {
  812.             if( st_cur->f_crc == crc )
  813.                 continue;
  814.             st_cur->f_crc = crc;
  815.         }
  816.         /* check the SNAP header to see if data is encrypted *
  817.          * as unencrypted data begins with AA AA 03 00 00 00 */
  818.         if( h80211[z] != h80211[z + 1] || h80211[z + 2] != 0x03 )
  819.         {
  820.             /* check the extended IV flag */
  821.             if( ( h80211[z + 3] & 0x20 ) == 0 )
  822.             {
  823.                 uchar K[64];
  824.                 stats.nb_wep++;
  825.                 if( opt.crypt != CRYPT_WEP )
  826.                     continue;
  827.                 memcpy( K, h80211 + z, 3 );
  828.                 memcpy( K + 3, opt.wepkey, opt.weplen );
  829.                 if( decrypt_wep( h80211 + z + 4, pkh.caplen - z - 4,
  830.                                  K, 3 + opt.weplen ) == 0 )
  831.                     continue;
  832.                 /* WEP data packet was successfully decrypted, *
  833.                  * remove the WEP IV & ICV and write the data  */
  834.                 pkh.len    -= 8;
  835.                 pkh.caplen -= 8;
  836.                 memcpy( h80211 + z, h80211 + z + 4, pkh.caplen - z );
  837.                 stats.nb_unwep++;
  838.                 h80211[1] &= 0xBF;
  839.                 if( write_packet( f_out, &pkh, h80211 ) != 0 )
  840.                     break;
  841.             }
  842.             else
  843.             {
  844.                 stats.nb_wpa++;
  845.                 if( opt.crypt != CRYPT_WPA )
  846.                     continue;
  847.                 /* if the PTK is valid, try to decrypt */
  848.                 if( st_cur == NULL || ! st_cur->valid_ptk )
  849.                     continue;
  850.                 if( st_cur->keyver == 1 )
  851.                 {
  852.                     if( decrypt_tkip( h80211, pkh.caplen,
  853.                                       st_cur->ptk + 32 ) == 0 )
  854.                         continue;
  855.                     pkh.len    -= 20;
  856.                     pkh.caplen -= 20;
  857.                 }
  858.                 else
  859.                 {
  860.                     if( decrypt_ccmp( h80211, pkh.caplen,
  861.                                       st_cur->ptk + 32 ) == 0 )
  862.                         continue;
  863.                     pkh.len    -= 16;
  864.                     pkh.caplen -= 16;
  865.                 }
  866.                 /* WPA data packet was successfully decrypted, *
  867.                  * remove the WPA Ext.IV & MIC, write the data */
  868.                 memcpy( h80211 + z, h80211 + z + 8, pkh.caplen - z );
  869.                 stats.nb_unwpa++;
  870.                 h80211[1] &= 0xBF;
  871.                 if( write_packet( f_out, &pkh, h80211 ) != 0 )
  872.                     break;
  873.             }
  874.         }
  875.         else
  876.         {
  877.             /* check ethertype == EAPOL */
  878.             z += 6;
  879.             if( h80211[z] != 0x88 || h80211[z + 1] != 0x8E )
  880.             {
  881.                 stats.nb_plain++;
  882.                 if( opt.crypt != CRYPT_NONE )
  883.                     continue;
  884.                 if( write_packet( f_out, &pkh, h80211 ) != 0 )
  885.                     break;
  886.             }
  887.             z += 2;
  888.             /* type == 3 (key), desc. == 254 (WPA) or 2 (RSN) */
  889.             if( h80211[z + 1] != 0x03 ||
  890.                 ( h80211[z + 4] != 0xFE && h80211[z + 4] != 0x02 ) )
  891.                 continue;
  892.             /* frame 1: Pairwise == 1, Install == 0, Ack == 1, MIC == 0 */
  893.             if( ( h80211[z + 6] & 0x08 ) != 0 &&
  894.                 ( h80211[z + 6] & 0x40 ) == 0 &&
  895.                 ( h80211[z + 6] & 0x80 ) != 0 &&
  896.                 ( h80211[z + 5] & 0x01 ) == 0 )
  897.             {
  898.                 /* set authenticator nonce */
  899.                 memcpy( st_cur->anonce, &h80211[z + 17], 32 );
  900.             }
  901.             /* frame 2 or 4: Pairwise == 1, Install == 0, Ack == 0, MIC == 1 */
  902.             if( ( h80211[z + 6] & 0x08 ) != 0 &&
  903.                 ( h80211[z + 6] & 0x40 ) == 0 &&
  904.                 ( h80211[z + 6] & 0x80 ) == 0 &&
  905.                 ( h80211[z + 5] & 0x01 ) != 0 )
  906.             {
  907.                 if( memcmp( &h80211[z + 17], ZERO, 32 ) != 0 )
  908.                 {
  909.                     /* set supplicant nonce */
  910.                     memcpy( st_cur->snonce, &h80211[z + 17], 32 );
  911.                 }
  912.             }
  913.             /* frame 3: Pairwise == 1, Install == 1, Ack == 1, MIC == 1 */
  914.             if( ( h80211[z + 6] & 0x08 ) != 0 &&
  915.                 ( h80211[z + 6] & 0x40 ) != 0 &&
  916.                 ( h80211[z + 6] & 0x80 ) != 0 &&
  917.                 ( h80211[z + 5] & 0x01 ) != 0 )
  918.             {
  919.                 if( memcmp( &h80211[z + 17], ZERO, 32 ) != 0 )
  920.                 {
  921.                     /* set authenticator nonce */
  922.                     memcpy( st_cur->anonce, &h80211[z + 17], 32 );
  923.                 }
  924.                 /* copy the MIC & eapol frame */
  925.                 st_cur->eapol_size = ( h80211[z + 2] << 8 )
  926.                                    +   h80211[z + 3] + 4;
  927.                 memcpy( st_cur->keymic, &h80211[z + 81], 16 );
  928.                 memcpy( st_cur->eapol, &h80211[z], st_cur->eapol_size );
  929.                 memset( st_cur->eapol + 81, 0, 16 );
  930.                 /* copy the key descriptor version */
  931.                 st_cur->keyver = h80211[z + 6] & 7;
  932.             }
  933.             st_cur->valid_ptk = calc_ptk( st_cur, opt.pmk );
  934.         }
  935.     }
  936.     fclose( f_in  );
  937.     fclose( f_out );
  938.     /* write some statistics */
  939.     printf( "33[KTotal number of packets read      % 8ldn"
  940.                  "Total number of WEP data packets  % 8ldn"
  941.                  "Total number of WPA data packets  % 8ldn"
  942.                  "Number of plaintext data packets  % 8ldn"
  943.                  "Number of decrypted WEP  packets  % 8ldn"
  944.                  "Number of decrypted WPA  packets  % 8ldn",
  945.             stats.nb_read, stats.nb_wep, stats.nb_wpa,
  946.             stats.nb_plain, stats.nb_unwep, stats.nb_unwpa );
  947.     return( 0 );
  948. }