文件在这里可以找到:

PcapngReaderPython/pcapng_demo.py · duocore/TurtleRock - Gitee.com

#coding=utf-8
#
# 说明文字大部分是这个网址翻译的:
# https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.txt
# 注意:
# 1、测试的pcapng文件里有些类型的包没有出现,下面的脚本执行过程中有一些未覆盖到。
# 2、一些option因为时间关系没有解析。后续有时间再补
# 3、运行版本python3.4+from enum import Enum
from optparse import OptionParserdef round_to_4byte(input_integer_value):"""32位向上对齐。例如输入值=3,则返回值=4。又比如0=>0, 5=>8:param input_integer_value: 需要向上对齐的数字:return:"""return (input_integer_value + 3) & (~3)class BlockTypeCode(Enum):BTS_SectionHeaderBlock = 0x0A0D0D0ABTS_InterfaceDescriptionBlock = 0x00000001BTS_PacketBlock_Obsolete = 0x00000002BTS_SimplePacketBlock = 0x00000003BTS_NameResolutionBlock = 0x00000004BTS_InterfaceStatisticsBlock = 0x00000005BTS_EnhancedPacketBlock = 0x00000006BTS_DecryptionSecretsBlock = 0x0000000ABTS_CustomBlockWhichCanBeCopied = 0x00000BADBTS_CustomBlockWhichShouldNotBeCopied = 0x40000BADclass PcapngBlockHeader:"""3.1.  General Block Structure捕获文件以块的形式组织,这些块相互堆叠以形成文件。 所有块共享一个通用格式,如图1所示。.0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                          Block Type                           |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/                          Block Body                           //          /* 可变长度, 但是必须32位(4字节)对齐*/             /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Figure 1: Basic block structure.这些字段具有以下含义:Block Type (32 bits): 标识块的唯一值。最高有效位(MSB)等于1的值保留供本地使用。 They allow to save private datato the file and to extend the file format. The list of currently defined types can be found in Appendix BBlock Total Length: 此块的总大小,以字节为单位。例如一个没有正文的块的长度是12个字节。Block Body: 块的内容。Block Total Length: 此块的总大小,以字节为单位。该字段和复制前值放在尾部以方便文件的反向访问。这种在所有块之间共享的结构使得处理文件和跳过不需要或未知的块变得容易。 一些块可以在内部包含其他块(嵌套块)。 一些块是必需的,即如果它们不存在则转储文件无效,其他块是可选的。The General Block Structure allows defining other blocks if needed. A parser that does non understand themcan simply ignore their content."""block_type = -1block_total_length = -1_is_big_endian = Truedef __init__(self, is_big_endian):self._is_big_endian = is_big_endiandef read_from_file_object(self, file_object):#open("file.pcapng", "rb") with file_objectreturn_value = Falsetry:string_from_bytes_endian = "big"if not self._is_big_endian:string_from_bytes_endian = "little"data = file_object.read(4)# 一般而言 big: 网络字节序, little:主机字节序self.block_type = int.from_bytes(data, string_from_bytes_endian) # 'big' or 'little'data = file_object.read(4)self.block_total_length = int.from_bytes(data, string_from_bytes_endian)print("block type:%x, block total length:%x"%(self.block_type, self.block_total_length))return_value = Trueexcept Exception as e:print(e)return return_valueclass PcapngOptions:"""3.5.  Options所有block的body部分都可以嵌入可选字段。可选字段可用于插入一些在读取数据时可能有用的信息,但对于数据包处理来说并不是真正需要的。因此每个工具都可以读取可选字段(如果有)的内容,或者跳过其中的一些甚至全部。一次跳过所有可选字段很简单,因为大多数块由具有固定格式的第一部分和可选的第二个部分组成。 因此,块长度字段(Block Length,出现在通用块结构中,参见第 2.1 节)可用于跳过所有内容,直到下一个块。选项是一系列类型 - 长度 - 值字段,每个字段包含一个值:Option Type (2 bytes): 它包含指定当前 TLV 记录类型的代码。最高有效位等于 1 的选项类型保留供本地使用;因此,不能保证所用的code在所有捕获文件(由其他应用程序生成)中是唯一的。In case of vendor-specific extensionsthat have to be identified uniquely, vendors must request an Option Code whose MSB is equal to zero.Option Length (2 bytes): 它包含以下“选项值”字段的实际长度,不含填充字节。Option Value (variable length): 它包含给定选项的值,与32位边界对齐(4字节对齐)。该字段的实际长度(即排除填充字节后)由选项长度字段指定。选项可能会重复多次(例如一个接口有多个关联的IP地址)TODO: mention for each option, if it can/shouldn'tappear more than one time. The option list is terminated by a Option which uses the special'End of Option' code (opt_endofopt).The format of the optional fields is shown in Figure 7.0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|      Option Code              |         Option Length         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/                       Option Value                            //         /* variable length, 4字节对齐(32 bits)*/            /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/                                                               //                 . . . other options . . .                     //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|   Option Code == opt_endofopt  |  Option Length == 0          |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Figure 7: Options format.以下code可以出现在任何可选字段中:Name          Code    Length    Description                              Example(s)opt_endofopt  0       0         It delimits the end of the optional fields. This block cannot be repeated within a given list of options.opt_comment   1      variable     包含与当前块关联的注释的 UTF-8 字符串。    "This packet is the beginning of all of our problems" / "Packets 17-23 showing a bogus TCP retransmission, as reported in bugzilla entry 1486!" / "Captured at the southern plant" / "I've checked again, now it's working ok" / ..."""_option_buffer = None_option_length = 0def __init__(self, option_buffer, option_length):self._option_buffer = option_bufferself._option_length = option_lengthdef parse_option_for_section_header_block(self, section_endian):"""解析并打印所有用于section header block的options。除了第2.5节中定义的选项外,还有以下选项在此块中有效:名字          代码  长度  说明                                         例子shb_hardware  2     可变  UTF-8字符串,描述创建此section的硬件。     "x86 Personal Computer" / "Sun Sparc Workstation" / ...shb_os        3     可变  UTF-8字符串,创建此section的操作系统名称。 "Windows XP SP2" / "openSUSE 10.2" / ...shb_userappl  4     可变  UTF-8字符串,创建此section的应用程序名称。 "dumpcap V0.99.7" / ...:section_endian: "big"或者"little"表示大端还是小端机器:return:"""remain_option_length = self._option_lengthcursor = 0opt_endofopt = 0pnp = {2:"opt_shb_hardware", 3:"opt_shb_os", 4:"opt_shb_userappl"}while remain_option_length != 0:option_code = int.from_bytes(self._option_buffer[cursor : cursor+2], section_endian)if option_code == opt_endofopt:print("match end of option list op code.")breakoption_length = int.from_bytes(self._option_buffer[cursor+2 : cursor+4], section_endian)option_value = self._option_buffer[cursor+4 : cursor+4+option_length]if option_code in pnp:print("option:%s, option_length:%d(%d)" % (pnp[option_code], option_length, round_to_4byte(option_length)),"option_value:", option_value)else:print("option:%d, option_length:%d(%d)"%(option_code, option_length, round_to_4byte(option_length)),"option_value:", option_value)cursor += (4 + round_to_4byte(option_length))def parse_option_for_interface_description_block(self, section_endian):pnp = {2: "if_name", 3: "if_description", 4: "if_IPv4addr",5: "if_IPv6addr", 6: "if_MACaddr", 7: "if_EUIaddr",8: "if_speed", 9: "if_tsresol", 10: "if_tzone",11: "if_filter", 12: "if_os", 13: "if_fcslen",14: "if_tsoffset"}remain_option_length = self._option_lengthcursor = 0opt_endofopt = 0while remain_option_length != 0:option_code = int.from_bytes(self._option_buffer[cursor: cursor + 2], section_endian)if option_code == opt_endofopt:print("match end of option list op code.")breakoption_length = int.from_bytes(self._option_buffer[cursor + 2: cursor + 4], section_endian)option_value = self._option_buffer[cursor + 4: cursor + 4 + option_length]if option_code in pnp:print("option:%s, option_length:%d(%d)" % (pnp[option_code], option_length, round_to_4byte(option_length)),"option_value:", option_value)else:print("option:%d, option_length:%d(%d)" % (option_code, option_length, round_to_4byte(option_length)),"option_value:", option_value)cursor += (4 + round_to_4byte(option_length))class PcapngSecionHeaderBlock:"""Section Header Block是必要数据。它用于标识捕获转储文件的一个section的开头。 Section Header Block不包含数据,而是标识逻辑相关的块(接口、数据包)列表。0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+---------------------------------------------------------------+0 |                   Block Type = 0x0A0D0D0A                     |+---------------------------------------------------------------+4 |                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+8 |                      Byte-Order Magic                         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+12|          Major Version        |         Minor Version         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+16|                                                               ||                          Section Length                       ||                                                               |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+24/                                                               //                      Options (variable)                       //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      Block Total Length                       |+---------------------------------------------------------------+Section Header Block 的块类型是与4个字符的字符串“\r\n\n\r”对应的整数(0x0A0D0D0A)。使用此值有两个原因:1,此数字用于检测文件是否已通过FTP或 HTTP 从一台机器传输到另一台机器并进行了不适当的ASCII转换。在这种情况下,此字段的值将不同于标准值 ("\r\n\n\r"),并且读取方可以检测到可能已损坏的文件。2,该值是回文的,因此无论节的字节序如何,读取方都能够识别节标题块。字节顺序是通过读取Byte-Order Magic来识别的,它位于块类型之后的8个字节。Block Total Length: total size of this block,以字节为单位。Byte-Order Magic: 幻数,其值为十六进制数 0x1A2B3C4D。这个数字可以用来区分这个section是小端机还是大端机上生成的。Major Version:当前格式主版本号。当前值为1。如果格式的更改导致工具无法读取旧格式存档,则该值应该更改。Minor Version:当前格式次版本号。当前值为0。如果格式的更改导致工具无法读取旧格式存档,则该值应该更改。Section Length:此section的长度,以字节为单位,不包含本Section Header Block的长度,此字段可用于跳过该section,以便在大文件中更快地导航。Section Length为-1(0xFFFFFFFFFFFFFFFF)表示未指定节的大小,跳过该节的唯一方法是解析其包含的块(block)。请注意如果此字段有效(即不是 -1),则其值始终与32位对齐,因为所有块(block)都与32位边界对齐。此外在访问此字段时应特别小心:由于文件中所有块的对齐方式都是32位,因此不能保证此字段与64位边界对齐。这可能在64位工作站上发生问题。Options: 可选的选项列表(根据第2.5节中定义的规则格式化)添加新的块类型或选项不一定需要更改Major或Minor版本号,因为不知道块类型或选项的代码可以跳过它;仅当跳过块或选项会导致无法工作时,才需要更改Minor版本号。除了第2.5节中定义的选项外,还有以下选项在此块中有效:名字          代码  长度  说明                                         例子shb_hardware  2     可变  UTF-8字符串,描述创建此section的硬件。     "x86 Personal Computer" / "Sun Sparc Workstation" / ...shb_os        3     可变  UTF-8字符串,创建此section的操作系统名称。 "Windows XP SP2" / "openSUSE 10.2" / ...shb_userappl  4     可变  UTF-8字符串,创建此section的应用程序名称。 "dumpcap V0.99.7" / ..."""magic = -1version_major = -1version_minor = -1section_length = -1 # 如值为-1表示未知_endian = ""incorrect_format = Falseblock_type = 0x0A0D0D0Ablock_total_length = -1block_total_length_with_padding = -1def read_from_file_object(self, file_object):return_value = Falsetry:# 这里先不计算,因为还不知道字节序,下面要根据magic的值确定是否要转换。# file_offset + 8 (函数调用前还有个0x0A0D0D0A头)block_total_length_raw = file_object.read(4)# file_offset + 12data = file_object.read(4)self.magic = int.from_bytes(data, "big")if 0x1A2B3C4D != self.magic:self._endian = "little"self.magic = int.from_bytes(data, "little")if 0x1A2B3C4D != self.magic:self.incorrect_format = Truereturn Falseelse:self._endian = "big"self.block_total_length = int.from_bytes(block_total_length_raw, self._endian)self.block_total_length_with_padding = round_to_4byte(self.block_total_length)print("block type:%#x, block total length:%#x(with padding: %#x)"%(self.block_type,self.block_total_length,self.block_total_length_with_padding))# file_offset + 14data = file_object.read(2)self.version_major = int.from_bytes(data, self._endian)# file_offset + 16data = file_object.read(2)self.version_minor = int.from_bytes(data, self._endian)print("File version: %d.%d"%(self.version_major, self.version_minor))# file_offset + 24data = file_object.read(8)self.section_length = int.from_bytes(data, self._endian)print("section length : %#x" % self.section_length)data_raw_options = file_object.read(self.block_total_length_with_padding - 24 - 4)po = PcapngOptions(data_raw_options, self.block_total_length_with_padding - 24 - 4)po.parse_option_for_section_header_block(self._endian)data = file_object.read(4)block_total_length_backward = int.from_bytes(data, self._endian)print("Block total length backward:%#x"%block_total_length_backward)if block_total_length_backward != self.block_total_length:print("错误,前后块长度不一致。")return Falsereturn_value = Trueexcept Exception as e:print(e)return return_valuedef get_endian(self):return self._endianclass PcapngInterfaceDescriptionBlock:"""4.2.  Interface Description Block (必需)网络接口描述块是必要的。 需要此块来细化进行捕获的网络接口的特征。为了将捕获的数据正确关联到相应的接口,必须在使用它的任何其他块之前定义接口描述块;因此,该块通常紧跟在Section Header Block之后。接口描述块仅在它所属的section内有效。The structure of a Interface Description Block is shown in Figure 9.0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+---------------------------------------------------------------+0 |                    Block Type = 0x00000001                    |+---------------------------------------------------------------+4 |                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+8 |           LinkType            |           Reserved            |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+12 |                            SnapLen                            |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+16 /                                                               //                      Options (variable)                       //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      Block Total Length                       |+---------------------------------------------------------------+Figure 9: Interface Description Block format.The meaning of the fields is:(1)Block Type: The block type of the Interface Description Block is 1.(2)Block Total Length: total size of this block, as described in Section 2.1.(3)LinkType: 定义此接口的链路层类型的值。附录C中提供了标准化链路层类型代码列表。(4)SnapLen: 从每个数据包中转储的最大字节数。每个数据包中超过此值的部分将不会存储在文件中。(TODO: Is there a need to signal "no limit"?)(5)Options: 可选项,可以提供选项列表(根据第 2.5 节中定义的规则格式化)。Interface ID: 写入/读取捕获文件的工具将一个渐进的 16 位数字(从“0”开始)关联到每个接口定义块(Interface Definition Block)。这个编号在每个Section中都是唯一的,并且唯一标识了接口(当前Section内部);因此,两个Section可以具有由相同标识符标识的接口。该唯一标识符被其他块(例如数据包块)引用以指出该块所引用的接口(例如用于捕获数据包的接口)。 (TODO - It would be nice, to have a "invalid Interface ID" defined,e.g. 0xFFFFFFFF)除了第2.5节中定义的选项之外,以下选项在此块中有效:Name           Code    Length     Description                            Example(s)if_name        2       Variable   用于捕获数据的设备名称(UTF-8字符串)。 "eth0" / "\Device\\NPF_{AD1CE675-96D0-47C5-ADD0-2504B9126B68}" / ...if_description 3       Variable   用于捕获数据的设备描述(UTF-8字符串)。 "Broadcom NetXtreme" / "First Ethernet Interface" / ...if_IPv4addr    4       8          IF地址和掩码。当多个IPv4地址分配给一个IF时,可以在同一Interface Description Block中多次重复此选项。192 168 1 1 255 255 255 0if_IPv6addr    5       17         接口网络地址和前缀长度(存储在最后一个字节中)。当一个IF分配了多个IPv6地址时,可以在同一接口描述块中多次重复此选项。2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"if_MACaddr     6       6          接口硬件MAC地址(48 bits).              00 01 02 03 04 05if_EUIaddr     7       8          接口硬件EUI地址(64 位),如果可用。   TODO: give a good exampleif_speed       8       8          接口速度(以bps为单位)。              100000000 for 100Mbpsif_tsresol     9       1          如果最高位等于 0,则其余位将时间戳的分辨率表示为 10 的负幂(例如,6 表示微秒分辨率,时间戳是自 1970 年 1 月 1 日以来的微秒数)。如果最高位等于 1,则其余位表示分辨率为2的负幂(例如,10 表示 1/1024 秒)。如果此选项不存在,则假定分辨率为 10^-6(即时间戳具有与标准“libpcap”时间戳相同的分辨率)。6if_tzone       10      4          GMT支持的时区(TODO: specify better).   TODO: give a good exampleif_filter      11      variable   用于捕获流量的过滤器(e.g. "capture only TCP traffic")。Option Data 的第一个字节保留了所用过滤器的代码(e.g. if this is a libpcap string, or BPF bytecode, and more).More details about this format will be presented in Appendix XXX (TODO).(TODO: better use different options for different fields? e.g.if_filter_pcap, if_filter_bpf, ...)00 "tcp port 23 and host 10.0.0.5"if_os          12      variable   一个UTF-8字符串,包含安装此接口的机器的操作系统名称。这可能与部分标题块(第 3.1 节)可以包含的相同信息不同,因为捕获可以在远程机器上完成。"Windows XP SP2" / "openSUSE 10.2" / ...if_fcslen      13      1          一个整型值,用于指定在此接口上应用的FCS的长度. For link layers whose FCS lengthcan change during time, the Packet Block Flags Word can be used (see Appendix A).4if_tsoffset    14      8          一个64位整数值的偏移量,每个数据包的时间戳加上它可以获得数据包的绝对时间戳(以秒为单位)。如果缺少该选项,则认为数据包中存储的时间戳为绝对时间戳。偏移量的时区可以通过选项if_tzone指定。 TODO: won't a if_tsoffset_low for fractional secondoffsets be useful for highly syncronized capture systems?1234"""_endian = "little"_block_total_length = -1_link_type = -1_reserved = -1_snap_length = -1def __init__(self, endian):self._endian = endiandef read_from_file_object(self, file_object):return_value = Falsetry:# file_offset + 8 (函数调用前还有个0x00000001头)data = file_object.read(4)self._block_total_length = int.from_bytes(data, self._endian)# file_offset + 10data = file_object.read(2)self._link_type = int.from_bytes(data, self._endian)# file_offset + 12data = file_object.read(2)self._reserved = int.from_bytes(data, self._endian)# file_offset + 16data = file_object.read(4)self._snap_length = int.from_bytes(data, self._endian)block_total_length_with_padding = round_to_4byte(self._block_total_length)option_length = block_total_length_with_padding - 16 - 4if option_length != 0:data_raw_options = file_object.read(option_length)po = PcapngOptions(data_raw_options, option_length)po.parse_option_for_interface_description_block(self._endian)data = file_object.read(4)block_total_length_backward = int.from_bytes(data, self._endian)print("Block total length backward:%#x" % block_total_length_backward)if block_total_length_backward != self._block_total_length:print("错误,前后块长度不一致。")return Falsereturn_value = Trueexcept Exception as e:print(e)return return_valueclass PcapngDecryptionSecretsBlock:"""4.7.  Decryption Secrets BlockDecryption Secrets Block (DSB)存储(会话)密钥,这些密钥可以对捕获文件中的数据包进行解密。这些密钥的格式由Secrets Type定义。一个pcapng文件中可以存在多个DSB,但它们应该写在需要这些密钥的数据包块之前。The structure of a Decryption Secrets Block is shown in Figure 15.1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+0 |                   Block Type = 0x0000000A                     |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+4 |                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+8 |                          Secrets Type                         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+12 |                         Secrets Length                        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+16 /                                                               //                          Secrets Data                         //              (variable length, 填充至32位对齐)                //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/                                                               //                       Options (variable)                      //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/                       Block Total Length                      /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Figure 15: Decryption Secrets Block FormatThe Decryption Secrets Block has the following fields.*  Block Type: Decryption Secrets Block 的块类型为10(0x0A)。*  Block Total Length: total size of this block, as described inSection 3.1.*  Secrets Type (32 bits): 描述接下来的Secrets字段格式的无符号整数标识符。请求新的 Secrets 类型代码时应通过创建pull请求来更新本文档,如第10.1节所述。*  Secrets Length (32 bits): 一个无符号整数,表示接下来的Secrets字段的大小,不包含填充字节。*  Secrets Data: 包含密钥的二进制数据,填充到32位对齐。*  Options: optionally, a list of options (formatted according to therules defined in Section 3.5) can be present. 当前没有专门适用于DSB的选项。下面是Secrets Types列表0x544c534b:TLS Key Log. This format is described at NSS Key Log Format(https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format).  Every lineMUST be properly terminated with either carriage return andlinefeed ('\r\n') or linefeed ('\n').  Tools MUST be able tohandle both line endings.0x57474b4c:WireGuard Key Log. Every line consists of the key type,equals sign ('='), and the base64-encoded 32-byte key withoptional spaces before and in between.  The key type is oneof LOCAL_STATIC_PRIVATE_KEY, REMOTE_STATIC_PUBLIC_KEY,LOCAL_EPHEMERAL_PRIVATE_KEY, or PRESHARED|_KEY.  This matchesthe output of extract-handshakes.sh(https://git.zx2c4.com/WireGuard/tree/contrib/examples/extract-handshakes/README), which is part of the WireGuard(https://www.wireguard.com/) project.  A PRESHARED_KEY lineis linked to a session matched by a previousLOCAL_EPHEMERAL_PRIVATE_KEY line.  Every line MUST beproperly terminated with either carriage return and linefeed('\r\n') or linefeed ('\n').  Tools MUST be able to handleboth line endings.Warning: LOCAL_STATIC_PRIVATE_KEY and potentially PRESHARED_KEY arelong-term secrets, users SHOULD only store non-production keys, orensure proper protection of the pcapng file.0x5a4e574b:ZigBee NWK Key and ZigBee PANID for that network.  NetworkKey as described in the ZigBee Specification(https://zigbeealliance.org/) 05-3473-21 (R21) section 4.2.2.The NWK Key is a 16 octet binary AES-128 key used to secureNWK Level frames within a single PAN.  The NWK key isimmediately followed by the 2 octet (16 bit) network PANID inlittle endian format.  If and when the NWK Key changes a newDSB will contain the new NWK Key.0x5a415053:ZigBee APS Key. Application Support Link Key as described inthe ZigBee Specification (https://zigbeealliance.org/)05-3473-21 (R21) section 4.4.  Each 16 octet binary AES-128key secures frames exchanged between a pair of network nodes.The APS Key is immediately followed by the 2 octet (16 bit)network PANID in little endian format.  The PANID is followedby the 2 octet (16 bit) short addresses, in little endianformat, of the nodes to which the APS Key applies.  Thenumerically lower short address shall come first.  There is aAPS Key DSB for each node pair for which the Link Key isknown.  As new links are formed, new DSBs contain the newKeys.  If the APS Key changes for an existing link, it iscontained in a new DSB with the new APS Key.0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+---------------------------------------------------------------+0 |                   Block Type = 0x0000000A                     |+---------------------------------------------------------------+4 |                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+8 |                  Secrets Type = 0x5a4e574b                    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+12 |                         Secrets Length                        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+16 |                            AES-128                            ||                            NKW Key                            ||                          (16 octets)                          ||                           (128 bits)                          |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+32 |          PAN ID               |           padding (0)         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+36 /                                                               //                       Options (variable)                      //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/                       Block Total Length                      /+---------------------------------------------------------------+Figure 16: ZigBee NWK Key Data Format0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+---------------------------------------------------------------+0 |                   Block Type = 0x0000000A                     |+---------------------------------------------------------------+4 |                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+8 |                  Secrets Type = 0x5a415053                    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+12 |                         Secrets Length                        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+16 |                            AES-128                            ||                            APS Key                            ||                          (16 octets)                          ||                           (128 bits)                          |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+32 |           PAN ID              |     Low Node Short Address    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+36 |    High Node Short Address    |         padding (0)           |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+40 /                                                               //                       Options (variable)                      //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/                       Block Total Length                      /+---------------------------------------------------------------+Figure 17: ZigBee APS Key Data Format"""_endian = "little"_block_total_length = -1_secret_type = None_secret_length = 0_secret_type_name = {0x544c534b: "TLS Key Log", 0x57474b4c: "WireGuard Key Log",0x5a4e574b: "ZigBee NWK Key and ZigBee PANID for that network.",0x5a415053: "ZigBee APS Key."}def __init__(self, endian):self._endian = endiandef get_secret_type(self, type_id):if type_id in self._secret_type_name:return self._secret_type_name[type_id]else:return "{0}".format(type_id)def dump_secret_data(self, secret_data_raw, secret_length, secret_type):if secret_type not in self._secret_type_name:print("Warning, unknown secret type.")returnif 0x544c534b == secret_type:print("The value is:\n", str(secret_data_raw, "utf-8"))else:print(secret_data_raw)def read_from_file_object(self, file_object):return_value = Falsetry:# file_offset + 8 (函数调用前还有个0x0000000A头)data = file_object.read(4)self._block_total_length = int.from_bytes(data, self._endian)block_total_length_with_padding = round_to_4byte(self._block_total_length)# file_offset + 12data = file_object.read(4)self._secret_type = int.from_bytes(data, self._endian)# file_offset + 16data = file_object.read(4)self._secret_length = int.from_bytes(data, self._endian)secret_length_with_padding = round_to_4byte(self._secret_length)# file_offset + 16 + secret_length_with_paddingsecret_data_raw_with_padding = file_object.read(secret_length_with_padding)secret_data_raw = secret_data_raw_with_padding[0:self._secret_length]print("This is a secret block.")print("Length:%d(%d), type:%s." % (self._secret_length, secret_length_with_padding, self.get_secret_type(self._secret_type)))self.dump_secret_data(secret_data_raw, self._secret_length, self._secret_type)option_length = block_total_length_with_padding - 16 - secret_length_with_padding - 4if option_length != 0:option_data_raw = file_object.read(option_length)print("option:", option_data_raw)data = file_object.read(4)block_total_length_backward = int.from_bytes(data, self._endian)print("Block total length backward:%#x" % block_total_length_backward)if block_total_length_backward != self._block_total_length:print("错误,前后块长度不一致。")return Falsereturn_value = Trueexcept Exception as e:print(e)return return_valueclass PcapngEnhancePackageBlock:"""4.3.  Enhanced Packet BlockEnhanced Packet Block(增强型数据包块EPB) 是用于存储来自网络的数据包的标准容器。The Enhanced Packet Block是可选的,因为数据包也可以存储到Simple Packet Block(SPB)中,SPB可以加快捕获文件的生成; 又或者可能文件中没有数据包。Enhanced Packet Block的格式见Figure 11。增强型数据包块是对原始的、现已过时的Packet Block(附录 A)的改进:*  它将Interface Identifier存储为32-bit integer value.这用于数据包来自大量接口的需求。*  与Packet Block(附录 A)不同,捕获系统在此数据包和前一个数据包之间丢弃的数据包数量不存储在head中,而是存储在块本身的option中。1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+0 |                    Block Type = 0x00000006                    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+4 |                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+8 |                         Interface ID                          |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+12 |                        Timestamp (High)                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+16 |                        Timestamp (Low)                        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+20 |                    Captured Packet Length                     |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+24 |                    Original Packet Length                     |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+28 /                                                               //                          Packet Data                          //              variable length, padded to 32 bits               //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/                                                               //                      Options (variable)                       //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Figure 11: Enhanced Packet Block FormatThe Enhanced Packet Block has the following fields:*  Block Type: The block type of the Enhanced Packet Block is 6.*  Block Total Length: total size of this block, as described inSection 3.1.*  Interface ID (32 bits): 一个无符号值,指定接收或传输此数据包的接口;一个正确的接口ID是接口描述块Interface Description Block(在文件的当前Section内)中相同编号(参见第 4.2 节)所标识的接口。 接口ID必须是有效的,这意味着对应的接口描述块必须存在。*  Timestamp (High) and Timestamp (Low): upper 32 bits and lower 32bits of a 64-bit timestamp.时间戳是一个 64 位无符号整数,表示自1970-01-01 00:00:00 UTC以来经过的时间单位数。 时间单位的精度由此数据包引用的Interface Description Block(接口描述块)的“if_tsresol”选项(参见图 10)指定。 注意,与libpcap文件格式中的时间戳不同,Enhanced Packet Blocks中的时间戳不会保存为两个32位值用于代表自1970-01-01 00:00:00 UTC以来经过的秒和微秒。 增强型数据包块(Enhanced Packet Blocks)中的时间戳保存为两个32位数字,代表单个64位数的高32位和低32位。*  Captured Packet Length (32 bits): 一个无符号值,表示从数据包中捕获的字节数(即Packet Data字段的长度)。 它将是接口的Original Packet Length(原始数据包长度)和快照长度(SnapLen,在图 10 中定义)中的最小值。 该字段的值不包括在Packet Data末尾添加的,用于让Packet Data 32位对齐的填充字节。*  Original Packet Length (32 bits): 一个无符号值,表示数据包在网络上传输时的实际长度。 如果数据包已被捕获过程截断,则它可以与Captured Packet Length(捕获的数据包长度)不同。*  Packet Data: 来自网络的数据,包括链路层报头。 该字段的实际长度是Captured Packet Length(捕获的数据包长度)加上使之32位对齐的填充数据。链路层报头的格式取决于接口描述块(Interface Description Block,见第 4.2 节)中指定的LinkType字段,并在[LINKTYPES]表中由该格式对应的条目中确定。*  Options: optionally, a list of options (formatted according to therules defined in Section 3.5) can be present.除在Section 3.5中定义的选项外,接下来的选项在本块中有效:+===============+======+========================+===================+| Name          | Code | Length                 | Multiple          ||               |      |                        | allowed?          |+===============+======+========================+===================+| epb_flags     | 2    | 4                      | no                |+---------------+------+------------------------+-------------------+| epb_hash      | 3    | variable, minimum hash | yes               ||               |      | type-dependent         |                   |+---------------+------+------------------------+-------------------+| epb_dropcount | 4    | 8                      | no                |+---------------+------+------------------------+-------------------+| epb_packetid  | 5    | 8                      | no                |+---------------+------+------------------------+-------------------+| epb_queue     | 6    | 4                      | no                |+---------------+------+------------------------+-------------------+| epb_verdict   | 7    | variable, minimum      | yes               ||               |      | verdict type-dependent |                   |+---------------+------+------------------------+-------------------+Table 4: Enhanced Packet Block Optionsepb_flags:epb_flags选项是一个包含链路层信息的32位标志。 可以在第4.3.1节中找到有关该标志所有有效值的完整规范。Example: '0'.epb_hash:epb_hash 选项包含数据包的哈希值。 第一个八位字节(algorithm octet)指定散列算法,而后面的八位字节包含实际散列,其大小取决于散列算法,即来自第一个八位字节中的值。 哈希算法可以是:2s complement(algorithm octet = 0, size = XXX),CRC32(算法octet=2,size=4),MD-5(algorithm octet = 3, size = 16), SHA-1 (algorithm octet = 4, size = 20),Toeplitz (algorithm octet = 5, size = 4)。 散列仅覆盖数据包,而不包含捕获驱动程序添加的head:这提供了在网卡内部计算它的可能性。散列允许更容易地比较/合并不同的捕获文件,以及数据采集系统和捕获库之间的可靠数据传输。Examples: '02 EC 1D 87 97', '03 45 6E C2 17 7C 10 1E 3C 2E 99 6E C29A 3D 50 8E'.epb_dropcount:epb_dropcount 选项是一个 64 位无符号整数值,指定此数据包与同一接口的前一个数据包之间(由接口和操作系统)丢弃的数据包数,对于接口的第一个数据包,则表示捕获过程的开始到此数据包之间丢弃的数据包数。Example: '0'.epb_packetid:epb_packetid 选项是一个 64 位无符号整数,用于唯一标识数据包。如果多个接口看到同一个数据包,并且捕获应用程序有办法将它们关联起来,则必须使用相同的epb_packetid值。 以在两个方向上的所有接口上捕获数据包的一个路由器为例。 当数据包在入口到达接口 A 时,会创建一个EPB条目,TTL递减,并且就在它从接口B出口之前,在跟踪文件中创建另一个EPB条目。 在这种情况下,捕获文件中有两个数据包,它们不相同,但可以使用epb_packetid将它们关联起来。Example: '0'.epb_queue:epb_queue选项是一个32位无符号整数,用于标识在接口的哪个队列上接收到特定数据包。Example: '0'.epb_verdict:epb_verdict 选项存储数据包的判定(verdict)。判定(verdict)表明在处理数据包后将对其进行什么操作。例如,防火墙可能会丢弃数据包。这个判定(verdict)可以由各种组件设置,即硬件、Linux 的 eBPF TC或XDP框架等。第一个八位字节指定判定类型,而后面的字节包含实际判定数据,其大小取决于判定类型,即来自第一个字节中的值。判定类型可以是:Hardware(type octet = 0,size = variable),Linux_eBPF_TC(type octet = 1,size = 8(64 位无符号整数),value = TC_ACT_*,定义在Linux pck_cls.h (https ://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/pkt_cls.h) 包含),Linux_eBPF_XDP(type octet = 2,size = 8 (64 位无符号整数),value= xdp_action 定义在Linux pbf.h包含(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/ uapi/linux/bpf.h))。Example: '02 00 00 00 00 00 00 00 02' for Linux_eBPF_XDP with verdictXDP_PASS.4.3.1.  Enhanced Packet Block Flags WordEnhanced Packet Block Flags Word是一个 32 位值,包含有关数据包的链路层信息。这个标志字是一个unsigned 32-bit integer, 使用Section Header Block中定义的endianness。 在下表中位0表示32位值的LSB(least significant bit)位31表示MSB(most-significant bit)各比特的含义如下:+========+======================================================+| Bit    | Description                                          || Number |                                                      |+========+======================================================+| 0-1    | Inbound / Outbound packet (00 = information not      ||        | available, 01 = inbound, 10 = outbound)              |+--------+------------------------------------------------------+| 2-4    | Reception type (000 = not specified, 001 = unicast,  ||        | 010 = multicast, 011 = broadcast, 100 =              ||        | promiscuous).                                        |+--------+------------------------------------------------------+| 5-8    | FCS长度,以字节为单位(0000表示次信息无效              ||        | 这个值覆盖了Interface Description Block中的if_fcslen ||        | 选项, and is                                         ||        | used with those link layers (e.g.  PPP) where the    ||        | length of the FCS can change during time.            |+--------+------------------------------------------------------+| 9-15   | Reserved (MUST be set to zero).                      |+--------+------------------------------------------------------+| 16-31  | link-layer-dependent errors (Bit 31 = symbol error,  ||        | Bit 30 = preamble error, Bit 29 = Start Frame        ||        | Delimiter error, Bit 28 = unaligned frame error, Bit ||        | 27 = wrong Inter Frame Gap error, Bit 26 = packet    ||        | too short error, Bit 25 = packet too long error, Bit ||        | 24 = CRC error, other?? are 16 bit enough?).         |+--------+------------------------------------------------------+Table 5NOTE: 注意:在本规范的早期版本中,位0被指定为MSB,位31是32位无符号整数的LSB,而不是位0对应LSB位31对应MSB。 一些实现将位0设定成了LSB,并且没有已知的实现将位0设置成MSB,因此对规范进行了更改以迁就这一现实。"""_endian = "little"_block_total_length = 0_block_total_length_with_padding = 0_interface_id = -1_timestamp_high = -1_timestamp_low = -1_captured_packet_length = -1_captured_packet_length_with_padding = -1_original_packet_length = -1def __init__(self, endian):self._endian = endiandef parse_options(self, option_raw_data, opition_real_len):if option_raw_data is None or opition_real_len == 0:return Falsepnp = {2: "epb_flags", 3: "epb_hash", 4: "epb_dropcount",5: "epb_packetid", 6: "epb_queue", 7: "epb_verdict"}remain_option_length = opition_real_lencursor = 0opt_endofopt = 0while remain_option_length != 0:option_code = int.from_bytes(option_raw_data[cursor: cursor + 2], section_endian)if option_code == opt_endofopt:print("match end of option list op code.")breakoption_length = int.from_bytes(option_raw_data[cursor + 2: cursor + 4], section_endian)option_value = option_raw_data[cursor + 4: cursor + 4 + option_length]if option_code in pnp:print("option:%s, option_length:%d(%d)" % (pnp[option_code], option_length, round_to_4byte(option_length)),"option_value:", option_value)if option_code == 2:option_epb_flag = int.from_bytes(option_value, section_endian)in_out_bound = option_epb_flag & 0x03if in_out_bound == 0x00:print("io bound: information is not available")elif in_out_bound == 0x01:print("io bound: in")else:print("io bound: out")reception_type = option_epb_flag & 0x1C #00011100b#(000 = not specified, 001 = unicast, 010 = multicast, 011 = broadcast, 100 = promiscuousif reception_type == 0:print("reception type: not specified")elif reception_type == 1:print("reception type: unicast")elif reception_type == 2:print("reception type: multicast")elif reception_type == 3:print("reception type: broadcast")elif reception_type == 4:print("reception type: promiscuous")else:print("reception type: unknown")#000111100000b#| 5 - 8 | FCS长度, 以字节为单位(0000表示此信息无效 这个值覆盖了InterfaceDescriptionBlock中的if_fcslen |fcs_len = (option_epb_flag & 0x1E0) >> 5print("FCS length override:", fcs_len)#16-31 link-layer-dependent errorslink_layer_dependent_errors = (option_epb_flag & 0xFFFF0000)print("link-layer-dependent errors: %#x"%link_layer_dependent_errors)print("option:%d, option_length:%d(%d)" % (option_code, option_length, round_to_4byte(option_length)),"option_value:", option_value)cursor += (4 + round_to_4byte(option_length))remain_option_length = opition_real_len - cursordef read_from_file_object(self, file_object):return_value = Falsetry:# file_offset + 8 (函数调用前还有个0x00000006头)data = file_object.read(4)self._block_total_length = int.from_bytes(data, self._endian)self._block_total_length_with_padding = round_to_4byte(self._block_total_length)print("length: %d(%d)"%(self._block_total_length, self._block_total_length_with_padding))# file_offset + 12data = file_object.read(4)self._interface_id = int.from_bytes(data, self._endian)print("interface id:", self._interface_id)# file_offset + 16data = file_object.read(4)self._timestamp_high = int.from_bytes(data, self._endian)# file_offset + 20data = file_object.read(4)self._timestamp_low = int.from_bytes(data, self._endian)print("timestamp with [high:low]: %d:%d"%(self._timestamp_high, self._timestamp_low))# file_offset + 24data = file_object.read(4)self._captured_packet_length = int.from_bytes(data, self._endian)self._captured_packet_length_with_padding = round_to_4byte(self._captured_packet_length)# file_offset + 28data = file_object.read(4)self._original_packet_length = int.from_bytes(data, self._endian)print("captured packet length: %d, original_packet_length: %d"%(self._captured_packet_length, self._original_packet_length))# file_offset + 32raw_captured_data_with_padding = file_object.read(self._captured_packet_length_with_padding)print("binary data:", raw_captured_data_with_padding[0:self._original_packet_length])option_length = self._block_total_length_with_padding - 32 - self._captured_packet_length_with_paddingif option_length != 0:option_data_raw = file_object.read(option_length)print("option:", option_data_raw)data = file_object.read(4)block_total_length_backward = int.from_bytes(data, self._endian)print("Block total length backward:%#x" % block_total_length_backward)if block_total_length_backward != self._block_total_length:print("错误,前后块长度不一致。")return Falsereturn_value = Trueexcept Exception as e:print(e)return return_valueclass PcapngSimplePacketBlock:"""4.4.  Simple Packet BlockSimple Packet Block (SPB)是一个轻量级容器,用于存储来自网络的数据包。它的存在是可选的。Simple Packet Block类似于Enhanced Packet Block(参见第 4.3 节),但它更小、更易于处理并且仅包含最少的信息集。 当性能或空间占用是关键因素时,例如在持续的流量捕获应用程序中,SPB块优于EPB。 捕获文件可以同时包含Simple Packet Block类似于Enhanced Packet Block:例如,当硬件资源变得紧张时,捕获工具可以从EPB切换到SPB。简单数据包块不包含接口 ID 字段。 因此,必须假设所有Simple Packet Blocks都在先前在第一个接口描述块(Interface Description Block)中指定的接口上被捕获。Figure 12 shows the format of the Simple Packet Block.1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+0 |                    Block Type = 0x00000003                    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+4 |                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+8 |                    Original Packet Length                     |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+12 /                                                               //                          Packet Data                          //              variable length, padded to 32 bits               //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Figure 12: Simple Packet Block FormatThe Simple Packet Block has the following fields:*  Block Type: The block type of the Simple Packet Block is 3.*  Block Total Length: total size of this block, as described inSection 3.1.*  Original Packet Length (32 bits): 一个无符号值,表示数据包在网络上传输时的实际长度。 如果数据包已被捕获过程截断,则它可以与Packet Data字段的长度不同,在这种情况下,第 4.2 节中的SnapLen值将小于这个Original Packet Length值,并且SnapLen值必须用于确定数据包数据字段长度的大小。*  Packet Data: 来自网络的数据,包括链路层报头。 该字段的长度可以从Block Header中的Block Total Length字段计算出,它是SnapLen(存在于Interface Description Block中)和Original Packet Length(存在于该Header中)中的最小值。 此数据包数据字段中的数据格式取决于接口描述块(见第 4.2 节)中指定的LinkType字段,并在[LINKTYPES]表对应该格式的条目中指定。Simple Packet Block简单数据包块不包含时间戳,因为这通常是PC上成本最高的操作之一。 此外,有些应用程序不需要它; 例如 入侵检测系统对数据包感兴趣,而不是它们的时间戳。由于不能引用正确的接口(它不包含任何接口ID字段),因此Simple Packet Block不能出现在具有多个接口的Section中。Simple Packet Block 在磁盘空间方面非常高效:a snapshot whose length is 100octets requires only 16 octets of overhead, which corresponds to anefficiency of more than 86%."""_endian = ""_block_total_length = 0_block_total_length_with_padding = 0_original_packet_length = 0def __init__(self, endian):self._endian = endiandef read_from_file_object(self, file_object):return_value = Falsetry:# file_offset + 8 (函数调用前还有个0x00000006头)data = file_object.read(4)self._block_total_length = int.from_bytes(data, self._endian)self._block_total_length_with_padding = round_to_4byte(self._block_total_length)print("length: %d(%d)"%(self._block_total_length, self._block_total_length_with_padding))# file_offset + 12data = file_object.read(4)self._original_packet_length = int.from_bytes(data, self._endian)print("original packet length: %d" % self._original_packet_length)packet_data_len = self._block_total_length_with_padding - 12raw_packet_data = file_object.read(packet_data_len)print("packet data length:", packet_data_len)print("packet data:", raw_packet_data)data = file_object.read(4)block_total_length_backward = int.from_bytes(data, self._endian)print("Block total length backward:%#x" % block_total_length_backward)if block_total_length_backward != self._block_total_length:print("错误,前后块长度不一致。")return Falsereturn_value = Trueexcept Exception as e:print(e)return return_valueclass PcapngNameResolveBlock:"""4.5.  Name Resolution BlockName Resolution Block (NRB)  用于支持数字地址(存在于捕获的数据包中)与其对应的规范名称的关联,它是可选的。 将文字名称保存在文件中可以满足稍后执行名称解析的需要,因为当前名称和地址之间的关联可能与捕获时对应的关联不同。此外,NRB避免了每次打开跟踪捕获时发出大量DNS请求的麻烦,并且还给在使用未连接到网络的机器上读取捕获时还提供名称解析(的便利)。Name Resolution Block 通常放置在文件的开头,但不能对其位置进行假设。 一个pcapng文件中可以存在多个 NRB,要么是由于内存限制,要么是因为文件处理工具(如网络分析器)执行了额外的名称解析。Name Resolution Block不需要包含任何记录,除了必须是最后一个记录的nrb_record_end记录。 NRB记录中的地址和姓名可以重复多次; 即同一个IP地址可以解析为多个名称,同一个名称可以解析为多个IP地址,甚至同一个“地址-名称”对可能在同一个NRB中或跨NRB出现多次。The format of the Name Resolution Block is shown in Figure 13.1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+0 |                    Block Type = 0x00000004                    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+4 |                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+8 |      Record Type              |      Record Value Length      |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+12 /                       Record Value                            //              variable length, padded to 32 bits               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+.                                                               ..                  . . . other records . . .                    ..                                                               .+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|  Record Type = nrb_record_end |   Record Value Length = 0     |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/                                                               //                      Options (variable)                       //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Figure 13: Name Resolution Block FormatThe Name Resolution Block has the following fields:*  Block Type: The block type of the Name Resolution Block is 4.*  Block Total Length: total size of this block, as described inSection 3.1.在这之后跟着零个或多个名称解析记录(TLV 格式),每个记录包含网络地址和名称之间的关联。 nrb_record_end必须添加在最后一个 Record之后,并且即使NRB中没有其他Records也必须存在。 目前有三种可能的记录类型:+=================+========+==========+| Name            | Code   | Length   |+=================+========+==========+| nrb_record_end  | 0x0000 | 0        |+-----------------+--------+----------+| nrb_record_ipv4 | 0x0001 | variable |+-----------------+--------+----------+| nrb_record_ipv6 | 0x0002 | variable |+-----------------+--------+----------+Table 6: Name Resolution Block Recordsnrb_record_end:nrb_record_end 记录分隔名称解析记录的结尾。 需要此记录来确定名称解析记录列表何时结束以及一些Options选项(如果有)何时开始。nrb_record_ipv4:nrb_record_ipv4记录指定一个IPv4地址(包含在前4个字节中),后跟一个或多个包含该地址的DNS条目的以零结尾的 UTF-8 字符串。 因此,此记录类型的最小有效记录长度为6:4(IP)、1 个字符和一个零值八位字节终止符。 请注意,IP地址被视为四个独立的字节,IP 地址的每个字节都是一个单位;它不是32位字,因此SHB的字节序不会影响该字段的值。Example: '127 0 0 1'"localhost".[Open issue: is an empty string (i.e., just a zero-value octet)valid?]nrb_record_ipv6:nrb_record_ipv6 记录指定一个IPv6地址(包含在前16个字节中),后跟一个或多个包含该地址的DNS条目的以零结尾的字符串。 因此,此记录类型的最小有效记录长度为18:IP为16字节、1 个字符和一个零值字节终止符。Example: '20 01 0d b8 00 00 00 00 00 00 00 00 12 34 56 78'"somehost".[Open issue: is an empty string (i.e., just a zero-value octet)valid?]那些在之前指定的记录类型以外的记录类型必须忽略并跳过,以避免破坏向后兼容性。因为将来可能会定义更多记录类型。每个Record Value都填充至与32位边界对齐。 对应的Record Value Length反映了Record Value的实际长度; 它不包括Record Type的长度、Record Value Length字段、Record Value的任何填充或Record Value之后的任何内容。 对于具有名称字符串的Record Types,Record Length确实包括终止该字符串的零值字节。 除非另有说明,否则记录长度为0是有效的。在名称解析记录列表之后,可以有一个选项列表(格式见第3.5节中定义的规则)。除了第3.5节中定义的选项外,以下选项在此块中有效:+===============+======+==========+===================+| Name          | Code | Length   | Multiple allowed? |+===============+======+==========+===================+| ns_dnsname    | 2    | variable | no                |+---------------+------+----------+-------------------+| ns_dnsIP4addr | 3    | 4        | no                |+---------------+------+----------+-------------------+| ns_dnsIP6addr | 4    | 16       | no                |+---------------+------+----------+-------------------+Table 7: Name Resolution Block Optionsns_dnsname:ns_dnsname 选项是一个UTF-8字符串,其中包含用于执行名称解析的机器(DNS服务器)的名称。 该字符串不是以零结尾的。Example: "our_nameserver".ns_dnsIP4addr:ns_dnsIP4addr选项指定DNS服务器的IPv4地址。 请注意,IP地址被视为四个八位字节,IP地址的每个字节是一个单位; 它不是32位字,因此SHB的字节序不会影响该字段的值。Example: '192 168 0 1'.ns_dnsIP6addr:ns_dnsIP6addr选项指定DNS服务器的IPv6 地址。Example: '20 01 0d b8 00 00 00 00 00 00 00 00 12 34 56 78'."""_endian = ""_block_total_length = 0_block_total_length_with_padding = 0def __init__(self, endian):self._endian = endiandef parse_options(self, option_raw_data, opition_real_len):if option_raw_data is None or opition_real_len == 0:return Falsepnp = {2: "ns_dnsname", 3: "ns_dnsIP4addr", 4: "ns_dnsIP6addr"}remain_option_length = opition_real_lencursor = 0opt_endofopt = 0while remain_option_length != 0:option_code = int.from_bytes(option_raw_data[cursor: cursor + 2], section_endian)if option_code == opt_endofopt:print("match end of option list op code.")breakoption_length = int.from_bytes(option_raw_data[cursor + 2: cursor + 4], section_endian)option_value = option_raw_data[cursor + 4: cursor + 4 + option_length]if option_code in pnp:#todo: 在这里解析并打印各option的值。print("option:%s, option_length:%d(%d)" % (pnp[option_code], option_length, round_to_4byte(option_length)),"option_value:", option_value)else:print("option:%d, option_length:%d(%d)" % (option_code, option_length, round_to_4byte(option_length)),"option_value:", option_value)cursor += (4 + round_to_4byte(option_length))remain_option_length = opition_real_len - cursordef read_from_file_object(self, file_object):return_value = Falsetry:data = file_object.read(4)self._block_total_length = int.from_bytes(data, self._endian)self._block_total_length_with_padding = round_to_4byte(self._block_total_length)print("length: %d(%d)" % (self._block_total_length, self._block_total_length_with_padding))record_type = int.from_bytes(file_object.read(2), self._endian)record_value_length = int.from_bytes(file_object.read(2), self._endian)file_offset = 4 + 4 + 4while record_type != 0x0000:record_value_length_with_padding = round_to_4byte(record_value_length)raw_record_value_with_padding = file_object.read(record_value_length_with_padding)if 0x0001 == record_type:print("record type nrb_record_ipv4")elif 0x0002 == record_type:print("record type nrb_record_ipv6")else:print("record type UNKNOWN")#todo:在这里根据不同的记录类型解析出IP和名字并打印内容。print("data:", raw_record_value_with_padding[0:record_value_length])record_type = int.from_bytes(file_object.read(2), self._endian)record_value_length = int.from_bytes(file_object.read(2), self._endian)file_offset = file_offset + raw_record_value_with_padding + 4options_length = self._block_total_length_with_padding - file_offset - 4if options_length != 0:options_raw_data = file_object.read(options_length)self.parse_options(options_raw_data, options_length)block_total_length_backward = int.from_bytes(file_object.read(4), self._endian)if block_total_length != block_total_length_backward:print("错误,前后块长度不一致。")return Falsereturn_value = Trueexcept Exception as e:print(e)return return_valueclass PcapngInterfaceStasticsBlock:"""4.6.  Interface Statistics BlockInterface Statistics Block (ISB)包含给定接口的捕获统计数据,它是可选的。统计数据和当前section中定义的接口关联,由接口ID字段标识。 Interface Statistics Block通常放置在文件的末尾,但不能对其位置进行假设 - 它甚至可以针对同一接口多次出现。The format of the Interface Statistics Block is shown in Figure 14.1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+0 |                   Block Type = 0x00000005                     |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+4 |                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+8 |                         Interface ID                          |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+12 |                        Timestamp (High)                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+16 |                        Timestamp (Low)                        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+20 /                                                               //                      Options (variable)                       //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Figure 14: Interface Statistics Block FormatThe fields have the following meaning:*  Block Type: The block type of the Interface Statistics Block is 5.*  Block Total Length: total size of this block, as described inSection 3.1.*  Interface ID: 指定这些统计信息所关联的接口; 正确的接口将是其Interface Description Block(在文件的当前Section内)由该字段的相同编号(参见第 4.2 节)标识的接口。*  Timestamp: 此统计数据所指的时间。 时间戳的格式与Enhanced Packet Block(第 4.3 节)中已经定义的相同; 时间单位的精度由此数据包参考的Interface Description Block的“if_tsresol”选项(参见图 10)指定。*  Options: optionally, a list of options (formatted according to therules defined in Section 3.5) can be present.所有统计字段都定义为选项,以应对没有完整统计集的系统使用。 因此,除了第 3.5 节中定义的选项外,以下选项在此块中有效:+==================+======+========+===================+| Name             | Code | Length | Multiple allowed? |+==================+======+========+===================+| isb_starttime    | 2    | 8      | no                |+------------------+------+--------+-------------------+| isb_endtime      | 3    | 8      | no                |+------------------+------+--------+-------------------+| isb_ifrecv       | 4    | 8      | no                |+------------------+------+--------+-------------------+| isb_ifdrop       | 5    | 8      | no                |+------------------+------+--------+-------------------+| isb_filteraccept | 6    | 8      | no                |+------------------+------+--------+-------------------+| isb_osdrop       | 7    | 8      | no                |+------------------+------+--------+-------------------+| isb_usrdeliv     | 8    | 8      | no                |+------------------+------+--------+-------------------+Table 8: Interface Statistics Block Optionsisb_starttime:isb_starttime 选项指定捕获开始的时间; 时间将存储在两块中,每块四字节。时间戳的格式与Enhanced Packet Block(第 4.3 节)中定义的格式相同; 时间单位的精度由此数据包引用的Interface Description Block的“if_tsresol”选项(参见图 10)指定。Example: '96 c3 04 00 73 89 6a 65', in Little Endian, decodes to2012-06-29 06:17:00.834163 UTC.isb_endtime:isb_endtime 选项指定捕获结束的时间; 时间将存储在两块中,每块四字节。时间戳的格式与Enhanced Packet Block(第 4.3 节)中定义的格式相同; 时间单位的精度由此数据包引用的Interface Description Block的“if_tsresol”选项(参见图 10)指定。Example: '97 c3 04 00 aa 47 ca 64', in Little Endian, decodes to2012-06-29 07:28:25.298858 UTC.isb_ifrecv:isb_ifrecv选项为64位无符号整数,表示捕获开始后从物理接口收到的数据包数。Example: the decimal number 100.isb_ifdrop:isb_ifdrop选项为64 位无符号整数,表示从捕获开始后由于缺少资源而被接口丢弃的数据包数。Example: '0'.isb_filteraccept:isb_filteraccept选项为64位无符号整数,表示捕获开始后从过滤器处接收的数据包数。Example: the decimal number 100.isb_osdrop:isb_osdrop选项为64位无符号整数,表示操作系统从捕获开始后丢弃的数据包数。Example: '0'.isb_usrdeliv:isb_usrdeliv 选项为64 位无符号整数,表示从捕获开始后传递给用户的数据包数。此字段的值可能与“isb_filteraccept - isb_osdrop”的结果不同,因为某些数据包可能在捕获结束时仍在操作系统缓冲区中。Example: '0'.所有与数据包计数器有关的字段都是 64 位值,用当前部分的字节序表示。 访问这些字段时必须特别小心:由于所有块都与32位边界对齐,因此不能保证这些字段在 64 位边界上对齐。"""_endian = ""_block_total_length = 0_block_total_length_with_padding = 0_interface_id = 0_timestamp_high = 0_timestamp_low = 0raw_options_data_length = 0_raw_options_data = Nonedef __init__(self, endian):self._endian = endiandef parse_options(self):if 0 == self.raw_options_data_length or self._raw_options_data is None:return Falsepnp = {2: "isb_starttime", 3: "isb_endtime", 4: "isb_ifrecv", 5: "isb_ifdrop", 6: "isb_filteraccept",7: "isb_osdrop", 8: "isb_usrdeliv"}remain_option_length = self.raw_options_data_lengthcursor = 0opt_endofopt = 0while remain_option_length != 0:option_code = int.from_bytes(self._raw_options_data[cursor: cursor + 2], section_endian)if option_code == opt_endofopt:print("match end of option list op code.")breakoption_length = int.from_bytes(self._raw_options_data[cursor + 2: cursor + 4], section_endian)option_value = self._raw_options_data[cursor + 4: cursor + 4 + option_length]if option_code in pnp:#todo: 在这里解析并打印各option的值。如下if 2 == option_code:的代码块所示:if 2 == option_code:if option_length != 8:raise Exception("bad length of option isb_starttime")start_time_high = int.from_bytes(option_value[0:4], section_endian)start_time_low = int.from_bytes(option_value[4:8], section_endian)print("option isb_starttime, (high:low) %d:%d"%(start_time_high, start_time_low))print("option:%s, option_length:%d(%d)" % (pnp[option_code], option_length, round_to_4byte(option_length)),"option_value:", option_value)else:print("option:%d, option_length:%d(%d)" % (option_code, option_length, round_to_4byte(option_length)),"option_value:", option_value)cursor += (4 + round_to_4byte(option_length))remain_option_length = self.raw_options_data_length - cursordef read_from_file_object(self, file_object):return_value = Falsetry:data = file_object.read(4)self._block_total_length = int.from_bytes(data, self._endian)self._block_total_length_with_padding = round_to_4byte(self._block_total_length)self._interface_id = int.from_bytes(file_object.read(4), self._endian)self._timestamp_high = int.from_bytes(file_object.read(4), self._endian)self._timestamp_low = int.from_bytes(file_object.read(4), self._endian)self.raw_options_data_length = self._block_total_length_with_padding - 24self._raw_options_data = file_object.read(self.raw_options_data_length)self.parse_options()block_total_length_backward = int.from_bytes(file_object.read(4), self._endian)if block_total_length != block_total_length_backward:print("错误,前后块长度不一致。")return Falsereturn_value = Trueexcept Exception as e:print(e)return return_valueclass PcapngCustomBlock:"""4.8.  Custom BlockCustom Block (CB) 是用于存储不属于另一个块的自定义数据的容器; 要将自定义数据存储为另一个块的一部分,请参阅第 3.5.1 节。 Custom Block是可选的,可以重复任意次数,并且可以出现在任何其他块之前或之后,除了必须在文件中首先出现的第一个Section Header Block。可以在同一个 pcapng 文件中使用不同类型代码和/或不同Private Enterprise Numbers的Custom Block。The format of a Custom Block is shown in Figure 18.1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+0 |             Block Type = 0x00000BAD or 0x40000BAD             |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+4 |                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+8 |                Private Enterprise Number (PEN)                |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+12 /                                                               //                          Custom Data                          //              variable length, padded to 32 bits               //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+/                                                               //                      Options (variable)                       //                                                               /+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      Block Total Length                       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Figure 18: Custom Block FormatCustom Block使用类型代码 0x00000BAD(十进制 2989)作为自定义块,pcapng 重写者可以将其复制到新文件中,类型代码 0x40000BAD(十进制为 1073744813)用于不应复制的块。有关详细信息,请参阅第 5.2 节。The Custom Block has the following fields:*  Block Type: The block type of the Custom Block is 0x00000BAD or0x40000BAD, as described previously.*  Block Total Length: total size of this block, as described inSection 3.1.*  Private Enterprise Number (32 bits): IANA 分配的私营企业编号,用于标识那个定义此Custom Block的组织。 有关详细信息,请参阅第 5.1 节。 PEN 必须使用与它在其范围内的Section Header Block相同的字节序进行编码。*  Custom Data: the custom data, padded to a 32 bit boundary.*  Options: optionally, a list of options (formatted according to therules defined in Section 3.5) can be present.  Note that customoptions for the Custom Block still use the custom option formatand type code, as described in Section 3.5.1."""_endian = ""_block_total_length = 0_block_total_length_with_padding = 0_private_enterprise_number = -1def __init__(self, endian):self._endian = endiandef read_from_file_object(self, file_object):return_value = Falsetry:data = file_object.read(4)self._block_total_length = int.from_bytes(data, self._endian)self._block_total_length_with_padding = round_to_4byte(self._block_total_length)self._private_enterprise_number = int.from_bytes(file_object.read(4), self._endian)print("private enterprise number:", self._private_enterprise_number)raw_custom_data_and_options_length = self._block_total_length_with_padding - 4 - 4 - 4 - 4raw_custom_data_and_options = file_object.read(raw_custom_data_and_options_length)# todo: parse custom data and options.block_total_length_backward = int.from_bytes(file_object.read(4), self._endian)if block_total_length != block_total_length_backward:print("错误,前后块长度不一致。")return Falsereturn_value = Trueexcept Exception as e:print(e)return return_valueif __name__ == '__main__':parser = OptionParser(usage="%prog [options]")parser.add_option("-f", "--file", action="store", type="string", dest="file_to_parse", help=u"指定一个需要解析的文件(需要全路径)")(options, args) = parser.parse_args()if options.file_to_parse is None:print("请使用-f或者--file=指定一个需要解析的文件(需要全路径)。")else:with open(options.file_to_parse, "rb") as f:data = f.read(4)# 一般而言 big: 网络字节序, little:主机字节序# 0x0A0D0D0A是回文,所以下面这句传入big or little都无所谓。block_type = int.from_bytes(data, "big")if block_type != BlockTypeCode.BTS_SectionHeaderBlock.value:f.close()exit(1)a = PcapngSecionHeaderBlock()result = a.read_from_file_object(f)print("parse pcapng section header block:", result)section_endian = a.get_endian()eof = Falsewhile not eof:print("-------------------------------------")data = f.read(4)block_type = int.from_bytes(data, section_endian)if BlockTypeCode.BTS_InterfaceDescriptionBlock.value == block_type:b = PcapngInterfaceDescriptionBlock(section_endian)result = b.read_from_file_object(f)print("parse pcapng interface description block:", result)elif BlockTypeCode.BTS_DecryptionSecretsBlock.value == block_type:c = PcapngDecryptionSecretsBlock(section_endian)result = c.read_from_file_object(f)print("parse pcapng Decryption Secrets Block:", result)elif BlockTypeCode.BTS_EnhancedPacketBlock.value == block_type:d = PcapngEnhancePackageBlock(section_endian)result = d.read_from_file_object(f)print("parse pcapng Enhance packet block:", result)elif BlockTypeCode.BTS_SimplePacketBlock.value == block_type:e = PcapngSimplePacketBlock(section_endian)result = e.read_from_file_object(f)print("parse pcapng Simple packet block:", result)elif BlockTypeCode.BTS_NameResolutionBlock.value == block_type:g = PcapngNameResolveBlock(section_endian)result = g.read_from_file_object(f)print("parse pcapng Name Resolve Block:", result)elif BlockTypeCode.BTS_InterfaceStatisticsBlock.value == block_type:h = PcapngInterfaceStasticsBlock(section_endian)result = h.read_from_file_object(f)print("parse pcapng Interface Stastics Block:", result)elif BlockTypeCode.BTS_CustomBlockWhichCanBeCopied.value == block_type \or BlockTypeCode.BTS_CustomBlockWhichShouldNotBeCopied.value == block_type:i = PcapngCustomBlock(section_endian)result = i.read_from_file_object(f)print("parse pcapng Custom Block:", result)else:data = f.read(4)block_total_length = int.from_bytes(data, section_endian)print("block type: %d, length: %d"%(block_type, block_total_length))if block_total_length == 0:print("read zero length block. break.")breakblock_total_length_with_padding = round_to_4byte(block_total_length)data = f.read(block_total_length_with_padding - 4)if not result:breakf.close()

