libpcap是一个抓取网络数据报文的C语言函数库,使用这个库可以非常方便的抓取网络上的报文,方便我们分析经过我们设备上的各种报文;

1.libpcap安装

下载文件:libpcap-x.x.x.tar.gz (这个是linux版本,x.x.x代表版本号)

下载地址:http://www.tcpdump.org/#latest-releases

解压(tar -zxvf)

./configure

make

sudo make install

2.使用pcap自动探测网络接口

先通过ifconfig观察一下设备情况:

然后开始编写代码,先包含头文件pcap.h,它的路径在:/usr/local/include/pcap/pcap.h 里面有每个类型定义的详细说明;

1)char * pcap_lookupdev(char * errbuf)

这个函数就是用来探测网络接口的,它会返回第一个合适的网络接口字符串指针,如果出错则在errbuf中返回,长度至少是PCAP_ERRBUF_SIZE。

pcap.cpp

#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>int main()
{char errBuf[PCAP_ERRBUF_SIZE], * devStr;devStr = pcap_lookupdev(errBuf);if (devStr)printf("success: device: %s\n", devStr);else{printf("error: %s\n", errBuf);exit(1);}return 0;
}

makefile(这里使用的C++风格,供参考):

all:pcap

pcap:pcap.o
        gcc -g -lstdc++ -lpcap -o pcap pcap.o

clean:
        rm -f pcap pcap.o

运行结果:

第一次显示"no suitable device found"是因为权限不够;用sudo执行后就显示出来了;

3.使用pcap_next捕获第一个报文

相关函数说明:

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

要捕获报文,在探测到接口之后我们还要打开它,该函数会返回指定接口的pcap_t类型指针,后面的所有操作都要使用这个指针;

参数一:device是第一步探测到的接口的字符串;

参数二:snaplen是对于每个数据包,从开头要抓多少个字节,我们可以设置这个值来只抓每个数据包的头部,而不关心具体的内容。典型的以太网帧长度是1518字节,但其他的某些协议的数据包会更长一点,但任何一个协议的一个数据包长度都必然小于65535个字节;

参数三:promisc指定是否打开混杂模式(Promiscuous Mode),0表示非混杂模式,任何其他值表示混合模式。如果要打开混杂模式,那么网卡必须也要打开混杂模式,可以使用如下的命令打开eth0混杂模式:
ifconfig eth0 promisc;

参数四:to_ms指定需要等待的毫秒数,超过这个数值后,第3步获取数据包的这几个函数就会立即返回。0表示一直等待直到有数据包到来;

参数五:用来返回错误信息;

3)void pcap_close(pcap_t * p)

释放网络接口,用于关闭pcap_open_live()获取的pcap_t的网络接口对象并释放相关资源;

4)u_char * pcap_next(pcap_t * p, struct pcap_pkthdr * h)

该函数收到一个包就立刻返回,返回值为NULL表示没有收到包;

第一个参数是第2)个函数pcap_open_live返回的指针,第二个参数记录了报文长度等,其结构也可以在pcap.h里查看到;

#include <pcap.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>int main()
{char errBuf[PCAP_ERRBUF_SIZE], * devStr;devStr = pcap_lookupdev(errBuf);if (devStr)printf("success: device: %s\n", devStr);else{printf("error: %s\n", errBuf);exit(1);}/* open a device, wait until a packet arrives */pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);if (!device){printf("error: pcap_open_live(): %s\n", errBuf);exit(1);}/* wait a packet to arrive */struct pcap_pkthdr packet;const u_char * pktStr = pcap_next(device, &packet);if (!pktStr){printf("did not capture a packet!\n");exit(1);}printf("Packet len:%d, Bytes:%d, Received time:%s\n", packet.len, packet.caplen, ctime((const time_t *)&packet.ts.tv_sec));for(int i=0; i < packet.len; ++i){printf(" %02x", pktStr[i]);if ((i + 1) % 16 == 0){printf("\n");}}printf("\n");pcap_close(device);return 0;
}

显示结果:

4.循环捕获报文

5)int pcap_loop(pcap_t * p, int cnt, pcap_handler callback, u_char * user)

第一个参数是第2)个函数pcap_open_live返回的指针,第二个参数是需要抓的数据包的个数,一旦抓到了cnt个数据包,pcap_loop立即返回。负数的cnt表示pcap_loop永远循环抓包,直到出现错误;第三个参数是一个回调函数指针,形式如下:void callback(u_char * userarg, const struct pcap_pkthdr * pkthdr, const u_char * packet) 第一个参数是pcap_loop的最后一个参数,第二个参数是收到的数据包的pcap_pkthdr结构,第三个参数是数据包数据;

6)int pcap_dispatch(pcap_t * p, int cnt, pcap_handler callback, u_char * user)

和pcap_loop()非常类似,它同时还受pcap_open_live()的第4个参数to_ms控制超时返回时间;

