在通过使用wireshark工具抓取主机不同网段的数据包时,把抓到的数据包保存起来会发现生成的文件是.pcap文件,此篇博客主要介绍pcap文件的格式,并利用C语言的结构体知识来初窥探数据包数据。
pcap文件格式
pcap文件数据结构如下图所示,每个pcap文件都是由Global Header、Packet Header、Packet Data三部分组成,文件的初始位置为Global Header,接着都是成对出现的Packet Header和Packet Data
文件头+ 数据包头+数据 +数据包头+数据 +数据包头+数据 +数据包头+数据+.........
结构名称 | 字节数 | 作用 |
文件头( Global Header ) | 24 | 整个数据流文件,只会有一个 Global Header,它定义了本文件的读取规则、最大储存长度限制等内容; |
数据包头( Packet Header ) | 16 | Packet Header可以有多个,每个Packet Header后面会跟着一串Packet Data,Packet Header定义了Packet Data的长度、时间戳等信息。 |
1、Global Header 结构
Global Header长度为24字节,下面的代码就是wireshark官网所给出的pcap文件的Global Header的数据结构定义,我们按照一个一个进行分析。
typedef struct pcap_hdr_s {guint32 magic_number; /* magic number */guint16 version_major; /* major version number */guint16 version_minor; /* minor version number */gint32 thiszone; /* GMT to local correction */guint32 sigfigs; /* accuracy of timestamps */guint32 snaplen; /* max length of captured packets, in octets */guint32 network; /* data link type */
} pcap_hdr_t;
- magic_number:翻译过来是魔数,表示用于检测文件格式本身和字节顺序。32bit,4字节
- version_major,version_minor:此文件格式的主次版本号。各自16bit,2字节
- thiszone:表示在格林威治标准时间(UTC)和下列包头时间戳的本地时区之间以秒为单位改正时间。举个例子,例如:如果时间戳是GMT (UTC),那么这个值就是0。如果时间戳是在中欧时间(阿姆斯特丹,柏林,…),即格林尼治标准时间+ 1点,这个区域必须是-3600。实际上,时间戳总是用GMT表示的,所以这个区域总是0。32bit,4字节
- sigfigs:从理论上讲,时间戳捕捉的准确性,一般情况下都是置0
- snaplen:捕获的“快照长度”(通常为65535或更多,但可能受到用户的限制)
- network:链路层报头类型,在包的开头指定报头的类型,这可以是各种类型的,如802.11,802.11与各种无线电信息,PPP,令牌环,FDDI等。
官方给的太过于高级,可能不方便我们使用,所以我自己重命名了几个数据类型,定义了一个类似的结构体来标识Global Header,附有相应的注释:
typedef unsigned char u_int8;
typedef unsigned short u_int16;
typedef unsigned int u_int32;
typedef unsigned long long u_int64;
//pacp文件头结构体
struct pcap_file_header
{u_int32 magic; //识别文件和字节顺序:小端/大端模式u_int16 version_major; //主版本号u_int16 version_minor; //次版本号u_int32 thiszone; //当地的标准时间u_int32 sigfigs; //时间戳精度u_int32 snaplen; //最大的存储长度u_int32 linktype; //链路类型
};
2、Packet Header
数据包头有三个属性,每个属性占固定大小,所以可以使用一个结构体表示 。下面结构体wireshark官网查找出:
typedef struct pcaprec_hdr_s {guint32 ts_sec; /* timestamp seconds */guint32 ts_usec; /* timestamp microseconds */guint32 incl_len; /* number of octets of packet saved in file */guint32 orig_len; /* actual length of packet */
} pcaprec_hdr_t;
- ts_sec:捕获此包的日期和时间。该值以秒为单位,自1970年1月1日00:00:00 GMT;这也称为UN*X time_t。32bit,4字节
- ts_usec:在常规pcap文件中,捕获此包的微秒数,作为ts_sec的偏移量,也就是在不足一秒的时间的微秒值,32bit,4字节
- incl_len:实际捕获并保存在文件中的数据包数据的字节数。这个值不应该大于orig_len或全局头文件的snaplen值。32bit,4字节
- orig_len:数据包被捕获时在网络上出现的长度。如果incl_len和orig_len不同,则实际保存的包大小受到snaplen的限制。32bit,4字节
为了方便我们通过C语言来解析.pcap文件,我重新定义了两个结构体 time_val 和 pcap_pkthdr:
//时间戳
struct time_val
{u_int32 tv_sec; //时间戳高位,精确到secondsu_int32 tv_usec; //时间戳地位,精确到microseconds
};//pcap数据包头结构体
struct pcap_pkthdr
{struct time_val ts; //捕获时间u_int32 caplen; //数据帧/区的长度u_int32 len; //离线数据长度
};
3、Packet Data
packet data就是我们打开wireshrak能够也能直观看到的数据报文,数据的数据格式也会不同。有着许许多多的报文,例如:tcp,udp,dhcp,imtp等等,这里就不一一做介绍了。