一 pcap与pcapng特征简介
1.pcap:早期计算机网络抓包格式,几乎所有抓包工具都支持pcap,pcap文件的首四个字节分别是0xd4,0xc3,0xb2,0xa1,pcap文件有文件头和块组成,文件头是固定格式:
struct pcap_file_header {
uint32_t magic = 0;
uint16_t max_version = 0;
uint16_t min_version = 0;
uint32_t time_zone = 0;
uint32_t sig_flag = 0;
uint32_t snap_len = 0;
uint32_t link_type = 0;
};
块由块头信息和数据信息组成,数据长度由块头信息决定,块头信息定义如下:
struct pcap_pkt_header {
uint32_t time_sec;
uint32_t time_usec;
uint32_t cap_len;
uint32_t pkt_len;
};
2.pcapng:下一代抓包格式,支持不同路线以寻求标准化,pcapng格式通过使用标准化块和字段来实现可扩展性需求,其特性包括:支持从多个接口捕获,改进时间戳分辨率,在捕获文件插入注释,在捕获文件插入额外元数据等,其基本格式如下:
与pcap不同,pcapng文件首4个字节是0xa,0xd,0xd,0xa。
二 pcapng转pcap
pcapng转pcap方式有很多中,其中列举两种:
1.使用tcpdump:tcpdump -r XXX.pcapng -w XXX.pcap
2.使用wireshark打开pcapng文件后,点击另存为pcap文件即可。
需要注意:不是所有pcapng都可以转pcap文件。
三 libpcap离线读取pcap与pcapng文件接口
libpcap支持在线抓包,也可以使用相应API进行离线抓包:
#include <pcap/pcap.h>
char errbuf[PCAP_ERRBUF_SIZE] = ""; // PCAP_ERRBUF_SIZE为512字节
pcap_t *pcap_open_offline(const char *fname, char *errbuf); // fname可指向pcap或pcapng
pcap_t *pcap_ptr = pcap_open_offline("./xx.pcapng", errbuf);
if (!pcap_ptr) {
// 如果ptr为空,则说明抓包文件有问题,不是pcap或者pcapng
}
struct pcap_pkthdr pkthdr = { 0 };
/*struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */ // 抓包长度
bpf_u_int32 len; /* length this packet (off wire) */ // 时间包长度 caplen <= len
};*/
while (true) {
const u_char *pkt_buff = pcap_next(pcap_ptr, &pkthdr); // 循环读取文件
if (!pkt_buff) {
std::cerr << "pcapng read over." << std::endl;
break;
}
if (pkthdr.caplen > G_MAX_PCAP_BUFFER_BODY_LEN) { // 读取文件异常
std::cerr << "read pcap body error." << std::endl;
break;
}
// pkt_buff执行抓包数据 可进行相关业务处理
...
}
pcap_close(pcap_ptr); // 必须关闭句柄 不然内存泄漏
四 使用libpcap离线读取pcap与pcapng文件客户端
1.功能描述:对指定目录里的pcap和pcapng进行处理
2.代码:https://github.com/wangzhicheng2013/pcapng_file_process
五 使用tcpdump将pcapng转为pcap
tcpdump -r bans3.pcapng -w bans3.pcap