I am trying to dissect packets, which encapsulate another packet-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 |
+------------+
For this I created a class derived from the existing PacketListField
, which looks like this:
class TagListField(PacketListField):
def __init__(self):
PacketListField.__init__(
self,
"tags",
[],
guessBACNetTagClass,
The referenced guessBACNetTagClass
is a function which returns the correct class needed to dissect 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)
Currently there are, as you can see from the BACNetTagClasses
dictionary from above, 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 the TagListField
just like another field.
class APDU(Packet):
name = "APDU"
fields_desc = [
# Some other fields
TagListField()
]
A packet, which I am currently trying to dissect, contains multiple tags. The first one (of the type BACNetTag_Object_Identifier
) can be correctly dissected, but the remaining tags are just listed as raw payload.
[<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'
|>>] |>>>>>>]
Is there something wrong with my implementation of PacketListField
? As I understand, the field should try to dissect the remaining tags until no more Bytes are left.
UPDATE:
Using .show()
reveals a bit more about the packets structure
###[ 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 just appends the remaining Bytes as a Raw
layer to the existing tags
field. That's interesting, but I still don't know why it is doing so.
Sniffing packets using scapy: To sniff the packets use the sniff() function. The sniff() function returns information about all the packets that has been sniffed. To see the summary of packet responses, use summary(). The sniff() function listens for an infinite period of time until the user interrupts.
Send and receive packets (sr) The function sr1() is a variant that only returns one packet that answered the packet (or the packet set) sent. The packets must be layer 3 packets (IP, ARP, etc.).
Scapy runs natively on Linux, Windows, OSX and on most Unixes with libpcap (see scapy's installation page). The same code base now runs natively on both Python 2 and Python 3.
ls() : Displays all the protocols supported by scapy. lsc() : Displays the list of commands and functions supported by scapy. conf : Displays all configuration options. help() : Displays help on a specific command, for example, help(sniff)
Try to overwrite the extract_padding
method of your BACNet_Tag*
classes with:
def extract_padding(self, s):
return '', s
I had similar problems with PacketListField
and found this stackoverflow post:
Scapy: Adding new protocol with complex field groupings
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With