pacpng文件格式说明相关推荐

  1. 《Java虚拟机规范》阅读(三):Class文件格式

    每一个Class都对应着唯一的一个类或借口的定义信息.这里,我们称为"Class文件格式"只是通俗的将任意一个符合有效的类或借口的格式这么称呼,但是它并不一定是以磁盘文件的形式存在 ...

  2. linux 压缩文件夹格式,Linux下常见文件格式的压缩、解压小结

    Linux下常见文件格式的压缩.解压小结 .tar 解包: tar xvf FileName.tar 打包:tar cvf FileName.tar DirName (注:tar是打包,不是压缩!) ...

  3. 二、OCR训练时,将txt文件和图片数据转为lmdb文件格式

    文章目录 前言 一.背景? 二.直接上内容 1.代码 2.文件说明 前言 随着人工智能的不断发展,机器学习这门技术也越来越重要,本文就介绍OCR训练前ldmb文件制作的基础内容. 提示:以下是本篇文章 ...

  4. Ubuntu 14.04 64bit上解析wireshark抓包pcap文件格式和源码实现

    pcap文件格式是常用的数据报存储格式,包括wireshark在内的主流抓包软件都可以生成这种格式的数据包 下面对这种格式的文件简单分析一下:  pcap文件的格式为:   文件头    24字节   ...

  5. 3D中的OBJ文件格式详解(转载)

    OBJ文件是Alias|Wavefront公司为它的一套基于工作站的3D建模和动画软件"Advanced Visualizer"开发的一种标准3D模型文件格式,很适合用于3D软件模 ...

  6. vim windows linux文件格式转换

    vim windows linux文件格式转换 set ff?     #显示当前文件格式 set ff=unix     #设置成unix格式 set ff=dos #设置成dos格式 posted ...

  7. PE文件和COFF文件格式分析——导出表的应用——一种摘掉Inline钩子(Unhook)的方法

    在日常应用中,某些程序往往会被第三方程序下钩子(hook).如果被下钩子的进程是我们的进程,并且第三方钩子严重影响了我们的逻辑和流程,我们就需要把这些钩子摘掉(Unhook).本件讲述一种在32位系统 ...

  8. PE文件和COFF文件格式分析——导出表的应用——通过导出表隐性加载DLL

    通过导出表隐性加载DLL?导出表?加载DLL?还隐性?是的.如果觉得不可思议,可以先看<PE文件和COFF文件格式分析--导出表>中关于"导出地址表"的详细介绍.(转载 ...

  9. PE文件和COFF文件格式分析——导出表的应用——一种插件模型

    可能在很多人想想中,只有DLL才有导出表,而Exe不应该有导出表.而在<PE文件和COFF文件格式分析--导出表>中,我却避开了这个话题.我就是想在本文中讨论下载Exe中存在导出表的场景. ...

  10. PE文件和COFF文件格式分析——导出表

    在之前的<PE可选文件头>相关博文中我们介绍了可选文件头中很多重要的属性,而其中一个非常重要的属性是(转载请指明来源于breaksoftware的CSDN博客) IMAGE_DATA_DI ...

最新文章

  1. UI设计培训技术分享:搞定萌萌哒可爱图标
  2. 【数据结构】树状数组 例题剖析
  3. 30分钟带你熟练性能优化的那点儿事儿(案例说明)
  4. WPF控件textBox多行输入设置
  5. php自定义中文分词方法,一个用PHP写的中文分词函数_php
  6. python中session的使用方法_python中requests库session对象的妙用详解
  7. javascript操作listbox方法 【转】
  8. Context mContext = getApplicationContext();
  9. Windows系统下将目录挂载为一个磁盘并分配盘符
  10. 操作系统实验一实验报告
  11. java后台模板_Java服务端后台常用模板
  12. 中英文对照 —— 风景名胜、国家城市(专有名词)
  13. 靠2块钱月入4万:越朴素的方法,往往越挣钱
  14. Spring boot 中使用 Thymeleaf
  15. Graph Representation Learning via Graphical Mutual Information Maximization
  16. 金融业信贷风控算法2-初等统计理论
  17. 对刚装好系统的Linux配置软件开发生产环境,让你开发效率一飞冲天!
  18. Dancing Line、网易蜗牛读书——创新性分析
  19. 【算法】重新排序数组中正数和负数
  20. offsetParent解释

热门文章

  1. html设置分割线虚线,css border设置虚线样式?
  2. 超详细VRRP基础配置
  3. 【Vue.$delete】 删除
  4. 自己做量化交易软件(38)小白量化实战11--双向高频马丁交易策略
  5. d3中文案例_D3js初探及数据可视化案例设计实战 -web开发
  6. GH4169高温合金执行什么标准
  7. it职位简称_IT行业常见职位英文缩写
  8. Spring框架浅谈及Spring框架学习小结
  9. c语言的二维数组的指针访问,用指针访问二维数组
  10. jacob将WORD转换成PDF文件(要装有Word另存为PDF文件的插件)