在python中解析ERF捕获文件

在python中解析ERF捕获文件,python,Python,在python中解析ERF(endace)捕获文件的最佳方法是什么?我找到了python的libpcap包装器,但我认为lipcap不支持ERF格式 谢谢 这里有一个简单的ERF记录解析器,它返回每个数据包的dict(我只是将它拼凑在一起,所以没有经过很好的测试。不是所有的标志字段都被解码,但是没有解码的标记字段并不广泛适用): 注意: ERF记录类型:1=HDLC,2=以太网,3=ATM,4=重新组装的AAL5,5-7个多通道变体,此处未处理额外的报头 如果snaplength太短,rlen

在python中解析ERF(endace)捕获文件的最佳方法是什么?我找到了python的libpcap包装器,但我认为lipcap不支持ERF格式


谢谢

这里有一个简单的ERF记录解析器,它返回每个数据包的dict(我只是将它拼凑在一起,所以没有经过很好的测试。不是所有的标志字段都被解码,但是没有解码的标记字段并不广泛适用):

注意:

  • ERF记录类型:1=HDLC,2=以太网,3=ATM,4=重新组装的AAL5,5-7个多通道变体,此处未处理额外的报头
  • 如果snaplength太短,
    rlen
    可以小于
    wlen+len(标头)
  • 间隙丢失计数器是当Dag数据包处理器的输入队列溢出时,该数据包与先前捕获的数据包之间丢失的数据包数
  • 如果不想使用scapy,请注释掉两行scapy
代码:

将scapy.layers.all作为sl导入
def erf_记录(f):
"""
生成器,它从类似于``f的文件中解析ERF记录``
"""
尽管如此:
#ERF头是固定长度的16字节
hdr=f.read(16)
如果hdr:
rec={}
#时间戳按英特尔字节顺序排列
rec['ts']=struct.unpack('bbhh',hdr[8:]))
rec['iface']=rec['flags']&0x03
rec['rx_err']=rec['flags']&0x10!=0
rec['pkt']=f.read(rec['rlen']-16)
如果rec['type']==2:
#ERF以太网在ERF报头之间有一个额外的两个字节的pad
#以及MAC报头的开头,以便IP层数据为DWORD
#对齐。从内存来看,其他类型都没有pad。
rec['pkt']=rec['pkt'][2:]
rec['pkt']=sl.Ether(rec['pkt'])
收益率
其他:
返回

ERF记录可以包含附加到16字节ERF记录头的可选扩展头。“类型”字段的高位表示存在扩展标头。我在strix的示例中添加了扩展头的测试,以及扩展头本身的解码。请注意,如果存在扩展标头,以太网帧的测试也需要稍微更改

警告:我相信ERF记录可以包含多个扩展头,但我不知道如何测试这些扩展头。扩展头结构没有很好的文档记录,我在Captive中仅有的记录只包含一个扩展

import struct
import scapy.layers.all as sl

def erf_records( f ):
    """
    Generator which parses ERF records from file-like ``f``
    """
    while True:
        # The ERF header is fixed length 16 bytes
        hdr = f.read( 16 )
        if hdr:
            rec = {}
            # The timestamp is in Intel byte-order
            rec['ts'] = struct.unpack( '<Q', hdr[:8] )[0]
            # The rest is in network byte-order
            rec.update( zip( ('type',  # ERF record type
                              'flags', # Raw flags bit field
                              'rlen',  # Length of entire record
                              'lctr',  # Interstitial loss counter
                              'wlen'), # Length of packet on wire
                             struct.unpack( '>BBHHH', hdr[8:] ) ) )
            rec['iface']  = rec['flags'] & 0x03
            rec['rx_err'] = rec['flags'] & 0x10 != 0

            #- Check if ERF Extension Header present.  
            #  Each Extension Header is 8 bytes.
            if rec['type'] & 0x80:
                ext_hdr = f.read( 8 )
                rec.update( zip( (
                        'ext_hdr_signature',     # 1 byte
                        'ext_hdr_payload_hash',  # 3 bytes
                        'ext_hdr_filter_color',  # 1 bye
                        'ext_hdr_flow_hash'),    # 3 bytes
                        struct.unpack( '>B3sB3s', ext_hdr ) ) )
                #- get remaining payload, less ext_hdr
                rec['pkt'] = f.read( rec['rlen'] - 24 )
            else:
                rec['pkt'] = f.read( rec['rlen'] - 16 )
            if rec['type'] & 0x02:
                # ERF Ethernet has an extra two bytes of pad between ERF header
                # and beginning of MAC header so that IP-layer data are DWORD
                # aligned.  From memory, none of the other types have pad.
                rec['pkt'] = rec['pkt'][2:]
                rec['pkt'] = sl.Ether( rec['pkt'] )
            yield rec
        else:
            return
