天天看點

使用WinPcap抓取各種包

使用WinPcap抓取各種包

使用WinPcap抓各種包

#include<stdio.h> 

#include<iostream> 

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

    } 

    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; 

繼續閱讀