Pierre-François Bonnefoi | 1 Feb 13:30 2010
Picon

Re: Adding protocol to Scapy

Hello,

I've added a new class to manage the list of pseudo-TLVs :
class ListeSTUNAttributs(PacketListField):
     def __init__(self, name, default, cls):
         PacketField.__init__(self, name, default, cls)

     def getfield(self, pkt, s):
         liste = []
         reste = s
         while len(reste) > 0:
             p = self.m2i(pkt, reste)
             if Padding in p:
                 pad = p[Padding]
                 reste = pad.load
                 del(pad.underlayer.payload)
             else:
                 reste = ""
             liste.append(p)
         return reste, liste

     def addfield(self, pkt, s, val):
         return s+reduce(str.__add__, map(str, val), "")

This code has been taken from OSPF extension.

I've also added to my code some bind_layers as :
  bind_layers(STUN, STUN_Attribut1)
  bind_layers(STUN, STUN_Attribut2)
  bind_layers(STUN_Attribut1, STUN_Attribut2)
(Continue reading)

Pierre-François Bonnefoi | 1 Feb 12:18 2010
Picon

Re: Adding protocol to Scapy

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
(Continue reading)

Zohaib Khalid | 1 Feb 17:06 2010
Picon

Re: Scapy on Win 7 / Vista

So I guess if you try the following at your Python prompt, you will see two lines where 'name': 'eth0', one with 'type:6' and one with 'type:71', right?

>>> import dnet
>>> for iface in dnet.intf(): print iface
 
yes 
{'flags': 32, 'type': 1, 'name': 'eth0', 'mtu': 0L}
{'flags': 33, 'link_addr': 0a:aa:20:52:41:53, 'type': 6, 'name': 'eth0', 'mtu': 1500L}
{'addr': 192.168.1.99/24, 'mtu': 1500L, 'flags': 33, 'link_addr': 00:1f:3c:34:1c:0c, 'type': 71, 'name': 'eth0'}


As far as I know, there is no way to specify that we want the type=6 (ethernet) interface. The dnet.eth() method and the underlying eth_open() C function only take the plain interface name as arguments.

Could you file a bug report for libdnet?
http://code.google.com/p/libdnet/issues

did that ...
 
Libdnet does not really seem to be actively maintained though. Nmap ships its own patched libdnet library. Some of their modifications [1] would surely be helpful for Scapy as well: On Jochen's system, Nmap worked fine. But they removed the Python binding, so it isn't usable for Scapy right out of the box. Several months ago I spent some hours trying to add them back, but failed. Maybe I should have a look at this again.

that would be very helpful ... 

zoh.
Jochen Bartl | 1 Feb 23:30 2010
Picon

Re: Adding protocol to Scapy

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

Pierre-François Bonnefoi | 2 Feb 00:53 2010
Picon

Re: Adding protocol to Scapy

Hello again,

I've found a new problem : I want to try my STUN classes on true STUN 
packets recorded in pcap format.

And the rdpcap() function doesn't return and go to a death loop.

I examine the extract_padding method in order to cut packets... but I 
don't understand why I've got an infinite loop (no link to Apple :-)

I've the size of the whole packet into the header and the TLV optional 
fields after the packet body.

How could I say to scapy to stop looping ?

Thank you for your help,
Pierre-François.

--

-- 
Bonnefoi Pierre-Francois                |    E-mail : bonnefoi <at> unilim.fr
Universite de Limoges, Laboratoire XLIM |       Tel : 06 28 18 03 38
83, rue d'Isle                          |  Mrs. Peel, we're needed...
87000 Limoges - FRANCE                  |                 The Avengers.

---------------------------------------------------------------------
To unsubscribe, send a mail to scapy.ml-unsubscribe <at> secdev.org

Xian Chen | 3 Feb 01:21 2010
Picon

sending packets using scapy

Hi All,


I am new here and try to understand the usage of scapy.  I follow the demos of  sendp("I'm travelling on Ethernet", iface="eth1", loop=1, inter=0.2)

Does scapy follow the 802.11 MAC rules, like back-off when executing sendp here? In this example, there is no destination. So the packets are just injected into the air, right?

Thanks,
Pierre-François Bonnefoi | 4 Feb 02:01 2010
Picon

Re: Adding protocol to Scapy

Hello again,

I've solved my previous problem and I've something working according to 
the RFC3489.
Now, I want to add support to the RFC5389.

My current problem is :
- I have a PacketListField for variable number of attributes and a 
MagicCookie field in my STUN packet ;
- in this list I've one kind of attribute implemented as a class packet 
that contains some kind of IPField (I've to make a subclass to apply xor 
operator between the IP address and the value of the magic cookie) ;

So my question is: how to access from a packet inside the list of 
packets, to the underlayer packet ?