导入结构
将scapy.layers.all作为sl导入
def erf_记录(f):
"""
生成器,它从类似于``f的文件中解析ERF记录``
"""
尽管如此:
#ERF头是固定长度的16字节
hdr=f.read(16)
如果hdr:
rec={}
#时间戳按英特尔字节顺序排列
rec['ts']=struct.unpack('bbhh',hdr[8:]))
rec['iface']=rec['flags']&0x03
rec['rx_err']=rec['flags']&0x10!=0
#-检查是否存在ERF扩展标题。
#每个扩展头是8个字节。
如果rec['type']&0x80:
ext_hdr=f.read(8)
记录更新(邮编((
“ext_hdr_签名”,1字节
“ext_hdr_payload_hash”,3字节
“ext_hdr_filter_color”,再见
“ext_hdr_flow_hash”),#3字节
解包结构('>B3sB3s',ext_hdr)))
#-获取剩余有效负载,减少ext_hdr
rec['pkt']=f.read(rec['rlen']-24)
其他:
rec['pkt']=f.read(rec['rlen']-16)
如果rec['type']&0x02:
#ERF以太网在ERF报头之间有一个额外的两个字节的pad
#以及MAC报头的开头,以便IP层数据为DWORD
#对齐。从内存来看,其他类型都没有pad。
rec['pkt']=rec['pkt'][2:]
rec['pkt']=sl.Ether(rec['pkt'])
收益率
其他:
返回

可能不是您要求的,但您可以使用DAG API轻松捕获数据包,并使用libpcap以pcap格式存储跟踪。编辑:您可以使用
dagconvert
将ERF转换为pcap。
import struct
import scapy.layers.all as sl

def erf_records( f ):
    """
    Generator which parses ERF records from file-like ``f``
    """
    while True:
        # The ERF header is fixed length 16 bytes
        hdr = f.read( 16 )
        if hdr:
            rec = {}
            # The timestamp is in Intel byte-order
            rec['ts'] = struct.unpack( '<Q', hdr[:8] )[0]
            # The rest is in network byte-order
            rec.update( zip( ('type',  # ERF record type
                              'flags', # Raw flags bit field
                              'rlen',  # Length of entire record
                              'lctr',  # Interstitial loss counter
                              'wlen'), # Length of packet on wire
                             struct.unpack( '>BBHHH', hdr[8:] ) ) )
            rec['iface']  = rec['flags'] & 0x03
            rec['rx_err'] = rec['flags'] & 0x10 != 0

            #- Check if ERF Extension Header present.  
            #  Each Extension Header is 8 bytes.
            if rec['type'] & 0x80:
                ext_hdr = f.read( 8 )
                rec.update( zip( (
                        'ext_hdr_signature',     # 1 byte
                        'ext_hdr_payload_hash',  # 3 bytes
                        'ext_hdr_filter_color',  # 1 bye
                        'ext_hdr_flow_hash'),    # 3 bytes
                        struct.unpack( '>B3sB3s', ext_hdr ) ) )
                #- get remaining payload, less ext_hdr
                rec['pkt'] = f.read( rec['rlen'] - 24 )
            else:
                rec['pkt'] = f.read( rec['rlen'] - 16 )
            if rec['type'] & 0x02:
                # ERF Ethernet has an extra two bytes of pad between ERF header
                # and beginning of MAC header so that IP-layer data are DWORD
                # aligned.  From memory, none of the other types have pad.
                rec['pkt'] = rec['pkt'][2:]
                rec['pkt'] = sl.Ether( rec['pkt'] )
            yield rec
        else:
            return