#include <pcap.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>void processPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{int *count = (int *)arg;printf("Packet Count: %d\n", ++(*count));printf("Received Packet Size: %d\n", pkthdr->len);printf("Payload:\n");for(int i=0; i < pkthdr->len; ++i){printf("%02x ", packet[i]);if ((i + 1) % 16 == 0){printf("\n");}}printf("\n\n");return;
}int main()
{char errBuf[PCAP_ERRBUF_SIZE], * devStr;devStr = pcap_lookupdev(errBuf);if (devStr)printf("success: device: %s\n", devStr);else{printf("error: %s\n", errBuf);exit(1);}/* open a device, wait until a packet arrives */pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);if (!device){printf("error: pcap_open_live(): %s\n", errBuf);exit(1);}int count = 0;/*Loop forever & call processPacket() for every received packet.*/pcap_loop(device, -1, processPacket, (u_char *)&count);pcap_close(device);return 0;
}

结果(一部分):

5.过滤数据包

libpcap捕获报文是把经过的报文复制一份,当接口上报文数量很大时,抓取报文非常的占用系统资源,通过过滤数据包来捕获数据包,既可以过滤掉我们不想要的报文,又可以提高效率;

设置过滤条件,就是过滤表达式;

举例:

src host 192.168.1.177,dst port 80,not tcp等;

7)int pcap_compile(pcap_t * p, struct bpf_program * fp, char * str, int optimize, bpf_u_int32 netmask)

fp是一个传出参数,存放编译后的bpf,str是过滤表达式,optimize是否需要优化过滤表达式,metmask简单设置为0即可;

8)int pcap_setfilter(pcap_t * p,  struct bpf_program * fp)

fp就是前一步pcap_compile()的第二个参数;

#include <pcap.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>void processPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{int *count = (int *)arg;printf("Packet Count: %d\n", ++(*count));printf("Received Packet Size: %d\n", pkthdr->len);printf("Payload:\n");for(int i=0; i < pkthdr->len; ++i){printf("%02x ", packet[i]);if ((i + 1) % 16 == 0){printf("\n");}}printf("\n\n");return;
}int main()
{char errBuf[PCAP_ERRBUF_SIZE], * devStr;devStr = pcap_lookupdev(errBuf);if (devStr)printf("success: device: %s\n", devStr);else{printf("error: %s\n", errBuf);exit(1);}/* open a device, wait until a packet arrives */pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);if (!device){printf("error: pcap_open_live(): %s\n", errBuf);exit(1);}/* construct a filter */struct bpf_program filter;pcap_compile(device, &filter, "tcp", 1, 0);pcap_setfilter(device, &filter);int count = 0;/*Loop forever & call processPacket() for every received packet.*/pcap_loop(device, 30, processPacket, (u_char *)&count);pcap_close(device);return 0;
}

6.把数据包保存到文件

捕获到数据包之后,通常就是对数据包的分析,具体的报文分析方法要依据网络协议详细分类并展开处理,这里不做讨论。我们可以暂时把捕获到的数据包保存到文件中,稍后再由分析报文的程序或者工具来具体分析;libpcap库提供了保存为pcap类型的函数,非常方便,保存之后就可以用Wireshark直接打开了,如果想保存为纯粹的数据包,我们也可以用C语言的文件操作,直接把数据包以二进制的形式保存到文件中;

9)pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *file)

函数返回pcap_dumper_t类型的指针,file是文件名,可以是绝对路径,例如:/home/iona/packet.pcap;

10)void   pcap_dump_close(pcap_dumper_t *p);

用来关闭pcap_dump_open打开的文件,入参是pcap_dump_open返回的指针;

11)int  pcap_dump_flush(pcap_dumper_t *p)

刷新缓冲区,把捕获的数据包从缓冲区真正拷贝到文件;

12)void   pcap_dump(u_char * userarg, const struct pcap_pkthdr * pkthdr, const u_char * packet)

输出数据到文件,与pcap_loop的第二个参数回调函数void callback(u_char * userarg, const struct pcap_pkthdr * pkthdr, const u_char * packet) 形式完全相同,可以直接当pcap_loop的第二个参数;

#include <pcap.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>void processPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{pcap_dump(arg, pkthdr, packet);printf("Received Packet Size: %d\n", pkthdr->len);return;
}int main()
{char errBuf[PCAP_ERRBUF_SIZE], * devStr;devStr = pcap_lookupdev(errBuf);if (devStr)printf("success: device: %s\n", devStr);else{printf("error: %s\n", errBuf);exit(1);}/* open a device, wait until a packet arrives */pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);if (!device){printf("error: pcap_open_live(): %s\n", errBuf);exit(1);}/*open pcap write output file*/pcap_dumper_t* out_pcap;out_pcap  = pcap_dump_open(device,"pack.pcap");/*Loop forever & call processPacket() for every received packet.*/pcap_loop(device, 20, processPacket, (u_char *)out_pcap);/*flush buff*/pcap_dump_flush(out_pcap);pcap_dump_close(out_pcap);pcap_close(device);return 0;
}

抓包结果:

把数据包保存为二进制文件与保存为pcap文件很相似,只要把pcap_dump相关操作换成FILE相关操作就可以了,和libpcap库函数没什么关系,就不再描述了(上传的代码中有示例);

相关的资料和代码都传上来了:

https://download.csdn.net/download/lvjian_/11022128

