我一直在玩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'>
当我想把以太对象转换成字符串时 它给我的是十六进制和阿斯奇数字的混合体 (如随机括号和括号所示)
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,但我找不到解析它的方法。
我现在找不到合适的dupe,但这只是一个误用误解,对 str()
. 原始数据为字节格式,例如 x = b'moo'
.
当 str()
检索你的字节字符串,它将通过调用 __str__
的作用 bytes
classobject。这将返回一个自身的表示。该表示将保持 b
在开头,因为它被认为是为了区分并使人类更容易理解这是一个字节对象,以及避免编码问题,我想。(均为猜测).
就像你尝试访问 tcpPackets[0]
在终端上,它将调用 __repr__
并向你展示这样的东西 <class 'scapy.layers.l2.Ether'>
最有可能。
作为一个你可以实验的例子代码,可以试试这个。
class YourEther(bytes):
def __str__(self):
return '<Made Up Representation>'
print(YourEther())
很明显scapy's会返回另一个表示方式, 而不是一个静态的字符串说 "编造的表示方式". 但你大概明白了。
所以在这样的情况下 <class 'scapy.layers.l2.Ether'>
它 __repr__
或 __str__
函数可能返回 b'$\\xa2\\.......
而不是它的默认类表示 (这里可能会有一些修正,因为我不记得知道所有行为的技术命名).
作为一种变通办法。这个 可能会解决你的问题。
hexlify(str(tcpPackets[0]))
但你可能要考虑到前缀的问题。b'
以及尾随 '
并据此删除这些。(注意 "
不会添加在开头或结尾,这些只是打印时在你的控制台的第二种表示。从数据上看,它们其实并不存在)
Scapy可能更多的是想用 tcpPackets[0].dst
而不是抓取原始数据。但我对Scapy没有什么经验,但它是一个抽象层是有原因的,它可能隐藏了原始数据,或者它在核心文档的某个地方,我现在找不到。
更多关于 __str__
说明。python的`str()`函数是否会调用类的`__str__()`函数?
最后一个问题,就是如果你真的想访问原始数据,似乎可以用 原始的 类。发现原始负载,如何访问?
你可以把一个数据包的所有字节放到一个 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
比把所有的数据包放到一个类似的大数组中需要20倍的时间。for
1.5GB文件的循环。