Wednesday, June 6, 2012

Need to Quickly Generate Some Specific Packets? Scapy!

I came across Scapy a couple of years ago via a coworker.  This Python-based software makes it incredibly easy to craft one (or thousands of!) network packet(s), which makes Scapy one of my favorite tools to "go get" when I'm in need of some specific packet crafting.

Let's say I need to create and send an IP packet to a machine at 1.0.0.2 with the "more frags" flag bit set in the header:


root@dev1:~# scapy
INFO: Can't import python gnuplot wrapper . Won't be able to plot.
INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().
WARNING: No route found for IPv6 destination :: (no default route?)
INFO: Can't import python Crypto lib. Won't be able to decrypt WEP.
Welcome to Scapy (2.0.1)
>>> mypkt = IP(dst="1.0.0.2")
>>> print mypkt
E@xç
>>> mypkt.display()
###[ IP ]###
  version= 4
  ihl= None
  tos= 0x0
  len= None
  id= 1
  flags=
  frag= 0
  ttl= 64
  proto= ip
  chksum= 0x0
  src= 1.0.0.1
  dst= 1.0.0.2
  options= ''
>>> mypkt.flags = 0x01
>>> mypkt.display()
###[ IP ]###
  version= 4
  ihl= None
  tos= 0x0
  len= None
  id= 1
  flags= MF
  frag= 0
  ttl= 64
  proto= ip
  chksum= 0x0
  src= 1.0.0.1
  dst= 1.0.0.2
  options= ''
>>> send(mypkt)
.
Sent 1 packets.

Cool, huh?

Scapy also has an easy-to-use packet processing function called sniff.  You can pass it an interface to sniff on, a filter (ala tcpdump filter verbiage) to only look at certain packets, and a callback function to send matched packets to.  If one wanted to, say, process LLDP packets on interface eth0 with a function called packetProcess(self, pkt), you could do so by calling sniff like this:

sniff(prn = packetProcess, store = 0, iface = "eth0", filter = "ether proto 0x88cc")

This will call packetProcess for each LLDP (i.e. packets with ethertype 0x88cc) packet seen on eth0.  Note that I say "seen" rather than "ingressing" since sniff() will pickup both ingressing *and* egressing packets on that interface. Also, the "store = 0" above tells Scapy to not store the packet itself, just forward a copy of it to the callback function.

No comments:

Post a Comment