How to Use Scapy – Python Networking Tool Explained
As a full-stack developer, you know the importance of understanding and debugging network traffic. While tools like Wireshark are great for analyzing packets, sometimes you need more flexibility and control. That‘s where Scapy comes in. Scapy is a powerful Python library that allows you to construct, manipulate, send and capture network packets.
In this expert-level guide, we‘ll dive deep into using Scapy for network analysis and penetration testing. Whether you‘re investigating a performance issue, reverse-engineering a protocol or simulating an attack, Scapy has you covered. We‘ll walk through installing Scapy, cover essential concepts like protocol layers and packet fields, and build up to advanced techniques like fuzzing and custom packet dissectors.
Are you ready to add a versatile new tool to your networking toolkit? Let‘s get started!
Installing Scapy
The first step is getting Scapy installed on your system. Scapy is a Python library, so you‘ll need Python (2.7 or 3.4+) set up. Use pip to fetch and install the latest version of Scapy:
sudo pip install scapy
On Windows, you may need to install some dependencies like Winpcap first. See the install docs for full details.
To verify Scapy is working, run the scapy
command to launch the interactive shell:
sudo scapy
Welcome to Scapy
>>>
If you see the Scapy prompt, you‘re good to go! Use help()
to view built-in docs.
Scapy Fundamentals
Network traffic is made up of packets containing data. Packets have a layered structure where each layer corresponds to a protocol in the network stack. For example, here‘s a simplified diagram of layers in a typical HTTP request:
With Scapy, you work with packets as Python objects. Let‘s build a packet with an Ethernet header and raw payload:
>>> pkt = Ether() / Raw(load="Hello world!")
>>> pkt
<Ether type=0x7a69 |<Raw load=‘Hello world!‘ |>>
Scapy overloads the /
operator to combine layers. We can view the packet‘s contents:
>>> pkt.show()
###[ Ethernet ]###
dst = ff:ff:ff:ff:ff:ff
src = 00:00:00:00:00:00
type = 0x7a69
###[ Raw ]###
load = ‘Hello world!‘
Each layer is shown with its fields and values. ff:ff:ff:ff:ff:ff is the default broadcast MAC address. Let‘s change the source MAC:
>>> pkt.src = "11:22:33:44:55:66"
>>> pkt
<Ether dst=ff:ff:ff:ff:ff:ff src=11:22:33:44:55:66 type=0x7a69 |<Raw load=‘Hello world!‘ |>>
Here we directly set the src
field of our packet. We can also access specific layers by name and slice notation:
>>> pkt[Ether].src
‘11:22:33:44:55:66‘
>>> pkt[Raw].load
‘Hello world!‘
As you can see, it‘s easy to examine and modify packets piece by piece.
Sniffing and Dissecting Traffic
Scapy can capture packets passing through a network interface. Let‘s sniff some traffic:
>>> pkts = sniff(count=5)
>>> pkts
<Sniffed: TCP:3 UDP:1 ICMP:1>
sniff
captures 5 packets and stores them in pkts. To view a packet‘s details:
>>> pkts[0]
<Ether dst=01:00:5e:00:00:fb src=00:0c:29:b9:13:27 type=IPv4 |<IP version=4 ihl=5 tos=0x0 len=32 id=0 flags=DF frag=0 ttl=1 proto=icmp chksum=0xf953 src=192.168.0.14 dst=224.0.0.251 |<ICMP type=membership_query code=0 chksum=0xee4a id=0x0 seq=0x0 gaddr=224.0.0.251 |>>>
This is an ICMP membership query packet with an IP and Ethernet header. The indented lines show the structure and values of each layer.
To search packets that match specific criteria, provide a filter to sniff
:
>>> results, unans = sr(IP(dst="8.8.8.8")/ICMP())
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
>>> results[0]
(<IP frag=0 proto=icmp dst=8.8.8.8 |<ICMP |>>, <IP version=4 ihl=5 tos=0x0 len=28 id=36912 flags= frag=0 ttl=119 proto=icmp chksum=0x85a8 src=8.8.8.8 dst=192.168.0.14 |<ICMP type=echo-reply code=0 chksum=0x0 id=0x0 seq=0x0 |>>)
sr
sends and receives packets. We crafted an ICMP echo request, then displayed the response which came from 8.8.8.8. Play around and see what other protocols you can elicit responses from!
Forging Packets and Attacks
In addition to passively analyzing traffic, Scapy lets you create custom packets from scratch. This is useful for testing out uncommon scenarios:
>>> ip = IP(src=‘1.2.3.4‘, dst=‘10.0.0.1‘)
>>> tcp = TCP(sport=1500, dport=80, flags=‘S‘)
>>> pkt = ip/tcp
>>> pkt.show()
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 40
id = 1
flags =
frag = 0
ttl = 64
proto = tcp
chksum = 0x74ca
src = 1.2.3.4
dst = 10.0.0.1
###[ TCP ]###
sport = 1500
dport = http
seq = 0
ack = 0
dataofs = 5
reserved = 0
flags = S
window = 8192
chksum = 0x1d7a
urgptr = 0
options = {}
Here we spoofed the source IP and initialized a TCP SYN packet on a non-standard port. What kind of response do you think this will trigger?
We can even reconstruct attacks to see how a target behaves. This code snippets injects a huge IP packet:
>>> send( IP(dst=‘10.0.0.5‘)/ICMP()/("X"*60000) )
.
Sent 1 packets.
Oversized ICMP payloads can cause a denial of service. Please only test on your own systems and networks!
As you can see, Scapy makes it simple to precisely handcraft packets for penetration testing, fuzz testing, and vulnerability research. With some creativity, you can simulate all sorts of corner cases and analyze the results.
Writing Scapy Scripts
While Scapy‘s interactive shell is great for exploration, at some point you‘ll want to automate your work. Scapy integrates with Python scripts seamlessly.
For example, here‘s a script to scan for live hosts on a network using ARP:
#!/usr/bin/env python
from scapy.all import *
network = "192.168.0.0/24"
ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=network),
timeout=2)
for send, recv in ans:
print recv.sprintf(r"%Ether.src% - %ARP.psrc%")
This broadcasts an ARP request to every possible IP in the 192.168.0.0/24 subnet. For each response, we print the MAC and IP address of live hosts.
Save this script and run it to quickly map out your local devices:
sudo python arp_scan.py
11:22:33:44:55:66 - 192.168.0.1
aa:bb:cc:dd:ee:ff - 192.168.0.12
00:0c:29:f0:f8:16 - 192.168.0.14
You can use this technique to write custom ping sweeps, port scanners, fuzzers and more. Imagination‘s the limit!
Final Thoughts
We‘ve only scratched the surface of what Scapy can do. Its protocol support, packet crafting API and sniffing capabilities provide immense flexibility for network analysis and hacking.
Play with the built-in protocol layers, decode some unfamiliar traffic, and write your own custom dissectors. Consult the official docs to go further.
Remember, with great power comes great responsibility! Only use Scapy on your own systems and networks unless you have explicit permission.
Happy packet hacking!