My site
本文主要参考了以下资料:RaiChen的博客,WinPcap官方文档,《网络分析技术揭秘》-吕雪峰,Phinecos(洞庭散人)的博客
我们每次捕获的都是所有流经我们网络适配器的数据包,如果不进行过滤,数以万计的数据包我们是不可能一个个看完的。因此WinPcap提供了数据包过滤引擎,使用pcap_compile()和pcap_setfilter()函数来过滤数据包。
pcap_compile()是一个将高层的布尔过滤表达式编译成能够被过滤引擎所解释的底层字节码,高层的布尔过滤表达式可能像这样:”ip and tcp“,这个表达式说明我们只想保留IPv4和TCP的数据包,或者还有这样:”src 192.168.1.1 and port 20“,这样的表达式说明我们只想保留源地址为192.168.1.1并且端口号为20的数据包。更多布尔过滤表达式的资料请参阅:过滤串表达式的语法
pcap_setfilter()将一个过滤器与内核捕获会话相关联,当pcap_setfilter()被调用时, 这个过滤器将被应用到来自网络的所有数据包,并且,所有符合要求的数据包将会立即复制给应用程序。
以下代码展示了如何编译并设置过滤器。在编译过滤器之前我们必须从pcap_if结构体中获得掩码,因为一些使用pcap_compile()创建的过滤器需要它。
if (d->addresses != NULL)
/* Retrieve the mask of the first address of the interface */
netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
/* If the interface is without an address we suppose to be in a C class network */
netmask=0xffffff;
compile the filter
if (pcap_compile(adhandle, &fcode, "ip and tcp", 1, netmask) < 0)
{
fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
set the filter
if (pcap_setfilter(adhandle, &fcode) < 0)
{
fprintf(stderr,"\nError setting the filter.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
我们先通过pcap_if结构获取适配器的掩码,然后调用pcap_compile()函数,函数原型如下:
int pcap_compile ( pcap_t * p,
struct bpf_program * fp,
char * str,
int optimize,
bpf_u_int32 netmask
)
Compile好了过滤表达式之后,就要把编译好的底层字节码应用到适配器上,调用pcap_setfilter()函数,函数原型如下:
int pcap_setfilter( pcap_t * p,
struct bpf_program * fp
)
1.第一个参数和上面一个函数的一样,都是打开网络适配器后得到的捕获Session,目的就是要将编译好的底层字节码关联到这个捕获Session上。 2.第二个参数是刚才通过pcap_compile()函数编译过滤表达式得到的底层字节码。
如此便设置好了一个捕获会话的过滤条件,接下来调用捕获函数开始捕获,就可以得到过滤后的数据包了。
捕获到数据包后,我们只能得到一堆二进制数据,如果不进行分析的话是不知道数据包具体的细节的,所以接下来才是重中之重,下一篇:分析数据包