使用libpcap分析网络报文
来源:互联网 发布:淘宝打包员好做吗 编辑:程序博客网 时间:2024/05/17 03:31
最近要对tcpdump抓到的报文进行分析,开始的时候用wireshark的命令行工具tshark把分析的结果保存成文本文件然后再用正则表达式匹配需要的字段,这样好处是不用自己分析协议,只要抓取需要的字段就行了,缺点是相当地慢,330M的tcpdump文件经过tshark处理后得到5G+的文本文件,还要从这5G+文本中做字符串匹配……
于是往下走一层,发现wireshark和tcpdump都使用了同样的库--libpcap,来实现抓包操作。对于抓包需要用到的libpcap函数并不多,主要是自己分析协议部分比较麻烦。网上找了些libpcap的资料,在这里总结一下。
简介(参考资料[1])
libpcap是一个C语言库,libpcap的英文意思是 Packet Capture library,即数据包捕获函数库,其功能是通过网卡抓取网络以太网中的数据包。这个库为不同的平台提供了一致的c函数编程接口,在安装了 libpcap 的平台上,以 libpcap 为接口写的程序、应用,能够自由地跨平台使用。它支持多种操作系统。libpcap 结构简单,使用方便;它提供了20多个api封装函数,我们利用这些api函数即可完成本网络探测器所需的网络数据包监听功能。
第一个pcap程序:
#include <stdio.h>#include <pcap.h> int main(){ pcap_t* pd; char ebuf[PCAP_ERRBUF_SIZE], *dev; const u_char* pkt; struct pcap_pkthdr ph; dev = pcap_lookupdev(ebuf); if (!dev) { fprintf(stderr, "%s\n", ebuf); return -1; } printf("get net device -> %s\n", dev); pd = pcap_open_live(dev, 65535, 0, 0, ebuf); if (!pd) { fprintf(stderr, "%s\n", ebuf); return -1; } pkt = pcap_next(pd, &ph); printf("A packet is captured.\n"); pcap_close(pd); return 0;
使用libpcap的函数要包含头文件pcap.h,编译时加上链接选项-lpcap。函数
char *pcap_lookupdev(char *errbuf);
用来获取当前机器上可用的网络接口名称,如果找到则返回名称,找不到则返回NULL,失败原因保存在errbuf中。errbuf的长度至少为PCAP_ERRBUF_SIZE。这个函数好像只查找以太网卡,并没有把我机器上的无线网卡也列出来,不知道如果有多块以太网卡的时候会怎样。
找到设备之后就可以进行监听了。函数
pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf);
如果要打开tcpdump或wireshark保存的数据文件可以使用函数
pcap_t *pcap_open_offline(const char *fname, char *errbuf);
接下来开始捕获报文。函数
const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h);
+---------------------+-------------------+-----+| struct ether_header | ip/arp/... header | ... |+---------------------+-------------------+-----+
pcap_next()会把pcap加上的信息填充到参数h指向的结构体中,并且返回指向实际数据包的指针(也就是struct ether_header的起始位置)。函数的返回时间取决于在pcap_open_live中的to_ms参数值,对于直接打开文件来说则不需要阻塞。
当pcap_next()返回后打印信息”A packet is captured.”(因为在pcap_open_live()中设置超时间隔为0,也就是说pcap_next()会一直阻塞直到有数据包到达)。
当分析完成后使用函数
void pcap_close(pcap_t *p);
另一个pcap程序:
#include <stdio.h>#include <pcap.h> static void printer(u_char* arg, const struct pcap_pkthdr* ph, const u_char* packet){ printf("A packet is captured.\n");} int main(){ pcap_t* pd; char ebuf[PCAP_ERRBUF_SIZE], *dev; dev = pcap_lookupdev(ebuf); if (!dev) { fprintf(stderr, "%s\n", ebuf); return -1; } printf("get net device -> %s\n", dev); pd = pcap_open_live(dev, 65535, 0, 0, ebuf); if (!pd) { fprintf(stderr, "%s\n", ebuf); return -1; } pcap_dispatch(pd, 0, printer, NULL); pcap_close(pd); return 0;
前面打开设备的部分与第一个程序相同,不同的是捕获的部分使用了另一个函数
int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);第一个参数user就是传递给pcap_dispatch()的最后一个参数;第二个参数是指向pcap数据包起始位置的struct pcap_pkthdr的指针(见前面的图),bytes(或者叫packet比较符合实际)指向实际的网络报文起始位置(在前面的图中就是struct ether_header的位置),其中整个报文的长度(从bytes指向的位置开始到整个报文的结束)由struct pcap_pkthdr中的caplen指定。struct pcap_pkthdr的定义为:
struct pcap_pkthdr { struct timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */};
第一个参数ts为捕获报文的时间,第三个参数len没搞明白,但是从实际输出来看和caplen的值一样。
从实际输出看到,每次捕获到一个报文都会调用回调函数printer()打印消息。
另外还有一个和pcap_dispatch()功能相似的函数
int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
这个函数在读取超时的时候不会返回,只在捕获了cnt个数据包或读取出错时才返回。
另外可以使用函数pcap_dump_open(),pcap_dump()和pcap_dump_close()把报文保存在文件中。tcpdump和wireshark保存的报文格式都遵循pcap格式,所以它们可以打开对方的数据文件,不过直接使用pcap函数保存的文件会在文件开头加上一些pcap的信息,这个文件不能直接用tcpdump或wireshark打开,要把开头的pcap内容删掉才行。
好了,目前用到的函数主要就是这些,更多函数可以参考[1]和pcap.h的内容。
参考资料
[1] libpcap函数库
[2] The Sniffer’s Guide to Raw Traffic (a libpcap tutorial)
转自 http://ouonline.net/libpcap-1
- 使用libpcap分析网络报文
- 使用wireshark分析网络报文
- 用 libpcap抓取http报文
- 利用libpcap分析网络上的数据包(入门级)
- Wireshark基本用法---分析网络协议报文
- libpcap使用
- libpcap使用
- libpcap使用
- libpcap使用
- libpcap使用
- libpcap使用
- libpcap使用
- libpcap使用
- libpcap使用
- libpcap使用
- libpcap使用
- libpcap使用
- libpcap使用
- 给大家介绍几个代码查看工具
- Java基础之容器(集合)
- UITableView循环重复显示的问题
- Java文件下载相关
- fisheye2.3.6 安装笔记
- 使用libpcap分析网络报文
- sum rule
- Flex和Java通信之Socket
- android service 介绍
- 基于axis2的WebService获取客户端请求IP地址
- 深入理解 Android Activity的生命周期
- 动态显示文章发表时间的方法
- 利用apache的HttpClient组件得到http内容
- C++中final类的实现