← retour aux outils back to tools

# Scapy

Framework de manipulation de paquets interactif basé sur Python. Forgez, envoyez, sniffez et décodez des paquets à n'importe quelle couche protocolaire. Idéal pour les attaques sur mesure et le fuzzing de protocoles. Python-based interactive packet manipulation framework. Craft, send, sniff, and dissect packets at any protocol layer. Ideal for custom attacks and protocol fuzzing.

↗ https://scapy.net

## Overview

Scapy is an interactive Python packet manipulation library. It lets you forge or decode packets at any layer (Ethernet, IP, TCP, DNS, etc.), send them, capture responses, and script complex network interactions. Ideal for building custom tools, PoCs, and protocol research.

## Starting Scapy

Interactive mode

    sudo scapy

Or import in Python script

    from scapy.all import *

## Packet Crafting

    # Build a simple TCP SYN packet
    pkt = IP(dst="10.10.10.1") / TCP(dport=80, flags="S")

    # ICMP ping
    pkt = IP(dst="10.10.10.1") / ICMP()

    # UDP DNS query
    pkt = IP(dst="8.8.8.8") / UDP(dport=53) / DNS(rd=1, qd=DNSQR(qname="target.com"))

    # Custom Ethernet frame
    pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst="10.10.10.1")

    # View packet structure
    pkt.show()
    pkt.show2()  # Computed fields

    # Dump as hex
    hexdump(pkt)

## Sending Packets

    # Layer 3 send (no response handling)
    send(IP(dst="10.10.10.1") / ICMP())

    # Layer 2 send
    sendp(Ether() / IP(dst="10.10.10.1") / ICMP(), iface="eth0")

    # Send and receive (Layer 3) — returns answered, unanswered
    ans, unans = sr(IP(dst="10.10.10.1") / TCP(dport=80, flags="S"), timeout=2)

    # Send and receive one packet
    ans = sr1(IP(dst="8.8.8.8") / ICMP(), timeout=2)

    # Layer 2 send/receive
    ans, unans = srp(Ether() / IP(dst="10.10.10.1") / ICMP(), iface="eth0", timeout=2)

## Sniffing

    # Sniff 10 packets
    pkts = sniff(count=10)

    # Sniff with filter
    pkts = sniff(filter="tcp port 80", count=20, iface="eth0")

    # Sniff with callback
    sniff(prn=lambda x: x.summary(), filter="icmp")

    # Sniff and save to pcap
    sniff(filter="tcp port 80", count=100, iface="eth0") \
        .nsummary()
    wrpcap("capture.pcap", pkts)

    # Read pcap
    pkts = rdpcap("capture.pcap")

## Common Use Cases

    # ARP Scan (host discovery)
    ans, _ = srp(Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst="10.10.10.0/24"),
                 timeout=2, iface="eth0")
    for sent, recv in ans:
        print(recv.sprintf("%ARP.psrc% - %Ether.src%"))

    # TCP SYN Scan
    ans, unans = sr(IP(dst="10.10.10.1") / TCP(dport=[22,80,443,445], flags="S"),
                    timeout=2)
    for sent, recv in ans:
        if recv.haslayer(TCP) and recv[TCP].flags == 0x12:  # SYN-ACK
            print(f"Port {recv[TCP].sport} open")

    # DNS Query
    resp = sr1(IP(dst="8.8.8.8") / UDP(dport=53) /
               DNS(rd=1, qd=DNSQR(qname="target.com")), timeout=2)
    print(resp[DNS].summary())

    # ARP Spoofing (MITM)
    def arp_spoof(target_ip, spoof_ip, iface="eth0"):
        target_mac = getmacbyip(target_ip)
        pkt = ARP(op=2, pdst=target_ip, hwdst=target_mac, psrc=spoof_ip)
        send(pkt, verbose=False)

## Fuzzing

    # Fuzz TCP flags
    for flag in ["S", "SA", "F", "R", "P", "U", "A"]:
        sr1(IP(dst="10.10.10.1") / TCP(dport=80, flags=flag), timeout=1)

    # Fuzz payload length
    for size in range(0, 1000, 100):
        send(IP(dst="10.10.10.1") / UDP(dport=9999) / Raw(b"A" * size))

    # Built-in fuzz function (randomizes fields)
    send(IP(dst="10.10.10.1") / fuzz(TCP()))

## Tips

- Always run as root/sudo — raw sockets require elevated privileges
- `pkt.show()` and `ls(pkt)` are invaluable for exploring packet fields
- `conf.iface = "eth0"` sets the default interface
- Scapy can read/write pcap files: `rdpcap()` and `wrpcap()`

Useful commands reference

    ls()               # List all protocols
    ls(IP)             # List IP fields
    conf.iface         # Default interface
    conf.verb = 0      # Suppress output

    pkt.show()         # Pretty print packet
    pkt.summary()      # One-line summary
    hexdump(pkt)       # Hex dump

    send()             # L3 send
    sendp()            # L2 send
    sr()               # L3 send+receive (multiple)
    sr1()              # L3 send+receive (one)
    srp()              # L2 send+receive
    sniff()            # Capture packets
    rdpcap()           # Read pcap
    wrpcap()           # Write pcap
    getmacbyip()       # ARP lookup

