The Very Unofficial Dummies
Guide To Scapy
Author: Adam Maxwell (@catalyst256)
Find me at http://itgeekchronicles.co.uk
Table of Contents
Chapter 1 - Introduction ...................................................................................................................... 1
Chapter 2 - Installing Scapy ................................................................................................................. 2
Chapter 3 - Creating a packet .............................................................................................................. 4
Chapter 4 – Sending & Receiving Packets .......................................................................................... 6
Chapter 5 – Getting more out of your packets ................................................................................ 13
Chapter 6 – Reading & Writing Packets to pcap .............................................................................. 20
Chapter 7 – Layering Packets ............................................................................................................ 26
Chapter 8 – Even more uses for Scapy ............................................................................................. 30
Chapter 9 – And now the end is near and so I face the final chapter ........................................... 32
Appendix A – Common Scapy Commands ....................................................................................... 34
Appendix B – ICMP Types .................................................................................................................. 42
Appendix C – TCP Header Information ............................................................................................ 44
Appendix D – DNS Record Types ...................................................................................................... 45
Appendix E – BPF (Berkeley Packet Filter) ........................................................................................ 47
Disclaimer: This is by no means an expert’s guide to Scapy in fact until recently
I had never used Scapy before. The aim of this guide is to provide people who
have no experience/knowledge of Scapy with some guidance to creating packets
and giving them the confidence to go further. Some of the details in here might
be wrong, but I will do my best to ensure that information is correct and where
examples are provided that they have been tested.
Chapter 1 - Introduction
Hello and welcome to this very unofficial dummies guide to Scapy, and when I use the term
“dummies” I mean no offence, as I am referring more to myself than you (honest). I started getting
more into InfoSec in January 2012 after spending 15 years working in IT (mostly infrastructure type
roles), as part of my on-going development I started to look into this tool called Scapy.
What is Scapy??
“Scapy is a powerful interactive packet manipulation program. It is able to forge or decode packets of a wide
number of protocols, send them on the wire, capture them, match requests and replies, and much more. It can
easily handle most classical tasks like scanning, tracerouting, probing, unit tests, attacks or network discovery
(it can replace hping, 85% of nmap, arpspoof, arp-sk, arping, tcpdump, tethereal, p0f, etc.). It also performs
very well at a lot of other specific tasks that most other tools can't handle, like sending invalid frames, injecting
your own 802.11 frames, combining techniques (VLAN hopping+ARP cache poisoning, VOIP decoding on WEP
encrypted channel ...), etc.” (Sourced from https://www.secdev.org/projects/Scapy/).
Sound interesting? well it did to me but then at the same time it kind of scared me, the information I
could find on the internet was “involved” and I couldn’t find any kind of guides that made it easy for
a beginner (like me) to get comfortable using Scapy. So I decided to write one, both as a learning
tool for myself but maybe for other people who are interested in learning more about this seriously
cool tool.
Now bear in mind this is my first guide so it might be a bit disjointed but it’s a work in progress so it
should get better over time.
So I guess you want to know what you might be able to find in this guide?? Here is an overview of
some of the topics we are going to cover through the course of the guide;
●
Installing Scapy (the pre-reqs and any other helpful software)
By Adam Maxwell (@catalyst256)
1
http://itgeekchronicles.co.uk
● Creating a packet
● Send/Receiving packets
● Basic Scapy commands
● Capturing packets (and reading packet capture files into Scapy)
● Layering packets
● More Examples
Throughout this guide I will provide examples (that I’ve tried and tested) as well as output from
Wireshark so you can “see” what the packets look like. At the end of the guide I’m going to include a
section of appendixes that you might found useful, ranging from DNS record types to Scapy
commands.
Throughout this guide anything that is in italics is a command to type or run. I’ve also used some
funky icons in order to provide some pleasing visuals. Below is a table showing the icons and their
meanings.
Wonder what this could mean?? If you spot this icon it’s a warning, either that I’m not 100%
sure what I’m writing about or I’ve encountered an issue with something along the way.
Information only people, I’ve used this to denote pieces of information you might find
useful.
So you ready to start creating some packets??? Let’s get Scapy installed and see what all the fuss is
about..
Chapter 2 - Installing Scapy
I am only going to cover installing Scapy on Ubuntu (I’ve followed this same process of Ubuntu 10.x
through to 12.x). If you want to know how to install it on other version of nix or windows you can find
the instructions at http://www.secdev.org/projects/Scapy/doc/installation.html
If you experience issues installing Scapy, you can boot a vanilla Backtrack 5 R2 install that comes with
Scapy 2.0.1 pre-installed.
You might also want to install Wireshark on the same machine as Scapy, this will allow you to capture
packets as you create them so you can actually see the results as you go (this guide won’t cover how
to use Wireshark).
The main prerequisite to run Scapy is Python 2.5, one of the cool things about Scapy is that once you
get the hang of creating packets within the application you can then use it in python scripts/code
and have even more fun with it. So this is what you need to get started with Scapy;
1. Install Python 2.5+
2. Download and install Scapy
3. (Optional): Install additional software for special features.
4. Run Scapy with root privileges.
1. Install Python 2.5+ - The official documentation for Scapy states Python 2.5 to run Scapy 2.x, I’m
currently running Python 2.7 and never had a problem with it. If you are unsure what version of
Python you are using then from a terminal type:
max@dumbass:~$ python -V
Python 2.7.3
If you haven’t got Python 2.5+ already installed then from Ubuntu you can simply type:
By Adam Maxwell (@catalyst256)
2
http://itgeekchronicles.co.uk
max@dumbass:~$ sudo apt-get install python
2. Download and install Scapy - Once you have python installed you need to get scapy. now there
are a few ways you can do this so I will go through the ones I’ve used:
max@dumbass:~$ sudo apt-get install python-scapy
max@dumbass:~$ cd /tmp
$ wget scapy.net
$unzip scapy-latest.zip
$ cd scapy-2.*
$ sudo python setup.py install
3. (Optional): Install additional software for special features - Now by this point you should
have Scapy installed, you can test this by simply typing this in a terminal:
max@dumbass:~$ sudo scapy
WARNING: No route found for IPv6 destination :: (no default route?)
Welcome to Scapy (2.2.0)
To exit out of Scapy, just type:
Welcome to Scapy (2.2.0)
>>> exit()
Version 2.2.0 seems to be latest stable build and for the remainder of this guide that’s the version
we will use. Now when you just ran Scapy you might have noticed some errors about components
missing, Scapy can do a lot of extra things such as providing 3D maps, graphs, charts etc but you
need some extra packages. Here’s the command to get all those extra goodies:
max@dumbass:~$ sudo apt-get install tcpdump graphviz imagemagick python-gnuplot python-
crypto python-pyx (this is all one line)
4. Run Scapy with root privileges - Now this is the easy one, and if fact if you’ve already done this
but nevertheless the command is this:
max@dumbass:~$ sudo scapy
And this time you should hopefully see this:
WARNING: No route found for IPv6 destination :: (no default route?)
Welcome to Scapy (2.2.0)
>>>
So that covers the install of Scapy, hopefully it was painless and you are all set to get started, if you
have had some “issues” let me know and I will try and help, or you could use the oracle that is
GOOGLE.
By Adam Maxwell (@catalyst256)
3
http://itgeekchronicles.co.uk
Chapter 3 - Creating a packet
Appendix A towards the back of the guide will provide a list of “common” Scapy functions and
protocols.
The examples throughout this guide should work (and they have been tested) against Scapy version
2.x.
That’s right it’s time to play.. so to start with we are going to jump straight in and write your very first
packet. Now you might be thinking “Don’t I need to understand more about Scapy??” well maybe
you do but I learn best by doing and this is my guide. For each packet we create I will provide a
breakdown of what and why we use the commands listed. Hopefully as we work through the guide
you will slowly build your knowledge and start experimenting yourself (with Scapy that is).
So packet number 1 is going to be....... a simple (yet useful) ICMP packet. To start with we are going
to create a single ICMP packet with the well-known message “HelloWorld” contained as the payload.
The IP addresses used in this guide are only relevant to my home network, you need to change them
to the appropriate local addresses you use. Please also make sure you only send packets to devices
you own or allowed to poke at.
Welcome to Scapy (2.2.0)
>>> send(IP(dst="10.1.99.2")/ICMP()/"HelloWorld")
.
Sent 1 packets.
>>>
So let’s break this down shall we;
send - this tells Scapy that you want to send a packet (just a single packet)
IP - the type of packet you want to create, in this case an IP packet
(dst=”10.1.99.2”) - the destination to send the packet to (in this case my router)
/ICMP() - you want to create an ICMP packet with the default values provided by Scapy
/”HelloWorld”) - the payload to include in the ICMP packet (you don’t have to provide this in order
for it to work.
Now I’ve explained that a bit quick, so let’s put it into some context by seeing what Wireshark saw:
No. Time Source Destination Protocol Length Info
5 2012-05-16 21:25:34.306827 10.1.99.22 10.1.99.2 ICMP 52 Echo (ping) request id=0x0000, seq=0/0, ttl=64
Frame 5: 52 bytes on wire (416 bits), 52 bytes captured (416 bits)
Arrival Time: May 16, 2012 21:25:34.306827000 BST
Epoch Time: 1337199934.306827000 seconds
[Time delta from previous captured frame: 50.948599000 seconds]
[Time delta from previous displayed frame: 50.948599000 seconds]
[Time since reference or first frame: 77.326326000 seconds]
Frame Number: 5
Frame Length: 52 bytes (416 bits)
Capture Length: 52 bytes (416 bits)
[Frame is marked: False]
[Frame is ignored: False]
[Protocols in frame: eth:ip:icmp:data]
[Coloring Rule Name: ICMP]
[Coloring Rule String: icmp || icmpv6]
Ethernet II, Src: Dell_e7:90:ae (00:22:19:e7:90:ae), Dst: Netgear_83:ab:70 (30:46:9a:83:ab:70)
Destination: Netgear_83:ab:70 (30:46:9a:83:ab:70)
Address: Netgear_83:ab:70 (30:46:9a:83:ab:70)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
.... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
Source: Dell_e7:90:ae (00:22:19:e7:90:ae)
Address: Dell_e7:90:ae (00:22:19:e7:90:ae)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
By Adam Maxwell (@catalyst256)
4
http://itgeekchronicles.co.uk
.... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
Type: IP (0x0800)
Internet Protocol Version 4, Src: 10.1.99.22 (10.1.99.22), Dst: 10.1.99.2 (10.1.99.2)
Version: 4
Header length: 20 bytes
Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
0000 00.. = Differentiated Services Codepoint: Default (0x00)
.... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)
Total Length: 38
Identification: 0x0001 (1)
Flags: 0x00
0... .... = Reserved bit: Not set
.0.. .... = Don't fragment: Not set
..0. .... = More fragments: Not set
Fragment offset: 0
Time to live: 64
Protocol: ICMP (1)
Header checksum: 0xa0bc [correct]
[Good: True]
[Bad: False]
Source: 10.1.99.22 (10.1.99.22)
Destination: 10.1.99.2 (10.1.99.2)
Internet Control Message Protocol
Type: 8 (Echo (ping) request)
Code: 0
Checksum: 0xf7ff [correct]
Identifier (BE): 0 (0x0000)
Identifier (LE): 0 (0x0000)
Sequence number (BE): 0 (0x0000)
Sequence number (LE): 0 (0x0000)
[Response In: 6]
Data (10 bytes)
Data: 48656c6c6f576f726c64
[Length: 10]
0000 30 46 9a 83 ab 70 00 22 19 e7 90 ae 08 00 45 00 0F...p."......E.
0010 00 26 00 01 00 00 40 01 a0 bc 0a 01 63 16 0a 01 .&....@.....c...
0020 63 02 08 00 f7 ff 00 00 00 00 48 65 6c 6c 6f 57 c.........HelloW
0030 6f 72 6c 64
For this first packet I’ve included everything from Wireshark, in future I won’t (the guide would be
huge), but what I have done is bold some parts of the Wireshark dump that relate to the packet we
just created.
Let’s see the original packet we just wrote again, matched against the bold sections above:
send(IP(dst="10.1.99.2")/ICMP()/"HelloWorld")
Internet Protocol Version 4, Src: 10.1.99.22 (10.1.99.22), Dst: 10.1.99.2 (10.1.99.2)
Protocol: ICMP
Data: 48656c6c6f576f726c64 or “HelloWorld”
Do you notice how the packet we created appears as you would expect with any normal ICMP
packet when using something like Wireshark? Can we take this further? Let’s look at another ICMP
packet but with an extra option:
send(IP(src="10.1.99.100", dst="10.1.99.2")/ICMP()/"HelloWorld")
Notice the difference? Yes that’s right we “spoofed” the source address, if we look at Wireshark now
we see this:
Internet Protocol Version 4, Src: 10.1.99.100 (10.1.99.100), Dst: 10.1.99.2 (10.1.99.2)
Protocol: ICMP
HelloWorld
What you didn’t see (and I didn’t show you) is that in the first packet we got a corresponding Ping
Reply packet for our original Ping Request, in this second example we didn’t (because we spoofed
the IP source address).
orld
By Adam Maxwell (@catalyst256)
5
http://itgeekchronicles.co.uk
Having fun yet???
So what else can we add into this simple packet without making it too complicated?? How about
changing the TTL (Time to Live) for the ICMP packet?? In the original Wireshark dump I highlighted
Time to live: 64 which is the default TTL, but what if we wanted to change that? Is that possible?? Well
with Scapy yes, yes it is and here how:
send(IP(src="10.1.99.100", dst="10.1.99.2", ttl=128)/ICMP()/"HelloWorld")
Can this be any easier?? and what does that look like to wireshark??
Internet Protocol Version 4, Src: 10.1.99.100 (10.1.99.100), Dst: 10.1.99.2 (10.1.99.2)
Time to live: 128
Anyway back to these ICMP packets, so before we call it quits on these bad boys, let’s just explore
one last option (I promise it will get more exciting soon).
OK so what do you think this ICMP packet does??
send(IP(src="10.1.99.100", dst="10.1.99.2", ttl=128)/ICMP(type=0)/"HelloWorld")
Well if you are thinking that it’s just sent a Ping Reply (ICMP Type 0) to 10.1.99.2 then you are
correct, here are the Wireshark highlights.
Internet Protocol Version 4, Src: 10.1.99.100 (10.1.99.100), Dst: 10.1.99.2 (10.1.99.2)
Internet Control Message Protocol
Type: 0 (Echo (ping) reply)
For reference I've included a list of the other ICMP types in Appendix B (which you can find at the
back of the book).
Hopefully by now you are realising how powerful Scapy is, the method I’ve shown you here is not
the only way you can create packets, because Scapy is based on Python what you can do with Scapy
is only limited by your imagination (and some limitations of the application).
In chapter 7 I will provide you with another way to write Scapy packets in a different way but for the
time being we will continue using the same format as we have done with the ICMP packets.
Summary
In this chapter we have looked at creating a simple ICMP packet, then modifying some of the packet
headers. Out of the box Scapy (thanks to the developers) will use default values based on the packet
type if you don't supply them thus enabling you to focus on the parts you want to change rather
than having to include all the options yourself.
In the next chapter we will look at Sending & Receiving Scapy packets.
Chapter 4 – Sending & Receiving Packets
So you all set to move onto the next level of Scapy?? Well here we go then, in this chapter we are
going to look at sending and receiving packets via Scapy. The “send”n”receive” functions are the
heart of Scapy (after all you won't get far just sending packets), and they work as a “couple” and
return two lists. The first element is a list of couples (packet sent, answer), and the second element
is the list of unanswered packets. Both of these two elements are lists, but Scapy wraps them up in
an object to present them better, and to provide them with some methods that do the most
frequently needed actions.
There are 3 main functions to s&r (sending and receiving) these are:
By Adam Maxwell (@catalyst256)
6
http://itgeekchronicles.co.uk
● sr()
- The sr() function is for sending packets and receiving answers. The function returns
a couple of packet and answers, and the unanswered packets.
● sr1()
- This function is a variant that only returns one packet that answered the sent
packet (or the packet set) sent.
When using sr() or sr1() the packets must be layer 3 packets (IP, ARP, etc.)
● srp()
- The function srp() does the same for layer 2 packets (Ethernet, 802.3, etc).
Throughout this chapter we are going to use both the sr() function and the sr1() function and we
will again be using the ICMP packet for the exercises.
So this is how you write a simple ICMP packet in Scapy using the sr() function.
h=sr1(IP(dst="10.1.99.2")/ICMP())
So most of this should familiar to you from the previous chapter, let’s look at the differences;
h – This is the name of my packet, if you are familiar with Python this is how you declare a name
(name=)
sr1– This is the Scapy function that we discussed at the start of the chapter.
>>> h=sr1(IP(dst="10.1.99.2")/ICMP())
Begin emission:
.Finished to send 1 packets.
*
Received 2 packets, got 1 answers, remaining 0 packets
Now that we have sent a packet (yes, yes I know ICMP isn't very “sexy”), let’s start to look at what the
sr1() function allows us to do.
To see the “answered” packet (remember the sr functions can show the answered and unanswered
packets, but sr1() is only interested in the first answered packet), simply type:
>>> h (remember h is the name we gave our packet)
You should see something like this:
>>> h
>>
Now if you remember back to the previous chapter this is the same information that Wireshark
showed us, if you want a slightly better formatted version you can type:
>>> h.show()
This will return you something similar to this:
>>> h.show()
###[ IP ]###
version= 4L
By Adam Maxwell (@catalyst256)
7
http://itgeekchronicles.co.uk