I've tried to make a link between the new subclass inheriting from the 
IPField class, by adding a new parameter to the underlaying packet :

class STUN_Attribut1(STUN_Attribut_defaut):
     name = "XOR-MAPPED-ADDRESS"
     fields_desc = [ ShortField("Type", 0x0001),
                     ShortField("Longueur", 8),
                     ByteField("Vide",0),
                     ByteField("Famille", 0x01),
                     ShortField("Port", 0x0001),
                     STUN_xorIPField("Adresse", "0.0.0.0", lambda pkt: 
pkt.underlayer.MagicCookie)]

class STUN_xorIPField(IPField):
     def __init__(self, name, default, fld):
         IPField.__init__(self, name, default)
         self.fld = fld

     def m2i(self, pkt, x):
         adresse = IPField.m2i(self, pkt, x)
         m = pkt.get_field(self.fld)
	[...]
         return ".".join(adresse_retour)

I've no success...

Thank you for your help,
Pierre-François.

--

-- 
Bonnefoi Pierre-Francois                |    E-mail : bonnefoi <at> unilim.fr
Universite de Limoges, Laboratoire XLIM |       Tel : 06 28 18 03 38
83, rue d'Isle                          |  Mrs. Peel, we're needed...
87000 Limoges - FRANCE                  |                 The Avengers.

---------------------------------------------------------------------
To unsubscribe, send a mail to scapy.ml-unsubscribe <at> secdev.org

chris | 4 Feb 18:07 2010
Picon
Picon

Improving Scapy performance with Psyco, Pyrex, Cython & Co.

Hi list,

I am using Scapy to bridge traffic on a high-volume network link, i.e.
sniffing on eth1 and sending it on eth0 and vice versa. To safe
performance, sniffing is done in Raw mode. The problem is, as soon as I
put some MBits/s on the bridge, I experience CPU bound performance
issues. There is some other art that the script is doing with the
packets, but this is not performance critical.

Although I am not at all experienced in using these 'tools', I've read
that using Cython/Pyrex or Psyco usually helps to increase CPU bound
performance bottlenecks. Does anybody on the list have experience in
using these tools in combination with Scapy? Or can you already guess
that using them would help / would not help?

Thanks in advance for your opinions!

Regards,
Chris

---------------------------------------------------------------------
To unsubscribe, send a mail to scapy.ml-unsubscribe <at> secdev.org

Dirk Loss | 4 Feb 19:52 2010
Picon

Re: Improving Scapy performance with Psyco, Pyrex, Cython & Co.

On 04.02.10 18:07, chris wrote:
> Although I am not at all experienced in using these 'tools', I've read
> that using Cython/Pyrex or Psyco usually helps to increase CPU bound
> performance bottlenecks. Does anybody on the list have experience in
> using these tools in combination with Scapy? Or can you already guess
> that using them would help / would not help?

Testing Psyco should be as easy as adding the following code to the 
start of your script:

     try:
         import psyco
         psyco.full()
         print "Using Psyco"
     except ImportError:
         Print "Not using Psyco"

A quick test with Psyco 2.0 on Python 2.6/Windows showed no problems, 
but I haven't done any performance measurements.

BTW: Has anyone done some profiling on Scapy already to identify the 
performance critical sections?

Using Cython/Pyrex will be more work I guess (.pyx file, compilation, 
adding static type declarations, etc.). Personally I have used it to 
recompile the pypcap wrapper, but not for Scapy itself.

Regards
Dirk

---------------------------------------------------------------------
To unsubscribe, send a mail to scapy.ml-unsubscribe <at> secdev.org

Pierre-François Bonnefoi | 5 Feb 19:21 2010
Picon

Explanations about Field and Packet

Hello all,

Could I get some good explanation about links between layers, Packet and 
Fields :

- when a packet has been put on top of a first one and under a second 
one, you could access the second by using 'payload' and the first with 
'underlayer'.
- when a field is embedded into a Packet, you get access to the packet 
to wich it belongs by the argument 'packet' given to its method.

- when a PacketListField is embedded into a packet, it contains a "list 
of packets". How from one of these packets do you get access to the 
"list of packets" and to the whole packet that contains the 
PacketListField ?

Thank you for your help,
Pierre-François.

P-S: I'm examining the monolithic code of Scapy 1.2.0.2

--

-- 
Bonnefoi Pierre-Francois                |    E-mail : bonnefoi <at> unilim.fr
Universite de Limoges, Laboratoire XLIM |       Tel : 06 28 18 03 38
83, rue d'Isle                          |  Mrs. Peel, we're needed...
87000 Limoges - FRANCE                  |                 The Avengers.

---------------------------------------------------------------------
To unsubscribe, send a mail to scapy.ml-unsubscribe <at> secdev.org


Gmane