第一部分:PCAP包文件格式

一 基本格式:

文件头 数据包头数据报数据包头数据报......

二、文件头:

文件头结构体
 sturct pcap_file_header
 {
      DWORD           magic;
      DWORD           version_major;
      DWORD           version_minor;
      DWORD           thiszone;
      DWORD           sigfigs;
      DWORD           snaplen;
      DWORD           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            BSD       loopback devices, except for later OpenBSD
1            Ethernet, and Linux loopback devices   以太网类型,大多数的数据包为这种类型。
6            802.5 Token Ring
7            ARCnet
8            SLIP
9            PPP
10          FDDI
100        LLC/SNAP-encapsulated ATM
101        raw IP, with no link
102        BSD/OS SLIP
103        BSD/OS PPP
104        Cisco HDLC
105        802.11
108        later OpenBSD loopback devices (with the AF_value in network byte order)
113               special Linux cooked capture
114               LocalTalk

三 packet数据包头:

struct pcap_pkthdr
{
struct tim         ts;
      DWORD              caplen;
      DWORD              len;
}
 
struct tim
{
DWORD       GMTtime;
DWORD       microTime
}
说明:
 
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<stdio.h>

#include<string.h>

#include<stdlib.h>

#include<netinet/in.h>

#include<time.h>

#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;
      /* 0xa1b2c3d4 */

u_short version_major;
  /* magjor Version 2 */

u_short version_minor;
  /* magjor Version 4 */

bpf_int32 thiszone;
     /* gmt to local correction */

bpf_u_int32 sigfigs;
    /* accuracy of timestamps */

bpf_u_int32 snaplen;
    /* max length saved portion of each pkt */

bpf_u_int32 linktype;
   /* data link type (LINKTYPE_*) */

};

//时间戳

struct time_val

{

long tv_sec;  
      /* seconds 含义同 time_t 对象的值 */

long tv_usec;  
     /* and microseconds */

};

//pcap数据包头结构体

struct pcap_pkthdr

{

struct time_val ts;
 /* time stamp */

bpf_u_int32 caplen; /*
length of portion present */

bpf_u_int32 len;  
 /* length this packet (off wire) */

};

//数据帧头

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; //确认号

u_int8 HeaderLen; //数据报头的长度(4 bit) + 保留(4 bit)

u_int8 Flags; //标识TCP不同的控制消息

u_int16 Window; //窗口大小

u_int16 Checksum; //校验和

u_int16 UrgentPointer;
 //紧急指针

}TCPHeader_t;

//

void match_http(FILE
*fp, char *head_str, char *tail_str, char *buf, int total_len); //查找 http 信息函数

//

int main()

{

struct pcap_file_header
*file_header;

struct pcap_pkthdr
*ptk_header;

IPHeader_t *ip_header;

TCPHeader_t
*tcp_header;

FILE *fp, *output;

int   pkt_offset,
i=0;

int ip_len, http_len,
ip_proto;

int src_port, dst_port,
tcp_flags;

char buf[BUFSIZE],
my_time[STRSIZE];

char src_ip[STRSIZE],
dst_ip[STRSIZE];

char
 host[STRSIZE], uri[BUFSIZE];

//初始化

file_header = (struct
pcap_file_header *)malloc(sizeof(struct pcap_file_header));

ptk_header  =
(struct pcap_pkthdr *)malloc(sizeof(struct pcap_pkthdr));

ip_header = (IPHeader_t
*)malloc(sizeof(IPHeader_t));

tcp_header =
(TCPHeader_t *)malloc(sizeof(TCPHeader_t));

memset(buf, 0,
sizeof(buf));

//

if((fp =
fopen(“test.pcap”,”r”)) == NULL)

{

printf(“error: can not
open pcap file\n”);

exit(0);

}

if((output =
fopen(“output.txt”,”w+”)) == NULL)

{

printf(“error: can not
open output file\n”);

exit(0);

}

//开始读数据包

pkt_offset = 24; //pcap文件头结构 24个字节

while(fseek(fp,
pkt_offset, SEEK_SET) == 0) //遍历数据包

{

i++;

//pcap_pkt_header 16
byte

if(fread(ptk_header,
16, 1, fp) != 1) //读pcap数据包头结构

{

printf(“\nread end of
pcap file\n”);

break;

}

pkt_offset += 16 +
ptk_header->caplen;   //下一个数据包的偏移值

strftime(my_time,
sizeof(my_time), “%Y-%m-%d %T”, localtime(&(ptk_header->ts.tv_sec))); //获取时间

// printf(“%d: %s\n”,
i, my_time);

//数据帧头 14字节

fseek(fp, 14,
SEEK_CUR); //忽略数据帧头

//IP数据报头 20字节

if(fread(ip_header,
sizeof(IPHeader_t), 1, fp) != 1)

{

printf(“%d: can not
read ip_header\n”, i);

break;

}

inet_ntop(AF_INET,
(void *)&(ip_header->SrcIP), src_ip, 16);

inet_ntop(AF_INET,
(void *)&(ip_header->DstIP), dst_ip, 16);

ip_proto =
ip_header->Protocol;

ip_len =
ip_header->TotalLen; //IP数据报总长度

// printf(“%d:
 src=%s\n”, i, src_ip);

