python - Scapy:使用 PacketListField 剖析一个数据包中包含的多个数据包

标签 python packet scapy bacnet

我正在尝试剖析数据包,它封装了另一个类似数据包的结构,称为“标签”。结构看起来像这样

+---------+
|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 帖子:

Scapy: Adding new protocol with complex field groupings

关于python - Scapy:使用 PacketListField 剖析一个数据包中包含的多个数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33756348/

相关文章:

python - Python 中的 Bland-Altman 图

带模板的 C++ 数据包生成器

python - Clojure 素数惰性序列

javascript - 如何在ajax调用中使用flask url_for?

iOS 9 中的数据包隧道提供程序

java - Java中的数据包封装

python - 使用 scapy 作为 MITM 即时更改数据包

python - scapy如何检查是否设置了一个字段

python - 通过networkx并使用python在图中添加节点和边

python - 用于确认字符串是否为有效 Python 标识符的正则表达式?