pcap文件的python解析实例

article/2025/9/24 4:21:26
最近一直在分析数据包。
同时也一直想学python。

凑一块儿了...于是,便开工了。座椅爆炸!

正文

首先要说的是,我知道python有很多解析pcap文件的库,这里不使用它们的原因是为了理解pcap文件的格式细节。使用tcpdump你可以很容易抓取到一系列的数据包,然而tcpdump并没有分析数据包的功能,如果想从这个抓包文件中分析出一些端倪,比如重传情况,你必须使用wireshark之类的软件,用wireshark打开tcpdump抓取的pcap文件,如果你看到了一堆堆的深红色(类似静脉血管里流出的猪血的颜色)的数据包,那么这些包一定是“在协议层看来”异常的数据包,包括但不限于重传,乱序等等,欲知详情,请在wireshark的过滤器中敲进去“tcp.analysis.”然后就会自动补全,这一切简直方便到极点。如果你还想看一些全局的统计数据,那么请点击”统计“菜单的第一个”捕获文件属性“,你会看到更多的信息。虽然数据包早就已经过去,但是雁过留声,我们通过抓取的数据包,还是可以得到更多的信息,多谢有wireshark/tshark(一个字符界面的pcap文件分析工具,类似wireshark,但更适合玩机械键盘的命令行粉们使用)/shookshark(...)这些工具,使得我们真实能够分析pcap文件以获取信息。
        然而,这些我觉得还不够。
        有一个简单的需求,我想得到在一个TCP连接中,一个端节点一共发送了多少字节的TCP载荷数据,包括正常发送以及重传。我没有在wireshark中找到得到这个数据的功能,于是我迫不及待自己写一个。厨师还怕没肉吃吗?
        但有个前提,那就是我必须搞明白pcap文件的格式,因为我想裸分析pcap文件,试图找出每一个感兴趣数据包的TCP载荷(不包括TCP头和IP头)长度,然后将其累加。这样我必须知道pcap文件的格式细节才行。
        幸运的是,pcap文件非常简单,就像我几乎10年前分析Windows PE文件一样,如今依然循着老路做着同样的事情。
        如果你不善于查文档,那么作为一个编程者,看libpcap的源码也是个不错的选择,几乎和任何文件格式一样,pcap也是一个自描述的格式(这个自描述设计的不够优雅,以至于后来出现了pcapng文件格式,后面我会写一篇文章单独论述之),整体包括文件头和数据载荷,这里所谓的数据载荷就是网络数据包。在libpcap的pcap.h文件中,结构体pcap_file_header描述了文件头:
