- 目录
Libpcap
首先明确几点: 类UNIX系统上的网络嗅探软件一般都是基于标准接口BPF和libpcap的,如tcpdump。 类UNIX平台的网络嗅探技术主要通过内核态的BPF(伯克利包过滤)和用户态的libpcap抓包工具库实现。BPF是数据链路层的一种原始接口,提供原始链路层封包的收发功能。它支持过滤封包。对封包中的数据采取算数操作,并将结果与常量或封包中的数据或结果中的测试位相比较,以此决定是否接收包。
Libpcap是类UNIX平台用户态下的抓包工具库,与BPF配合使用,为类UNIX平台上的应用程序提供标准的网络嗅探接口。
libpcap的包捕获机制就是在数据链路层加一个旁路处理。当一个数据包到达网络接口时,libpcap首先从链路层驱动程序中获得该数据包的拷贝,再将数据包发给BPF过滤器。BPF过滤器根据用户已经定义好的过滤规则对数据包进行逐一匹配,匹配成功则放入内核缓冲区,并传递给用户缓冲区,匹配失败则直接丢弃。如果没有设置过滤规则,所有数据包都将放入内核缓冲区,并传递给用户层缓冲区。
下图为个人理解
libpcap的抓包框架
函数 | 功能 |
---|---|
pcap_lookupdev() | 用于查找网络设备,返回可被pcap_open_live()函数调用的网络设备名指针。 |
pcap_open_live() | 用于打开网络设备,并且返回用于捕获网络数据包的数据包捕获描述字。对于此网络设备的操作都要基于此网络设备描述字。 |
pcap_lookupnet() | 获得指定网络设备的网络号和掩码。 |
pcap_compile() | 用于将用户制定的过滤策略编译到过滤程序中。 |
pcap_setfilter() | 用于设置过滤器。 |
pcap_loop() pcap_dispatch() pcap_next_ex() pcap_next() |
用于捕获数据包,捕获后还可以进行处理 |
pcap_close() | 用于关闭网络设备,释放资源。 |
1、设置要嗅探的设备
char *pcap_lookupdev(char *errbuf)
2、打开设备进行嗅探,创建一个嗅探会话任务
pcap_t *pcap_open_live(char *device,int snaplen,int promisc,int to_ms,char *errbuf)第一个参数为在第一步指定好的采设备,第二个参数定义被pcap捕捉的最大字节数,promisc为true时设为混杂模式,to_ms是读取时的超时值,单位为毫秒,(若该值为0则一直持续到发生错误为止)
3、过滤
int pcap_compile(pcap_t *p,strUCt bpf_program *fp,char *str,int optimize,bpf_u_int32 netmask)
第一个参数为会话句柄。第二个参数是存储被编译的过滤器版本的地址引用,第三个参数是过滤表达式,第四个参数是定义的表达式是否被优化,0表示不优化,1表示优化。最后一个参数指定应用该过滤器的网络的掩码。该函数返回1时为失败。
int pcap_setfilter(pcap_t *p,struct bpf_program * fp)第一个参数为会话句柄,第二个参数是被编译表达式的版本的引用。
#include
pcap_t *handle; /* 会话的句柄 */
char dev[] = "eth0"; /* 执行嗅探的设备 */
char errbuf[PCAP_ERRBUF_SIZE]; /* 存储错误 信息的字符串 */
struct bpf_program filter; /*已经编译好的过滤表达式*/
char filter_app[] = "port 23"; /* 过滤表达式,过滤23号端口的数据包*/
bpf_u_int32 mask; /* 执行嗅探的设备的网络掩码 */
bpf_u_int32 net; /* 执行嗅探的设备的IP地址 */
pcap_lookupnet(dev, &net, &mask, errbuf);/* 获得指定设备和网络信息 */
handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);/* 创建嗅探会话 */
pcap_compile(handle, &filter, filter_app, 0, net);/* 编译过滤规则 */
pcap_setfilter(handle, &filter);/* 设置使用定义的过滤器 */
4、开始嗅探
u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)第一个参数是会话句柄,第二个参数指向包含当前数据包总体信息的结构体的指针,该函数返回一个u_char指针给被这个结构体描述的包。
例子:
#include
#include
int main()
{
pcap_t *handle; /* 会话句柄 */
char *dev; /* 执行嗅探的设备 */
char errbuf[PCAP_ERRBUF_SIZE]; /* 存储错误信息的字符串 */
struct bpf_program filter; /* 已经编译好的过滤器 */
char filter_app[] = "port 23"; /* 过滤表达式 */
bpf_u_int32 mask; /* 所在网络的掩码 */
bpf_u_int32 net; /* 主机的IP地址 */
struct pcap_pkthdr header; /* 由pcap.h定义 */
const u_char *packet; /* 实际的包 */
/* Define the device */
dev = pcap_lookupdev(errbuf);
/* 探查设备属性 */
pcap_lookupnet(dev, &net, &mask, errbuf);
/* 以混杂模式打开会话 */
handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
/* 编译并应用过滤器 */
pcap_compile(handle, &filter, filter_app, 0, net);
pcap_setfilter(handle, &filter);
/* 截获一个包 */
packet = pcap_next(handle, &header);
/* 打印它的长度 */
printf("Jacked a packet with length of [%d]
", header.len);
/* 关闭会话 */
pcap_close(handle);
return(0);
}
一般情况下,软件中使用的函数为: int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)或者 pcap_dispatch()对于pcap_loop来说,第一个参数为为嗅探会话句柄,第二个参数表示收到多少个数据包才进行返回,第三个参数为回调函数,回调函数用于处理数据包,第四个参数一般情况下设为NULL,只有在需要用自己写的回调函数的时候才会用到。
回调函数:void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
第一个参数对应pcap_loop()中的最后一个参数,第二个参数是pcap头文件,包括了本次嗅探的数据包被嗅探的时间、大小等信息。最后一个参数是pcap_loop()本次嗅探到的所有包。
在Libpcap中,定义了诸如IP,IP,以太网帧,UDP等类型的数据包的结构,可以通过这些结构对收到的数据包的数据进行拆包。 5、关闭嗅探会话
尝试写一个简单的抓包程序
首先下载需要的库文件Libpcap,在[dcpdump官网](https://www.tcpdump.org/release/)可下,下载完成后,解压,编译,需要用到如下命令:
sudo tar -xvzf libpcap-1.9.1.tar.gz
cd libpcap-1.9.1/
sudo ./configure
sudo make
sudo make install
在别人的电脑上可以运行,在我这就段错误!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
抓取手机上的包
使用电脑的热点,手机连不上
下载了wifi共享大师,所用的本地连接14,本机无法连接,尝试过修改IP地址,使用netsh wlan set hostednetwork mode=allow ssid=testWIFI key=12345678进行启动也不管用。
尝试了更新驱动,不好使。
wireshark找不到这个接口
2、另外,出现了libcpap.so链接库找不到的情况
解决办法,找到对应的链接库,将路径放到/etc/ld.so.conf的末尾