如何从 pcap 文件中获取原始十六进制值?

How to get raw hex values from pcap file?

我一直在玩弄scapy,想通读并分析每个十六进制字节。到目前为止,我一直在使用 scapy 只是因为我目前不知道另一种方式。在我自己编写工具来浏览 pcap 文件之前,我想知道是否有一种简单的方法可以做到这一点。这是我到目前为止所做的。

packets = rdpcap('file.pcap')
tcpPackets = []
  for packet in packets:
    if packet.haslayer(TCP):
      tcpPackets.append(packet)

当我 运行 type(tcpPackets[0]) 我得到的类型是:

<class 'scapy.layers.l2.Ether'>

然后,当我尝试将 Ether 对象转换为字符串时,它给了我十六进制和 ascii 的混合(如随机括号和方括号所示)。

str(tcpPackets[0])
"b'$\xa2\xe1\xe6\xee\x9b(\xcf\xe9!\x14\x8f\x08\x00E\x00\x00[:\xc6@\x00@\x06\x0f\xb9\n\x00\x01\x04\xc6)\x1e\xf1\xc0\xaf\x07[\xc1\xe1\xff0y<\x11\xe3\x80\x18 1(\xb8\x00\x00\x01\x01\x08\n8!\xd1\x888\xac\xc2\x9c\x10%\x00\x06MQIsdp\x03\x02\x00\x05\x00\x17paho/34AAE54A75D839566E'"

我也尝试过使用 hexdump,但找不到解析它的方法。

我现在找不到合适的复制品,但这只是 str() 的 miss-use/miss-understanding。原始数据为字节格式,例如 x = b'moo'.

str() 检索您的字节字符串时,它将通过调用 bytes class/object 的 __str__ 函数来实现。那将 return 代表自己。该表示形式将在开头保留 b 因为它被认为可以区分并使人们更容易理解它是一个字节对象,并且可以避免编码问题我猜 (所有这些都是猜测).

就像您尝试从终端访问 tcpPackets[0] 一样,它会调用 __repr__ 并最有可能向您显示类似 <class 'scapy.layers.l2.Ether'> 的内容。

作为您可以试验的示例代码,试试这个:

class YourEther(bytes):
    def __str__(self):
        return '<Made Up Representation>'

print(YourEther())

显然 scapy 的 return 是另一种表示形式,而不仅仅是表示 "made up representation" 的静态字符串。但你可能明白了。

所以在 <class 'scapy.layers.l2.Ether'> 的情况下,它是 __repr____str__ 函数可能 returns b'$\xa2\....... 而不是默认的 class表示 (这里可能会有一些更正,因为我没有 remember/know 行为的所有技术命名)

作为解决方法,this 可能会解决您的问题:

hexlify(str(tcpPackets[0]))

您可能必须考虑所有前缀 b' 以及尾随 ' 并相应地删除它们。 (注意:"不会添加在开头或结尾,它们只是打印时控制台中的第二个表示。它们实际上并不存在于数据中)

Scapy 可能更倾向于使用 tcpPackets[0].dst 而不是抓取原始数据。但我对 Scapy 的经验很少,但它是一个抽象层是有原因的,它可能隐藏了原始数据,或者它在我现在找不到的核心文档中。

有关 __str__ 描述的更多信息:

最后一点,那就是如果你真的想访问原始数据,你可以使用 Raw class: Raw load found, how to access?

来访问它

您可以将数据包的所有字节放入一个 numpy 数组,如下所示:

for p in tcpPackets:
    raw_pack_data = np.frombuffer(p.load, dtype = np.uint8)
    # Manipulate the bytes stored in raw_pack_data as you like.

这很快。在我的例子中,rdpcap 比将所有数据包放入一个类似 for 循环的大数组中用于 1.5GB 文件的时间长约 20 倍。