Python dpkt模块解析pcap报文

介绍一下如何使用python的dpkt模块对于pcap报文进行解析,报文解码。

通常使用wireshark来对于存储下来的pcap进行手动分析,如果需要使用程序灵活控制分析报文中的信息,我通常使用如下三种方法:

1,使用wireshark提供的Lua API,编写lua插件进行分析。优点是wireshark支持协议众多,2000+,同时对于报文内容解码非常的详细。由于底层使用的是C语言编写,因此解码效率也是很高。关于插件的使用,见这里

2,在python中调用方法一编写的Lua脚本,具体的方法我在我的CSDN博客上一篇文章中有说明,见这里

3,直接使用python 的dpkt模块进行解报文。比之wireshark,首先支持的协议有限。这里列出了dpkt中的所有模块,可以看出其支持解码的协议并不多。但是对于常见的ip,tcp,udp,ssl,http等协议是支持的。但是像google的quic协议wireshark已经支持,但是dpkt还没有。另外dpkt中的解码信息也不如wireshark丰富。

但是在很多场景下,dpkt模块还是有用武之地的,比如对于方法一二中需要显示或者隐式的调用tshark程序,因此需要提前安装好wireshark程序。同时wireshark是GPL的license,因此在有的商业项目中,可能由于GPL协议的要求,并不会采用wireshark。因此有必要学习和介绍一下dpkt模块,对于解决常用协议足够了。关于dpkt的介绍,在其官方文档描述的还是挺详细的,这里

1,安装 : pip install dpkt,在使用的时候import dpkt即可。

2,下面一个例子是解码一个HTTP报文的响应数据:

import sys
import os
import dpkt

def checkIfHTTPRes(data):

    if len(data) < 4:
        return False

    if data[:4] == str.encode('HTTP'):
        return True

    return False

def httpPacketParser(http):

    if checkIfHTTPRes(http):
        try:
            response = dpkt.http.Response(http)
            print(response.status)

        except Exception as e:
           #print(e)
            pass

def tcpPacketParser(tcp):

    stream = tcp.data
    if len(stream):
        httpPacketParser(stream)
 
def ipPacketParser(ip):
    if isinstance(ip.data, dpkt.tcp.TCP):
        tcpPacketParser(ip.data)
        

def decodePacket(packet):
    eth = dpkt.ethernet.Ethernet(packet)
    if isinstance(eth.data, dpkt.ip.IP):
        ipPacketParser(eth.data)

def pcapReader(filename):
    try:
        with open(filename, 'rb') as f:
            capture = dpkt.pcap.Reader(f)
            i = 1
            for timestamp, packet in capture:
                decodePacket(packet)
                i += 1

    except Exception as e:
        print('parse {}, error:{}'.format(filename, e))

 
if __name__ == "__main__":
    if len (sys.argv) < 2:
        print('HELP: python {} <PCAP_PATH>'.format(sys.argv[0]))
        sys.exit(0)
        #_EXIT_
    filename = sys.argv[1]
    
    if filename:
        pcapReader(filename)

dpkt的原理很简单,其对于每一个协议都有一个单独的类负责对于该层协议进行解析,输入就是该层协议的二进制数据,输出就是将二进制码流解析成有意义的单独字段。因此上面的例子中,首先使用 dpkt.pcap.Reader读取pcap报文,主要是去除报文的头部信息。同时将上层的数据根据解码情况传递到具体的协议类中进行解析。最终的应用层数据由http类中dpkt.http.Response负责解析。dpkt对于HTTP这个协议的支持,输入就是下层传递来的HTTP数据部分(二进制码流),即TCP上层数据(无SSL情况),输出就是dpkt给出的关于这部分数据的解码,包括HTTP 协议头部的信息,以及HTTP协议数据部分信息,如果数据部分压缩,dpkt还提供了gzip类进行解压。

在解码的过程中,我是建议大家多看看dpkt的源码,由于dpkt的主要代码在dpkt这个文件夹下面,文件基本是按照协议种类进行组织的,往往一个协议对应一个.py文件,因此源码读起来层次还是非常的清晰。我在使用dpkt的过程中,发现说明文档并不是特别的详细,而dpkt的代码组织还是很清晰的,同时能够从源码得知如何输出解码的字段信息。

上述dpkt中的示例还是非常的简单,主要是单片报文的解码。我们知道报文中一条流包含多个报文,HTTP响应必须将多个包组合起来才能表示完整的信息,比如HTML网页信息。同时抓取的报文中往往包含多条流,多条流的报文是交叉在一起的。因此对于DPKT来说,首先要构建流表,将每一条流组织起来,报文拼接起来。这里不得不说,如果使用wireshark,流表已经为你建好了,直接使用流索引stream即可,但是在dpkt中一切需要从头开始。关于流表的构建,后续的文章会继续分享。

本文为CSDN村中少年原创文章,转载记得加上小尾巴偶,博主链接这里

发布了132 篇原创文章 · 获赞 183 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/javajiawei/article/details/100513267