如何在 C# 中解析 Pcapng 文件?

How Can I Parse a Pcapng File in C#?

我是 Pcapng 文件的新手。 40多页的白皮书我都看完了,还在摸不着头脑,满头大汗。我了解到 Pcapng 文件是:

  1. 由节头块组成 - 这是每个 Pcapng 文件的开始。

问题 1:这有多大?

看起来是 BlockType(4 字节)+ BlockTotalLength(4 字节)+ 字节顺序魔法(4 字节)+ Mahor 和 Minor Version(总共 4 字节,每个 2 字节)+ Section Length(4 字节)+选项(可变)+ 块总长度(同样是 4 个字节)。

如果我正在构建一个解析器,我怎么知道我需要跳过多少字节才能到达我的第一个数据帧块?

问题2:数据存储在哪里?数据是指包含以太网、IP 和 TCP 数据的整个帧,如下图所示(图 1)。

文档指出:

A section includes data delimited by two section header blocks.

在进行手动检查时(是的,我逐字节查看文件以查看两帧之间有多少字节 :'( ),我注意到每条消息之间有 35 个字节(显示的每条消息在 wireshark 上,中间有 35 个字节。这些字节与 pcapng 块有关吗?

一旦我了解了如何到达第一个 tcp 帧,以及我需要跳过多少字节才能到达下一个,我就可以构建我的解析器。

我愿意将 Bitcoin/Monero 发送给任何可以帮助我了解如何最好地解析这些 pcapng 消息的人。谢谢!

我认为 @tee-zad-awk 找到了一个对 https://ask.wireshark.org/question/15159/how-can-i-display-as-much-pcapng-information-as-possible/ 有所帮助的答案,但为了其他任何寻找此问题答案的人的利益,我 linked它在这里并在下面提供了我的答案,以防万一 link 有一天被打破了。


看来,在阅读了 Pcapng 的 40 页白皮书后......

当前的 PCAP Next Generation (pcapng) Capture File Format draft document is 52 pages, so perhaps you're not looking at the most recent version? Other versions do exist, such as those at https://datatracker.ietf.org/doc/html/draft-tuexen-opswg-pcapng-00, https://pcapng.github.io/pcapng/ or https://www.tcpdump.org/pcap/pcap.html 可能还有其他的,但它们都已过时。

如果您正在寻找 pcapng 解析器来帮助您解密文件,那么 Wireshark 本身就是您的最佳选择。如果您已将 pcapng 文件加载到 Wireshark 中,则可以使用 "View -> Reload as File Format/Capture" (Ctrl+Shift+F) 来加载 Wireshark 并显示原始文件内容本身,而不是加载和显示文件中的数据包。这应该使您能够看到各种 pcapng 块并能够深入了解它们。例如:

Frame 1: 184 bytes on wire (1472 bits), 184 bytes captured (1472 bits)
MIME file
PCAPNG File Format
    Block: Section Header Block 1
    Block: Interface Description Block 0
    Block: Enhanced Packet Block 1

您还可以查看 Wireshark 源代码,例如 epan/dissectors/file-pcapng.c and wiretap/pcapng.c 文件。

顺便说一下,如果您希望支持所有扩展,Wireshark [PcapNg wiki 页面](https://wiki.wireshark.org/Development/PcapNg) has a link to Augmented PCAP Next Generation Dump File Format 页面您可能还想看看。我不知道如何许多其他扩展可能已经实现,但没有包含在主要的 pcapng 文件格式规范中,但希望不会很多,因为这可能很快就会成为问题,因为不同的项目可能对不同的块使用相同的块类型。这种做法应该非常不鼓励。

If I'm building a parser, how would I know how many bytes I need to skip to arrive at my first data frame block?

你不是那样做的。

如果您要构建解析器,请注意解析器必须查看的不仅仅是第一个数据帧块。

首先,它必须查看the Section Header Block (SHB),通过查看Byte-Order Magic 字段来确定所有后续块中数据的字节顺序。

在那之后,你需要查看所有后续块,寻找 Interface Description Blocks and Enhanced Packet Blocks (EPBs), Simple Packet Blocks (SPBs), and possibly Packet Blocks (PB)(那些已经过时,所以没有程序应该 写入 它们,但是程序应该准备好 阅读 它们)。每个 EPB 或 PB 都有一个引用 IDB 的接口 ID,它必须出现在相关 EPB 或 PB 之前; SPB 隐式引用第一个 IDB,同样,它必须出现在相关 SPB 之前。

EPB、SPB 或 PB 中数据包的格式取决于它所引用的 IDB 指定的 link 层类型,因此您需要阅读相关 IDB。

而且,如上所示,SHB与第一个EPB、SPB、PB之间没有固定字节数,所以没有简单的固定字节数要跳过的字节以到达第一个数据帧块。首先,字节数是可变的,您只能通过读取第一个 EPB、SPB 或 PB 之前的所有块来确定。另一方面,您不能跳过它们,您必须阅读它们以获得足够的信息来解释其中的数据包数据。

Where is the data stored? By data I mean the entire frame that contains Ethernet, IP, and TCP Data, as shown in the picture below (Figure 1).

它存储在 EPB、SPB 或 PB 中。请参阅这三种块类型的描述;帧在这些块的 "Packet Data" 字段中。

So I'm at my Interface Description Block and the 64 bit number that contains both a Timestamp Resolution of 9 (10^-9, Nanoseconds?) and 6 (10^-6, Microseconds).

正如 Christopher Maynard 指出的那样,9 不是时间戳解析,而是一种选项类型。 Pcapng 块在开头和 options 都有固定信息;选项以选项类型和选项值长度开头,然后是选项数据。 IDB if_tsresol 选项有

  • 2字节的选项类型,值为9;
  • 2个字节的选项值长度,值为1;
  • 1 个字节的选项值,该值在该选项的描述中指定。

值为 6 表示时间戳分辨率为 1/10^6 秒,即 1 微秒。

为了找出它,阅读网络设备的协议规范和已发送的包是有帮助的。例如,我们需要知道以太网设备的帧描述和TCP/IP包的包描述,才能理解原始数据。研究完这个,我们在Wireshark中记录一些流量,在Wireshark的上层windowselect一个block。中间的 window 会以明文告诉你 Wireshark 收到了什么。单击中间 window 中的任何一行时,Wireshark 将在下方 window 中标记原始数据的字节,这些字节包含单击行的信息。另外,您可以单击原始数据,然后标记明文。此外,状态行也会通知您。这对理解数据很有帮助。

我需要读取以太网流量的 TCP/IPv4 包。该块以标识block type = 0x00000006和块的长度开始。该设备是以太网,所以我有 link 类型 LINKTYPE_ETHERNET。段长度可以取自字节 16-23。块 header 的其他条目可以从 here.

中获取

在块 header 或 28 字节之后,以太网帧带有以下条目(有关说明,请参阅 here):

  • mac 地址目的地,6 字节
  • mac地址源,6字节
  • 类型:IPv4 为 0x0800,ARP 为 0x0806,IPv6 为 0x86DD,IEEE 802.1Q 标签为 0x8100。

对于 IPv4 包或 type = 0x0800,以下字节是 IPv4 header(参见 here 的描述):

  • IP 版本和 header 长度,1 个字节
  • 区分服务字段,1字节
  • 总长度,2字节
  • 标识,2字节
  • 标志,1 字节
  • 分片偏移,1字节
  • 生存时间,1 字节
  • TCP 为 0x06 的协议,1 个字节
  • header校验和,2字节
  • 源IP地址
  • 目的IP地址
  • 选项

总长度很重要:IPv4+TCP包最后一个字节后面的字节位于总长度字节条目IP版本和header长度之后。但是,此条目可能很棘手。尽管 IP header 长度已经有 20 个字节,但我使用了一个长度为 0 的条目。在这种情况下,Wireshark 很有帮助。报道

[总长度:1547字节(报0,推测是因为“TCP分段卸载”(TSO))]

关于这种现象的详细描述可以参考here。在这种情况下,我可以通过上面的部分长度减去以太网帧的长度(14 字节)减去 IP 的长度 Header 减去 TCP 的长度 header 来计算有效负载长度。但是,尽管我没有这些问题,但可能会出现填充问题。包长度扩展到4字节的倍数什么的时候会出现padding问题

如果IPv4header的协议是0x06,则后面是TCP包。 TCP包的详细信息可以从here中获取。当然,Wireshark也可以帮你解读TCP包:点击中间属于TCP包的行window或者点击原始数据

如此处所述,pcapng 文件的解释有很多假设和条件。