Re: Adding protocol to Scapy
Jochen Bartl <jochen.bartl <at> gmail.com>
2010-02-01 22:30:18 GMT
On Mon, 2010-02-01 at 12:18 +0100, Pierre-François Bonnefoi wrote:
> Hello Jochen,
>
> Thank you for your answer.
>
> First, I've to modify the GuessPayLoadClass() to :
>
> # This function tells the PacketListField, how it should extract
> # the TLVs from the payload
> def _STUNGuessPayloadClass(p, **kargs):
> cls = Raw
> print "Longueur du paquet", len(p)
> if len(p) >= 2:
> # Read 2 bytes (H - Unsigned short) from the payload
> # to get the TLV type value
> t = struct.unpack("!H", p[:2])[0]
> print "type :", t
> # Find out if the value t is in the dict _tlv_cls
> clsname = _tlv_cls.get(t, "STUN_Attribut_defaut")
> # if not, return the default TLV class CDPMsgGeneric
> cls = globals()[clsname]
>
> return cls(p, **kargs)
>
> Because __builtin__ is not applicable (I've used the code of OSPF scapy
> extension that you have contributed to).
>
> Second, I run into trouble :
> --Show
> ###[ STUNPacket ]###
> Type= Binding Request
> Taille= 0
> TransactionID= '1'
> \Attributs\
> ###[ MAPPED-ADDRESS ]###
> Type= 1
> Longueur= 8
> Vide= 0
> Famille= 1
> Port= 987
> Adresse= 1.2.3.4
> ###[ RESPONSE-ADDRESS ]###
> Type= 2
> Longueur= 8
> Vide= 0
> Famille= 1
> Port= 2345
> Adresse= 0.0.0.0
> --Show2
> ###[ STUNPacket ]###
> Type= Binding Request
> Taille= 24
> TransactionID= '1'
> \Attributs\
> |###[ MAPPED-ADDRESS ]###
> | Type= 1
> | Longueur= 8
> | Vide= 0
> | Famille= 1
> | Port= 987
> | Adresse= 1.2.3.4
> |###[ Raw ]###
> | load= '\x00\x02\x00\x08\x00\x01\t)\x00\x00\x00\x00'
>
> The second TLV sub-packet is not analyzed.
>
Did you add the guess_payload_class method which should return the class
"Padding" to the TLV sub-packet classes?
def guess_payload_class(self, p):
return Padding
> So, I've some new questions :
> - What do you mean by this remark :
> > 1.) Define PacketListField + function to extract TLVs in main header of
> > the protocol
> ?
>
PacketListField("tlvlist", [], _STUNGuessPayloadClass)
I just wanted to say that you will have to use the PacketListField and
hand it over the GuessPayLoadClass function to dissect the TLVs.
> I'm confused :
> - does the current packet of PacketListField must prepare the analyze of
> the next
> *or*
> does the PacketListField class take care of this through the
> GuessPayload function ?
> - from the point of view of my code, it seems that I have to do the
> first assumption.
>
Maybe someone other can comment and explain the GuessPayload and layer
dissection question especially in the combination with the
PacketListField, because I've got a bit stuck. But maybe I'll have
tomorrow more time to dig into the source code to come up with an easy
explanation
> My point is to make something the most simple and the most respectful of
> common practices of using Scapy.
>
> It's a work aiming at students so, I've to find the correct way to do
> this (I've some mor philosophical questions about Fields and Class
> inheriting from Packet, but I'll keep them from another time
>
> Thank you for your help,
> Pierre-François.
>
Best Regards,
Jochen
> Le 01/02/10 00:05, Jochen Bartl a écrit :
> > Hi Pierre-François,
> >
> > maybe I can help you to understand the code for parsing TLV fields,
> > because I have used code from the CDP layer for my EIGRP layer.
> >
> > At first, it seems like the AllPacketListField isn't needed anymore in
> > recent Scapy versions. It can be replaced by the normal PacketListField.
> > This reduces the code to the following code fragments, which we should
> > have a look at:
> >
> > # Dictionary to map the TLV type value to the class name of a sub-packet
> > _cdp_tlv_cls = { 0x0001: "CDPMsgDeviceID",
> > 0x0002: "CDPMsgAddr",
> > 0x0003: "CDPMsgPortID",
> > 0x0004: "CDPMsgCapabilities",
> > 0x0005: "CDPMsgSoftwareVersion",
> > 0x0006: "CDPMsgPlatform",
> > 0x0007: "CDPMsgIPPrefix"
> > }
> >
> > # Only a helper function for getting the TLV class
> > # from the global scope.
> > def get_cls(name, fallback_cls):
> > return __builtin__.__dict__.get(name, fallback_cls)
> >
> > # This function tells the PacketListField, how it should extract
> > # the TLVs from the payload
> > def _CDPGuessPayloadClass(p, **kargs):
> > cls = Raw
> > if len(p)>= 2:
> > # Read 2 bytes (H - Unsigned short) from the payload
> > # to get the TLV type value
> > t = struct.unpack("!H", p[:2])[0]
> > # Find out if the value t is in the dict _cdp_tlv_cls
> > # if not, return the default TLV class CDPMsgGeneric
> > cls = get_cls(_cdp_tlv_cls.get(t, "Raw"), CDPMsgGeneric)
> >
> > return cls(p, **kargs)
> >
> >
> > I hope this explanation is not too basic or confuses you more. You could
> > take the following steps to use this code for your own layer:
> >
> > 1.) Define PacketListField + function to extract TLVs in main header of
> > the protocol
> > 2.) Modify _CDPGuessPayloadClass, if your protocol's TLV type field
> > isn't 2 bytes long
> > 3.) Modify also CDPMsgGeneric if the TLV type or length field isn't 2
> > bytes long
> > 4.) Write TLV classes for your sub-packets (TLVs)
> > 5.) Add those classes to the _cdp_tlv_cls dictionary
> > 6.) Maybe you want to replace CDP class and function names with STUN in
> > the code
> >
> >
> > Best Regards,
> >
> > Jochen
> >
> >
> > On Sun, 2010-01-31 at 21:37 +0100, Pierre-François Bonnefoi wrote:
> >> Le 31/01/10 20:48, Tim Broberg a écrit :
> >>> Yep, there you go.
> >>>
> >>> ...or you can use a BitFieldLenField with the number of bits you need.
> >>>
> >>>
> >>> ...or you can derive field classes from FieldLenField like IntField,
> >>> ByteField, ShortField, etc do.
> >>>
> >>> class ByteFieldLenField(FieldLenField):
> >>>
> >>> def __init__(self, name, default, length_of = None, count_of =
> >>> None, adjust = lambda pkt, x=x, fld=None):
> >>>
> >>> FieldLenField.__init__(self, name=name, default=default,
> >>> length_of = length_of, fmt="B", count_of = count_of, adjust
> >>> = adjust, fld=fld)
> >>>
> >> Thank you for your answer.
> >>
> >> Now I'm stuck to understand how adding my protocol (STUN protocol) into
> >> scapy.
> >>
> >> STUN Protocol is defined as :
> >> - a header with some type field in order to identify the message ;
> >> - a body that contain a variable number of sub-packets with different
> >> format like some TLV, but not so simple :
> >> * a common sub-header (type length)
> >> * a body with some complex body format ;
> >> - no indication in the header of the count of sub-packet.
> >>
> >> I've defined some classes for all sub-packets body, one class for the
> >> common sub-header and now, I try to manage a new class inherited from
> >> PacketListField to analyze the raw packet in order to find the
> >> sub-header, extract the type and apply the good format for the
> >> sub-packet body.
> >>
> >> I try to understand the CDP scapy extension available at
> >> http://trac.secdev.org/scapy/attachment/ticket/18/scapy-cdp.py
> >>
> >> I get soon some strong headache !
> >>
> >> It's targeted to my students so I've to carefully understand in order to
> >> prepare my lecture notes.
> >>
> >> Thank you for your support,
> >> Pierre-François.
> >>
> >>
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, send a mail to scapy.ml-unsubscribe <at> secdev.org
> >
>
>
>
---------------------------------------------------------------------
To unsubscribe, send a mail to scapy.ml-unsubscribe <at> secdev.org