1. 程式人生 > >使用WinPcap抓取各種包

使用WinPcap抓取各種包

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

使用WinPcap抓取各種包

使用WinPcap抓各種包

#include<stdio.h> 

#include<iostream> 

#define

HAVE_REMOTE 

#include"pcap.h" 

#include"remote-ext.h" 

 

#pragmacomment(lib,"Ws2_32.lib"

#pragmacomment(lib,"wpcap.lib"

 

usingnamespace std; 

 

FILE*fp; 

 

//乙太網協議格式的定義 

typedefstructether_header { 

   

u_char ether_dhost[6];     // 目標地址 

   u_char ether_shost[6];     // 源地址 

   u_short ether_type;        // 乙太網型別 

}ether_header

 

//使用者儲存4位元組的IP地址 

typedefstructip_address { 

   u_char byte1; 

   u_char byte2; 

   u_char byte3; 

   u_char byte4; 

}ip_address

 

 

//用於儲存IPV4的首部 

typedefstructip_header

#ifdefWORDS_BIGENDIAN 

    u_char ip_version : 4, header_length :4; 

#else 

   u_char header_length : 4, ip_version : 4; 

#endif 

 

   u_char ver_ihl;    // 版本以及首部長度,各4 

   u_char tos;        // 服務質量 

   u_short tlen;      // 總長度 

   u_short identification;     //身份識別 

   u_short offset;        // 分組偏移 

   u_char ttl;        // 生命週期 

   u_char proto;      // 協議型別 

   u_short checksum;      // 包頭測驗碼 

   ip_address saddr;  //IP地址 

   ip_address daddr;  //目的IP地址 

   u_int op_pad;      //可選填充欄位 

}ip_header

 

//儲存TCP首部 

typedefstructtcp_header { 

   u_short sport; 

   u_short dport; 

   u_int sequence;    // 序列碼 

   u_int ack;                 // 回覆碼 

 

#ifdefWORDS_BIGENDIAN 

    u_char offset : 4, reserved : 4;       //偏移預留 

#else 

   u_char reserved : 4, offset : 4;       // 預留偏移 

#endif 

     

   u_char flags;              // 標誌 

   u_short windows;           // 視窗大小 

   u_short checksum;          // 校驗和 

   u_short urgent_pointer;    // 緊急指標 

}tcp_header

 

typedefstructudp_header { 

   u_int32_t sport;           // 源埠 

   u_int32_t dport;           // 目標埠 

   u_int8_t zero;             // 保留位 

   u_int8_t proto;            // 協議標識 

   u_int16_t datalen;         // UDP資料長度 

}udp_header

 

typedefstructicmp_header { 

   u_int8_t type;             // ICMP型別 

   u_int8_t code;             // 程式碼 

   u_int16_t checksum;        // 校驗和 

   u_int16_t identification;  // 標識 

   u_int16_t sequence;        // 序列號 

   u_int32_t init_time;       // 發起時間戳 

   u_int16_t recv_time;       // 接受時間戳 

   u_int16_t send_time;       // 傳輸時間戳 

}icmp_header

 

typedefstructarp_header {  

   u_int16_t arp_hardware_type; 

   u_int16_t arp_protocol_type; 

   u_int8_t arp_hardware_length; 

   u_int8_t arp_protocol_length; 

   u_int16_t arp_operation_code; 

   u_int8_t arp_source_ethernet_address[6]; 

   u_int8_t arp_source_ip_address[4]; 

   u_int8_t arp_destination_ethernet_address[6]; 

   u_int8_t arp_destination_ip_address[4]; 

}arp_header

 

