3

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

谢谢!

4

2 回答 2

3

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

注意:

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

代码:

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
            rec['pkt'] = f.read( rec['rlen'] - 16 )
            if rec['type'] == 2:
                # 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
于 2012-11-21T21:40:42.740 回答
2

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

警告: 我相信 ERF 记录可以包含多个扩展标题,但我不知道要测试这些。Extension Header 结构没有特别详细的文档记录,我在囚禁中的唯一记录只包含一个扩展名。

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
于 2013-05-26T16:30:53.910 回答