赞
踩
转载:https://blog.csdn.net/x_white/article/details/8545593
winpcap技术手册,除了安装文件里doc文件下有个帮助,这里在给一个:http://www.ferrisxu.com/WinPcap/html/index.html
这里我们用pcap_next_ex 函数抓取到数据包后,我们就要开始提取其中的关键信息了,这里我保存在了pkt_data里,之后又传到了处理函数中
代码如下,我也已经写的很清楚了。其中MAC地址是在数据链路层获取的,其他的诸如端口号,IP等都是通过分析IP包和TCP包获取。
唯一需要注意的就是在定义结构体的时候要注意字节的大小,不然获取的信息就是错误的了。
- #include <stdio.h>
- #include <iostream>
- #define HAVE_REMOTE
- #include "pcap.h"
- #include "remote-ext.h"
-
- #pragma comment(lib, "Ws2_32.lib")
- #pragma comment(lib, "wpcap.lib")
-
- using namespace std;
-
- FILE* fp;
-
- // 以太网协议格式的定义
- typedef struct ether_header {
- u_char ether_dhost[6]; // 目标地址
- u_char ether_shost[6]; // 源地址
- u_short ether_type; // 以太网类型
- }ether_header;
-
- // 用户保存4字节的IP地址
- typedef struct ip_address {
- u_char byte1;
- u_char byte2;
- u_char byte3;
- u_char byte4;
- }ip_address;
-
-
- // 用于保存IPV4的首部
- typedef struct ip_header {
- #ifdef WORDS_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首部
- typedef struct tcp_header {
- u_short sport;
- u_short dport;
- u_int sequence; // 序列码
- u_int ack; // 回复码
-
- #ifdef WORDS_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;
-
- typedef struct udp_header {
- u_int32_t sport; // 源端口
- u_int32_t dport; // 目标端口
- u_int8_t zero; // 保留位
- u_int8_t proto; // 协议标识
- u_int16_t datalen; // UDP数据长度
- }udp_header;
-
- typedef struct icmp_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;
-
- typedef struct arp_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;
-
- void tcp_protocol_packet_handle(
- u_char *argument,
- const struct pcap_pkthdr *packet_header,
- const u_char *packet_content
- ) {
- struct tcp_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 = (struct tcp_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");
- }
-
- void udp_protocol_packet_handle(
- u_char *argument,
- const struct pcap_pkthdr *packet_header,
- const u_char *packet_content
- ) {
- struct udp_header* udp_protocol;
- u_short sport;
- u_short dport;
- u_short datalen;
-
- udp_protocol = (struct udp_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);
- }
-
- void arp_protocol_packet_handle(
- u_char *argument,
- const struct pcap_pkthdr *packet_header,
- const u_char *packet_content
- ) {
- struct arp_header *arp_protocol;
- u_short protocol_type;
- u_short hardware_type;
- u_short operation_code;
- u_char hardware_length;
- u_char protocol_length;
-
- struct tm* 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 = (struct arp_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;
- }
- }
-
-
-
- void icmp_protocol_packet_handle(
- u_char *argument,
- const struct pcap_pkthdr *packet_header,
- const u_char *packet_content
- ) {
- struct icmp_header *icmp_protocol;
- u_short type;
- u_short datalen;
- u_int init_time;
- u_int recv_time;
- u_int send_time;
-
- icmp_protocol = (struct icmp_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("===========ICMP Protocol==========\n");
-
- switch(icmp_protocol->type) {
- case 8:
- // 回显请求报文
- break;
- case 0:
- // 回显应答报文
- break;
- default:
- break;
- }
- }
-
- void ip_protocol_packet_handle(
- u_char *argument,
- const struct pcap_pkthdr *packet_header,
- const u_char *packet_content
- ) {
- struct ip_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 = (struct ip_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;
- }
- }
-
-
- void ethernet_protocol_packet_handle (
- u_char *argument,
- const struct pcap_pkthdr *packet_header,
- const u_char *packet_content
- ) {
- u_short ethernet_type; // 以太网类型
- struct ether_header *ethernet_protocol; // 以太网协议变量
- u_char *mac_string; // 以太网地址
-
- ethernet_protocol = (struct ether_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;
- }
- }
-
- int main() {
- 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";
- struct bpf_program fcode;
- int res;
- struct pcap_pkthdr *header;
- struct tm *ltime;
- const u_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, "Error in 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, "\nUnable to open the adapter.%s is not supported by WinPcap\n", errbuf);
- pcap_freealldevs(alldevs);
- return -1;
- }
- // 检查数据链路层(只考虑了以太网)
- if(pcap_datalink(adhandle) != DLT_EN10MB) {
- fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
- pcap_freealldevs(alldevs);
- return -1;
- }
-
- if(d->addresses != NULL) {
- // 获得接口的第一个地址的掩码
- netmask = ((struct sockaddr_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 to compile the packet filter.Check the syntax\n");
- pcap_freealldevs(alldevs);
- return -1;
- }
-
- // 设置过滤器
-
- if(pcap_setfilter(adhandle, &fcode) < 0) {
- fprintf(stderr, "\nError setting the 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;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。