Scapy: using a PacketListField to process multiple packages contained in a package

I am trying to parse packages that encapsulate another package-like structure called "tags." The structure looks like this:

+---------+
|Ether    |
+---------+
|IP       |                   a tag
+---------+
|UDP      |                +------------+
+---------+                |tagNumber   |
|BVLC     |                +------------+
+---------+                |tagClass    |
|NPDU     |                +------------+
+---------+           +-+  |LVT field   |
|APDU     |           |    +------------+
|  +------+--+        |    |            |
|  |Tag 1    | <------+    |  data      |
|  +---------+             |            |
|  |Tag 2    |             +------------+
|  +---------+
|  |Tag n    |
+------------+

To do this, I created a class derived from an existing PacketListFieldone that looks like this:

class TagListField(PacketListField):
    def __init__(self):
        PacketListField.__init__(
            self,
            "tags",
            [],
            guessBACNetTagClass,

The specified guessBACNetTagClassis a function that returns the correct class needed to parse the tag.

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)

There are currently, as you can see from the dictionary BACNetTagClassesabove, two of these classes.

class BACNetTag_Object_Identifier(Packet):
    name = "BACNetTag_Object_Identifier"
    fields_desc =[
        # fields
    ]

class BACNetTag_U_int(Packet):
    name = "BACNetTag_U_int"
    fields_desc = [
        # fields
    ]

In the encapsulating layer called APDU, I added TagListFieldas another field.

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? , , .


UPDATE:

.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. , , .

+4

Source: https://habr.com/ru/post/1616217/


All Articles