if(ip_proto != 0×06) //判断是否是 TCP 协议

{

continue;

}

//TCP头 20字节

if(fread(tcp_header,
sizeof(TCPHeader_t), 1, fp) != 1)

{

printf(“%d: can not
read ip_header\n”, i);

break;

}

src_port =
ntohs(tcp_header->SrcPort);

dst_port =
ntohs(tcp_header->DstPort);

tcp_flags =
tcp_header->Flags;

// printf(“%d:
 src=%x\n”, i, tcp_flags);

if(tcp_flags == 0×18)
// (PSH, ACK) 3路握手成功后

{

if(dst_port == 80) //
HTTP GET请求

{

http_len = ip_len – 40;
//http 报文长度

match_http(fp, “Host:
“, “\r\n”, host, http_len); //查找 host 值

match_http(fp, “GET “,
“HTTP”, uri, http_len); //查找 uri 值

sprintf(buf, “%d:
 %s  src=%s:%d  dst=%s:%d  %s%s\r\n”, i, my_time, src_ip,
src_port, dst_ip, dst_port, host, uri);

//printf(“%s”, buf);

if(fwrite(buf,
strlen(buf), 1, output) != 1)

{

printf(“output file can
not write”);

break;

}

}

}

} // end while

fclose(fp);

fclose(output);

return 0;

}

//查找 HTTP 信息

void match_http(FILE
*fp, char *head_str, char *tail_str, char *buf, int total_len)

{

int i;

int http_offset;

int head_len, tail_len,
val_len;

char head_tmp[STRSIZE],
tail_tmp[STRSIZE];

//初始化

memset(head_tmp, 0,
sizeof(head_tmp));

memset(tail_tmp, 0,
sizeof(tail_tmp));

head_len =
strlen(head_str);

tail_len =
strlen(tail_str);

//查找 head_str

http_offset =
ftell(fp); //记录下HTTP报文初始文件偏移

while((head_tmp[0] =
fgetc(fp)) != EOF) //逐个字节遍历

{

if((ftell(fp) –
http_offset) > total_len) //遍历完成

{

sprintf(buf, “can not
find %s \r\n”, head_str);

exit(0);

}

if(head_tmp[0] ==
*head_str) //匹配到第一个字符

{

for(i=1; i<head_len;
i++) //匹配
head_str 的其他字符

{

head_tmp[i]=fgetc(fp);

if(head_tmp[i] !=
*(head_str+i))

break;

}

if(i == head_len) //匹配 head_str 成功,停止遍历

break;

}

}

// printf(“head_tmp=%s
\n”, head_tmp);

//查找 tail_str

val_len = 0;

while((tail_tmp[0] =
fgetc(fp)) != EOF) //遍历

{

if((ftell(fp) –
http_offset) > total_len) //遍历完成

{

sprintf(buf, “can not
find %s \r\n”, tail_str);

exit(0);

}

buf[val_len++] =
tail_tmp[0]; //用buf 存储 value 直到查找到 tail_str

if(tail_tmp[0] ==
*tail_str) //匹配到第一个字符

{

for(i=1; i<tail_len;
i++) //匹配
head_str 的其他字符

{

tail_tmp[i]=fgetc(fp);

if(tail_tmp[i] !=
*(tail_str+i))

break;

}

if(i == tail_len) //匹配 head_str 成功,停止遍历

{

buf[val_len-1] = 0; //清除多余的一个字符

break;

}

}

}

// printf(“val=%s\n”,
buf);

fseek(fp, http_offset,
SEEK_SET); //将文件指针 回到初始偏移

}