Linux下使用libpcap进行网络抓包并保存到文件相关推荐

  1. linux 抓包生成文件,Linux下使用libpcap进行网络抓包并保存到文件(函数介绍)

    libpcap是一个抓取网络数据报文的C语言函数库,使用这个库可以非常方便的抓取网络上的报文,方便我们分析经过我们设备上的各种报文: 使用libcap库编译时都要在后面加上-lpcap选项 使用pca ...

  2. linux 网卡包存储,Linux下使用libpcap进行网络抓包并保存到文件-Go语言中文社区

    libpcap是一个抓取网络数据报文的C语言函数库,使用这个库可以非常方便的抓取网络上的报文,方便我们分析经过我们设备上的各种报文: 1.libpcap安装 下载文件:libpcap-x.x.x.ta ...

  3. Linux系统抓包回放,Linux下24小时持续网络抓包(TCPDUMP)

    适用于CentOS/REHL/Ubuntu/Debian等,抓出来的包可用Wireshark直接打开分析. 参考文章: 原文的脚本相互调用时,名称有些问题,已修改 1.安装tcpdump 执行(Ubu ...

  4. 【学习点滴】linux调试工具、cmake和网络抓包

    目录 gdb 多进程调试 多线程调试: gdb底层原理 Linux下查看服务器端的并发连接个数: Valgrind memcheck strace Linux下,绑定1024以下的端口需要root权限 ...

  5. linux下如何使用 tcpdump 进行抓包详细教程

    今天要给大家介绍的一个 Unix 下的一个 网络数据采集分析工具,也就是我们常说的抓包工具. 与它功能类似的工具有 wireshark ,不同的是,wireshark 有图形化界面,而 tcpdump ...

  6. ubuntu下常用的抓包软件_告诉你Ubuntu下使用wireshark进行网络抓包的方法及命令

    接下来是在Ubuntu中进行网络抓包的教程. 1.安装wireshark 终端运行:sudo apt-get install wireshark 2.修改init.lua 直接运行wireshark的 ...

  7. linux下如何对某个端口抓包

    tcpdump -i any port 1111 -s 0 -w 0901.pcap 参数简介: -i :指定tcpdump需要监听的接口.若未指定该选项,将从系统接口列表中搜寻编号最小的已配置好的接 ...

  8. 关于Linux 网络抓包的一些笔记整理

    写在前面 遇到一个 ping 单通 的情况,需要抓包分析下,所以整理这部分笔记 博文内容涉及: HTTP/TCP 抓包分析 Demo ICMP 抓包分析 Demo Nginx 抓包分析用户名密码 De ...

  9. 基于原始套接字(raw socket)的网络抓包工具

    基于raw socket的网络抓包工具 1. 原始套接字(raw socket)简介 原始套接字可以接收本机网卡上的数据帧或者数据包,利用raw socket可以编写基于IP协议的程序.一般的TCP/ ...

最新文章

  1. webbrowser载入地图网页出现脚本错误解决
  2. linux添加审计账户_Linux下利用psacct审计系统帐号连接时间, 用户操作
  3. Codeforce 1255 Round #601 (Div. 2) A. Changing Volume (贪心)
  4. Class的 getSuperclass与getGenericSuperclass区别
  5. 循序渐进PYTHON3(十三) --8-- DJANGO之ADMIN
  6. linux ntp时间立即同步命令_记一次生产环境部署NTP服务及配置时间同步
  7. element 动态加载下拉框_动态增加select框(elementUI 框架)
  8. RectTransformUtility.ScreenPointToWorldPointInRectangle使用说明
  9. 零代码实现接口自动化测试-RF框架实践
  10. matlab 工具箱 comsol 联,基于MATLAB与COMSOL联合仿真的电磁优化设计
  11. PS 2021插件nik collection 闪退怎么办,Nik Collection崩溃闪退解决方法
  12. 织梦CMS插件-支持dedeCMS各大主题
  13. 点餐APP 冲刺三总结
  14. 中国互联网公司赚钱能力排行榜
  15. leecode [保持城市天际线]代码实现
  16. 图片怎么转文字?掌握这个实用方法,一键搞定
  17. win10杀毒软件Win Defender设置白名单
  18. Tekton系列之实践篇-使用Tekton Trigger让Tekton使用更简单
  19. 一个字节中的1的个数
  20. 比脸软件测试自学,【AI测试学习】FakeApp, Faceswap, DeepFaceLab等Deepfakes换脸程序的简单对比 (转)...

热门文章

  1. 时序电路——DFF再理解
  2. 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java高校会议室管理系统w169g
  3. php 数组转二进制,php转16进制_php 十六进制转化为二进制的代码
  4. 关于称重系统,你知道这六点吗?
  5. 知识付费项目怎么做?具体操作方法详解!
  6. 【每日早报】2019/08/01
  7. 微信app服务端php,微信APP支付服务端PHP完整代码
  8. 我的世界服务器无限凋零,我的世界:无法被完全隐形的六种生物,凋零:能不能给点面子?...
  9. Java I/O系统
  10. “华为天才少年”自制 B 站百大 Up 主奖杯