libpcap编程:Sniffer
来源:互联网 发布:淘宝网上有卖烟的吗 编辑:程序博客网 时间:2024/05/17 01:15
主要实现运用libpcap(winpcap)的api进行数据链路层的抓包操作,并一层层进行解析,解析TCP, UDP, ICMP等协议。
主要代码及解析如下:
/************************************************************************* > File Name: sniffer.c > Author: PCB > Mail: pangbin2415@gmai.com > Created Time: 2016年04月10日 星期日 20时40分52秒 ************************************************************************/ #include<stdio.h> #include<pcap.h> #include<string.h> #include<stdlib.h> #include<unistd.h> #include<signal.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<netinet/ip.h> #include<netinet/tcp.h> #include<netinet/udp.h> #include<netinet/ip_icmp.h> pcap_t* pd; int linkhdrlen; //链路层的长度 /* * device: 要连接的设备名字 * bpfstr: 要过滤的规则 * */ pcap_t* open_pcap_socket(char* device, const char* bpfstr) { char errbuf[PCAP_ERRBUF_SIZE]; //存放出错信息 pcap_t* pd; uint32_t srcip, netmask; //存放源的ip地址和子网掩码 struct bpf_program bpf; //存取bpf过滤规则的一个结构 //找到一个设备 if(!*device && !(device == pcap_lookupdev(errbuf))) { printf("pcap_lookupdev(): %s\n", errbuf); return NULL; } //打开该设备,并且等到一个包到来 if((pd = pcap_open_live(device, BUFSIZ, 1, 0, errbuf)) == NULL) { printf("pcap_open_live(): %s\n", errbuf); return NULL; } //得到设备的ip地址和ip的掩码 if(pcap_lookupnet(device, &srcip, &netmask, errbuf) < 0) { printf("pcap_lookupnet: %s\n", errbuf); return NULL; } //应用过滤规则 if(pcap_compile(pd, &bpf, (char*)bpfstr, 0, netmask)) { printf("pcap_compile(): %s\n", pcap_geterr(pd)); return NULL; } if(pcap_setfilter(pd, &bpf)<0) { printf("pcap_setfilter(): %s\n", pcap_geterr(pd)); return NULL; } //printf("Open_pcapSocket()\n"); return pd; }//end open_pcap_socket(char* device, const char* bpfstr); void capture_loop(pcap_t* pd, int packets, pcap_handler func) { int linktype; //判断数据链路层的类型 if((linktype = pcap_datalink(pd)) < 0) { printf("pcap_datalink(): %s\n", pcap_geterr(pd)); return; } switch(linktype) { case DLT_NULL://BSD回路封装;链路层协议是一个4字节的域 linkhdrlen = 4; break; case DLT_EN10MB: //以太网,链路层协议是一个14字节的域 linkhdrlen = 14; break; case DLT_SLIP: case DLT_PPP: linkhdrlen = 24; //链路层长度为24个字节 break; default: printf("Unsupport datalink (%d)\n", linktype); return; } //开始抓包 if(pcap_loop(pd, packets, func, 0) < 0) printf("pcap_loop failed: %s\n", pcap_geterr(pd)); } /* * 解析包的程序*/ void parse_packet(u_char *user, struct pcap_pkthdr* packethdr, u_char* packetptr) { struct ip* iphdr; //netinet库的ip结构 struct icmphdr* icmphdr; //icmp结构 struct tcphdr* tcphdr;//tcp结构 struct udphdr* udphdr;//udp结构 char iphdrInfo[256], srcip[256], dstip[256]; unsigned short id, seq; packetptr += linkhdrlen; //过滤掉数据链路层的数据 iphdr = (struct ip*)packetptr; strcpy(srcip, inet_ntoa(iphdr->ip_src)); strcpy(dstip, inet_ntoa(iphdr->ip_dst)); sprintf(iphdrInfo, "ID:%d TOS:0x%x, TTL:%d, Iplen:%d Dglen:%d", ntohs(iphdr->ip_id), iphdr->ip_tos, iphdr->ip_ttl, 4*iphdr->ip_hl, ntohs(iphdr->ip_len) ); //将ip的字段跳过去 packetptr += 4*iphdr->ip_hl; switch(iphdr->ip_p) { case IPPROTO_TCP: //如果是TCP协议 tcphdr = (struct tcphdr*)packetptr; printf("TCP %s:%d -> %s:%d\n", srcip, ntohs(tcphdr->source), dstip, ntohs(tcphdr->dest)); printf("%s\n", iphdrInfo); printf("%c%c%c%c%c%c Seq: 0x%x Ack: 0x%x Win: 0x%x TcpLen: %d\n", (tcphdr->urg ? 'U' : '*'), (tcphdr->ack ? 'A' : '*'), (tcphdr->psh ? 'P' : '*'), (tcphdr->rst ? 'R' : '*'), (tcphdr->syn ? 'S' : '*'), (tcphdr->fin ? 'F' : '*'), ntohl(tcphdr->seq), ntohl(tcphdr->ack_seq), ntohs(tcphdr->window), 4*tcphdr->doff ); break; case IPPROTO_UDP: //UDP协议 udphdr = (struct udphdr*) packetptr; printf("UDP %s:%d -> %s:%d\n", srcip, ntohs(udphdr->source), dstip, ntohs(udphdr->dest) ); printf("%s\n", iphdrInfo); break; case IPPROTO_ICMP: //ICMP协议 icmphdr = (struct icmphdr*)packetptr; printf("ICMP %s -> %s\n", srcip, dstip); printf("%s\n", iphdrInfo); memcpy(&id, (u_char*)icmphdr+4, 2); memcpy(&seq, (u_char*)icmphdr+6, 2); printf("Type:%d Code:%d ID:%d Seq:%d\n", icmphdr->type, icmphdr->code, ntohs(id), ntohs(seq)); break; } printf("---------------------------------------------\n\n"); } void quiteOut(int signo) { struct pcap_stat stats; if(pcap_stats(pd, &stats) >= 0) { printf("%d packets received\n", stats.ps_recv); printf("%d packtes dropped\n\n", stats.ps_drop); } pcap_close(pd); exit(0); } int main(int argc, char **argv) { char interface[256] = "", bpfstr[256] = ""; int packets = 0, c,i; while((c = getopt(argc, argv, "i:n:") ) != -1) //读取参数,当为-i时,指定接口,当为-n时,指定读取多少packets { switch(c) { case 'i': strcpy(interface, optarg); break; case 'n': packets = atoi(optarg); break; } } //获取过滤的字符串 for(i = optind; i < argc; i++) { strcat(bpfstr, argv[i]); strcat(bpfstr, " "); } //连接接口 if((pd = open_pcap_socket(interface, bpfstr))) { /*/ * 绑定中断事件给quiteOut函数*/ signal(SIGINT, quiteOut); signal(SIGTERM, quiteOut); signal(SIGQUIT, quiteOut); capture_loop(pd, packets, (pcap_handler)parse_packet); quiteOut(0); } exit(0); }
主要使用:
该程序支持监听的接口及一共要接收的数据包的大小,并且提供过滤功能,具体使用如下:
sudo ./sniffer -i eth0 tcp port 80
运行结果如下:
0 0
- libpcap编程:Sniffer
- sniffer开发工具包libpcap学习总结
- libpcap编程
- libpcap 编程二(libpcap函数库介绍)
- libpcap 编程入门资源
- libpcap编程--流量统计。。
- libpcap 编程入门资源
- libpcap编程入门资源
- libpcap编程(1)
- libpcap编程<4>
- Libpcap编程(6)
- Linux下libpcap编程流程
- QT5和libpcap混合编程
- sniffer
- sniffer
- sniffer
- sniffer
- sniffer
- Linux C程序异常退出怎么办——core文件帮你忙
- ios 导航栏透明
- 第一次写WIN32 SOCKET C/S模式聊天程序有感
- 禅与摩托车维修艺术语录摘抄(1)
- 如何配置我的php环境
- libpcap编程:Sniffer
- Oracle 11g新特性:多列统计信息(MultiColumn Statistics)
- 慢查询日志的数据结构与API
- linux偶发性崩溃的程序该怎么调试 coredump gdb
- calculate a point in triangle
- hdu1179Ollivanders: Makers of Fine Wands since 382 BC.(二分匹配)
- 使用cocoapods 中的use_frameworks! 和.h文件冲突
- Oracle 11g新特性:SQL Query Result Cache
- Android中Spinner控件关于二次点击同一item无响应事件解析及处理方法