libpcap文件格式分析的更多相关文章

  1. 多媒体(2):WAVE文件格式分析

    目录 多媒体(1):MCI接口编程 多媒体(2):WAVE文件格式分析 多媒体(3):基于WindowsAPI的视频捕捉卡操作 多媒体(4):JPEG图像压缩编码 多媒体(2):WAVE文件格式分析

  2. 实践2.4 ELF文件格式分析

    实践2.4 ELF文件格式分析 1.ELF文件头 查看/usr/include/elf.h文件: #define EI_NIDENT (16) typedef struct { unsigned ch ...

  3. wav文件格式分析详解

    wav文件格式分析详解 文章转载自:http://blog.csdn.net/BlueSoal/article/details/932395 一.综述    WAVE文件作为多媒体中使用的声波文件格式 ...

  4. AMR音频文件格式分析

    AMR音频文件格式分析 1 概要 如今非常多智能手机都支持多媒体功能,特别是音频和视频播放功能,而AMR文件格式是手机端普遍支持的音频文件格式.AMR,全称是:Adaptive Multi-Rate, ...

  5. PE文件格式分析

    PE文件格式分析 PE 的意思是 Portable Executable(可移植的执行体).它是 Win32环境自身所带的执行文件格式.它的一些特性继承自Unix的Coff(common object ...

  6. Linux课题实践四——ELF文件格式分析

    2.4   ELF文件格式分析 20135318 刘浩晨 ELF全称Executable and Linkable Format,可执行连接格式,ELF格式的文件用于存储Linux程序.ELF文件(目 ...

  7. linux第三次实践:ELF文件格式分析

    linux第三次实践:ELF文件格式分析 标签(空格分隔): 20135328陈都 一.概述 1.ELF全称Executable and Linkable Format,可执行连接格式,ELF格式的文 ...

  8. 20135337——linux实践三:ELF文件格式分析(32位系统)

    ELF文件格式分析 可重定位文件 十六进制形式显示内容 显示各个段.符号表相关信息 查看各个段信息 elf文件头信息 段表 符号表信息 查看堆栈 具体分析 1.ELF文件头信息(小字节优先,均十六进制 ...

  9. 20135306 2.4 ELF文件格式分析

    2.4   ELF文件格式分析 20135306 黄韧 ELF全称Executable and Linkable Format,可执行连接格式,ELF格式的文件用于存储Linux程序.ELF文件(目标 ...

随机推荐

  1. poj1556The Doors

    链接 枚举两点 若不和任何线段相交 建边为dis(i,j) floyd求最短路 #include <iostream> #include<cstdio> #include< ...

  2. 9月java货车版速记

    运算符的优先级java自带的方法正则表达式数组和二维数组:数组遍历,填充数组,数组排序,复制数组,数组查询数组算法:冒泡,选择,反转,快速类和对象:封装,继承,多态,this关键字,抽象类和接口重写和 ...

  3. POJ 2385 Apple Catching

    比起之前一直在刷的背包题,这道题可以算是最纯粹的dp了,写下简单题解. 题意是说cows在1树和2树下来回移动取苹果,有移动次数限制,问最后能拿到的最多苹果数,含有最优子结构性质,大致的状态转移也不难 ...

  4. 【spring-quartz】 定时调度,时间设置

    .   CronTrigger时间格式配置说明 CronTrigger配置格式: 格式: [秒] [分] [小时] [日] [月] [周] [年] 序号 说明 是否必填 允许填写的值 允许的通配符 1 ...

  5. C++ typedef 四个用途

    第一.四个用途 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如:char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针, ...

  6. Android_程序结构分析

    一.Android程序运行过程 二.Android项目结构  

  7. Oracle 修改一行数据内存主要变化

    向Oracle 数据库发出请求,修改一行数据,在内存中主要有以下变化: 1. 服务器进程将包含该行数据的块读取到内存中 2. 写redo日志.将内存中该数据块指向undo表空间中数据块的变更向量(Ch ...

  8. Linux技巧学习

    主要是收集一些Linux的技巧: 1.编写可靠shell脚本的八个建议 指定bash,推荐使用 /usr/bin/env bash 和 /bin/bash,不要使用/usr/bin/bash. set ...

  9. Machine Learning - 第5周(Neural Networks: Learning)

    The Neural Network is one of the most powerful learning algorithms (when a linear classifier doesn't ...

  10. java 抽象类

    抽象类: 1)函数没有方法体,就必须用abstract修饰. 2)抽象函数所在的类必须也是抽象的. 3)非抽象的类继承于抽象类,必须实现其全部方法. 4)抽象类中可以存在抽象方法,也可以不存在. 5) ...