我正在尝试剖析数据包,它封装了另一个类似数据包的结构,称为“标签”。结构看起来像这样
+---------+
|Ether |
+---------+
|IP | a tag
+---------+
|UDP | +------------+
+---------+ |tagNumber |
|BVLC | +------------+
+---------+ |tagClass |
|NPDU | +------------+
+---------+ +-+ |LVT field |
|APDU | | +------------+
| +------+--+ | | |
| |Tag 1 | <------+ | data |
| +---------+ | |
| |Tag 2 | +------------+
| +---------+
| |Tag n |
+------------+
为此,我创建了一个派生自现有 PacketListField
的类,如下所示:
class TagListField(PacketListField):
def __init__(self):
PacketListField.__init__(
self,
"tags",
[],
guessBACNetTagClass,
引用的 guessBACNetTagClass
是一个返回解析标签所需的正确类的函数。
BACNetTagClasses = {
0x2: "BACNetTag_U_int",
0xC: "BACNetTag_Object_Identifier"
}
def guessBACNetTagClass(packet, **kargs):
""" Returns the correct BACNetTag Class needed to dissect
the current tag
@type packet: binary string
@param packet: the current packet
@type cls: class
@param cls: the correct class for dissection
"""
tagByteBinary = "{0:b}".format(int(struct.unpack("!B", packet[0])[0]))
tagNumber = int(tagByteBinary[0:4],2)
clsName = BACNetTagClasses.get(tagNumber)
cls = globals()[clsName]
return cls(packet, **kargs)
正如您从上面的 BACNetTagClasses
字典中看到的,目前有两个这样的类。
class BACNetTag_Object_Identifier(Packet):
name = "BACNetTag_Object_Identifier"
fields_desc =[
# fields
]
class BACNetTag_U_int(Packet):
name = "BACNetTag_U_int"
fields_desc = [
# fields
]
在封装层中,称为 APDU
我添加了 TagListField
就像另一个字段一样。
class APDU(Packet):
name = "APDU"
fields_desc = [
# Some other fields
TagListField()
]
我目前正在尝试剖析的一个数据包包含多个标签。第一个标签(BACNetTag_Object_Identifier
类型)可以被正确剖析,但其余标签仅作为原始负载列出。
[<Ether |<UDP |<BVLC |<NPDU |<APDU
pduType=UNCONFIRMED_SERVICE_REQUEST reserved=None serviceChoice=I_AM
tags=[<BACNetTag_Object_Identifier tagNumber=BACNET_OBJECT_IDENTIFIER
tagClass=APPLICATION lengthValueType=4L objectType=DEVICE
instanceNumber=640899L |<Raw load='"\x01\xe0\x91\x00!\xde'
|>>] |>>>>>>]
我对 PacketListField
的实现有问题吗?据我了解,该字段应尝试剖析剩余的标签,直到没有更多的字节为止。
更新:
使用 .show()
揭示了更多关于数据包结构的信息
###[ APDU ]###
pduType = UNCONFIRMED_SERVICE_REQUEST
reserved = None
serviceChoice= I_AM
\tags \
|###[ BACNetTag_Object_Identifier ]###
| tagNumber = BACNET_OBJECT_IDENTIFIER
| tagClass = APPLICATION
| lengthValueType= 4L
| objectType= DEVICE
| instanceNumber= 640899L
|###[ Raw ]###
| load = '"\x01\xe0\x91\x00!\xde'
Scapy 只是将剩余的字节作为 Raw
层附加到现有的 tags
字段。这很有趣,但我仍然不知道它为什么这样做。
最佳答案
尝试覆盖 BACNet_Tag*
类的 extract_padding
方法:
def extract_padding(self, s):
return '', s
我在使用 PacketListField
时遇到了类似的问题,并发现了这个 stackoverflow 帖子:
关于python - Scapy:使用 PacketListField 剖析一个数据包中包含的多个数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33756348/