struct pcap_file_header {bpf_u_int32 magic;u_short version_major;u_short version_minor;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 pcap_pkthdr {struct timeval ts;    /* time stamp */bpf_u_int32 caplen;    /* length of portion present 由于tcpdump可以设置-s参数指定抓取的长度,这个字段表示实际抓取的数据包长度 */bpf_u_int32 len;    /* length this packet (off wire) 这个字段表示数据包的自然长度 */
};

这个结构体描述了数据包抓取的时间信息以及长度信息,在这个结构之后才会是数据包,因此一个典型的pcap文件应该是如下所示:




这简直清晰至极啊,再次看我的那个需求,我想统计的两个量怎么得到呢?

一个TCP连接实际发送的字节数:每一个数据包的TCP载荷长度的加和。
一个TCP理论上应该发送的字节数:结束的TCP序列号与初始序列号之差。
有了上面的论述,我觉得这个需求超级简单就实现了,为了展示一下学习python的出血效果,给出以下的代码:
	#!/usr/bin/pythonimport sysimport socketimport structfilename = sys.argv[0]filename = sys.argv[1]ipaddr = sys.argv[2]direction = sys.argv[3]packed = socket.inet_aton(ipaddr)ip32 = struct.unpack("!L", packed)[0]file = open(filename, "rb") pcaphdrlen = 24pkthdrlen=16pkthdrlen1=14iphdrlen=20tcphdrlen=20stdtcp = 20total = 0pos = 0start_seq = 0end_seq = 0cnt = 0# Read 24-bytes pcap headerdata = file.read(pcaphdrlen)(tag, maj, min, tzone, ts, ppsize, lt) = struct.unpack("=L2p2pLLLL", data)# 具体的LinkType细节,请看:# http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html#appendixBlockCodesif lt == 0x71:pkthdrlen1 = 16else:pkthdrlen1 = 14ipcmp = 0# Read 16-bytes packet headerdata = file.read(pkthdrlen)while data:(sec, microsec, iplensave, origlen) = struct.unpack("=LLLL", data)# read linklink = file.read(pkthdrlen1)# read IP headerdata = file.read(iphdrlen)(vl, tos, tot_len, id, frag_off, ttl, protocol, check, saddr, daddr) = struct.unpack(">ssHHHssHLL", data)iphdrlen = ord(vl) & 0x0F iphdrlen *= 4# read TCP standard headertcpdata = file.read(stdtcp)	(sport, dport, seq, ack_seq, pad1, win, check, urgp) = struct.unpack(">HHLLHHHH", tcpdata)tcphdrlen = pad1 & 0xF000tcphdrlen = tcphdrlen >> 12tcphdrlen = tcphdrlen*4if direction == 'out':ipcmp = saddrelse:ipcmp = daddrif ipcmp == ip32:cnt += 1total += tot_lentotal -= iphdrlen + tcphdrlenif start_seq == 0:  # BUG?start_seq = seqend_seq = seq# skip dataskip = file.read(iplensave-pkthdrlen1-iphdrlen-stdtcp)# read next packetpos += 1data = file.read(pkthdrlen)# 打印出实际传输的字节数,以及本应该传输的字节数print pos, cnt, 'Actual:'+str(total),  'ideal:'+str(end_seq-start_seq)

很简单吧!懂python的人都会嘲笑我!
        其实,在我看pcap文件格式之前,我曾经一直以为pcap文件是由类似ASN.1组织的,但是看了以后却发现不是,也是挺失望的。我之所以失望是因为,看起来以上描述的这种pcap不能描述除了数据包之外的更多东西,它事实上并不是自描述的,它是一种固定长度格式的文件结构,虽然处理起来很快,但是却十分不灵活不易扩展!彻底的自描述结构就是ASN.1!
......
我们来看一个例子。随便抓一个TCP包获得test.pcap文件,用UE打开这个pcap,请自行脑补!如果你真的理解了pcap的文件组织形式,那么请认真分析,如果不,请理解透彻而不要脑补!


执行python脚本pcap-parser.py,我们一无所获,因为这只是包含一个纯ACK包的pcap,没有携带任何数据,而python脚本旨在得到TCP数据流实际传输的数据量,因此我们不得不抓取一个携带TCP流量的pcap文件,而这非常简单。
        两台虚拟机A,B互联,A启动httpd,B上执行wget下载一个文件,同时设置丢包率以获得额外的重传数据量。执行:
pcap-parser.py ./testTCP.pcap 192.168.44.129 out
我们得到了以下结果:
...请自行执行获取
肉眼计算后发现结果是一致的,我认为这个脚本可用了。然而...
        然而当我用我写的python脚本去分析一个tshark抓取的数据包的时候,发现解析错了,这个时候魔术字就起作用了,我用UE残忍地打开了这个pcap文件,结果呢?

魔术字都是错的!于是上wireshark网站,知道了这是一个pcapng这个文件格式,同时,也知道了pcapng不能向下兼容。这是令人悲伤的一件事,但是幸运的是,pcapng文件格式要比pcap简单的多,而且,它基本就是类似ASN.1的组织办法。

       我们发现pcap的文件格式中,大部分的元描述结构都是固定数量且定长的,以LinkType为例,一次抓包我只能指定一个LinkType,它被记录在pcap文件开始的pcap_file_header中,这意味着,我无法同时在以太网卡和非以太的PPP网卡上抓包并同时得到详细的链路层信息!而pcapng解决了这个问题。

