Using Scapy in RIPE labs¶
Scapy is a packet manipulation tool and library. It lets you build, send, receive, and decode packets down to the protocol field level. Think of it as ping + tcpdump + Wireshark + a packet foundry, but interactive and scriptable.
1. Starting Scapy¶
scapy
If you see a >>> Python-like prompt, you’re in. Quit later with exit(), quit(), or Ctrl+D.
2. Building packets¶
In Scapy, packets are built layer by layer using / to stack protocols:
pkt = IPv6(src="2001:db8:5::5", dst="ff02::1") / ICMPv6ND_NA()
IPv6(...)→ the IPv6 headersrc= source IPv6 addressdst= destination IPv6 address (ff02::1= all nodes on the local link)
/ ICMPv6ND_NA()→ attach an ICMPv6 Neighbor Advertisement message on top.
At this point, you have an object called pkt. It’s not sent yet, just sitting in memory.
3. Sending packets¶
3.1 One-way send¶
send(pkt)
This just fires it off. No listening for replies. Good for testing or attacks where you don’t care about responses.
4. Probing with Echo Requests¶
Let’s try an ICMPv6 ping:
f = IPv6(dst="2001:db8:f:1::1") / ICMPv6EchoRequest()
The
IPv6layer sets the destination.The
ICMPv6EchoRequest()layer is the IPv6 equivalent ofping.
4.1 Send and receive¶
ans, unans = sr(f)
sr()= send packet(s) and receive answers.ans= answered packets (pairs of request + reply).unans= unanswered packets (request sent, but no reply received).
5. Inspecting Results¶
ans.summary()
This gives a one-line overview of request → reply mapping:
IPv6 / ICMPv6 Echo Request ==> IPv6 / ICMPv6 Echo Reply
For deep inspection:
ans.show()
Which prints full decoded layers, e.g.:
0000 IPv6 / ICMPv6 Echo Request (id: 0x0 seq: 0x0) ==>
IPv6 / ICMPv6 Echo Reply (id: 0x0 seq: 0x0)
5.1 Accessing individual results¶
First request/reply pair:
ans[0]
Which is a tuple: (<sent packet>, <received packet>)
Just the reply:
ans[0][1]
Just the request:
ans[0][0]
Show all fields of the request:
ans[0][0].show()
Output example:
###[ IPv6 ]###
version= 6
tc= 0
fl= 0
plen= None
nh= ICMPv6
hlim= 64
src= 2001:db8:f:1:216:3eff:feee:a
dst= 2001:db8:f:1::1
###[ ICMPv6 Echo Request ]###
type= Echo Request
code= 0
cksum= None
id= 0x0
seq= 0x0
6. Repeated probing with srloop¶
ans, unans = srloop(f)
This continuously sends requests until you break it (Ctrl+C).
Example output:
RECV 1: IPv6 / ICMPv6 Echo Reply (id: 0x0 seq: 0x0)
RECV 1: IPv6 / ICMPv6 Echo Reply (id: 0x0 seq: 0x0)
RECV 1: IPv6 / ICMPv6 Echo Reply (id: 0x0 seq: 0x0)
^C
Sent 3 packets, received 3 packets. 100.0% hits.
You can then summarise the results:
ans.summary()
7. Capturing packets¶
To capture packets in Scapy, use the sniff() function. You need to pass the interface where you want to capture
packets and define a filtering rule if you do not want to capture all of the packets arriving on that interface.
>>> pkts=sniff(iface="eth0",lfilter = lambda x: x.haslayer(IPv6))
^C
8. Summary¶
Packet composition: Use
/to stack headers and protocols.Sending:
send()= fire and forget.sr()= send and receive (store replies).srloop()= send repeatedly until you stop it.
Inspection:
summary()for one-liners.show()for all fields.Index into
ansfor detailed request/reply tuples.
Scapy does not validate whether fields are “legal”. If you want to set insane values (like Flow Label abuse for covert channels), Scapy will happily craft and send it.