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

其他

开发平台:

Unix_Linux

  1. /*
  2.  *  pcap-compatible 802.11 packet sniffer (Win32 version)
  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 <windows.h>
  21. #include <stdio.h>
  22. #include <time.h>
  23. #define snprintf _snprintf
  24. #include "capture.h"
  25. #include "console.h"
  26. #include "timeval.h"
  27. #include "pcap.h"
  28. #include "uniqueiv.c"
  29. #define FORMAT_CAP 1
  30. #define FORMAT_IVS 2
  31. #define REFRESH_TIMEOUT 200000
  32. #define BROADCAST_ADDR "xFFxFFxFFxFFxFFxFF"
  33. /* linked list of detected access points */
  34. struct AP_info
  35. {
  36.     struct AP_info *prev;     /* the prev AP in list      */
  37.     struct AP_info *next;     /* the next AP in list      */
  38.     time_t tinit, tlast;      /* first and last time seen */
  39.     int power, chanl;         /* signal power and channel */
  40.     int speed, crypt;         /* maxrate & encryption alg */
  41.     unsigned long nb_bcn;     /* total number of beacons  */
  42.     unsigned long nb_pkt;     /* total number of packets  */
  43.     unsigned long nb_data;    /* number of WEP data pkts  */
  44.     unsigned char bssid[6];   /* the access point's MAC   */
  45.     unsigned char essid[33];  /* ascii network identifier */
  46.     unsigned char lanip[4];   /* last detected ip address */
  47.                               /* if non-encrypted network */
  48.     unsigned char **uiv_root; /* unique iv root structure */
  49.                               /* if wep-encrypted network */
  50. };
  51. /* linked list of detected clients */
  52. struct ST_info
  53. {
  54.     struct ST_info *prev;    /* the prev client in list   */
  55.     struct ST_info *next;    /* the next client in list   */
  56.     struct AP_info *base;    /* AP this client belongs to */
  57.     time_t tinit, tlast;     /* first and last time seen  */
  58.     int power;               /* signal power              */
  59.     unsigned long nb_pkt;    /* total number of packets   */
  60.     unsigned char stmac[6];  /* the client's MAC address  */
  61. };
  62. /* bunch of global stuff */
  63. struct AP_info *ap_1st, *ap_end;
  64. struct AP_info *ap_cur, *ap_prv;
  65. struct ST_info *st_1st, *st_end;
  66. struct ST_info *st_cur, *st_prv;
  67. struct pcap_file_header pfh_out;
  68. struct pcap_file_header pfh_out;
  69. unsigned char prev_bssid[6];
  70. FILE *f_cap_in  = NULL;
  71. FILE *f_csv_out = NULL;
  72. FILE *f_cap_out = NULL;
  73. FILE *f_ivs_out = NULL;
  74. int dump_initialize( char *output_prefix, int ivs_only )
  75. {
  76.     int n;
  77.     char o_filename[1024];
  78.     ap_1st = ap_end = NULL;
  79.     st_1st = st_end = NULL;
  80.     /* create the output csv file */
  81.     if( strlen( output_prefix ) >= sizeof( o_filename ) - 5 )
  82.         output_prefix[sizeof( o_filename ) - 5] = '';
  83.     if( strcmp( output_prefix, "-" ) != 0 )
  84.     {
  85.         memset( o_filename, 0, sizeof( o_filename ) );
  86.         snprintf( o_filename,  sizeof( o_filename ) - 1,
  87.                   "%s.txt", output_prefix );
  88.         if( ( f_csv_out = fopen( o_filename, "wb+" ) ) == NULL )
  89.         {
  90.             perror( "fopen failed" );
  91.             fprintf( stderr, "n  Could not create "%s".n", o_filename );
  92.             return( 1 );
  93.         }
  94.     }
  95.     /* open or create the output packet capture file */
  96.     if( ivs_only == 0 )
  97.     {
  98.         n = sizeof( struct pcap_file_header );
  99.         if( strcmp( output_prefix, "-" ) != 0 )
  100.         {
  101.             memset( o_filename, 0, sizeof( o_filename ) );
  102.             snprintf( o_filename,  sizeof( o_filename ) - 1,
  103.                       "%s.cap", output_prefix );
  104.         }
  105.         else
  106.         {
  107.             f_cap_out = fdopen( 1, "wb" );
  108.             goto write_cap_header;
  109.         }
  110.         if( ( f_cap_out = fopen( o_filename, "rb+" ) ) == NULL )
  111.         {
  112.         create_cap_file:
  113.             if( ( f_cap_out = fopen( o_filename, "wb+" ) ) == NULL )
  114.             {
  115.                 perror( "fopen failed" );
  116.                 fprintf( stderr, "n  Could not create "%s".n", o_filename );
  117.                 return( 1 );
  118.             }
  119.         write_cap_header:
  120.             pfh_out.magic           = TCPDUMP_MAGIC;
  121.             pfh_out.version_major   = PCAP_VERSION_MAJOR;
  122.             pfh_out.version_minor   = PCAP_VERSION_MINOR;
  123.             pfh_out.thiszone        = 0;
  124.             pfh_out.sigfigs         = 0;
  125.             pfh_out.snaplen         = 65535;
  126.             pfh_out.linktype        = LINKTYPE_IEEE802_11;
  127.             if( fwrite( &pfh_out, 1, n, f_cap_out ) != (size_t) n )
  128.             {
  129.                 perror( "fwrite(pcap file header) failed" );
  130.                 return( 1 );
  131.             }
  132.         }
  133.         else
  134.         {
  135.             if( fread( &pfh_out, 1, n, f_cap_out ) != (size_t) n )
  136.                 goto create_cap_file;
  137.             if( pfh_out.magic != TCPDUMP_MAGIC &&
  138.                 pfh_out.magic != TCPDUMP_CIGAM )
  139.             {
  140.                 fprintf( stderr, "n  "%s" isn't a pcap file (expected "
  141.                                  "TCPDUMP_MAGIC).n", o_filename );
  142.                 return( 1 );
  143.             }
  144.             if( pfh_out.magic == TCPDUMP_CIGAM )
  145.                 SWAP32( pfh_out.linktype );
  146.             if( pfh_out.linktype != LINKTYPE_IEEE802_11 )
  147.             {
  148.                 fprintf( stderr, "n  Wrong linktype from pcap file header "
  149.                                  "(expected LINKTYPE_IEEE802_11) -n"
  150.                                  "this doesn't look like a regular 802.11 "
  151.                                  "capture.n" );
  152.                 return( 1 );
  153.             }
  154.             if( fseek( f_cap_out, 0, SEEK_END ) != 0 )
  155.             {
  156.                 perror( "fseek(SEEK_END) failed" );
  157.                 return( 1 );
  158.             }
  159.         }
  160.     }
  161.     if( ivs_only == 1 )
  162.     {
  163.         memset( prev_bssid, 0, 6 );
  164.         if( strcmp( output_prefix, "-" ) != 0 )
  165.         {
  166.             memset( o_filename, 0, sizeof( o_filename ) );
  167.             snprintf( o_filename,  sizeof( o_filename ) - 1,
  168.                       "%s.ivs", output_prefix );
  169.         }
  170.         else
  171.         {
  172.             f_ivs_out = fdopen( 1, "wb" );
  173.             goto write_ivs_header;
  174.         }
  175.         if( ( f_ivs_out = fopen( o_filename, "rb+" ) ) == NULL )
  176.         {
  177.         create_ivs_file:
  178.             if( ( f_ivs_out = fopen( o_filename, "wb+" ) ) == NULL )
  179.             {
  180.                 perror( "fopen failed" );
  181.                 fprintf( stderr, "n  Could not create "%s".n", o_filename );
  182.                 return( 1 );
  183.             }
  184.         write_ivs_header:
  185.             if( fwrite( IVSONLY_MAGIC, 1, 4, f_ivs_out ) != sizeof( n ) )
  186.             {
  187.                 perror( "fwrite(IVs file header) failed" );
  188.                 return( 1 );
  189.             }
  190.         }
  191.         else
  192.         {
  193.             unsigned char ivs_hdr[4];
  194.             if( fread( ivs_hdr, 1, 4, f_ivs_out ) != 4 )
  195.                 goto create_ivs_file;
  196.             if( memcmp( ivs_hdr, IVSONLY_MAGIC, 4 ) != 0 )
  197.             {
  198.                 fprintf( stderr, "n  "%s" isn't a IVs file (expected "
  199.                                  "IVSONLY_MAGIC).n", o_filename );
  200.                 return( 1 );
  201.             }
  202.             if( fseek( f_ivs_out, 0, SEEK_END ) != 0 )
  203.             {
  204.                 perror( "fseek(SEEK_END) failed" );
  205.                 return( 1 );
  206.             }
  207.         }
  208.     }
  209.     return( 0 );
  210. }
  211. int dump_add_packet( unsigned char *h80211, int caplen, int power,
  212.                      int channel, uint tv_sec, uint tv_usec )
  213. {
  214.     int i, n;
  215.     struct pcap_pkthdr pkh;
  216.     unsigned char *p;
  217.     unsigned char bssid[6];
  218.     unsigned char stmac[6];
  219.     ap_cur = NULL;
  220.     st_cur = NULL;
  221.     pkh.caplen = pkh.len = caplen;
  222.     /* skip packets smaller than a 802.11 header */
  223.     if( pkh.caplen < 24 )
  224.         goto write_packet;
  225.     /* skip (uninteresting) control frames */
  226.     if( ( h80211[0] & 0x0C ) == 0x04 )
  227.         goto write_packet;
  228.     /* locate the access point's MAC address */
  229.     switch( h80211[1] & 3 )
  230.     {
  231.         case  0: memcpy( bssid, h80211 + 16, 6 ); break;
  232.         case  1: memcpy( bssid, h80211 +  4, 6 ); break;
  233.         case  2: memcpy( bssid, h80211 + 10, 6 ); break;
  234.         default: memcpy( bssid, h80211 +  4, 6 ); break;
  235.     }
  236.     /* skip broadcast packets */
  237.     if( memcmp( bssid, BROADCAST_ADDR, 6 ) == 0 )
  238.         goto write_packet;
  239.     /* update our chained list of access points */
  240.     ap_cur = ap_1st;
  241.     ap_prv = NULL;
  242.     while( ap_cur != NULL )
  243.     {
  244.         if( ! memcmp( ap_cur->bssid, bssid, 6 ) )
  245.             break;
  246.         ap_prv = ap_cur;
  247.         ap_cur = ap_cur->next;
  248.     }
  249.     /* if it's a new access point, add it */
  250.     if( ap_cur == NULL )
  251.     {
  252.         if( ! ( ap_cur = (struct AP_info *) malloc(
  253.                          sizeof( struct AP_info ) ) ) )
  254.         {
  255.             perror( "malloc failed" );
  256.             return( 1 );
  257.         }
  258.         memset( ap_cur, 0, sizeof( struct AP_info ) );
  259.         if( ap_1st == NULL )
  260.             ap_1st = ap_cur;
  261.         else
  262.             ap_prv->next  = ap_cur;
  263.         memcpy( ap_cur->bssid, bssid, 6 );
  264.         ap_cur->prev = ap_prv;
  265.         if( tv_sec == 0 )
  266.         {
  267.             ap_cur->tinit = time( NULL );
  268.             ap_cur->tlast = time( NULL );
  269.         }
  270.         else
  271.         {
  272.             ap_cur->tinit = tv_sec;
  273.             ap_cur->tlast = tv_sec;
  274.         }
  275.         ap_cur->power = power;
  276.         ap_cur->chanl = -1;
  277.         ap_cur->speed = -1;
  278.         ap_cur->crypt = -1;
  279.         ap_cur->uiv_root = uniqueiv_init();
  280.         ap_end = ap_cur;
  281.     }
  282.     if( tv_sec == 0 )
  283.         ap_cur->tlast = time( NULL );
  284.     else
  285.         ap_cur->tlast = tv_sec;
  286.     if( ( h80211[1] & 1 ) == 0 )
  287.         ap_cur->power = power;
  288.     if( h80211[0] == 0x80 )
  289.         ap_cur->nb_bcn++;
  290.     ap_cur->nb_pkt++;
  291.     /* locate the station MAC in the 802.11 header */
  292.     switch( h80211[1] & 3 )
  293.     {
  294.         case  0: memcpy( stmac, h80211 + 10, 6 ); break;
  295.         case  1: memcpy( stmac, h80211 + 10, 6 ); break;
  296.         case  2:
  297.             /* reject broadcast MACs */
  298.             if( h80211[4] != 0 ) goto skip_station;
  299.             memcpy( stmac, h80211 +  4, 6 ); break;
  300.         default: goto skip_station; break;
  301.     }
  302.     /* skip non-data packets */
  303.     if( ( h80211[0] & 0x0C ) != 0x08 )
  304.         goto skip_station;
  305.     /* update our chained list of wireless clients */
  306.     st_cur = st_1st;
  307.     st_prv = NULL;
  308.     while( st_cur != NULL )
  309.     {
  310.         if( ! memcmp( st_cur->stmac, stmac, 6 ) )
  311.             break;
  312.         st_prv = st_cur;
  313.         st_cur = st_cur->next;
  314.     }
  315.     /* if it's a new client, add it */
  316.     if( st_cur == NULL )
  317.     {
  318.         if( ! ( st_cur = (struct ST_info *) malloc(
  319.                          sizeof( struct ST_info ) ) ) )
  320.         {
  321.             perror( "malloc failed" );
  322.             return( 1 );
  323.         }
  324.         memset( st_cur, 0, sizeof( struct ST_info ) );
  325.         if( st_1st == NULL )
  326.             st_1st = st_cur;
  327.         else
  328.             st_prv->next  = st_cur;
  329.         memcpy( st_cur->stmac, stmac, 6 );
  330.         st_cur->prev = st_prv;
  331.         st_cur->base = ap_cur;
  332.         if( tv_sec == 0 )
  333.         {
  334.             st_cur->tinit = time( NULL );
  335.             st_cur->tlast = time( NULL );
  336.         }
  337.         else
  338.         {
  339.             st_cur->tinit = tv_sec;
  340.             st_cur->tlast = tv_sec;
  341.         }
  342.         st_cur->power = power;
  343.         st_end = st_cur;
  344.     }
  345.     /* every 1s, update the last time seen & receive power */
  346.     if( tv_sec == 0 )
  347.         st_cur->tlast = time( NULL );
  348.     else
  349.         st_cur->tlast = tv_sec;
  350.     if( ( h80211[1] & 3 ) == 1 )
  351.         st_cur->power = power;
  352.     st_cur->nb_pkt++;
  353. skip_station:
  354.     /* packet parsing: Beacon or Probe Response */
  355.     if( h80211[0] == 0x80 ||
  356.         h80211[0] == 0x50 )
  357.     {
  358.         if( ap_cur->crypt < 0 )
  359.             ap_cur->crypt = ( h80211[34] & 0x10 ) >> 4;
  360.         p = h80211 + 36;
  361.         while( p < h80211 + pkh.caplen )
  362.         {
  363.             if( p + 2 + p[1] > h80211 + pkh.caplen )
  364.                 break;
  365.             if( p[0] == 0x00 && p[1] > 0 && p[2] != '' &&
  366.                 ( p[1] > 1 || p[2] != ' ' ) )
  367.             {
  368.                 /* found a non-cloaked ESSID */
  369.                 n = ( p[1] > 32 ) ? 32 : p[1];
  370.                 memset( ap_cur->essid, 0, 33 );
  371.                 memcpy( ap_cur->essid, p + 2, n );
  372.                 for( i = 0; i < n; i++ )
  373.                     if( ap_cur->essid[i] < 32 ||
  374.                       ( ap_cur->essid[i] > 126 && ap_cur->essid[i] < 160 ) )
  375.                         ap_cur->essid[i] = '.';
  376.             }
  377.             if( p[0] == 0x01 || p[0] == 0x32 )
  378.                 ap_cur->speed = ( p[1 + p[1]] & 0x7F ) / 2;
  379.             if( p[0] == 0x03 )
  380.                 ap_cur->chanl = p[2];
  381.             p += 2 + p[1];
  382.         }
  383.     }
  384.     /* packet parsing: Association Request */
  385.     if( h80211[0] == 0x00 )
  386.     {
  387.         p = h80211 + 28;
  388.         while( p < h80211 + pkh.caplen )
  389.         {
  390.             if( p + 2 + p[1] > h80211 + pkh.caplen )
  391.                 break;
  392.             if( p[0] == 0x00 && p[1] > 0 && p[2] != '' &&
  393.                 ( p[1] > 1 || p[2] != ' ' ) )
  394.             {
  395.                 /* found a non-cloaked ESSID */
  396.                 n = ( p[1] > 32 ) ? 32 : p[1];
  397.                 memset( ap_cur->essid, 0, 33 );
  398.                 memcpy( ap_cur->essid, p + 2, n );
  399.                 for( i = 0; i < n; i++ )
  400.                     if( ap_cur->essid[i] < 32 ||
  401.                       ( ap_cur->essid[i] > 126 && ap_cur->essid[i] < 160 ) )
  402.                         ap_cur->essid[i] = '.';
  403.             }
  404.             p += 2 + p[1];
  405.         }
  406.     }
  407.     /* packet parsing: some data */
  408.     if( ap_cur->chanl == -1 )
  409.         ap_cur->chanl = channel;
  410.     if( ( h80211[0] & 0x0C ) == 0x08 )
  411.     {
  412.         /* check the SNAP header to see if data is encrypted */
  413.         unsigned int z = ( ( h80211[1] & 3 ) != 3 ) ? 24 : 30;
  414.         if( z + 26 > pkh.caplen )
  415.             goto write_packet;
  416.         if( h80211[z] == h80211[z + 1] && h80211[z + 2] == 0x03 )
  417.         {
  418.             if( ap_cur->crypt < 0 )
  419.                 ap_cur->crypt = 0;
  420.             /* if ethertype == IPv4, find the LAN address */
  421.             if( h80211[z + 6] == 0x08 && h80211[z + 7] == 0x00 &&
  422.                 ( h80211[1] & 3 ) == 0x01 )
  423.                     memcpy( ap_cur->lanip, &h80211[z + 20], 4 );
  424.             if( h80211[z + 6] == 0x08 && h80211[z + 7] == 0x06 )
  425.                 memcpy( ap_cur->lanip, &h80211[z + 22], 4 );
  426.         }
  427.         else
  428.             ap_cur->crypt = 2 + ( ( h80211[z + 3] & 0x20 ) >> 5 );
  429.         if( z + 10 > pkh.caplen )
  430.             goto write_packet;
  431.         if( ap_cur->crypt == 2 )
  432.         {
  433.             /* WEP: check if we've already seen this IV */
  434.             if( ! uniqueiv_check( ap_cur->uiv_root, &h80211[z] ) )
  435.             {
  436.                 /* first time seen IVs */
  437.                 if( f_ivs_out != NULL )
  438.                 {
  439.                     unsigned char iv_info[64];
  440.                     if( memcmp( prev_bssid, ap_cur->bssid, 6 ) == 0 )
  441.                     {
  442.                         iv_info[0] = 0xFF;
  443.                         memcpy( iv_info + 1, &h80211[z    ], 3 );
  444.                         memcpy( iv_info + 4, &h80211[z + 4], 2 );
  445.                         n =  6;
  446.                     }
  447.                     else
  448.                     {
  449.                         memcpy( prev_bssid , ap_cur->bssid,  6 );
  450.                         memcpy( iv_info    , ap_cur->bssid,  6 );
  451.                         memcpy( iv_info + 6, &h80211[z    ], 3 );
  452.                         memcpy( iv_info + 9, &h80211[z + 4], 2 );
  453.                         n = 11;
  454.                     }
  455.                     if( fwrite( iv_info, 1, n, f_ivs_out ) != (size_t) n )
  456.                     {
  457.                         perror( "fwrite(IV info) failed" );
  458.                         return( 1 );
  459.                     }
  460.                 }
  461.                 uniqueiv_mark( ap_cur->uiv_root, &h80211[z] );
  462.                 ap_cur->nb_data++;
  463.             }
  464.         }
  465.         else
  466.             ap_cur->nb_data++;
  467.     }
  468. write_packet:
  469.     if( f_cap_out != NULL )
  470.     {
  471.         struct timeval tv;
  472.         gettimeofday( &tv, NULL );
  473.         if( tv_sec == 0 )
  474.         {
  475.             pkh.tv_sec  = tv.tv_sec;
  476.             pkh.tv_usec = ( tv.tv_usec & ~0x1ff ) + power;
  477.         }
  478.         else
  479.         {
  480.             pkh.tv_sec  = tv_sec;
  481.             pkh.tv_usec = tv_usec;
  482.         }
  483.         if( pfh_out.magic == TCPDUMP_CIGAM )
  484.         {
  485.             SWAP32( pkh.tv_sec  );
  486.             SWAP32( pkh.tv_usec );
  487.             SWAP32( pkh.caplen  );
  488.             SWAP32( pkh.len     );
  489.         }
  490.         n = sizeof( pkh );
  491.         if( fwrite( &pkh, 1, n, f_cap_out ) != (size_t) n )
  492.         {
  493.             perror( "fwrite(packet header) failed" );
  494.             return( 1 );
  495.         }
  496.         fflush( stdout );
  497.         n = pkh.caplen;
  498.         if( fwrite( h80211, 1, n, f_cap_out ) != (size_t) n )
  499.         {
  500.             perror( "fwrite(packet data) failed" );
  501.             return( 1 );
  502.         }
  503.         fflush( stdout );
  504.     }
  505.     return( 0 );
  506. }
  507. void dump_print( int ws_row, int ws_col )
  508. {
  509.     int nlines;
  510.     char strbuf[512];
  511.     /* print some informations about each detected AP */
  512.     fprintf( stderr, "n BSSID              PWR  Beacons"
  513.                      "   # Data  CH  MB  ENC   ESSIDnn" );
  514.     nlines = 5;
  515.     ap_cur = ap_end;
  516.     while( ap_cur != NULL )
  517.     {
  518.         if( f_cap_in == NULL && ( ap_cur->nb_pkt < 2 ||
  519.               time( NULL ) - ap_cur->tlast > 120 ) )
  520.         {
  521.             ap_cur = ap_cur->prev;
  522.             continue;
  523.         }
  524.         if( ws_row != 0 && nlines > ws_row )
  525.             return;
  526.         nlines++;
  527.         fprintf( stderr, " %02X:%02X:%02X:%02X:%02X:%02X",
  528.                 ap_cur->bssid[0], ap_cur->bssid[1],
  529.                 ap_cur->bssid[2], ap_cur->bssid[3],
  530.                 ap_cur->bssid[4], ap_cur->bssid[5] );
  531.         fprintf( stderr, "  %3d %8ld %8ld",
  532.                  ap_cur->power,
  533.                  ap_cur->nb_bcn,
  534.                  ap_cur->nb_data );
  535.         fprintf( stderr, " %3d %3d  ", ap_cur->chanl, ap_cur->speed );
  536.         switch( ap_cur->crypt )
  537.         {
  538.             case  0: fprintf( stderr, "OPN " ); break;
  539.             case  1: fprintf( stderr, "WEP?" ); break;
  540.             case  2: fprintf( stderr, "WEP " ); break;
  541.             case  3: fprintf( stderr, "WPA " ); break;
  542.             default: fprintf( stderr, "    " ); break;
  543.         }
  544.         memset( strbuf, 0, sizeof( strbuf ) );
  545.         snprintf( strbuf,  sizeof( strbuf ) - 1,
  546.                   "%-32s", ap_cur->essid );
  547.         strbuf[ws_col - 58] = '';
  548.         fprintf( stderr, "  %sn", strbuf );
  549.         ap_cur = ap_cur->prev;
  550.     }
  551.     /* print some informations about each detected station */
  552.     memset( strbuf, 0, ws_col );
  553.     nlines += 3;
  554.     if( ws_row != 0 && nlines > ws_row )
  555.         return;
  556.     memset( strbuf, 0x20, ws_col - 1 );
  557.     fprintf( stderr, "%sn", strbuf );
  558.     memcpy( strbuf, " BSSID              STATION "
  559.             "           PWR  Packets  ESSID", 58 );
  560.     fprintf( stderr, "%sn", strbuf );
  561.     memset( strbuf, 0x20, ws_col - 1 );
  562.     fprintf( stderr, "%sn", strbuf );
  563.     ap_cur = ap_end;
  564.     while( ap_cur != NULL )
  565.     {
  566.         if( f_cap_in == NULL && ( ap_cur->nb_pkt < 2 ||
  567.               time( NULL ) - ap_cur->tlast > 120 ) )
  568.         {
  569.             ap_cur = ap_cur->prev;
  570.             continue;
  571.         }
  572.         if( ws_row != 0 && nlines > ws_row )
  573.             return;
  574.         st_cur = st_end;
  575.         while( st_cur != NULL )
  576.         {
  577.             if( st_cur->base != ap_cur || ( f_cap_in == NULL &&
  578.                   time( NULL ) - ap_cur->tlast > 120 ) )
  579.             {
  580.                 st_cur = st_cur->prev;
  581.                 continue;
  582.             }
  583.             if( ws_row != 0 && nlines > ws_row )
  584.                 return;
  585.             nlines++;
  586.             fprintf( stderr, " %02X:%02X:%02X:%02X:%02X:%02X",
  587.                     ap_cur->bssid[0], ap_cur->bssid[1],
  588.                     ap_cur->bssid[2], ap_cur->bssid[3],
  589.                     ap_cur->bssid[4], ap_cur->bssid[5] );
  590.             fprintf( stderr, "  %02X:%02X:%02X:%02X:%02X:%02X",
  591.                     st_cur->stmac[0], st_cur->stmac[1],
  592.                     st_cur->stmac[2], st_cur->stmac[3],
  593.                     st_cur->stmac[4], st_cur->stmac[5] );
  594.             if( st_cur->power != -1 )
  595.                 fprintf( stderr, "  %3d", st_cur->power );
  596.             else
  597.                 fprintf( stderr, "     " );
  598.             fprintf( stderr, " %8ld", st_cur->nb_pkt );
  599.             memset( strbuf, 0, sizeof( strbuf ) );
  600.             snprintf( strbuf,  sizeof( strbuf ) - 1,
  601.                       "%-32s", ap_cur->essid );
  602.             strbuf[ws_col - 54] = '';
  603.             fprintf( stderr, "  %sn", strbuf );
  604.             st_cur = st_cur->prev;
  605.         }
  606.         ap_cur = ap_cur->prev;
  607.     }
  608. }
  609. void dump_write_csv( void )
  610. {
  611.     struct tm *ltime;
  612.     if( f_csv_out == NULL )
  613.         return;
  614.     fseek( f_csv_out, 0, SEEK_SET );
  615.     fprintf( f_csv_out,
  616.         "rnBSSID, First time seen, Last time seen, Channel, Speed, "
  617.         "Privacy, Power, # beacons, # data, LAN IP, ESSIDrn" );
  618.     ap_cur = ap_1st;
  619.     while( ap_cur != NULL )
  620.     {
  621.         if( ap_cur->nb_pkt < 2 )
  622.         {
  623.             ap_cur = ap_cur->next;
  624.             continue;
  625.         }
  626.         fprintf( f_csv_out, "%02X:%02X:%02X:%02X:%02X:%02X, ",
  627.                  ap_cur->bssid[0], ap_cur->bssid[1],
  628.                  ap_cur->bssid[2], ap_cur->bssid[3],
  629.                  ap_cur->bssid[4], ap_cur->bssid[5] );
  630.         ltime = localtime( &ap_cur->tinit );
  631.         fprintf( f_csv_out, "%04d-%02d-%02d %02d:%02d:%02d, ",
  632.                  1900 + ltime->tm_year, 1 + ltime->tm_mon,
  633.                  ltime->tm_mday, ltime->tm_hour,
  634.                  ltime->tm_min,  ltime->tm_sec );
  635.         ltime = localtime( &ap_cur->tlast );
  636.         fprintf( f_csv_out, "%04d-%02d-%02d %02d:%02d:%02d, ",
  637.                  1900 + ltime->tm_year, 1 + ltime->tm_mon,
  638.                  ltime->tm_mday, ltime->tm_hour,
  639.                  ltime->tm_min,  ltime->tm_sec );
  640.         fprintf( f_csv_out, "%2d, %3d, ",
  641.                  ap_cur->chanl,
  642.                  ap_cur->speed );
  643.         switch( ap_cur->crypt )
  644.         {
  645.             case  0: fprintf( f_csv_out, "OPN " ); break;
  646.             case  1: fprintf( f_csv_out, "WEP?" ); break;
  647.             case  2: fprintf( f_csv_out, "WEP " ); break;
  648.             case  3: fprintf( f_csv_out, "WPA " ); break;
  649.             default: fprintf( f_csv_out, "    " ); break;
  650.         }
  651.         fprintf( f_csv_out, ", %3d, %8ld, %8ld, ",
  652.                  ap_cur->power,
  653.                  ap_cur->nb_bcn,
  654.                  ap_cur->nb_data );
  655.         fprintf( f_csv_out, "%3d.%3d.%3d.%3d, ",
  656.                  ap_cur->lanip[0], ap_cur->lanip[1],
  657.                  ap_cur->lanip[2], ap_cur->lanip[2] );
  658.         fprintf( f_csv_out, "%-32srn", ap_cur->essid );
  659.         ap_cur = ap_cur->next;
  660.     }
  661.     fprintf( f_csv_out,
  662.         "rnStation MAC, First time seen, Last time seen, "
  663.         "Power, # packets, BSSID, ESSIDrn" );
  664.     st_cur = st_1st;
  665.     while( st_cur != NULL )
  666.     {
  667.         ap_cur = st_cur->base;
  668.         if( ap_cur->nb_pkt < 2 )
  669.         {
  670.             st_cur = st_cur->next;
  671.             continue;
  672.         }
  673.         fprintf( f_csv_out, "%02X:%02X:%02X:%02X:%02X:%02X, ",
  674.                  st_cur->stmac[0], st_cur->stmac[1],
  675.                  st_cur->stmac[2], st_cur->stmac[3],
  676.                  st_cur->stmac[4], st_cur->stmac[5] );
  677.         ltime = localtime( &st_cur->tinit );
  678.         fprintf( f_csv_out, "%04d-%02d-%02d %02d:%02d:%02d, ",
  679.                  1900 + ltime->tm_year, 1 + ltime->tm_mon,
  680.                  ltime->tm_mday, ltime->tm_hour,
  681.                  ltime->tm_min,  ltime->tm_sec );
  682.         ltime = localtime( &st_cur->tlast );
  683.         fprintf( f_csv_out, "%04d-%02d-%02d %02d:%02d:%02d, ",
  684.                  1900 + ltime->tm_year, 1 + ltime->tm_mon,
  685.                  ltime->tm_mday, ltime->tm_hour,
  686.                  ltime->tm_min,  ltime->tm_sec );
  687.         fprintf( f_csv_out, "%3d, %8ld, ",
  688.                  st_cur->power,
  689.                  st_cur->nb_pkt );
  690.         fprintf( f_csv_out, "%02X:%02X:%02X:%02X:%02X:%02X, ",
  691.                  ap_cur->bssid[0], ap_cur->bssid[1],
  692.                  ap_cur->bssid[2], ap_cur->bssid[3],
  693.                  ap_cur->bssid[4], ap_cur->bssid[5] );
  694.         fprintf( f_csv_out, "%-32srn", ap_cur->essid );
  695.         st_cur = st_cur->next;
  696.     }
  697.     fprintf( f_csv_out, "rn" );
  698.     fflush( f_csv_out );
  699. }
  700. struct arguments
  701. {
  702.     int card_index;
  703.     int card_model;
  704.     int channels[16];
  705.     char *oprefix;
  706.     int ivs_only;
  707. }
  708. arg;
  709. int rawlen;
  710. unsigned char rawbuf[65536];
  711. unsigned char buffer[65536];
  712. HANDLE semPacket1;
  713. HANDLE semPacket2;
  714. int prompt_exit( int retval )
  715. {
  716.     int i;
  717.     printf( "n  Press Ctrl-C to exit.n" );
  718.     scanf( "%d", &i );
  719.     exit( retval );
  720. }
  721. int bg_chans[] = { 1, 5, 10, 2, 6, 11, 3, 7, 12, 4, 8, 13, 9, 0 };
  722. int parse_channels( char *s )
  723. {
  724.     int i = 0, j, n;
  725.     while( sscanf( s, "%d", &n ) == 1 )
  726.     {
  727.         if( n == 0 )
  728.         {
  729.             for( j = 0; j < 14; j++ )
  730.                 arg.channels[j] = bg_chans[j];
  731.             return( 0 );
  732.         }
  733.         if( n < 1 || n > 14 )
  734.             return( 1 );
  735.         arg.channels[i] = n; i++;
  736.         arg.channels[i] = 0;
  737.         if( i == 14 ) break;
  738.         while( isdigit( *s ) != 0 )
  739.             s++;
  740.         while( isdigit( *s ) == 0 )
  741.         {
  742.             if( *s == '' )
  743.                 return( 0 );
  744.             s++;
  745.         }
  746.     }
  747.     return( i == 0 );
  748. }
  749. void ask_parameters( void )
  750. {
  751.     int nbcards;
  752.     char strbuf[512];
  753.     nbcards = show_cards();
  754.     if( nbcards == 0 )
  755.     {
  756.         fprintf( stderr, "  No adapters have been detected - make sure"
  757.                  " peek5.sys is present and your card is plugged in.n" );
  758.         prompt_exit( 1 );
  759.     }
  760. ask_arg1:
  761.     printf( "  Network interface index number  -> " );
  762.     scanf( "%s", strbuf );
  763.     arg.card_index = atoi( strbuf );
  764.     if( open_adapter( arg.card_index ) != 0 )
  765.         goto ask_arg1;
  766.     printf( "n  Interface types:  'o' = HermesI/Realtekn"
  767.             "                    'a' = Aironet/Atherosn" );
  768. ask_arg2:
  769.     printf( "n  Network interface type (o/a)  -> " );
  770.     scanf( "%s", strbuf );
  771.     arg.card_model = strbuf[0] & 0xDF;
  772.     if( arg.card_model != 'O' &&
  773.         arg.card_model != 'A' )
  774.         goto ask_arg2;
  775. ask_arg3:
  776.     printf( "n  Channel(s): 1 to 14, 0 = all  -> " );
  777.     scanf( "%s", strbuf );
  778.     if( parse_channels( strbuf ) != 0 )
  779.         goto ask_arg3;
  780.     printf( "n  (note: if you specify the same output prefix, " 
  781.             "airodump will resumen   the capture session by "    
  782.             "appending data to the existing capture file)n" );
  783. ask_arg4:
  784.     printf( "n  Output filename prefix        -> " );
  785.     scanf( "%s", strbuf );
  786.     if( strbuf[0] == '' )
  787.         goto ask_arg4;
  788.     arg.oprefix = malloc( strlen( strbuf ) );
  789.     memcpy( arg.oprefix, strbuf, strlen( strbuf ) + 1 );
  790.     printf( "n  (note: to save space and only store the captured " 
  791.             "WEP IVs, press y.n   The resulting capture file "   
  792.             "will only be useful for WEP cracking)n" );
  793. ask_arg5:
  794.     printf( "n  Only write WEP IVs (y/n)      -> " );
  795.     scanf( "%s", strbuf );
  796.     if( ( strbuf[0] & 0xDF ) != 'Y' &&
  797.         ( strbuf[0] & 0xDF ) != 'N' )
  798.         goto ask_arg5;
  799.     arg.ivs_only = ( ( strbuf[0] & 0xDF ) == 'Y' ) ? 1 : 0;
  800.     printf( "n" );
  801. }
  802. int WINAPI capture_thread( unsigned char *data, int len, int caplen,
  803.                            __int64 timestamp, int flags, int arg7 )
  804. {
  805.     if( ( flags & 1 ) == 0 )
  806.     {
  807.         rawlen = len;
  808.         memcpy( rawbuf, data, rawlen );
  809.         ReleaseSemaphore( semPacket1, 1, NULL );
  810.         WaitForSingleObject( semPacket2, INFINITE );
  811.     }
  812.     return( 1 );
  813. }
  814. int do_exit = 0;
  815. int WINAPI sighandler( int signum )
  816. {
  817.     stop_monitor();
  818.     do_exit = 1;
  819.     return( TRUE );
  820. }
  821. int main( int argc, char *argv[] )
  822. {
  823.     unsigned char *h80211;
  824.     unsigned long tick_prev;
  825.     int caplen, chan_index;
  826.     int ws_row, ws_col;
  827.     time_t tt;
  828.     set_console_icon( " airodump 2.3 " );
  829.     set_console_size( 45, 90 );
  830.     printf( "nnnttt" );
  831.     set_text_color( BLUE_WHITE );
  832.     printf( "airodump 2.3 - (C) 2004,2005 Christophe Devine" );
  833.     set_text_color( TEXTATTR );
  834.     printf( "nnnn  usage: airodump <nic index> <nic type> "
  835.             "<channel(s)> <output prefix> [ivs only flag]nnn" );
  836.     if( argc < 5 || argc > 6 )
  837.     {
  838.         if( load_peek() != 0 )
  839.             prompt_exit( 1 );
  840.         ask_parameters();
  841.     }
  842.     else
  843.     {
  844.         if( load_peek() != 0 )
  845.             prompt_exit( 1 );
  846.         arg.card_index = atoi( argv[1] );
  847.         if( open_adapter( arg.card_index ) != 0 )
  848.         {
  849.             fprintf( stderr, "  Invalid network card indexn" );
  850.             prompt_exit( 1 );
  851.         }
  852.         arg.card_model = argv[2][0] & 0xDF;
  853.         if( arg.card_model != 'O' &&
  854.             arg.card_model != 'A' )
  855.         {
  856.             fprintf( stderr, "  Invalid network card typen" );
  857.             prompt_exit( 1 );
  858.         }
  859.         if( parse_channels( argv[3] ) != 0 )
  860.         {
  861.             fprintf( stderr, "  Invalid wireless channel listn" );
  862.             prompt_exit( 1 );
  863.         }
  864.         arg.oprefix = argv[4];
  865.         if( argc == 6 )
  866.             arg.ivs_only = ( ( argv[5][0] & 0xDF ) == 'Y' ) ? 1 : 0;
  867.     }
  868.     if( dump_initialize( arg.oprefix, arg.ivs_only ) )
  869.         prompt_exit( 1 );
  870.     semPacket1 = CreateSemaphore( NULL, 0, 1, NULL );
  871.     semPacket2 = CreateSemaphore( NULL, 0, 1, NULL );
  872.     SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
  873.     if( start_monitor( capture_thread ) != 0 )
  874.         prompt_exit( 1 );
  875.     tick_prev = GetTickCount();
  876.     set_channel( arg.channels[chan_index = 0] );
  877.     set_cursor_pos( 0, 0 );
  878.     clear_console( NULL, NULL );
  879.     tt = time( NULL );
  880.     while( 1 )
  881.     {
  882.         if( do_exit )
  883.             break;
  884.         if( time( NULL ) - tt >= 20 )
  885.         {
  886.             tt = time( NULL );
  887.             dump_write_csv();
  888.         }
  889.         if( GetTickCount() - tick_prev >= 300 ||
  890.             GetTickCount() < tick_prev )
  891.         {
  892.             tick_prev = GetTickCount();
  893.             if( arg.channels[++chan_index] == 0 )
  894.                 chan_index = 0;
  895.             set_channel( arg.channels[chan_index] );
  896.             sprintf( buffer, " Channel : %02d - airodump 2.1 ",
  897.                        arg.channels[chan_index] );
  898.             SetConsoleTitle( buffer );
  899.             clear_console( &ws_row, &ws_col );
  900.             set_cursor_pos( 0, 0 );
  901.             dump_print( ws_row, ws_col );
  902.         }
  903.         if( WaitForSingleObject( semPacket1, 100 ) == WAIT_TIMEOUT )
  904.             continue;
  905.         memcpy( buffer, rawbuf, rawlen );
  906.         switch( arg.card_model )
  907.         {
  908.         case 'A':
  909.             caplen = rawlen - 12;
  910.             h80211 = buffer +  8;
  911.             break;
  912.         default:
  913.             caplen = rawlen -  8;
  914.             h80211 = buffer +  4;
  915.             break;
  916.         }
  917.         ReleaseSemaphore( semPacket2, 1, NULL );
  918.         if( dump_add_packet( h80211, caplen, buffer[2],
  919.                              arg.channels[chan_index], 0, 0 ) != 0 )
  920.         {
  921.             dump_write_csv();
  922.             if( f_csv_out != NULL ) fclose( f_csv_out );
  923.             if( f_cap_out != NULL ) fclose( f_cap_out );
  924.             if( f_ivs_out != NULL ) fclose( f_ivs_out );
  925.             stop_monitor();
  926.             prompt_exit( 1 );
  927.         }
  928.     }
  929.     dump_write_csv();
  930.     if( f_csv_out != NULL ) fclose( f_csv_out );
  931.     if( f_cap_out != NULL ) fclose( f_cap_out );
  932.     if( f_ivs_out != NULL ) fclose( f_ivs_out );
  933.     stop_monitor();
  934.     return( 0 );
  935. }