Linux系统下手动写一个pcap包嗅探器,了解抓包原理。
首先要了解的是pcap嗅探器的总体布局。代码流程如下:
1.我们首先确定我们想要嗅探哪个接口。在Linux中,这可能类似于eth0,在BSD中它可能是xl1等。我们可以在字符串中定义此设备,或者我们可以要求pcap自己为我们提供将完成工作的接口的名称。
2.初始化pcap。这是我们实际告诉pcap我们正在嗅探的设备。如果我们愿意,我们可以嗅探多个设备。我们如何区分它们?使用文件句柄。就像打开文件进行读写一样,我们必须命名我们的嗅探“会话”,以便我们可以将其与其他此类会话区分开来。
3.如果我们只想嗅探特定的流量(例如:TCP/IP数据包,去往端口23的数据包等),我们必须创建一个规则集,“编译”并应用它。这是一个三阶段的过程,所有这些都是密切相关的。规则集保存在一个字符串中,并转换为pcap可以读取的格式(因此编译它。)编译实际上只是通过调用程序中的函数来完成的。它不涉及使用外部应用程序。然后我们告诉pcap将它应用于我们希望过滤的会话。
4.最后,我们告诉pcap进入它的主要执行循环。在这种状态下,pcap会一直等到它收到了我们想要它的数据包。每次获取新数据包时,它都会调用我们已经定义的另一个函数。它调用的函数可以做任何我们想做的事情;它可以解析数据包并将其打印给用户,它可以将其保存在文件中,或者根本不执行任何操作。
5.在满足我们的嗅探需求后,我们会结束会话并完成。
这实际上是一个非常简单的过程。共计五个步骤,其中一个是可选的(步骤3)让我们看一下每个步骤以及如何实现它们。
一.设置嗅探设备
利用pcap库,让pcap自己设置设备。其中errbuf表示若查找设备失败,则用errbuf保存错误信息。
编译
执行
二.打开设备进行嗅探
在上段代码中加入对设备嗅探的代码:
pcap_open_live()函数原型
pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms,char *ebuf)
- 此函数用于打开网络设备,返回一个pcap_t结构体的指针。
- 帮助文档中的说法是:用于获取一个数据包捕获的描述符,以便用来查看网络上的数据包。
- device是网卡名称。
- snaplen表示捕获的最大字节数,如果这个值小于被捕获的数据包的大小,则只显示前snaplen位(实验表明,后面为全是0),通常来讲数据包的大小不会超过65535。
- promisc表示是否开启混杂模式。
- to_ms表示读取的超时时间,毫秒为单位,就是说没有必要看到一个数据包这个函数就返回,而是设定一个返回时间,这个时间内可能会读取很多个数据包,然后一起返回。如果这个值为0,这个函数一直等待足够多的数据包到来。
- errbuf用于存储错误信息。
三.过滤流量
首先明确几个函数的作用:
1.pcap_compile()函数:编译程序
int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask)
pcap_t *p:会话句柄
struct bpf_program:编译版本的位置引用
char *str:表达式:字符串形式
int optimize:整数,决定表达式是否该优化(0为假,1为真)
bpf_u_int32 netmask:指定过滤器适用的网络的网络掩码。
2.pcap_setfilter()函数:应用编译后的程序
int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
pcap_t *p:会话处理程序
struct bpf_program:编译版本的位置引用
四.实际的嗅探
利用pcap_loop()函数
int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
pcap_t *p:是我们的会话句柄。
int cnt:一个整数,它告诉pcap_loop()在返回之前它应该嗅探多少个数据包(负值意味着它应该嗅探直到发生错误)。
pcap_handler callback“第三个参数是回调函数的名称(只是函数名,没有括号)。
u_char *user:最后一个参数在某些应用程序中很有用,但很多时候只是设置为NULL。
这里着重写的就是回调函数。回调函数原型:
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
pcap_pkthdr的定义为:查看pcap.h头文件方法:
首先查找文件所在位置
sudo find / -type f -name pcap.h
代码实现:
五.回调函数和输出处理
查找IP数据类型:
首先查找所在位置:
查看目录下对应的文件:
可以看到里面的一些数据结构: