基于Libpcap/Winpcap网络监听与过滤

基于Libpcap/Winpcap网络监听与过滤
3.1 Libpcap/Winpcap简介
Libcap(Winpcap是其windows版本)可以提供与平台无关的接口,而且操作简单,它是基于改进的BPF(Berkeley Packet Filter),该软件来自Berkeley的Lawrence National Laboratory研究院.Winpcap是Libpcap 的windows版本,linux用户使用Libpcap,Windows用户使用Winpcap. 使用Winpcap包过程比较规范.在密码学协议分析中,我们常用它来实现协议攻击.
3.2 Libpcap源代码逻辑结构
(1)初始化:这部分的功能包括打开设备、读取设备,设置过滤器部分.主要的函数如下:pcap_read(),pcap_open_live(),pcap_setfilter().在源代码中是以pcap-*.c方式出现;
(2)过滤规则表达式的处理:这部分的功能包括对过滤规则表达式进行编译、优化、调试(该部分过滤机制采用的是伪主机技术),如果各熟悉BPF程序的编码规则,甚至可以修改其中代码,创建自己的过滤规则.这部分代码在:gencode.c,grammar.c,scanner.c,optimize.c,这一部分代码的工作方式是通过将我们输入的过滤规则表达式编译成BPF代码,然后存在一个名为bpf_program的结构中,最后利用pcap_setfilter()来加载;
(3)本机网络设置部分:这部分是通过获取socket的状态,来检测TCP/IP层网络设置.主要函数有:pcap_lookupdev()、pcap_lookupnet()等,这部分代码在inet.c中;
(4)其他部分:在pcap.c中定义了读数据的对外统一接口pcap_next()来获取下一个数据包,获取当前错误信息的pcap_geterr()等函数.另外,Libcap还支持脱机方式监听,在savefile.c中,有两个函数:pcap_open_offline()和pcap_offline_read().
3.2基于Libcap/Winpcap库的基本使用流程
基于Libcap/Winpcap库的基本使用流程比较规范,一般为: 
step1: 使用pcap_lookupdev获取设备;
step2: 使用pcap_lookupnet获取网络地址和子网掩码;
step3: 使用pcap_open_live打开设备;
step4: 使用pcap_complile编译过滤规则;
step5: 使用pcap_setfilter设置过滤规则;
step6: 使用pcap_loop循环捕获数据包,在其中调用相应处理函数;
step7: 使用pcap_close关闭设备句柄.
3.3一些使用难点和关键代码说明
(1) 获得本地的网卡列表
pcap_if_t *alldevs; //用于存储网卡信息
char errbuf[PCAP_ERRBUF_SIZE];// 用于存储错误信息
if (pcap_findalldevs(&alldevs, errbuf) == -1) // 这个API用来获得本机网卡列表 
{
fprintf(stderr,"Error in pcap_findalldevs: %s/n", errbuf);
exit(1);
}

pcap_freealldevs(alldevs);//最后用pcap_freealldevs()释放内存资源
(2) 接受数据包
使用循环调用pcap_next来接受数据报,当然也可以用pcap_next_ex来接受数据包,不过pcap_next_ex效率会高些.
pcap_t *adhandle;
int res;
struct pcap_pkthdr *header;
u_char *pkt_data

while((res = pcap_next_ex( adhandle, &header, &pkt_data)) >= 0){ }

(3) 数据包过滤
数据包过滤处理是监听技术中的难点和重点.我们用pcap_compile()来编译一个过滤设备,它通过一个高层的boolean型变量和字串产生一系列的能够被底层驱动所解释的二进制编码.boolean表示语法能够在这个文件的过滤表示语法中找到.pcap_setfilter() 用来联系一个在内核驱动上过滤的过滤器,这时所有网络数据包都将流经过滤器,并拷贝到应用程序中.下面的代码展示了如何编译并社定一个过滤设备.注意我们必须从pcap_if结构中获得掩码,因为一些过滤器的创建需要这个参数.下面的代码段中的pcap_compile()的"ip and tcp"参数说明只有IPV4和TCP数据才会被内核保存并被传递到应用程序.

if(d->addresses != NULL)
// 获得第一个接口地址的掩码 
netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
//如果这个接口没有地址那么我们假设他为C类地址 
netmask=0xffffff; 
//编译过滤规则
if(pcap_compile(adhandle, &fcode, "ip and tcp", 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");

(4)与脱机方式监听相关操作
有些时候我们想使用脱机方式以便进一步深入研究.Winpcap为我们提供了很多API函数来处理脱机器监听.通过Winpcap,我们可以将流经网络的数据包保存到一个堆文件,以后也可以读取堆的内容.详细过程和完整示例代码请参考[6].
将数据包保存到文件的过程如下:打开网卡后,调用pcap_dump_open()来打开一个文件,将文件和某个网卡相关联.在自己的包处理函数packet_handler()内部通过调用pcap_dump()来将捕获的数据报存储到文件.
从文件读数据包的过程如下:利用pcap_open_offline()用来打开一个堆文件,之后用pcap_loop()来循环从文件中读取数据. Winpcap的最新版本提供了一个新的方法来将数据包存储到磁盘,就是使用pcap_live_dump()函数.他需要三个参数:一个参数文件名、一个参数是该文件允许的最大长度、一个参数是该文件所允许的最大包的数量.对这些参数来说, 0意味着没有最大限制.但是实际上我们可以在调用pcap_live_dump()前设置一个过滤器来定义哪些数据包需要进行存储.pcap_live_dump() 是运行在非阻塞模式的,所以他会立刻返回:数据的存储过程将会异步的进行,直到文件到达了指定的最大长度或最大数据报的数目为止.应用程序能够用pcap_live_dump_ended()来等检查是否数据存储完毕,如果你指定的最大长度参数和数据报数量为0,那么该操作将永远阻塞.pcap_live_dump() 和 pcap_dump()的不同在于性能,pcap_live_dump()采用Winpcap NPF驱动来从内核级的层次上向文件中写数据,从而使内存拷贝最小化.显然,这些特点在其他的操作系统下是不能够实现的,pcap_live_dump()是Winpcap所特有的,而且只能够应用于Win32环境.

4、总结
Libcap/Winpcap库函数的使用简化了我们的工作,使得我们在网络监听与包过滤技术的研究主要集中在过滤规则的设置和对数据包的分析上,为我们的研究提供了大大的方便.[6]中给出了Libcap/Winpcap库函数在IPV6下的许多新特性.另外,在网络协议分析攻击的真正实现和IDS实现上, Libcap/Winpcap库函数提供了巨大的帮助,使得我们可以把主要的精力放在原理方案设计上,而不需要关注底层的细节.在IPV6下的对网络监听的技术研究是目前的一个热点话题,我们将继续关注,进一步深入研究.

你可能感兴趣的:(基于Libpcap/Winpcap网络监听与过滤)