Scapydoc
Scapydoc
Philippe BIONDI
phil(at)secdev.org
2
Contents
1 Introduction 5
1.1 About this document . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2 What is Scapy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Scapys concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.1 Fast packet design . . . . . . . . . . . . . . . . . . . . . . 5
1.3.2 Probe once, interpret many . . . . . . . . . . . . . . . . . 6
1.3.3 Scapy decodes, it does not interpret . . . . . . . . . . . . 6
I Examples 9
2 Quick start 11
3 Packet manipulation 13
4 Network discovery 15
5 Attacks 17
II Reference 19
6 Packet manipulation 21
6.0.4 Users methods . . . . . . . . . . . . . . . . . . . . . . . . 21
6.0.5 Developers methods . . . . . . . . . . . . . . . . . . . . . 23
8 Commands 29
8.1 Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
8.2 Communication commands . . . . . . . . . . . . . . . . . . . . . 34
8.2.1 Sni family . . . . . . . . . . . . . . . . . . . . . . . . . . 34
8.2.2 Send family . . . . . . . . . . . . . . . . . . . . . . . . . . 35
8.2.3 Send and receive family . . . . . . . . . . . . . . . . . . . 35
8.3 high-level commands . . . . . . . . . . . . . . . . . . . . . . . . . 37
8.4 Answering machines . . . . . . . . . . . . . . . . . . . . . . . . . 38
3
4 CONTENTS
13 Scripting Scapy 53
IV Internals 57
15 Networking code 59
15.1 Supersockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
15.2 Routing packets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
16 Object model 63
1
Introduction
Scapy is a Python program that enables you to forge, dissect, emit or sni
network packets, probe, scan or attack networks.
5
6 CHAPTER 1. INTRODUCTION
Scapy paradigm is to propose a DSL1 that enables a powerful and fast descrip-
tion of any kind of packet. The trick to use the Python syntax and a Python
interpreter as the DSL syntax and the DSL interpreter has many advantages:
there is no need to write the interpreter, users dont need to learn another
language again and they benefit from a complete, concise and very powerful
language.
Scapy enables you to describe a packet or a set of packets as layers that you
stack one upon the other. Fields of each layer have useful default values that
you can overload.
Scapy does not oblige you to use predetermined scenarii or templates. This
means that each time you want to send packets, you have to write a new tool.
In C, it would take an average of 60 lines only to describe the packet. With
scapy, you only need one line to describle the packets you want to send, and one
line to print the result. 90% of the network probing tools can be rewritten in 2
lines of Scapy.
Network discovery is blackbox testing. When probing a network, you will send
many stimuli, and some of them will be answered. If you choose the right stimuli,
you can obtain the information you need from the responses or from the lack of
responces. Unlike many tools, Scapy will give you all the information, i.e. all
the stimuli you sent and all the responses you got. You will have to look into
them to get the information you are looking for. When the dataset is small,
you can just dig for it. In other cases, you will have to choose a point of view
on this data. Most tools choose the point of view for you and loose all the data
not related to the given point of view. Because Scapy give you the whole raw
data, you can use them many times and have your point of view evolve during
your analysis. For example, you can probe for a TCP port scan, visualize the
data like the result of a port scan, then decide you would like to also visualize
the TTL of response packet. You do not need to do a new probe each time you
want to visualize other data.
A common problem in network probing tools is that they try to interpret the
answers they got instead of only decoding and giving facts. Saying something
like I received a TCP Reset on port 80 is not subject to interpretation errors.
Saying The port 80 is closed is an interpretation that can be right most of the
1 Domain Specific Language.
1.3. SCAPYS CONCEPTS 7
time but wrong in some specific contexts the tools author did not thought of.
For instance, some scanners tend to report a filtered TCP port when they receive
an ICMP destination unreachable packet. This may be right, but in some cases
it means the packet was not fitered by the firewall but there was no host to
forward the packet to.
Interpretating results can help people that dont know what a port scan is. But
it can also make more harm than good, as it bias the results. In fact, what
happen to people that know exactly what they are doing and that know very
well thier tools is that they try to reverse the tools interpretation to get the facts
that triggered the interpretation, in order to do the interpretation themeselves.
Too bad so much information has been lost in the operation.
8 CHAPTER 1. INTRODUCTION
Part I
Examples
9
2
Quick start
11
12 CHAPTER 2. QUICK START
3
Packet manipulation
13
14 CHAPTER 3. PACKET MANIPULATION
4
Network discovery
15
16 CHAPTER 4. NETWORK DISCOVERY
5
Attacks
17
18 CHAPTER 5. ATTACKS
Part II
Reference
19
Packet manipulation
6
6.0.4 Users methods
constructor
stacking
testing
reaching
haslayer
haslayer(self, cls)
True if self has a layer that is an instance of cls. Superseded by cls in
self syntax.
getlayer
getlayer(self, cls, nb=1 )
Returns the nbth layer that is an instance of cls.
psdump
psdump(self, filename=None) Creates an EPS file describing a packet. If
filename is not provided a temporary file is created and gs is called.
pdfdump
pdfdump(self, filename=None)
Creates a PDF file describing a packet. If filename is not provided a
temporary file is created and xpdf is called.
21
22 CHAPTER 6. PACKET MANIPULATION
hide defaults
hide defaults(self)
Remove fields values that are the same as default values.
show
show(self, indent=3, lvl=, label lvl=)
Print a hierarchical view of the packet.
show2
show2(self)
Prints a hierarchical view of an assembled version of the packet, so that
automatic fields are calculated (checksums, etc.)
sprintf
sprintf(self, fmt, relax=1 )
where format is a string that can include directives. A directive begins and
ends by % and has the following format %[fmt[r],][cls[:nb].]field%.
fmt is a classic printf directive, r can be appended for raw substitution
(ex: IP.flags=0x18 instead of SA), nb is the number of the layer we want
(ex: for IP/IP packets, IP:2.src is the src of the upper IP layer). Special
case : %.time% is the creation time.
A side eect is that, to obtain { and } characters, you must use %( and
%).
decode payload as
decode payload as(self, cls)
Reassembles the payload and decode it using another packet class.
command
command(self)
Returns a string representing the command you have to type to obtain
the same packet.
23
copy
copy(self)
Returns a deep copy of the instance.
lastlayer
lastlayer(self, layer=None)
Returns the uppest layer of the packet.
answers
answers(self, other)
True if self is an answer from other
haslayer str
haslayer str(self, cls)
True if self has a layer that whose class name is cls.
Packet list manipulation
7
7.1 Users methods
show
show(self)
Best way to display the packet list. Defaults to nsummary() method
nzpadding
nzpadding(self, lfilter=None)
same as padding() but only non null padding
plot
plot(self, f, lfilter=None)
Apply a function to each packet to get a value that will be plotted with
GnuPlot. A gnuplot object is returned.
hexdump
hexdump(self)
Print an hexadecimal dump of each packet in the list
25
26 CHAPTER 7. PACKET LIST MANIPULATION
hexraw
hexraw(self, lfilter=None)
Same as nsummary(), except that if a packet has a Raw layer, it will be
hexdumped
pdfdump
pdfdump(self, filename=None)
create a PDF file with a pdfdump() of every packet.
filename: name of the file to write to. If empty, a temporary file is used
and conf.prog.pdfreader is called.
nsummary
nsummary(self, prn=None, lfilter=None)
print a summary of each packet with the packets number
conversations
conversations(self, getsrcdst=None, prog=None, type=svg, target=| dis-
play)
Graph a conversations between sources and destinations and display it
(using graphviz and imagemagick)
getsrcdst: a function that takes an element of the list and return the
source and dest by defaults, return source and destination IP
type: output type (svg, ps, gif, jpg, etc.), passed to dots -T option
target: filename or redirect. Defaults pipe to Imagemagicks display pro-
gram
padding
padding(self, lfilter=None)
Same as hexraw(), for Padding layer.
psdump
psdump(self, filename=None)
Creates a multipage poscript file with a psdump() of every packet
filename: name of the file to write to. If empty, a temporary file is used
and conf.prog.psreader is called.
7.1. USERS METHODS 27
sr
sr(self, multi=0 )
Match packets in the list and return ((matchedcouples), (unmatchedpackets))
summary
summary(self, prn=None, lfilter=None)
print a summary of each packet
prn: function to apply to each packet instead of lambda x:x.summary()
lfilter: truth function to apply to each packet to decide whether it will be
displayed
filter
filter(self, func)
Return a packet list filtered by a truth function
make table
make table(self)
Print a table using a function that returs for each packet its head column
value, head row value and displayed value.
display
display(self)
deprecated. is show()
timeskew graph
timeskew graph(self, ip)
Try to graph the timeskew between the timestamps and real time for a
given IP.
28 CHAPTER 7. PACKET LIST MANIPULATION
8
Commands
8.1 Tools
ls
ls(obj=None)
Lists available layers, or infos on a given layer
>>> ls()
ARP : ARP
BOOTP : BOOTP
CookedLinux : cooked linux
DNS : DNS
GRE : GRE
[...]
>>> ls(Ether)
dst : DestMACField = (None)
src : SourceMACField = (None)
type : XShortEnumField = (0)
>>> a=Ether()/Dot1Q(type=0x1234)
>>> ls(a)
dst : DestMACField = ff:ff:ff:ff:ff:ff (None)
src : SourceMACField = None (None)
type : XShortEnumField = 33024 (0)
--
prio : BitField = 0 (0)
id : BitField = 0 (0)
vlan : BitField = 1 (1)
type : XShortEnumField = 4660 (0)
29
30 CHAPTER 8. COMMANDS
lsc
lsc(cmd=None)
Lists documented commands
>>> lsc()
sr : Send and receive packets at layer 3
sr1 : Send packets at layer 3 and return only the first answer
[...]
hexdump
hexdump(x)
Prints an hexadecimal dump of a string or a packet
>>> hexdump(Ether(type=0x1234,dst="ba:be:fe:ed:be:ef")/IP())
0000 BA BE FE ED BE EF 00 00 00 00 00 00 12 34 45 00 .............4E.
0010 00 14 00 01 00 00 40 00 7C E7 7F 00 00 01 7F 00 ......@.|.......
0020 00 01 ..
linehexdump
linehexdump(x, onlyasc=0 )
Prints a one line hexadecimal view of a string or packet. If onlyasc is
not null, it can be used as a filter for safe printing strings from untrusted
source (SSID, etc).
>>> linehexdump("\x01\x23\x45\x67")
01 23 45 67 .#Eg
>>> linehexdump("\x01\x23\x45\x67",onlyasc=1)
.
save session
save session(fname, session=None, pickleProto=-1 )
Saves in a file all the variables in the user scope (everything seen with the
dir() command). This command is very handy but there are some an-
noying caveats that come from the Python cpickle module. For example,
lambda functions cant be saved and loaded modules wont be reloaded.
Another problem can arise from automatic fields like source IP that can
change from one machine to another, so the session will seem altered.
>>> save session("/tmp/session.scapy")
load session
load session(fname)
Loads a previously saved session, smashing everything in the current ses-
sion.
>>> load session("/tmp/session.scapy")
update session
update session(fname)
Tries to merge the current session with a previously saved session.
>>> update session("/tmp/session.scapy")
8.1. TOOLS 31
import hexcap
import hexcap()
Expects lines on standard input copy/pasted from a tcpdump -xX output,
parse them, and output a string you can dissect with the protocol of your
choice.
>>> IP(import hexcap())
0x0000: 4500 0054 0000 4000 4001 242a c0a8 080e E..T..@.@.$*....
0x0010: 4266 0b63 0800 81e0 112a 0000 442e 9ca2 Bf.c.....*..D...
0x0020: 0007 991a 0809 0a0b 0c0d 0e0f 1011 1213 ................
0x0030: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 .............!"#
0x0040: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 $%&()*+,-./0123
0x0050: 3435 3637 4567
^D
<IP version=4L ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64
proto=ICMP chksum=0x242a src=192.168.8.14 dst=66.102.11.99 options=
|<ICMP type=echo-request code=0 chksum=0x81e0 id=0x112a seq=0x0 |<Raw
load=D.\x9c\xa2\x00\x07\x99\x1a\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15
\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\()*+,-./01234567 |>>>
export object
export object(obj)
Prints a bas64-encoded bzipped pickled version of the object that can be
copy/pasted and imported to another Scapy session. If the two sessions
run on dierent machines, automatic fields like source IP may not be the
same.
>>> export object(IP(ttl=3))
eNpdVWtbE1cQluwmgShV6q2ttVaruAgJEvACeIOQwDoSloSxsRXpQhZma5LNZDcUqNtqC62l2ruX
3r/7U/qt/6izEDX1yZPn7HPOeed9Z85c7oYW5ubKpl2Zm4vpRoxbuu5xyGdFw8iibZWKLqs+h1Hx
vBJHQHExZpZs0/VWq5bL0VlupRYTY/VK0aqVzFWrxm1ZbNtCBlc45vNOTXtJMWp7meAwxrscbvf5
NQ2jRWvRrJc83g07MOSu8R4IobJY9rgDQ0cn+HVUK2bZ4r2oLtbMJd6HqmuvWbwf2uvz1N5kPF2u
UowPOHzQ5zfERKnIbzYd5516bcHSjYaAtxw+5PPbGu3O0h5QqQOVowMuH6a9qLi1BX5HlLneFvUR
VOST363Pu/N0sNmdVc9KV+rlhsmjDh/z+T1N7LWIkaTNx30+oaGayxsZ7gQdVd1YPssnoQuV9LjB
GrRiW7AVzwSudUEPhtP6eM7gU1DAUCbF3bAhW9nUiME9MB9Yum5wHBICGzNy8dTkjMEJ6BTDqUmD
e4VX1fN6nk/DHVQMfZL7YAkVXbiS0IbKhFzqh30N0i3MAAyhMpMy+AxEMFrI5uNimc/CAVSv50TJ
OahiND0zkc7pBp8HE0OyDspbqfqYHA9BHKNT4l/AMQw3ZHtcrF4IHjEnhi7CIVQKovISHEc1DwK+
DIOojMnZFTiBUT0/FZ8xBngEDqMynkvzKPSiei0pkBS42Kob+XQqPjLBY9CPsS3dWSe74nEahjE8
Ukgkz3AGZgUrAsZBadzJOXXP4gnoRgWFSoeOwOnAVDpv8FVIBm8hYgBuYSg/w9cgjBHdSE2J+Eko
NSI0VfVczsIFUZ4SQVOwLlEJYm7AtMQXDZ6GXYHG+PYb5UCtSwKFqzXHczhPktMUpPEoz6BiJ11G
n69rsjkILdQLIboACo1L9uVgg7ohQmeglTRooyTsomnoIB32UT8coLOwTlNwiC7CYRqBMF2D43QJ
TtAV6KQEdNFJ6KYJ6KEuiNMQJCgOvTQKSboK/TQGg3QZhmgAhikNFygLOnXCNBlQoFNwg4ZhljJw
iwBMOg/z1ANL1AclmoQqnQOXUnCHTtel2I41pX4hyP1G3r/vcMHnG9qWu5L7DZc/CErJc1z+ULAF
jaQyb/o8S81F+aIcbzk85/NHYgPb+pLnEqfl18dmc2nO017arsGbzULy5NSed5UFh4s+W42iDtF2
C1kUIZEFuu3Wy7wkWorNXaEJTQ7bPn/8Cvp24EbJqnBJoPb/tDtVz3YqbgNedrjisxO4sKMJXxV8
tHGTGSM1K8BzDXaIvYpG0gldn70gemoTLMij6LJVcwXHy7RfMmue3Cb6TMlcek79icMrPq8GnSeE
4bK0U5vX7geZuBjc4k9fZOIE38Fw0NVc9mf5M22WP8fQZIbvmrN8D0NjGf5Cvr5E1Vq2S7xuWsKs
CPPKltANn796JTxfB+GxqcT3Gxo3XmmQDYnfOLzp87eBm1eakuSBPGpEUJsaSfgf+vxdcKOlieB7
IQjZRf5Bbj2so+rZ0pJ/HB/5d+ez9WeJB7jTrtieLWNpzSryT9IBOxwJW8kxi1ZxrjHEfvb5F4xW
zdVgmx+9FJh1jO3NGD+W0ffE56caycj7lWS4/UaPTWrLkkyx32mL8cjdp5v/kJCQWPyDHtETfK0x
v55T/enzX6JUlr81apeoH8zSMVkK8r9JJhWzZGepIiniynuvyO5GljYlJg+hRYos8R8yYmBq
import object
import object(obj=None)
Reads a base64-encoded bzipped pickled object on standard input.
32 CHAPTER 8. COMMANDS
rdpcap
rdpcap(filename, count=-1 )
reads a pcap file and returns the list of read packets. If count is positive,
only the first count packets are read.
>>> rdpcap("ike.cap")
<ike.cap: UDP:45 TCP:0 ICMP:0 Other:0>
>>> rdpcap("ike.cap", count=10)
<ike.cap: UDP:10 TCP:0 ICMP:0 Other:0>
wrpcap
wrpcap(filename, pkt, linktype=None)
Write a packet or list of packets to a pcap file. linktype can be used to
force the link type value written into the file.
>>> wrpcap("my.cap", packet list)
fragment
fragment(pkt, fragsize=1480 )
Fragments an IP packet with a large payload into many IP packets with a
smaller payload and with the fragofs and flags fields correctly set up.
>>> fragment(IP(dst="1.2.3.4")/ICMP()/("X"*50), fragsize=10)
[<IP flags=MF frag=0 proto=ICMP dst=1.2.3.4 |<Raw load=\x08\x00W \x00\x00\x00\x00XXXXXXXX
|>>, <IP flags=MF frag=2 proto=ICMP dst=1.2.3.4 |<Raw load=XXXXXXXXXXXXXXXX
|>>, <IP flags=MF frag=4 proto=ICMP dst=1.2.3.4 |<Raw load=XXXXXXXXXXXXXXXX
|>>, <IP flags= frag=6 proto=ICMP dst=1.2.3.4 |<Raw load=XXXXXXXXXX |>>]
8.1. TOOLS 33
fuzz
fuzz(p) Transform a packet into a fuzzed packet. Whas is done is replacing
each field whose default value is not automatically calculated by a random
value compatible with the field. Values that have to be automatically cal-
culated (like checksums or lengths) are identified by the fact their default
value is None. This characterization is a good approximation but keep
in mind it could be wrong. Because the random value is considered as a
default value on fuzzed packets, values set by the user or the upper layer
overload the random value.
>>> a=IP(version=4)/UDP()
>>> hexdump(a)
0000 45 00 00 1C 00 01 00 00 40 11 7C CE 7F 00 00 01 E.......@.|.....
0010 7F 00 00 01 00 35 00 35 00 08 01 72 .....5.5...r
>>> hexdump(a)
0000 45 00 00 1C 00 01 00 00 40 11 7C CE 7F 00 00 01 E.......@.|.....
0010 7F 00 00 01 00 35 00 35 00 08 01 72 .....5.5...r
>>> b=fuzz(a)
>>> hexdump(b)
0000 47 DE 00 24 D3 E9 40 00 DE 11 42 FF C0 A8 08 0E [email protected].....
0010 63 7E DF 17 0E ED 74 01 F4 C6 00 00 97 14 24 5E c~....t.......$^
0020 00 08 39 1F ..9.
>>> hexdump(b)
0000 4B 0D 00 34 64 CE 60 00 95 11 FD CE C0 A8 08 0E K..4d..........
0010 80 5E B7 6B 57 B9 BA 1D 58 C4 91 BD E6 E4 DB 39 .^.kW...X......9
0020 61 58 0E E6 FF 3E CF 98 5F 00 00 00 2B F3 B5 C5 aX...>.. ...+...
0030 00 08 1D A5 ....
interact
interact(mydict=None, argv=None, mybanner=None, loglevel=1 )
Runs an interactive session with completion and history. Use it in your
own tools.
>>> a=IP()/UDP()
>>> a.ttl
64
>>> bind top down(IP, UDP, {ttl:12} )
>>> a=IP()/UDP()
>>> a.ttl
12
bind bottom up
bind bottom up(lower, upper, fval)
Informs lower layer that, when dissected, if all of its fields match the fval
dictionnary, the payload is upper
>>> UDP("ABCDEFGHIJKL")
<UDP sport=16706 dport=17220 len=17734 chksum=0x4748 |<Raw load=IJKL |>>
>>> bind bottom up(UDP, Dot1Q, {"dport":17220} )
>>> UDP("ABCDEFGHIJKL")
<UDP sport=16706 dport=17220 len=17734 chksum=0x4748 |<Dot1Q prio=2L id=0L
vlan=2378L type=0x4b4c |>>
bind layers
bind layers(lower, upper, fval)
Does a bind bottom up and a bind top down.
sendp
sendp(pkts, inter=0, loop=0, iface=None, iface hint=None, verbose=None)
Send packets at layer 2 using the conf.L2socket supersocket. pkts can
be a packet, an implicit packet or a list of them.
The send and receive functions family is central to interact with the network
with Scapy.
sr
sr(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0,
retry=0, multi=0 ) Send and receive packets at layer 3 using the conf.L3socket
supersocket.
nofilter: put 1 to avoid use of bpf filters on systems that dont support it
retry: if positive, how many times to resend unanswered packets if neg-
ative, how many consecutive unanswered probes before giving up.
Only the negative value is really useful.
timeout: how much time to wait after the last packet has been sent. By
default, sr will wait forever and the user will have to interrupt (Ctrl-
C) it when he expects no more answers.
verbose: set verbosity level.
multi: whether to accept multiple answers for the same stimulus.
filter: provide a BPF filter.
36 CHAPTER 8. COMMANDS
sr1
sr1(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0,
retry=0, multi=0 ) Same as sr except only the first answer is returned. This
command is very useful for one packet probes like pinging an IP.
>>> sr1(IP(dst="192.168.0.1")/ICMP())
<IP version=4L ihl=5L tos=0x0 len=28 id=34897 flags= frag=0L ttl=64 proto=ICMP
chksum=0x713d src=192.168.0.1 dst=192.168.0.1 options= |<ICMP type=echo-reply
code=0 chksum=0xffff id=0x0 seq=0x0 |>>
srp
srp(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0,
retry=0, multi=0, iface hint=None)
Same as srp but for working at layer 2 with conf.L2socket supersocket.
There is also an additional parameter, iface hint, which give an hint that
can help choosing the right output interface. By default, if not speci-
fied by iface, conf.iface is chosen. The hint takes the form of an IP to
which the layer 2 packet might be destinated. The Scapy routing table
(conf.route) is used to determine which interface to use to reach this IP.
srp1
srp(pkts, filter=None, iface=None, timeout=2, inter=0, verbose=None, chainCC=0,
retry=0, multi=0, iface hint=None)
Same as srp, except only the first answer is returned. This command is
very useful for one packet probes like ARP pinging an IP.
srbt
srbt(peer, pkts, inter=0.1 )
Same as sr but for the conf.BTsocket supersocket. It is a Bluetooth
supersocket that needs the peers address, provided by the peer parameter.
srloop
srloop(pkts, prn=lambda x:x[1].summary(),, prnfail=lambda x:x.summary(),
inter=1, timeout=None, count=None, verbose=0 )
Send in loop a packet or a set of packets with conf.L3socket supersocket
and print the results at each round.
timeout: time to wait for answers after the last packet has been sent. By
default, the timeout will be min(2 inter, 5)
count: number of rounds. By default, runs forever.
verbose: control verbosity.
>>> srloop(IP(dst="192.168.0.1")/TCP(dport=[21,22,25,80]),count=3)
RECV 2: IP / TCP 192.168.0.1:ssh > 192.168.0.1:ftp-data SA
IP / TCP 192.168.0.1:www > 192.168.0.1:ftp-data RA
fail 2: IP / TCP 192.168.0.1:ftp-data > 192.168.0.1:smtp S
IP / TCP 192.168.0.1:ftp-data > 192.168.0.1:ftp S
RECV 2: IP / TCP 192.168.0.1:ssh > 192.168.0.1:ftp-data SA
IP / TCP 192.168.0.1:www > 192.168.0.1:ftp-data RA
fail 2: IP / TCP 192.168.0.1:ftp-data > 192.168.0.1:smtp S
IP / TCP 192.168.0.1:ftp-data > 192.168.0.1:ftp S
RECV 2: IP / TCP 192.168.0.1:ssh > 192.168.0.1:ftp-data SA
IP / TCP 192.168.0.1:www > 192.168.0.1:ftp-data RA
fail 2: IP / TCP 192.168.0.1:ftp-data > 192.168.0.1:smtp S
IP / TCP 192.168.0.1:ftp-data > 192.168.0.1:ftp S
Sent 12 packets, received 6 packets. 50.0% hits.
srploop
srploop(pkts)
Same as srloop but for layer 2.
traceroute
traceroute(target, dport=80, minttl=1, maxttl=30, sport=RandShort, l4=None,
filter=None, timeout=2 )
arping
arping(net, timeout=2 )
Send ARP who-has requests to determine which hosts are up arping(net,
iface=conf.iface) - None
is promisc
is promisc(ip, fake bcast=::00:00:00:00)
Try to guess if target is in Promisc mode. The target is provided by its
ip.
dhcp request
dhcp request(iface=None)
38 CHAPTER 8. COMMANDS
fragleak
fragleak(target, sport=123, dport=123, timeout=0.2, onlyasc=0 )
fragleak2
fragleak2(target, timeout=0.4, onlyasc=0 )
report ports
report ports(target, ports)
portscan a target and output a LATEXtable
arpcachepoison
arpcachepoison(target, victim, interval=60 )
Poison targets cache with (your MAC,victims IP) couple
dns spoof
airpwn
bootpd
farpd
Part III
Extending Scapy
39
Adding a new protocol
9
Adding new layer in Scapy is very easy. All the magic is in the fields. If the
fields you need are already there and the protocol is not too brain-damaged,
this should be a matter of minutes.
A layer is a subclass of the Packet class. All the logic behind layer manipulation
is hold by the Packet class and will be inherited.
In this example, our layer has three fields. The first one is an 2 byte integer
field named mickey and whose default value is 5. The second one is a 1 byte
41
42 CHAPTER 9. ADDING A NEW PROTOCOL
integer field named minnie and whose default value is 3. The dierence between
a vanilla ByteField and a XByteField is only the fact that the prefered human
representation of the fields value is in hexadecimal. The last field is a 4 byte
integer field named s donald. It is dierent from a vanilla IntField by the fact
that some of the possible values of the field have litterate representations. For
example, if it is worth 3, the value will be displayed as angry. Moreover, if the
"cool" value is assigned to this field, it will understand that it has to take the
value 2.
>>> d=Disney(mickey=1)
>>> ls(d)
mickey : ShortField = 1 (5)
minnie : XByteField = 3 (3)
donald : IntEnumField = 1 (1)
>>> d.show()
###[ Disney Packet ]###
mickey= 1
minnie= 0x3
donald= happy
>>> d.donald="cool"
>>> str(d)
\x00\x01\x03\x00\x00\x00\x02
>>> Disney( )
<Disney mickey=1 minnie=0x3 donald=cool |>
9.2 Fields
Many fields already exist. Some are very generic, as ByteField, and some very
specific and used only in one layer, as TCPOptionsField.
FieldLenField The FieldLenField is a field whose value gives the length of another
field. If the other field is a FieldListField or a PacketListField, the value is
the number of elements of the list. Else, it correspond to the number of
bytes belonging to the other field. The third parameter is the name of the
other field. The default value should be None to indicate that it should
be calculated automatically. A shift value can be given that need to be
added to the value of the field to obtain the field value. This is needed
when a field holds the length of a set of fields and must be adjusted to get
only the variable fields length.
9.3. LAYERS METHODS 43
To do this, we will use the FieldLenField and the StrLenField. The FieldLenField
is a field whose value gives the length of another field. Here, the other field
is "the_string". The string field is also special because it needs to know
its length from the lengh field when the packet is dissected. So, it references
"the_length" as its third argument.
To make it short, when dissecting, "the_string" knows its lenght from freshly
dissected "the_length" field and when assembling, "the_length" can be au-
tomatically computed from the length of "the_string".
1 c l a s s VarStr ( Packet ) :
2 name = " Variable String "
3 f i e l d s d e s c = [ F i e l d L e n F i e l d ( " the_length" , None , " the_string" , "I" ) ,
4 S t r L e n F i e l d ( " the_string" , " The default value" , " the_length" ) ]
>>> p=VarStr()
>>> p.show2()
###[ Variable String ]###
the length= 17L
the string= The default value
>>> p.the string="The new value"
>>> p.show2()
###[ Variable String ]###
the length= 13L
the string= The new value
>>> hexdump(p)
0000 00 00 00 0D 54 68 65 20 6E 65 77 20 76 61 6C 75 ....The new valu
0010 65 e
44 CHAPTER 9. ADDING A NEW PROTOCOL
10
Adding a new field
The class field is responsible for both extracting the field value from the raw
packet string being dissected and for adding the field in a raw packet string
being assembled.
The value held into a field can have many forms. We have the assembled form,
the internal form, the human readable form and a rich representation. For
example, the TCP flags for a SYN-ACK packet will have the "SA" string as
rich representation. In the packet, we will find the character "\x12". But the
internal useful value will be the integer 18. Each field will provide functions to
translate values between all those representations, even if, in most of the cases,
some of the representations will be identical. A special function is also here to
try guess its input form to enable the user to fill a field with human readable or
rich representation.
45
46 CHAPTER 10. ADDING A NEW FIELD
getfield
getfield(self, pkt, s)
Extracts and returns the value of the field from the raw string packet s.
The field belongs to the Packet instance pkt.
randval
randval(self)
Returns a VolatileValue subclass instance whose values will be randomly
chosen in the domain of the field.
copy
copy(self)
Returns a deep copy of the instance.
i2h
i2h(self, pkt, x)
Translates the internal value representation into the human readable rep-
resentation.
h2i
h2i(self, pkt, x)
Translates the human readable representation into the internal represen-
tation.
m2i
m2i(self, pkt, x)
Translates the machine representation into the internal representation.
The machine representation is the raw bytes found into the raw string
packet.
any2i
any2i(self, pkt, x)
Try to guess the input representation and returns the internal representa-
tion.
i2m
i2m(self, pkt, x)
Translates the internal representation into the machine representation.
The machine representation is the raw bytes found into the raw string
packet.
i2repr
i2repr(self, pkt, x)
Translates the internal value to the rich representation.
i2len
i2en(self, pkt, x)
10.1. THE FIELD API 47
Computes the length of the field for it to be used in another field (usually,
a length field). Depending on the field and the layer, the value can be for
example a byte count or a number of elements in a list, and can even be
shifted to fit the needs of the the length field.
48 CHAPTER 10. ADDING A NEW FIELD
11
Adding an answering machine
49
50 CHAPTER 11. ADDING AN ANSWERING MACHINE
12
Making your own tools
51
52 CHAPTER 12. MAKING YOUR OWN TOOLS
13
Scripting Scapy
53
54 CHAPTER 13. SCRIPTING SCAPY
14
Adding a new high-level function
55
56 CHAPTER 14. ADDING A NEW HIGH-LEVEL FUNCTION
Part IV
Internals
57
15
Networking code
15.1 Supersockets
There are many dierent ways to access the network even on the same OS. The
abstraction for all of these in Scapy is supersockets.
A supersocket can be initialized with a BPF filter. It can be read with the
recv() method and written with the send() method. In both cases, packets
are provided, and the recv() method has to determine which layer is suitable
for the considered link type. A supersocket also has a fileno() method for it
to be selected for reading. In the case there is one file descriptor for reading
and one for writing, the first one must be returned.
Functions that use supersockets (sr, sendp, sni, etc.) choose the supersocket
layer type they need in the conf variable. If they need a layer 3 supersocket,
they will use conf.L3socket.
59
60 CHAPTER 15. NETWORKING CODE
socket for sending and a PF PACKET for receiving. Hence many limitations
apply to sending. For example, if IP checksum is 0, it will be calculated,
packets can be blocked by the local firewall, etc. But it has the advantage
to work on the loopback interface.
L2ListenSocket: This socket uses PF PACKET/SOCK RAW for sning use only.
L3dnetSocket: This supersocket uses libpcap for receiving and libdnet for send-
ing. It works at layer 3 and handles layer 2.
L2dnetSocket: This supersocket uses libpcap for receiving and libdnet for send-
ing. It works at layer 2.
StreamSocket: This socket uses a kernel stream socket (TCP connexion, etc.)
as a link layer. The layer class to use as the link layer protocol must be
provided.
When Scapy is launched, its routing tables are synchronized with hosts routing
table. For a packet sent at layer 3, the destination IP determine the output
interface, source address and gateway to be used. For a layer 2 packet, the
output interface can be precised, or an hint can be given in the form of an IP
to determine the output interface. If no output interface nor hint are given,
conf.iface is used.
15.2. ROUTING PACKETS 61
>>> conf.route
Network Netmask Gateway Iface Output IP
127.0.0.0 255.0.0.0 0.0.0.0 lo 127.0.0.1
172.16.15.0 255.255.255.0 0.0.0.0 eth0 172.16.15.42
0.0.0.0 0.0.0.0 172.16.15.1 eth0 172.16.15.42
>>> conf.route.add(net="192.168.1.0/24",gw="172.16.15.23")
>>> conf.route.add(host="192.168.4.5",gw="172.16.15.24")
>>> conf.route
Network Netmask Gateway Iface Output IP
127.0.0.0 255.0.0.0 0.0.0.0 lo 127.0.0.1
172.16.15.0 255.255.255.0 0.0.0.0 eth0 172.16.15.42
192.168.1.0 255.255.255.0 172.16.15.23 eth0 172.16.15.42
192.168.4.5 255.255.255.255 172.16.15.24 eth0 172.16.15.42
0.0.0.0 0.0.0.0 172.16.15.1 eth0 172.16.15.42
>>> conf.route.delt(net="192.168.1.0/24",gw="172.16.15.23")
>>> conf.route.resync()
>>> conf.route
Network Netmask Gateway Iface Output IP
127.0.0.0 255.0.0.0 0.0.0.0 lo 127.0.0.1
172.16.15.0 255.255.255.0 0.0.0.0 eth0 172.16.15.42
0.0.0.0 0.0.0.0 172.16.15.1 eth0 172.16.15.42
62 CHAPTER 15. NETWORKING CODE
16
Object model
63