## Vue d’ensemble

Scapy est une bibliothèque Python interactive de manipulation de paquets. Elle permet de forger ou décoder des paquets à n’importe quelle couche (Ethernet, IP, TCP, DNS, etc.), de les envoyer, de capturer les réponses, et de scripter des interactions réseau complexes. Idéal pour construire des outils sur mesure, des PoC et de la recherche protocolaire.

## Démarrer Scapy

    # Mode interactif
    sudo scapy

    # Ou importer dans un script Python
    from scapy.all import *

## Fabrication de paquets

    # Construire un simple paquet TCP SYN
    pkt = IP(dst="10.10.10.1") / TCP(dport=80, flags="S")

    # Ping ICMP
    pkt = IP(dst="10.10.10.1") / ICMP()

    # Requête DNS UDP
    pkt = IP(dst="8.8.8.8") / UDP(dport=53) / DNS(rd=1, qd=DNSQR(qname="target.com"))

    # Trame Ethernet personnalisée
    pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst="10.10.10.1")

    # Voir la structure du paquet
    pkt.show()
    pkt.show2()  # Champs calculés

    # Dump en hexadécimal
    hexdump(pkt)

## Envoi de paquets

    # Envoi couche 3 (pas de gestion des réponses)
    send(IP(dst="10.10.10.1") / ICMP())

    # Envoi couche 2
    sendp(Ether() / IP(dst="10.10.10.1") / ICMP(), iface="eth0")

    # Envoyer et recevoir (couche 3) : renvoie answered, unanswered
    ans, unans = sr(IP(dst="10.10.10.1") / TCP(dport=80, flags="S"), timeout=2)

    # Envoyer et recevoir un seul paquet
    ans = sr1(IP(dst="8.8.8.8") / ICMP(), timeout=2)

    # Envoi/réception couche 2
    ans, unans = srp(Ether() / IP(dst="10.10.10.1") / ICMP(), iface="eth0", timeout=2)

## Sniffing

    # Sniffer 10 paquets
    pkts = sniff(count=10)

    # Sniffer avec filtre
    pkts = sniff(filter="tcp port 80", count=20, iface="eth0")

    # Sniffer avec callback
    sniff(prn=lambda x: x.summary(), filter="icmp")

    # Sniffer et sauvegarder en pcap
    sniff(filter="tcp port 80", count=100, iface="eth0") \
        .nsummary()
    wrpcap("capture.pcap", pkts)

    # Lire un pcap
    pkts = rdpcap("capture.pcap")

## Cas d’usage courants

    # Scan ARP (découverte d'hôtes)
    ans, _ = srp(Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst="10.10.10.0/24"),
                 timeout=2, iface="eth0")
    for sent, recv in ans:
        print(recv.sprintf("%ARP.psrc% - %Ether.src%"))

    # Scan TCP SYN
    ans, unans = sr(IP(dst="10.10.10.1") / TCP(dport=[22,80,443,445], flags="S"),
                    timeout=2)
    for sent, recv in ans:
        if recv.haslayer(TCP) and recv[TCP].flags == 0x12:  # SYN-ACK
            print(f"Port {recv[TCP].sport} open")

    # Requête DNS
    resp = sr1(IP(dst="8.8.8.8") / UDP(dport=53) /
               DNS(rd=1, qd=DNSQR(qname="target.com")), timeout=2)
    print(resp[DNS].summary())

    # ARP Spoofing (MITM)
    def arp_spoof(target_ip, spoof_ip, iface="eth0"):
        target_mac = getmacbyip(target_ip)
        pkt = ARP(op=2, pdst=target_ip, hwdst=target_mac, psrc=spoof_ip)
        send(pkt, verbose=False)

## Fuzzing

    # Fuzzer les flags TCP
    for flag in ["S", "SA", "F", "R", "P", "U", "A"]:
        sr1(IP(dst="10.10.10.1") / TCP(dport=80, flags=flag), timeout=1)

    # Fuzzer la longueur du payload
    for size in range(0, 1000, 100):
        send(IP(dst="10.10.10.1") / UDP(dport=9999) / Raw(b"A" * size))

    # Fonction de fuzz intégrée (randomise les champs)
    send(IP(dst="10.10.10.1") / fuzz(TCP()))

## Conseils

- Toujours lancer en root/sudo : les sockets raw nécessitent des privilèges élevés
- `pkt.show()` et `ls(pkt)` sont précieux pour explorer les champs d’un paquet
- `conf.iface = "eth0"` définit l’interface par défaut
- Scapy peut lire/écrire des fichiers pcap : `rdpcap()` et `wrpcap()`

Référence des commandes utiles

    ls()               # List all protocols
    ls(IP)             # List IP fields
    conf.iface         # Default interface
    conf.verb = 0      # Suppress output

    pkt.show()         # Pretty print packet
    pkt.summary()      # One-line summary
    hexdump(pkt)       # Hex dump

    send()             # L3 send
    sendp()            # L2 send
    sr()               # L3 send+receive (multiple)
    sr1()              # L3 send+receive (one)
    srp()              # L2 send+receive
    sniff()            # Capture packets
    rdpcap()           # Read pcap
    wrpcap()           # Write pcap
    getmacbyip()       # ARP lookup