voidtcp_protocol_packet_handle( 

   u_char *argument,  

   conststructpcap_pkthdr *packet_header,  

   constu_char *packet_content  

) { 

   structtcp_header*tcp_protocol; 

   u_short sport; 

   u_short dport; 

   int header_length; 

   u_short windows; 

   u_short urgent_pointer; 

   u_int sequence; 

   u_int acknowledgement; 

   u_short checksum; 

   u_char flags; 

 

    printf("===========TCP Protocol===========\n"); 

 

    tcp_protocol = (structtcp_header*)(packet_content + 14 + 20); 

    sport = ntohs(tcp_protocol->sport); 

    dport = ntohs(tcp_protocol->dport); 

    header_length = tcp_protocol->offset *4; 

    sequence =ntohl(tcp_protocol->sequence); 

    acknowledgement =ntohl(tcp_protocol->ack); 

    windows =ntohs(tcp_protocol->windows); 

    urgent_pointer =ntohs(tcp_protocol->urgent_pointer); 

    flags = tcp_protocol->flags; 

    checksum =ntohs(tcp_protocol->checksum); 

 

    fprintf(fp,"%d0%d%d%c%d", header_length, sport, dport,flags, windows); 

 

   switch(dport) { 

   default

       break

    } 

 

   if(flags & 0x08) printf("PSH"); 

   if(flags & 0x10) printf("ACK"); 

   if(flags & 0x02) printf("SYN"); 

   if(flags & 0x20) printf("URG"); 

   if(flags & 0x01) printf("FIN"); 

   if(flags & 0x04) printf("RST"); 

    printf("\n"); 

 

voidudp_protocol_packet_handle( 

   u_char *argument

   conststructpcap_pkthdr *packet_header

   constu_char *packet_content 

) { 

   structudp_header*udp_protocol; 

   u_short sport; 

   u_short dport; 

   u_short datalen; 

     

    udp_protocol = (structudp_header*)(packet_content + 14 + 20); 

    sport = ntohs(udp_protocol->sport); 

    dport = ntohs(udp_protocol->dport); 

    datalen =ntohs(udp_protocol->datalen); 

 

    fprintf(fp,"0%d%d%d",datalen, sport, dport); 

 

voidarp_protocol_packet_handle( 

   u_char *argument

   conststructpcap_pkthdr *packet_header

   constu_char *packet_content 

) { 

   structarp_header*arp_protocol;    

   u_short protocol_type;    

   u_short hardware_type;    

   u_short operation_code;    

   u_char hardware_length;    

   u_char protocol_length;    

 

   structtm* ltime; 

   char timestr[16]; 

   time_t local_tv_sec; 

    local_tv_sec =packet_header->ts.tv_sec; 

    ltime = localtime(&local_tv_sec); 

    strftime(timestr,sizeof(timestr),"%H:%M:%S", ltime); 

 

    printf("--------   ARP協議    --------\n");    

    arp_protocol = (structarp_header*)(packet_content + 14);    

    hardware_type =ntohs(arp_protocol->arp_hardware_type);    

    protocol_type =ntohs(arp_protocol->arp_protocol_type);    

    operation_code =ntohs(arp_protocol->arp_operation_code);    

    hardware_length =arp_protocol->arp_hardware_length;    

    protocol_length =arp_protocol->arp_protocol_length; 

     

    fprintf(fp,"%d%s", protocol_length, timestr); 

 

   switch (operation_code)    

    { 

       case 1:    

            printf("ARP請求協議\n");    

           break;    

       case 2:    

            printf("ARP應答協議\n");    

           break;    

       case 3:    

            printf("RARP請求協議\n");    

           break;    

       case 4:    

            printf("RARP應答協議\n");    

           break;    

       default:    

           break;    

    }    

 

 

 

voidicmp_protocol_packet_handle( 

   u_char *argument

   conststructpcap_pkthdr *packet_header

   constu_char *packet_content 

) { 

   structicmp_header*icmp_protocol; 

   u_short type; 

   u_short datalen; 

   u_int init_time; 

   u_int recv_time; 

   u_int send_time; 

 

    icmp_protocol = (structicmp_header*)(packet_content + 14 + 20); 

    datalen =sizeof(icmp_protocol); 

    type = icmp_protocol->type; 

    init_time =icmp_protocol->init_time; 

    recv_time =icmp_protocol->recv_time; 

    send_time =icmp_protocol->send_time; 

  

    fprintf(fp,"%d%c%d%d%d", datalen, type, init_time,recv_time, send_time); 

 

//  printf("===========ICMPProtocol==========\n"); 

 

   switch(icmp_protocol->type) { 

   case 8: 

       //回顯請求報文 

       break

   case 0: 

       //回顯應答報文 

       break

   default

       break

    } 

 

voidip_protocol_packet_handle( 

   u_char *argument,  

   conststructpcap_pkthdr *packet_header,  

   constu_char *packet_content  

) { 

   structip_header*ip_protocol; 

   u_int header_length; 

   u_char tos; 

   u_short checksum; 

     

   ip_address saddr; 

   ip_address daddr; 

   u_char ttl; 

   u_short tlen; 

   u_short identification; 

   u_short offset; 

 

    printf("===========IP Protocol===========\n"); 

 

    ip_protocol = (structip_header*)(packet_content + 14); 

    header_length =ip_protocol->header_length * 4; 

    checksum =ntohs(ip_protocol->checksum); 

    tos = ip_protocol->tos; 

    offset =ntohs(ip_protocol->offset); 

 

    saddr = ip_protocol->saddr; 

    daddr = ip_protocol->daddr; 

    ttl = ip_protocol->ttl; 

    identification =ip_protocol->identification; 

    tlen = ip_protocol->tlen; 

    offset = ip_protocol->offset; 

 

    fprintf(fp,"%d%d%c%d%d%d", saddr, daddr, ttl,identification, tlen, offset); 

 

   switch(ip_protocol->proto) { 

   case 6: 

        tcp_protocol_packet_handle(argument,packet_header,packet_content); 

       break

   case 17: 

        udp_protocol_packet_handle(argument,packet_header,packet_content); 

       break

   case 1: 

        icmp_protocol_packet_handle(argument,packet_header,packet_content); 

       break

   default

       break

    } 

}  

 

 

voidethernet_protocol_packet_handle ( 

   u_char *argument,  

   conststructpcap_pkthdr *packet_header,  

   constu_char *packet_content 

) { 

   u_short ethernet_type;     // 乙太網型別 

   structether_header*ethernet_protocol;    // 乙太網協議變數 

   u_char *mac_string;        // 乙太網地址 

 

    ethernet_protocol = (structether_header*)packet_content;      //獲取乙太網資料內容 

    printf("Ethernet type is : \n"); 

    ethernet_type =ntohs(ethernet_protocol->ether_type);   //獲取乙太網型別 

   printf("   %04x\n", ethernet_type); 

 

     

 

   switch(ethernet_type) { 

   case 0x0800: 

        printf("The network layer is IP protocol\n"); 

       break

   case 0x0806: 

        printf("The network layer is ARP protocol\n"); 

       break

   default

       break

    } 

 

   // 獲取乙太網源地址 

//  printf("MAC Source Address is :\n"); 

    mac_string =ethernet_protocol->ether_shost; 

     

    fprintf(fp,"%02x:%02x:%02x:%02x:%02x:%02x",  

        *mac_string, 

        *(mac_string + 1), 

        *(mac_string + 2), 

        *(mac_string + 3), 

        *(mac_string + 4), 

        *(mac_string + 5) 

        ); 

 

   // 獲取乙太網目的地址 

//  printf("MAC Target Address is :\n"); 

    mac_string = ethernet_protocol->ether_dhost; 

    fprintf(fp,"%02x:%02x:%02x:%02x:%02x:%02x",  

        *mac_string, 

        *(mac_string + 1), 

        *(mac_string + 2), 

        *(mac_string + 3), 

        *(mac_string + 4), 

        *(mac_string + 5) 

        ); 

 

    fprintf(fp,"%d",sizeof(packet_content)); 

 

   switch(ethernet_type) { 

   case 0x0800: 

        ip_protocol_packet_handle(argument,packet_header,packet_content); 

       break

   default

       break

    } 

 

intmain() { 

   pcap_if_t *alldevs; 

   pcap_if_t *d; 

   pcap_t *adhandle; 

   char errbuf[PCAP_ERRBUF_SIZE]; 

   int inum; 

   int i = 0; 

   u_int netmask; 

   char packet_filter[] ="ip and tcp"

   structbpf_programfcode; 

   int res; 

   structpcap_pkthdr*header; 

   structtm *ltime; 

   constu_char *pkt_data; 

   time_t local_tv_sec; 

   char timestr[16]; 

   ip_header *ih; 

 

   // 獲得裝置列表pcap_findalldevs_ex() 

 

   if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL, &alldevs, errbuf)== -1) { 

        fprintf(stderr,"Errorin pcap_findalldevs: %s\n", errbuf); 

        exit(1); 

    } 

 

   for(d = alldevs; d; d = d->next) { 

        printf("%d. %s", ++i, d->name); 

       if(d->description) { 

            printf("(%s)\n", d->description); 

        } 

       else

            printf("No description available\n"); 

        } 

    } 

     

   if(0 == i) { 

        printf("\nNo interface found!Make sure WinPcap is installed\n"); 

       return -1; 

    } 

 

    printf("Enter the interface number(1-%d):",i); 

    scanf_s("%d", &inum); 

   if(inum < 1 || inum > i) { 

        printf("\nInterface number out of range.\n"); 

        pcap_freealldevs(alldevs); 

       return -1; 

    } 

 

   for(d = alldevs, i = 0; i < inum-1; d=d->next, i++); 

   // 跳轉到該裝置,開啟介面卡 

 

   // 裝置名,要捕捉的資料包的部分(65536保證能捕獲到不同資料鏈路層上的每個資料包的全部內容),混雜模式,讀取超時時間,錯誤緩衝池 

   if((adhandle = pcap_open_live(d->name, 65536, 1, 1000, errbuf)) ==NULL) { 

        fprintf(stderr,"\nUnableto open the adapter.%s is not supported by WinPcap\n", errbuf); 

        pcap_freealldevs(alldevs); 

       return -1; 

    } 

   // 檢查資料鏈路層(只考慮了乙太網) 

   if(pcap_datalink(adhandle) !=DLT_EN10MB) { 

        fprintf(stderr,"\nThisprogram works only on Ethernet networks.\n"); 

        pcap_freealldevs(alldevs); 

       return -1; 

    } 

 

   if(d->addresses !=NULL){ 

       //獲得介面的第一個地址的掩碼 

        netmask = ((structsockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr; 

    } 

   else

        netmask = 0xffffff; 

    } 

/*

    //編譯過濾器

    if(pcap_compile(adhandle, &fcode,packet_filter, 1, netmask) < 0) {

        fprintf(stderr, "\nUnable tocompile the packet filter.Check the syntax\n");

        pcap_freealldevs(alldevs);

        return -1;

    }

    

    //設定過濾器

    

    if(pcap_setfilter(adhandle, &fcode)< 0) {

        fprintf(stderr, "\nError settingthe filter.\n");

        pcap_freealldevs(alldevs);

        return -1;

    }

    printf("\nlistenting on %s...\n",d->description);

*/ 

    fp = freopen("in.txt","w",stdin); 

 

   while((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0){  

 

       //請求超時 

       if(0 == res) { 

           continue

        } 

 

       //分析資料包 

        ethernet_protocol_packet_handle(NULL, header, pkt_data); 

 

       //將時間戳轉換成可識別的格式 

        local_tv_sec =header->ts.tv_sec; 

        ltime =localtime(&local_tv_sec); 

        strftime(timestr,sizeof(timestr),"%H:%M:%S", ltime); 

        ih = (ip_header *)(pkt_data + 14);//乙太網頭部長度 

 

       //輸出時間和IP資訊 

        printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec,header->len); 

 

        printf("%d.%d.%d.%d -> %d.%d.%d.%d\n"

            ih->saddr.byte1, 

            ih->saddr.byte2, 

            ih->saddr.byte3, 

            ih->saddr.byte4, 

            ih->daddr.byte1, 

            ih->daddr.byte2, 

            ih->daddr.byte3, 

            ih->daddr.byte4); 

    } 

 

     

   if(-1 == res) { 

        printf("Error reading the packet:%s\n",pcap_geterr(adhandle)); 

       return -1; 

    } 

    pcap_freealldevs(alldevs); 

 

    fclose(fp); 

    fclose(stdin); 

 

   return 0; 

 

 

 

 

 

 

 

 

 

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述