        欲知pcapng如何,且看下篇文字。


附录

细节1:Cooked Capture与Ethernet

如果说使用tcpdump -i any参数,我们不会看到标准的以太头信息,我们看到的是Cooked Capture,而不是Ethernet!关键的是,Cooked Capture描述的元信息长度是16字节而不是Ethernet的14字节。以下是Cooked Capture的头示例:



这个信息可以通过LinkType来获取。为什么会有这种Cooked Capture类型的数据包?因为抓包工具在-i any的情况下,无法用一种统一的方式来处理链路层的长度,比如很多协议,内部又区分了很多的子协议,其协议头的长度根据应用层而定,这是内核在抓包层面所处理不了的。pcap文件中,只能在一处指定LinkType,那就是文件头之后的pcap_pkthdr,如果说我指定-i eth0 -i lo -i ppp0 -i tun0,那就彻底没辙了!幸运的是,如果使用pcapng格式来存储抓包文件,那就可以针对这些网卡区别对待了,每一个网卡抓到的包都会关到一个LinkType,你会更轻松处理链路层,不过,大多数人不在乎链路层,也不在乎IP,更多人在乎的是TCP。

细节2:时钟跳变

作为一个pcap文件写的练习,这里有一个关于时钟跳变现象重现的例子。
        我们抓包发现了一个奇怪的现象,那就是从客户端抓包上看,中间间隔了几十秒没有收到任何数据,在服务端抓包看来一切正常,总共的数据传输时间也就十几秒,这是怎么回事呢?
        当即判断是客户端抓包时发生了时钟的跳变,比如时钟突然后跳了40秒,为了重现这个现象,我拿一个真实的普通正常的TCP下载为例,在收发第900个数据包的时候以及以后,数据包描述头里的时间戳字段统一加上40秒,看看是什么效果...代码非常简单:
       if pos > 900:data = struct.pack("=LLLL", sec+40, microsec, iplensave, origlen)file_out.write(data)
然后就重现了这个现象:




http://chatgpt.dhexx.cn/article/URn4BYp0.shtml

相关文章

CapAnalysis Pcap分析工具

CapAnalysis Pcap分析工具: CapAnalysis 对 PCAP 文件的数据集进行索引并以多种形式呈现它们的内容,从 TCP、UDP 或 ESP 流/流列表开始,传递到连接的地理表示。对于由一个或多个 PCAP 文件组成的每个数据集,CapAnalysis 收集数据…

wirehark数据分析与取证misc1.pcap

什么是wireshark? wiresharekwireshark--misc1.pcap数据包 wiresharek Wireshark(前称Ethereal)是一个网络封包分析软件。网络封包分析软件的功能是检索取网络封包,并同时显示出最详细的网络封包数据。Wireshark使用WinPCAP作为接…

.pcapng文件格式和.pcap文件格式

原网页 本文为机翻后人工修饰了一些,总结一句话就是 .pcapng是.pcap的升级版 pcap捕获文件格式自计算机网络早期以来一直是通用的包捕获格式。 几乎所有捕获工具都支持pcap格式。 虽然供应商多年来已经创建了新的格式,但大多数工具支持转换为pcap格式。 …

Java之Pcap文件解析(一:Pcap格式分析)

前言 需求 本系列文章主要完成以下功能: 1. 对Pcap文件进行解析,并从中提取TCP和UDP会话 2. 从TCP会话中提取出其数据负载信息 软件最终结果 [主界面] [File 菜单] [Help 的 About 菜单项,版权声明] [选择Pcap文件] [选择输…

wirehark数据分析与取证0051.pcap

什么是wireshark? wiresharekwireshark0051.pcap数据包数据包下载 请私信博主 wiresharek Wireshark(前称Ethereal)是一个网络封包分析软件。网络封包分析软件的功能是检索取网络封包,并同时显示出最详细的网络封包数据。Wiresha…

C++ 缺少winpcap头文件 pcap.h 解决方案

最近在做课设的时候看到一个代码用到了winpcap的一个头文件 pcap.h ,为了能让代码跑起来也是找了很多资料,因此在这里汇总一下。 在官网下载开发包,我下载的是 WinPcap 4.1.2 Developer’s Pack 的版本,下载后解压缩,并…

PACP学习笔记一:使用 PCAP 编程

pcap代码流程 我们首先确定要嗅探哪个接口。在 Linux 中这可能是 eth0,在 BSD 中可能是 xl1,等等。我们可以在字符串中定义这个设备,或者我们可以让 pcap 为我们提供一个接口的名称来完成这项工作。初始化pcap。这其实是实际告诉pcap我们正在…

pcap(cap)包文件解析

https://blog.csdn.net/m0_37710388/article/details/89217421 pcap文件是常用的数据报存储格式,可以理解为就是一种文件格式,只不过里面的数据是按照特定格式存储的,所以我们想要解析里面的数据,也必须按照一定的格式。普通的记事…

pcap1

一、前言 本题方向为Misc——GFSJ0963,难度偏简单 来源地址:攻防世界(https://adworld.xctf.org.cn/challenges/list) 链接:https://pan.baidu.com/s/1VWT0rDY5P2qvOp_GMCZwkQ 提取码:lyyy 二、解题过程 思…

pcap文件解析

pcap文件解析 1. pcap简介: pcap文件是一种常用的数据报存储文件,这种文件可以保存我们所抓到的报文。它有这固定的存储格式,通过notepad中的插件Hex-Editor我们可以观察其中的16进制数据,从而来进行pcap文件的分析。 2. Pcap文…

pcap详解

一、pcap文件格式 一共三部分: ①Global Header:文件头(共24bytes),它定义了本文件的读取规则、最大储存长度限制等内容。 Magic:4Byte:标记文件开始,并用来识别文件自己和字节顺序。0xa1b2c3d…

pcap文件分析

pcap文件解析 pcap文件解析1、 .pcap文件本质2、wireshark查看pcap文件格式文件头数据包头Packet 3、snaplen参数个人理解:tcpdump官网定义:tcpdump源码: pcap文件解析 学了一点.pcap文件的东西,赶紧记录下 1、 .pcap文件本质 …

pcap包解析

pcap包解析 在接触激光雷达的时候,不可避免的第一步就是看硬件说明书以及调试厂商发的样例数据。一般情况下,厂商在存储硬件的数据包的时候,都是通过存储pcap包实现的,所以如何读取pcap包,并从中解析出真正有用的数据…

PCAP(packet capture)格式

PCAP(packet capture)格式 文章目录 PCAP(packet capture)格式定义pcap文件的格式文件头24 Bytes 各字段的含义:常用链路类型 实际pcap文件的文件头Packet Data 综述wireshark添加 lua plugins解析pcap脚本存放位置sud…

Pcap文件详解

Pcap文件详解 一、简介 pcap文件是常用的数据报存储格式,可以理解为就是一种文件格式,只不过里面的数据是按照特定格式存储的,所以我们想要解析里面的数据,也必须按照一定的格式。 普通的记事本打开pcap文件显示的是乱码&#…

Pcap 数据包捕获格式详解

Pcap 是 Packet Capture 的英文缩写,是一种行业标准的网络数据包捕获格式。如果你是网络开发人员,那么通常会使用 Wireshark、Tcpdump 或 WinDump 等网络分析器捕获 TCP/IP 数据包,而抓包后存盘的文件格式就是 .pcap 文件。 文件格式 Pcap …

MySQL - 多表查询与案例详解

目录 多表查询概述 内连接 外连接 1). 左外连接 2). 右外连接 自连接 联合查询 子查询 标量子查询 列子查询 行子查询 表子查询 多表查询练习 隐式内连接 显式内连接 去重distinct 左外连接 between ... and ... 三表查询 函数AVG 标量子查询 命名引用 多表查询概述 分…

MySQL数据库多表查询

MySQL数据库多表查询 前言 在之前的文章MySQL数据库之SQL入门中,我们讲到了四类SQL中的DQL(数据库查询语言,用于查询表中数据),但是我仅仅用DQL去查询一张表中数据,而在实际的应用中,经常是对多张数据库表进行查找。…

Oracle多表查询

什么是多表查询 多表查询:当查询的数据并不是来源一个表时,需要使用多表链接操作完成查询。根据不同表中的数据之间的关系查询相关联的数据 多表链接方式 内连接(inner join) 连接两个表,通过相等或不等判断链接列&…

(八)多表查询

目录 多表查询 笛卡尔积的错误 连接条件 表的别名 多表查询分类 自连接 和 非自连接 内连接 和 外连接 SQL92 SQL99 UNION的使用 UNION操作符 UNION ALL操作符 7种SQL JOINS的实现 QL99语法新特性 自然连接 USING连接 多表查询 多表查询,也称…