利用libpcap抓取数据包

概述

libpcap是一个网络数据包捕获函数库,tcpdump就是以libpcap为基础的。

主要作用:

捕获各种数据包,例如:网络流量统计

过滤网络数据包,例如:过滤掉本地上的一些数据,类似防火墙

分析网络数据包,例如:分析网络协议,数据的采集

存储网络数据包,例如:保存捕获的数据以为将来进行分析

 

libpcap的抓包框架

pcap_lookupdev():函数用来查找网络设备,返回可被pcap_open_live()函数调用的网络设备名指针。

pcap_lookupnet():函数获得指定网络设备的网络号和掩码。

pcap_open_live():函数用于打开设备,并且返回用于捕获网络数据包的数据包捕获描述字。对于此网络设备的操作都要基于此网络设备描述字。

pcap_compile():函数用于将用户制定的过滤策略编译到过滤程序中

pcap_setfilter():函数用于设置过滤器

pcap_loop():pcap_next()pcap_next_ex()两个函数一样用来捕获数据包

pcap_close():函数用于关闭网络设备,释放资源

 

利用libpcap函数库开发应用程序的步骤:

打开网络设备

设置过滤规则

捕获数据

关闭网络设备

 

详细步骤:

首先要使用libpcap,需要包含pcap.h头文件。


获取网络设备接口:

char *pcap_lookupdev(char * errbuf);

功能:自动获取可用的网络设备名指针

参数:errbuf,存放出错信息字符串,有宏定义缓冲区大小,PCAP_ERRBUF_SIZE

返回值:成功返回设备名指针(第一个合适的网络接口的字符串指针),失败则返回NULL,同时,errbuf存放出错信息字符串

640?wx_fmt=png


获取网络号(ip地址)和掩码

int pcap_lookupnet(char* device,bpf_u_int32*netp,bpf_u_int32 *maskp,char *errbuf);

功能:获取指定网卡的ip地址,子网掩码

参数:device:网络设备名,为第一步获取的网络接口字符串,也可以人为指定,如“eth0”

netp:存放ip地址的指针,buf_u_int3232位无符号整型

maskp:存放子网掩码的指针

errbuf:存放出错信息

返回值:成功返回0,失败返回1

利用libpcap抓取数据包_第1张图片




打开网络接口:

pcap_t *pcap_open_live(const char *device,int snaplen,int promisc,int to_ms,char *errbuf);

功能:打开一个用于捕获数据的网络端口

参数:device:网络接口的名字,为第一步获取的网络接口字符串,也可以人为指定,如:”eth0“

 snaplen:捕获数据包的长度,不能大于65535个字节

promise”1“代表混杂模式,其他值代表非混杂模式

to_ms:指定需要等地啊的毫秒数,超过这个时间后,获得数据包的函数会立即返回,0表示一直等待直到有数据包到来

errbuf:存储错误信息

返回值:返回pcap_t类型指针,后面的所有操作都要使用这个指针。

利用libpcap抓取数据包_第2张图片


 

获取数据包:

方法一:constu_char *pcap_next(pcap_t *p,struct pcap_pkthdr *h);

功能:捕获一个网络数据包,收到一个数据包立即返回

参数:ppcap_open_live()返回的pcap_t类型的指针

         h:数据包头

pcap_pkthdr类型的定义如下:

利用libpcap抓取数据包_第3张图片


lencaplen的区别:因为在某些情况下不能保证捕获的包是完整的,例如一个包长1480,但是你捕获到1000的时候,可能因为某些原因就终止捕获了,所以caplen是记录实际捕获的包长,也就是1000,而len就是1480

返回值:成功则返回捕获数据包的地址,失败返回NULL

利用libpcap抓取数据包_第4张图片



方法二:intpcap_loop(pcap_t *p,int cnt,pcap_handler callback,u_char *user);

功能:循环捕获网络数据包,直到遇到错误或者满足退出条件,每次捕获一个数据包就会调用callback指定的回调函数,所以,可以在回调函数中进行数据包的处理操作。

参数:ppcap_open_live()返回的pcap_t类型的指针

         cnt:指定捕获数据包的个数,一旦抓到cnt个数据包,pcap_loop立即返回,如果是-1,就会一直捕获直到出错

         callback:回调函数,名字任意,根据需要自行取名

         user:向回调函数中传递的参数

callback回调函数的定义:

void callback(u_char *userarg,const structpcap_pkthdr *pkthdr,const u_char *packet)

userarg:pcap_loop()的最后一个参数,当收到足够数量的包后pcap_loop会调用callback回调函数,同时将pcap_loop()user参数传递给它

pkthdr:是收到数据包的pcap_pkthdr类型的指针,和pcap_next()第二个参数是一样的

packet:收到的数据包数据

返回值:成功返回0,失败返回负数

方法三:intpcap_dispatch(pcap_t *p,int cnt,pcap_handler callback,u_char *user);

这个函数和pcap_loop()非常类似,只是在超过to_ms毫秒后就会返回(to_mspcap_open_live()的第四个参数)

释放网络接口:

void pcap_close(pcap_t *p);

功能:关闭pcap_open_live()打开的网络接口,并释放相关资源

参数:p:需要关闭的网络接口,pcap_open_live()的返回值


利用libpcap抓取数据包_第5张图片

利用libpcap抓取数据包_第6张图片

利用libpcap抓取数据包_第7张图片

利用libpcap抓取数据包_第8张图片

利用libpcap抓取数据包_第9张图片

利用libpcap抓取数据包_第10张图片

利用libpcap抓取数据包_第11张图片

 




过滤数据包:

设置过滤条件:举一些例子:

src host 192.168.1.177:只接收源ip地址是192.168.1.177的数据包

dst port 80:只接收tcpudp的目的端口是80的数据包

not tcp:只接收不使用tcp协议的数据包

tcp[13] == 0x02 and (dst port 22 or dstport 23) :只接收 SYN 标志位置位且目标端口是 22 23 的数据包( tcp 首部开始的第 13 个字节)

icmp[icmptype] == icmp-echoreply oricmp[icmptype] == icmp-echo:只接收 icmp ping 请求和 ping 响应的数据包

ehter dst 00:e0:09:c1:0e:82:只接收以太网 mac 地址是 00:e0:09:c1:0e:82 的数据包

ip[8] == 5:只接收 ip ttl=5 的数据包(ip首部开始的第8个字节)

编译BPF过滤规则:

int pcap_compile(pcap_t *p,structbpf_program *fp,char *buf,int optimize,bpf_u_int32 mask);

参数:

ppcap_open_live()返回的pcap_t类型的指针

fp:存放编译后的bpf,应用过来规则时需要使用这个指针

buf:过滤规则

optimize:是否需要优化过滤表达式

mask:指定本地网络的网络掩码,不需要时可写0

返回值:成功返回0,失败返回-1

应用BPF过滤规则:

int pcap_setfilter(pcap_t *p,structbpf_program *fp);

功能:应用BPF过滤规则

参数:ppcap_open_live()返回的pcap_t类型的指针

        fppcap_compile()的第二个参数

返回值:成功返回0,失败返回-1




利用libpcap抓取数据包_第12张图片

利用libpcap抓取数据包_第13张图片

利用libpcap抓取数据包_第14张图片

640?wx_fmt=jpeg


你可能感兴趣的:(利用libpcap抓取数据包)