Scapy 是一个强大的交互式数据包处理程序(使用python编写)。它能够伪造或者解码大量的网络协议数据包,还能够发送、捕捉、匹配请求和回复包等等。关于网络数据包的解析,其实wireshark这款经典的工具已经能满足大部分工作人员的需求,但是涉及到一些复杂的、自定义型的数据包解析,仅用wireshark就有点不够看了。这次我使用的是一个Python的库Scapy,对于解析pcap文件它算是一个冷门库,网络上关于它的资料实在少的可怜,所以我只能撸起袖子自己开搞,最终一步步用它解析pcap文件。
安装Scapy
关于Scapy的安装参考如下:
pip3 install scapy-python3
yum install libffi-devel
pip3 install cryptography
ln -s /opt/python/bin/scapy /usr/bin/scapy
就可以完成安装了,之后可以在命令行中输入Scapy来进入交互式命令来检验安装是否成功。但是需要注意的,我是在linux的python3的环境下成功安装的,2.7以及window的安装会麻烦很多(亲身体验过),所以还是建议使用linux和python3。安装成功以后,在python文件中使用
from scapy.all import *
就可以导入并使用scapy库了
解析pcap文件
读取pcap文件
通过阅读使用手册,我找到了读取pcap文件使用的语句:
rdpcap("xxx.pcap")
这个语句可以读取一个pcap文件,并返回一个数据类型,我们来实验一下:
可以看到,当我们直接打印这个变量(pcaps),可以直接得到数据包的总概况,图中我传入的pcap文件中只有7个TCP数据包。通过查阅资料,我知道了这个类型的用法类似于List,我们可以直接调用每个数据包:
我一开始选择直接打印第一个数据包,结果出现了一堆乱七八糟的十六进制数据,看的我一脸懵逼,这样肯定是不行的,于是我查了一下这个变量的数据类型:
结果查出一个没见过的数据类型,于是我决定去help中查一下这个类型。我先在命令行中直接输入Scapy
进入交互命令环境,最后输入
help(scapy.layers.l2.Ether)
显示的界面如下:
一阅读help,我就看到了上图中的三个函数中的mysummary,这个函数的效果是返回一个字符串标明来源和目的地,但是我抱着试一试的态度直接打印了这个指针,结果返回值:
直接返回了我们看得懂的,可以操作的值!只要str()字符串化一下,我们可以提取出包里所有的特征了,接下来就是字符串的处理了。
提取数据包特征
当然,只到上一步肯定是有朋友不满意的,处理字符串太麻烦了,难道没有直接提取包中的特征的办法?为了解决这个问题,我继续了研究,然后我就在help中发现了show()
这个函数:
可以看到数据包的层次、字段被排列的很清晰,为了方便大家查看,我把wireshark的图也附上:
OK!可以确定只要wireshark能解析出来的,scapy也都能解析出来,下面就是单独提取字段的问题了。看着show显示的排列结果,我突然有了一个大胆的想法,排列出的字段名缩写会不会就是属性?于是我试了一试:
果然,我的猜想是正确的!这样每一个特征就可以单独提取出来了,搞定,写完收工。
新的问题和解决
咳咳,收工只是个玩笑话,因为很快就会有朋友发现问题,IP和TCP都有’chksum’、’options’和’flags’这3个字段,packet的这三个属性到底属于谁?实验了一下:
可以发现,着三个属性都属于IP的字段,那TCP的这三个字段怎么提取?在一番尝试失败后,我只能不太情愿地捡起了源码看。经过了很长一段时间的研究后,我终于找到了一个函数: haslayer(self, cls)
,这是一个判断某一层结构存不存在的函数,实验一下:
可以看到,存在的层返回的值是1(也就是true),而不存在的层返回就是0(也就是false)。于是我顺藤摸瓜,又找到了一个函数 getlayer(self, cls, nb=1, _track=None)
,尝试一下:
存在的层可以显示出自己的字段数据,而不存在的层直接报错,这下问题终于解决了!
(注:函数中参数可以是’TCP’也可以是TCP)
后续的一些问题
另外的一种分层表达法
其实在后来,我在一位大佬的博客(现在找不到了)上看到了一种更方便的表达方法来实现分层字段显示:可以看到这种方式和我之前实验的方式结果差不多,不过表达更加简洁。
关于其他的一些字段
如果要统计流的一些属性,流的时间和包的总大小是必备的,属性如下:因为是第一个包,所以时间值就是一个基准值,其他的包可以通过这个值计算出自己到达的相对时间,wireshark中关于这些值都已经给你统计好了,不过我们也可以通过一些简单的计算得到这些值。包的长度用
len()
这个函数统计,值得注意的是,packet.len这个值是属于IP包长度的值,在上图已经标出,切勿混淆。关于应用数据(报文)的获取
关于报文的获取是用RAW这个层,具体看下图:
可以看出,根据这个信息可以判断一个包的数据是否加密(如果不存在应用层数据(三次握手等),使用RAW就会直接报错)。
其他
很抱歉,之前由于域名的问题博客无法访问,我也一直没有机会发博客,现在小白兔的博客已经恢复正常了,而且进行了美化,开放了RSS订阅和评论,支持我请把鼠标下移到“赏”,谢谢大家!