一、
根据教材参考代码,编写有个简单网络抓包工具。要求核心代码和运行结果截图1-2张。
- 首先再再再次感谢启龙同学,这次作业或许对于有基础的人来说并不难,但对于我这种基础很差、网络协议都是上学期自己补课的人来说属实有点难度,若不是启龙同学的帮助提供程序并解答我的部分疑惑,我怕是不可能按时完成这次作业。
- 虽然我尽力想要弄明白程序的原理,但是我能力有限,再加上时间也不充裕(其他学科的作业和导师的学习任务也占据了不少时间),所以我只能大概描绘一下我运行这个程序时的流程,如果后续我还有余力的话,我会来更新博客。
程序运行结果
- 首先我来放一些程序运行结果,代码和分析在之后再放。
- 程序准备开始运行
- 开始抓包
- 登陆了我的qq邮箱,来抓包
- 可以看到抓到的文件
程序代码和分析
首先我先把的代码贴上
constant.h #include <stdio.h> #include <pcap.h> #include <string.h> #include "util.h" #define INTRODUCTION "Author hanbing nudt.\n\ Simple packet dump" #define COMMAND_BUFFER_SIZE 50 #define COMMAND_CODE_QUIT 1 /*command quit*/ #define COMMAND_QUIT "quit" #define COMMAND_CODE_LIST_ALL_DEVICE 2 /*list all valiable device*/ #define COMMAND_LIST_ALL_DEVICE "show-device" #define COMMAND_CODE_SHOW_OPTIONS 3 /*show options of setting a filter*/ #define COMMAND_SHOW_OPTIONS "show-options" #define COMMAND_CODE_SET 4 #define COMMAND_SET "set" #define TOKEN " " #define COMMAND_CODE_BEGIN 5 #define COMMAND_BEGIN "begin"
- 这个头文件里都是一些宏定义,我就不详细说了。
- 接下来是各个协议的头部定义
#include <arpa/inet.h> #define ETHERNET_HEADER_LENGTH 14 #define IP_HEADER_LENGTH 20 #define IMCP_HEADER_LENGTH 8 /*tls 头部定义*/ struct tls_header { }; /*UDP头部格式定义*/ struct udp_header { u_int16_t udp_source_port; //源端口号 u_int16_t udp_destination_port; //目的端口号 u_int16_t udp_length; //长度 u_int16_t udp_checksum ; //校验和 }; struct tcp_header { u_int16_t tcp_source_port; u_int16_t tcp_destination_port; u_int32_t tcp_syn; //SYN number u_int32_t tcp_ack; //ACK number #ifdef WORDS_BEGENDIAN u_int8_t tcp_offset:4, tcp_reserved:4; #else u_int8_t tcp_reserved:4, tcp_offset:4; #endif u_int8_t tcp_flags; u_int16_t tcp_windows; u_int16_t tcp_checksum; u_int16_t tcp_urgent_pointer; }; /*ICMP头部格式定义*/ struct icmp_header { u_int8_t icmp_type; u_int8_t icmp_code; u_int16_t icmp_checksum; u_int16_t icmp_id; u_int16_t icmp_sequence; }; /*IP协议头部格式*/ struct ip_header { #ifdef WORDS_BEGENDIAN u_int8_t ip_version:4, //ip协议版本 ip_header_length:4; //ip协议首部长度 #else u_int8_t ip_header_length:4, //ip协议首部长度 ip_version:4; //ip协议版本 #endif u_int8_t ip_tos; /*TOS服务质量*/ u_int16_t ip_length; //总长度 u_int16_t ip_id; //标识 u_int16_t ip_off;//偏移 u_int8_t ip_ttl; /*生存时间*/ u_int8_t ip_protocol; //协议类型 u_int16_t ip_checksum; //校验和 struct in_addr ip_source_address; //源ip地址 struct in_addr ip_destination_address; //目的ip地址 }; /*arp protocol format*/ struct arp_header { u_int16_t arp_hardware_type; /*硬件地址类型 Ethernet is 1*/ u_int16_t arp_protocol_type; /*网络层协议类型 ipv4 0x0800*/ u_int8_t arp_hardware_length; /*硬件地址长度*/ u_int8_t arp_protocol_length; /*网络层协议地址长度*/ u_int16_t arp_operation_code; /*操作类型 1 request 2 reply*/ u_int8_t arp_source_ethernet_address[6]; /*源以太网地址*/ u_int8_t arp_source_ip_address [4]; /*源ip地址*/ u_int8_t arp_destination_ethernet_address[6]; /*目的以太网地址*/ u_int8_t arp_destination_ip_address [4]; /*目的ip地址*/ }; //util to get ethernet packets struct ether_header //data structure of ethernet protocol { u_int8_t ether_dhost[6]; //Destination address u_int8_t ether_shost[6]; //Source address u_int16_t ether_type; //Ethernet type }; void arp_protocol_packet_callback(u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content); void ethernet_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content); void ip_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content); void icmp_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content); void udp_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content); void tcp_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content); #endif
-
这个文件里包含的就是各个文件的头部的结构体的定义。由于上学期我看的网络协议看的很糙,并且也没怎么复习,所有我又复习了下各个协议的头部格式。
-
IP头部
-
TCP头部
-
UDP头部
-
以太网帧头部
-
然后是callback.c文件。在这个文件中主要是对各个协议的分析
-
Callback.c里的函数
-
void tcp_protocol_packet_callback 输出源端口、目标端口、并根据端口判别应用层协议输出,输出标志位、输出窗口大小、输出校验和、输出紧急指针,总之把头部里能输出的都输出了
-
void udp_protocol_packet_callback 输出源端口、目标端口、并根据端口判别应用层协议输出,输出长度、输出校验和
-
void icmp_protocol_packet_callback 跳过IP协议头部,直接获取IP数据包中icmp协议,如果是回显请求或者回显应答数据包,就输出icmp的类型。然后统一输出标识符、序列号、校验和
-
void arp_protocol_packet_callback 输出硬件类型、协议类型、硬件长度、操作码、请求协议还是相应协议、arp还是rarp、源ip和mac,目标ip和mac
-
void ip_protocol_packet_callback 输出IP版本、头长度、总长度、服务类型、标识、偏移、TTL、校验和、源地址和目标地址、并判定传输层协议,然后扔到相应的callback函数中
-
void ethernet_protocol_packet_callback 输出目的mac地址和源mac地址,然后根据上层协议类型扔到ip或者arp的函数。
#include "callback.h" static int number = 0; void tls_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content) { } void tcp_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content) { struct tcp_header *tcp_protocol; u_char flags; int header_length; u_short source_port; u_short destination_port; u_short windows; u_short urgent_pointer; u_int sequence; u_int acknowlegement; u_int16_t checksum; tcp_protocol=(struct tcp_protocol*)(packet_content+ETHERNET_HEADER_LENGTH+IP_HEADER_LENGTH);//以太头部长度和ip头部长度 source_port = ntohs(tcp_protocol->tcp_source_port);//回调函数实现ip分析,找出tcp头部中的源端口号,下同 destination_port = ntohs(tcp_protocol->tcp_destination_port); header_length = tcp_protocol->tcp_offset * 4; sequence = ntohs(tcp_protocol->tcp_syn); acknowlegement = ntohs(tcp_protocol->tcp_ack); windows = ntohs(tcp_protocol->tcp_windows); urgent_pointer = ntohs(tcp_protocol->tcp_windows); flags = tcp_protocol->tcp_flags; checksum = ntohs(tcp_protocol->tcp_checksum); printf("--------------------TCP Protocol (Transport Layer)--------------------------\n"); printf("Source Port: %d\n",source_port ); printf("Destination Port: %d\n",destination_port ); switch(destination_port) //判断上层协议 通过端口判断应用层协议 { case 80:printf("HTTP protocol \n");break; case 21:printf("FTP protocol \n");break; case 23:printf("Telnet protocol \n");break; case 25:printf("SMTP protocol \n");break; case 110:printf("POP3 protocol\n");break; case 443:printf("HTTPS protocol \n");break; default:break; } printf("Sequence Number: %u\n",sequence ); printf("Acknowlegement Number: %u\n", acknowlegement ); //%u unsigned integer printf("Header Length: %d\n",header_length ); printf("Reserve: %d\n",tcp_protocol->tcp_reserved ); //提取标志位 if (flags & 0x20)printf("URG"); if (flags & 0x01)printf("FIN"); if (flags & 0x04)printf("RST"); if (flags & 0x08)printf("PSH"); if (flags & 0x10)printf("ACK"); if (flags & 0x02)printf("SYN"); printf("\n"); printf("Window Size: %d\n",windows ); printf("Checksum: %d\n", checksum); printf("Urgent Pointer: %d\n",urgent_pointer ); switch(destination_port) //判断上层协议 { case 443: tls_protocol_packet_callback(argument,packet_header,packet_content); break; default: break; } } void udp_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content) { struct udp_header *udp_protocol; //UDP协议变量 u_short source_port; //源端口号 u_short destination_port; //目的端口号 u_short length; //长度 /*获得ICMP协议数据内容,跳过以太网协议与ip协议部分*/ udp_protocol = (struct udp_header *)(packet_content+ETHERNET_HEADER_LENGTH+IP_HEADER_LENGTH); source_port = ntohs(udp_protocol->udp_source_port); destination_port = ntohs(udp_protocol->udp_destination_port); length = ntohs(udp_protocol->udp_length); printf("-------------------------UDP Protocol (Transport Layer) ----------------------\n"); printf("Source port: %d\n", source_port); printf("Destination port: %d\n", destination_port); switch(destination_port) { //NetBios数据报服务 case 138: printf("NETBIOS Datagram Service\n"); break; case 137: printf("NETBIOS Name Service\n"); break; case 139: printf("NETBIOS Session Service\n"); break; case 53:printf("name-domain server \n");break; default:break;//其他端口号在此没有分析,后续版本会添加 } printf("Length:%d \n", length ); printf("Checksum: %d\n", ntohs(udp_protocol->udp_checksum)); //获得校验和 } void icmp_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content) { struct icmp_header *icmp_protocol; /*获得ICMP协议数据内容,跳过以太网协议与ip协议部分*/ icmp_protocol = (struct icmp_header *) (packet_content+ETHERNET_HEADER_LENGTH+IP_HEADER_LENGTH); printf("---------------ICMP Protocol (Transport Layer)---------------------"); printf("ICMP Type: %d\n",icmp_protocol->icmp_type ); switch(icmp_protocol->icmp_type) //ICMP数据包类型较多,待扩展 { case 8://回显请求ICMP数据包 printf("ICMP Echo REquest Protocol \n"); printf("ICMP Identifier: %s\n", icmp_protocol->icmp_id); printf("ICMP Sequence Number: %s\n", icmp_protocol->icmp_sequence); break; case 0://回显应答数据包 printf("ICMP Echo Reply Protocol \n"); printf("ICMP Identifier: %s\n", icmp_protocol->icmp_id); printf("ICMP Sequence Number: %s\n", icmp_protocol->icmp_sequence); break; default: printf("Header Data %s%s\n", icmp_protocol->icmp_id,icmp_protocol->icmp_sequence); } printf("ICMP Checksum:%d\n",ntohs(icmp_protocol->icmp_checksum) ); printf("ICMP Payload: %s", packet_content+ ETHERNET_HEADER_LENGTH+IP_HEADER_LENGTH+IMCP_HEADER_LENGTH); } /*arp协议分析回调函数*/ void arp_protocol_packet_callback(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 *mac_string; //以太网地址 struct in_addr source_ip_address; struct in_addr destination_ip_address; u_char hardware_length; //硬件地址长度 u_char protocol_length; //协议地址长度 printf("---------- ARP Protocol (Network Layer) ---------------\n"); /*获得arp协议数据。逐一在这里要跳过以太网数据部分*/ arp_protocol = (struct arp_header *)(packet_content+ETHERNET_HEADER_LENGTH); /*使用ntohs函数将网络字节序转换为本机字节序*/ 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; printf("ARP Hardware Type: %d\n", hardware_type);//输出硬件类型 printf("ARP Protocol Type: %d\n",protocol_type);//输出协议类型 printf("ARP Hardware Length: %d\n", hardware_length);//输出硬件长度 printf("ARP Operation: %d\n", operation_code);//输出操作码 switch(operation_code){//根据操作吗判别清秀协议还是响应协议,是arp还是逆向的rarp case 1: printf("ARP Request Protocol\n"); break; case 2: printf("ARP Reply Protocol\n"); break; case 3: printf("RARP Request Protocol\n"); break; case 4: printf("RARP Reply Protocol\n"); break; default: break; } printf("Ethernet Source Address is : \n"); mac_string = arp_protocol->arp_source_ethernet_address; printf("%02x:%02x:%02x:%02x:%02x:%02x:\n",*(mac_string), *(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4), *(mac_string+5) ); memcpy((void *) &source_ip_address, (void *) &arp_protocol-> arp_source_ip_address, sizeof(struct in_addr)); printf("Source IP Address: %s\n", inet_ntoa(source_ip_address)); printf("Ethernet destination_ip_address Address is : \n"); mac_string = arp_protocol->arp_destination_ethernet_address; printf("%02x:%02x:%02x:%02x:%02x:%02x\n",*(mac_string), *(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4), *(mac_string+5) ); memcpy((void *) &destination_ip_address, (void *) &arp_protocol-> arp_destination_ip_address, sizeof(struct in_addr)); printf("Destination IP Address: %s\n", inet_ntoa(destination_ip_address)); } /*回调函数实现ip协议包分析*/ void ip_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content) { struct ip_header *ip_protocol; u_int header_length; u_int offset; u_char tos; u_int16_t checksum; /*去掉以太网头部,获得ip协议数据内容*/ ip_protocol = (struct ip_header *)(packet_content + ETHERNET_HEADER_LENGTH); checksum = ntohs(ip_protocol->ip_checksum); header_length = ip_protocol->ip_header_length*4; tos = ip_protocol->ip_tos; offset = ntohs(ip_protocol->ip_off); printf("------------------IP Protocol (Network Layer)----------------------\n"); printf("IP Version: %d\n",ip_protocol->ip_version); printf("Header_length: %d\n",header_length); printf("Tos:%d\n", tos); printf("Total length: %d\n", ntohs(ip_protocol->ip_length)); printf("Identification: %d\n",ntohs(ip_protocol->ip_id) ); printf("offset: %d\n",(offset & 0x1fff)*8 ); printf("TTL: %d\n",ip_protocol->ip_ttl ); printf("Protocol: %d\n",ip_protocol->ip_protocol ); switch(ip_protocol->ip_protocol) { case 6: printf("The Transport Layer Protocol is TCP\n");break; case 17: printf("The Transport layer Protocol is UDP\n");break; case 1: printf("The Transport layer Protocol is ICMP\n");break; default: break; } printf("Header checksum: %d\n", checksum); printf("Source address: %s\n",inet_ntoa(ip_protocol->ip_source_address)); printf("Destination address: %s\n", inet_ntoa(ip_protocol->ip_destination_address)); switch(ip_protocol->ip_protocol) { case 6: tcp_protocol_packet_callback(argument,packet_header,packet_content);break; case 17: udp_protocol_packet_callback(argument,packet_header,packet_content);break; case 1: icmp_protocol_packet_callback(argument,packet_header,packet_content);break; default: break; } } /*回调函数实现以太网协议分析*/ void ethernet_protocol_packet_callback(u_char *argument, //arguments pass by user const struct pcap_pkthdr *packet_header, const u_char *packet_content){ pcap_dump(arguement, packet_header, packet_content); number++; printf("\n"); printf("\n"); printf("The num %d packets\n", number); u_short ethernet_type; //以太网类型 struct ether_header *ethernet_protocol; //以太网协议类型 u_char *mac_string; //以太网地址 static int packet_number = 1; printf("--------------------Ethernet Protocol (Link Layer)-------------------\n"); ethernet_protocol = (struct ethernet_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; case 0x0835: printf("The network layer is RARP protocol\n");break; } /*获得源以太网地址*/ printf("Mac Source Address is : \n"); mac_string = ethernet_protocol->ether_shost; printf("%02x:%02x:%02x:%02x:%02x:%02x\n",*(mac_string), *(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4), *(mac_string+5) ); /*获得目的以太网地址*/ printf("Mac Destination Address is : \n"); mac_string = ethernet_protocol->ether_dhost; printf("%02x:%02x:%02x:%02x:%02x:%02x\n",*(mac_string), *(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4), *(mac_string+5) ); /*调用上层协议分析回调函数*/ switch(ethernet_type) { case 0x0800: ip_protocol_packet_callback(argument,packet_header,packet_content); break; case 0x0806: arp_protocol_packet_callback(argument,packet_header,packet_content); break; case 0x0835: break; default: break; } printf("-------------------------------------------------------------------------\n"); }
-
可以看出来上面的函数层层递进得来分析协议,先是对以太网帧进行分析,然后根据分析得出来的上层协议,来转到IP或者ARP的分析函数。
-
然后在IP的分析函数中,也是通过分析数据,来转到TCP、UDP或者ICMP的函数中。
-
分析完上面的几个文件之后,我是从main函数开始,将我的抓包过程的所经历的程序分析了一遍。
-
首先是main.c文件
#include "constant.h" static char buffer[COMMAND_BUFFER_SIZE]; static int command_code; static filter_options_t options; void init_interpreter(){ puts(INTRODUCTION); } void PrintUsage(){ printf("%s\n", USAGE); } void show_options(){ printf("过滤规则: %s\n", options.filter); printf("网络设备: %s\n",options.device); } int ParseCommandLine(char *command){ if (strcmp(command,COMMAND_QUIT) == 0) { command_code = COMMAND_CODE_QUIT; return 0; } else if (strcmp(command,COMMAND_LIST_ALL_DEVICE) == 0) { command_code = COMMAND_CODE_LIST_ALL_DEVICE; return 0; } else if (strcmp(command,COMMAND_SHOW_OPTIONS) == 0) { command_code = COMMAND_CODE_SHOW_OPTIONS; return 0; } else if(strcmp(command,COMMAND_BEGIN) == 0){ command_code = COMMAND_CODE_BEGIN; return 0; } else{ char *tmp = NULL; tmp = strtok(command,TOKEN); if (strcmp(tmp,COMMAND_SET) == 0) { if(pares_option_setting()){ command_code = COMMAND_CODE_SET; return 0; } } } command_code = 0; return 1; } int pares_option_setting(){ char *tmp; char *option; tmp = strtok(NULL,TOKEN); if (!tmp) { return 0; //false } option = strtok(NULL,TOKEN); if (!option) { return 0; //false } if (strtok(NULL,TOKEN)) { return 0; } if (!strcmp(tmp,"device")) { strcpy(options.device,option); return 1; } else if(!strcmp(tmp,"filter")) { strcpy(options.filter,option); return 1; } else if(!strcmp(tmp,"path")) { strcpy(options.path,option); return 1; } else { return 0;//false } } int CommandDispacther(){ switch(command_code){ case COMMAND_CODE_QUIT: return 0; //return status code 0 when quit case COMMAND_CODE_LIST_ALL_DEVICE: findalldevs(); return 1; case COMMAND_CODE_SHOW_OPTIONS: show_options(); return 1; case COMMAND_CODE_SET: return 1; case COMMAND_CODE_BEGIN: capture_packets(&options); return 1; default: return 0; //defalt retrun true } } int main(int argc, char const *argv[]) { int status = 1; init_interpreter(); do{ printf(">>"); gets(buffer); /*Parse args options*/ if (ParseCommandLine(buffer)){ PrintUsage(); }else{ status = CommandDispacther(); } } while (status); return 1; }
-
这里只看main函数的话是非常的简洁,只有这几行,所以我的运行过程也很简单(如果难的话我应该就看不懂了)
-
main
函数里首先定义了一个作用的变量status
,用于do while
循环。然后void init_interpreter()
就是输出了宏定义的一句话(这个函数删了也没什么影响吧,只是输出一句话,我看启龙同学的博客都删掉了)。然后开始do while
循环。 -
在我的程序里,我第一个输入的
buffer
是set device eth0
这个eth0就是我的网卡。接下看ParseCommandLine(buffer)
。这个函数也在main.c
里面,可以在上面的代码里找到。我输入的很显然不是这些任何一个宏定义,然后转到else
。接着在else里转到下一个pares_option_setting
函数,在这里进行了strcpy(options.device,option)
,将网卡保存了下来。之后可以看到该函数返回了1
,然后继续向上推,上一个函数返回0
,并且将command_code
设置为一个宏定义。接下来回到main
函数,因为if
返回0
,执行else
,在CommandDispacther
里又可以得到返回1.也就是继续进行do while循环
。 -
其实上面的一大串,不过是储存了我设置的网卡,然后继续循环。所以接下来我输入的
set path
也就不再罗里吧嗦的说了,可以顺着看。 -
第三次循环我输入begin。顺着运行可以看到,最后执行了
capture_packets(&options)
这个函数再另一个文件里:
int findalldevs(){ pcap_if_t *alldevs;//网卡链表里的一个元素 pcap_if_t *d; char *s; bpf_u_int32 net,mask; int exit_status = 0; char errbuf[PCAP_ERRBUF_SIZE+1]; if (pcap_findalldevs(&alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); return 1; } for(d=alldevs;d;d=d->next) { if (!ifprint(d)){ return 1; } } if ( (s = pcap_lookupdev(errbuf)) == NULL) { fprintf(stderr,"Error in pcap_lookupdev: %s\n",errbuf); exit_status = 2; } else { printf("Preferred device name: %s\n",s); } if (pcap_lookupnet(s, &net, &mask, errbuf) < 0) { fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf); exit_status = 2; } else { printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask)); } return exit_status; } void capture_packets(struct filter_options *options){ char error_content[PCAP_ERRBUF_SIZE]; pcap_t *pcap_handle; bpf_u_int32 net_mask; //netmask bpf_u_int32 net_ip; //net ip char *net_interface; struct bpf_program bpf_filter; //bpf过滤规则 char *bpf_filter_string = options->filter; //bpf过滤规则 //net_interface = pcap_lookupdev(error_content); /*获取网络接口*/ net_interface = options->device; printf("net_interface :%s\n", net_interface); /*获取网络地址和掩码地址*/ pcap_lookupnet(net_interface,//用于监测网卡所在的网络的地址和子网掩码 &net_ip, &net_mask, error_content); /*打开网络接口*/ pcap_handle = pcap_open_live(net_interface,//该函数用于打开网卡捕获的数据报 BUFSIZ, 1, /*混杂模式*/ 0, /*等待实践*/ error_content); if (!pcap_handle) { printf("打开网络接口失败,请检查输入的网络接口是否存在,或者是否具有权限打开此网络接口。\n"); return; } /*编译并设置bpf过滤规则*/ if (pcap_compile(pcap_handle, &bpf_filter,bpf_filter_string,0,net_mask)) { printf("请检查你的输入规则是否有误。\n"); return; } pcap_setfilter(pcap_handle,&bpf_filter);//指定一个过滤程序出错时放回-1 if (pcap_datalink(pcap_handle) != DLT_EN10MB) { return; } pcap_dumper_t* out_pcap = NULL; out_pcap = pcap_dump_open(pcap_handle,options->path);//创建一个用于保存数据包的文件,打开用于写入 pcap_loop(pcap_handle,//回调函数 30 //30个数据包被读取时返回 ,ethernet_protocol_packet_callback //回调函数。开始一层层揭开 ,(u_char *)out_pcap); //pass arguments to callback pcap_close(pcap_handle);//关闭指针响应的文件,释放资源 pcap_dump_close(out_pcap);//同上 }
-
可以看到这里开始有了很多的pcap的函数和数据类型。我再网上找了一些大致的简介。
-
pcap_t
一种结构体。详细参考来自这里 -
pcap_open_live
该函数用于打开网卡捕获的数据报。 -
pcap_dump_open
创建一个用于保存数据包的文件,打开用于写入 -
pcap_lookupnet
用于监测网卡所在的网络的地址和子网掩码 -
这些我在尝试读程序的时候在注释里也写了一些,就不全列出了。
-
然后注意
ethernet_protocol_packet_callback
,开始使用回调函数。在前面我也提到,在以太网帧解析完毕之后会一层层传递,也就是这一句函数就把这个数据解释完毕了。 -
然后再看回mian函数,这个时候就应该输入
COMMAND_QUIT
的宏定义准备退出了。但是我每次都是CTRL+C
直接结束,所以没有截图。。。
二、
找一个网站或者搭建一个本地网站,登录网站,并嗅探,分析出账号和密码,结果截图1-2张。
-
由于我不会搭建网站,所以就想登录别的网站然后抓包。但是尴尬的是所有的网站都在加密,抓下来我也只能知道密文。这个让人很是头疼。
-
在同学的帮助下,我了解了POP3的服务是明文。我就下载了一个foxmail,然后在用foxmail登录的过程取消了ssl加密
-
结果
- 当然这里的不是我的密码,是pop3的授权码,我已经禁止pop3了所以没有打马赛克。
三、
抓取手机App的登录过程数据包,分析账号和密码。
- 首先,在上周的作业中有学到,现在的都是交换机,有“MAC地址-端口映射表”,很难用电脑来抓取手机的数据包,除非“洪泛攻击”、“MAC欺骗”、“ARP欺骗"三种方法。但是我一种都不会。前面也说过,最近时间属实有点紧迫,所以暂时放弃了学习这三种方法,直接用手机连接了电脑的热点。
- 这个加密就更加愁人了,启龙同学告诉我苹果的app store似乎不允许明文传输。
- 这是登录邮箱app抓下来的包
- 我不像建国一样有那么深厚的密码学功底,不可能在这个周末就解密出来明文。而我又找不到明文传输的APP,所以我只能退而求其次,采用了大家都用的TIM,至少能抓个账号的明文。
- 然后抓取数据包,这是结果:
来源:https://www.cnblogs.com/maomutang/p/12587762.html