Meisha 第一部分:PCAP 包文件格式
一 基本格式:
文件头 数据包头数据报数据包头数据报......
二、文件头:
文件头结构体
sturct pcap_file_header
DWORD
DWORD
DWORD
DWORD
DWORD
DWORD
DWORD
{
}
说明:
magic;
version_major;
version_minor;
thiszone;
sigfigs;
snaplen;
linktype;
1、标识位:32 位的,这个标识位的值是 16 进制的 0xa1b2c3d4。
a 32-bit
magic number ,The magic number has the value hex a1b2c3d4.
2、主版本号:16 位, 默认值为 0x2。
a 16-bit
major version number,The major version number should
have the value 2.
3、副版本号:16 位,默认值为 0x04。
a 16-bit
minor version number,The minor version number should
have the value 4.
4、区域时间:32 位,实际上该值并未使用,因此可以将该位设置为 0。
a 32-bit
time zone offset field that actually not used, so you
can (and probably should) just make it 0;
5、精确时间戳:32 位,实际上该值并未使用,因此可以将该值设置为 0。
a 32-bit
time stamp accuracy field tha not actually used,so you
can (and probably should) just make it 0;
6、数据包最大长度:32 位,该值设置所抓获的数据包的最大长度,如果所有数据包都要抓
获,将该值设置为 65535;例如:想获取数据包的前 64 字节,可将该值设置为 64。
a 32-bit
snapshot length" field;The snapshot length field
should be the maximum number of bytes perpacket that will be captured. If the entire
packet is captured, make it 65535; if you only capture, for example, the first 64
bytes of the packet, make it 64.
7、链路层类型:32 位, 数据包的链路层包头决定了链路层的类型。
a 32-bit link layer type field.The link-layer type depends on the type of link-layer
header that the
packets in the capture file have:
以下是数据值与链路层类型的对应表
0
OpenBSD
1
多数的数据包为这种类型。
BSD
loopback devices, except for later
Ethernet, and Linux loopback devices
以太网类型,大
6
7
8
802.5 Token Ring
ARCnet
SLIP
9
10
100
101
102
103
104
105
108
order)
113
114
PPP
FDDI
LLC/SNAP-encapsulated ATM
raw IP, with no link
BSD/OS SLIP
BSD/OS PPP
Cisco HDLC
802.11
later OpenBSD loopback devices (with the AF_value in network byte
special Linux cooked capture
LocalTalk
三 packet 数据包头:
struct pcap_pkthdr
{
struct tim
ts;
DWORD
DWORD
caplen;
len;
}
struct tim
{
DWORD
GMTtime;
microTime
DWORD
}
说明:
1、时间戳,包括:
秒计时:32 位,一个 UNIX 格式的精确到秒时间值,用来记录数据包抓获的时间,记录方式
是记录从格林尼治时间的 1970 年 1 月 1 日 00:00:00 到抓包时经过的秒数;
微秒计时:32 位, 抓取数据包时的微秒值。
a time stamp, consisting of:
a UNIX-format time-in-seconds when the packet was captured, i.e. the number of
seconds since January 1,1970, 00:00:00 GMT (that GMT, *NOT* local time!);
the number of microseconds since that second when the packet was captured;
2、数据包长度:32 位 ,标识所抓获的数据包保存在 pcap 文件中的实际长度,以字节为单
位。
a 32-bit value giving the number of bytes of packet data that were captured;
3、数据包实际长度: 所抓获的数据包的真实长度,如果文件中保存不是完整的数据包,那
么这个值可能要比前面的数据包长度的值大。
a 32-bit value giving the actual length of the packet, in bytes (which may be greater
than the previous number, if you are not saving the entire packet).
四:packet 数据:
即 Packet(通常就是链路层的数据帧)具体内容,长度就是 Caplen,这个长度的后面,
就是当前 PCAP 文件中存放的下一个 Packet 数据包,也就是说:PCAP 文件里面并没有规定
捕获的 Packet 数据包之间有什么间隔字符串,下一组数据在文件中的起始位置。我们需要
靠第一个 Packet 包确定。最后,Packet 数据部分的格式其实就是标准的网路协议格式了可
以任何网络教材上找得到。
五:举例分析
图中最开始的绿色部分就是 24 Bytes 的 Pcap Header,接下来红色的 16 Bytes 是第一个消
息的 Pcap Header。后面的红色的 16 Bytes 是第二个消息的 Pcap Header。两块蓝色的部分
分别是两个消息从链路层开始的完整内容。在网络上实际传输的数据包在数据链路层上每一
个 Packet 开始都会有 7 个用于同步的字节和一个用于标识该 Packet 开始的字节,最后还会
有四个 CRC 校验字节;而 PCAP 文件中会把前 8 个字节和最后 4 个校验自己去掉,因为这些
信息对于协议分析是没有用的。
用 Wireshark 打开一个 PCAP 数据包,每条消息的所有 field 会被解析出来并会按照协议层
次折叠起来。第一层显示的是 FrameXXX,这一级别没有对应某层具体的协议,而是对本条
消息的一个概括性总结,描述了一些有用的概括性信息,比如从里面我们可以看到本条消息
各种协议的层次关系,展开其它协议层之后对应的是该协议的各个域,如下图所示:
第二部分:PCAP 文件解析
1、 pcap 解析工具 Xplico
Xplico 是一个从 pcap 文件中解析出 IP 流量数据的工具,可解析每个邮箱 (POP,
IMAP, 和 SMTP 协议), 所有 HTTP 内容, VoIP calls (SIP) 等等
2、 C 语言实现 PCAP 文件分析
实现步骤:
1)用 Wireshark 软件抓包得到 test.pcap 文件
2)程序:分析 pcap 文件头 -> 分析 pcap_pkt 头 -> 分析帧头 -> 分析 ip 头 -> 分析 tcp 头 -> 分
析 http 信息
#include
#include
#include
#include
#include
#define BUFSIZE 10240
#define STRSIZE 1024
typedef long bpf_int32;
typedef unsigned long bpf_u_int32;
typedef unsigned short u_short;
typedef unsigned long u_int32;
typedef unsigned short u_int16;
typedef unsigned char u_int8;
//pacp 文件头结构体
struct pcap_file_header
{
bpf_u_int32 magic;
u_short version_major;
u_short version_minor;
bpf_int32 thiszone;
bpf_u_int32 sigfigs;
/* 0xa1b2c3d4 */
/* magjor Version 2 */
/* magjor Version 4 */
/* gmt to local correction */
/* accuracy of timestamps */
/* max length saved portion of each pkt */
/* data link type (LINKTYPE_*) */
/* seconds 含义同 time_t 对象的值 */
/* and microseconds */
/* length this packet (off wire) */
bpf_u_int32 snaplen;
bpf_u_int32 linktype;
};
//时间戳
struct time_val
{
long tv_sec;
long tv_usec;
};
//pcap 数据包头结构体
struct pcap_pkthdr
{
struct time_val ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len;
};
//数据帧头
typedef struct FramHeader_t
{ //Pcap 捕获的数据帧头
u_int8 DstMAC[6]; //目的 MAC 地址
u_int8 SrcMAC[6]; //源 MAC 地址
u_short FrameType;
} FramHeader_t;
//IP 数据报头
typedef struct IPHeader_t
{ //IP 数据报头
u_int8 Ver_HLen;
u_int8 TOS;
u_int16 TotalLen;
u_int16 ID; //标识
u_int16 Flag_Segment;
u_int8 TTL;
u_int8 Protocol;
u_int16 Checksum;
u_int32 SrcIP; //源 IP 地址
u_int32 DstIP; //目的 IP 地址
} IPHeader_t;
//TCP 数据报头
typedef struct TCPHeader_t
{ //TCP 数据报头
u_int16 SrcPort; //源端口
u_int16 DstPort; //目的端口
u_int32 SeqNO; //序号
u_int32 AckNO; //确认号
//生存周期
//协议类型
//标志+片偏移
//帧类型
//版本+报头长度
//服务类型
//总长度
//头部校验和