Scapy
Description
Scapy est un logiciel libre de manipulation de paquets, écrit en langage python. Il est capable, entre autres, d'intercepter le trafic sur un segment réseau, de générer des paquets dans un nombre important de protocoles, de réaliser une prise d'empreinte de la pile TCP/IP, de faire un traceroute et d'analyser le réseau.
Installation
Sous Windows
L'installation de Scapy sous Windows est bien moins triviale que sous Linux.
La procédure d'installation est décrite ici.
Sous Linux (Debian)
Installation par les packages
Il existe un package Scapy. Néanmoins, celui-ci correspond à une ancienne version (1.1.1-3) et il est préférable d’effectuer une installation manuelle. La commande suivante installe scapy ainsi que les dépendances nécessaires :
# apt-get install python-gnuplot python-crypto python-pyx ebtables python-visual sox xpdf gv python-scapy
Installation par les sources
Installation des dépendances
gnuplot (nécessaire pour gnuplot-py)
# cd /usr/local/src/ # wget http://downloads.sourceforge.net/sourceforge/gnuplot/gnuplot-4.2.5.tar.gz?use_mirror=freefr # tar xzvf gnuplot-4.2.5.tar.gz # cd gnuplot-4.2.5/ # ./configure # make # make install
package pyhton-dev (requis pour numpy)
# apt-get install python-dev
numpy (nécessaire pour gnuplot-py)
# cd /usr/local/src/ # wget http://downloads.sourceforge.net/sourceforge/numpy/numpy-1.3.0.tar.gz?use_mirror=freefr # tar xzvf numpy-1.3.0.tar.gz # cd numpy-1.3.0/ # python setup.py install
gnuplot-py
# cd /usr/local/src/ # wget http://downloads.sourceforge.net/sourceforge/gnuplot-py/gnuplot-py-1.8.tar.gz?use_mirror=freefr # tar xzvf gnuplot-py-1.8.tar.gz # cd gnuplot-py-1.8/ # python setup.py install
LaTeX
# cd /usr/local/src/ # wget http://ctan.math.utah.edu/ctan/tex-archive/systems/texlive/tlnet/2008/install-tl-unx.tar.gz # tar xzvf install-tl-unx.tar.gz # cd install-tl/ # ./install-tl
Suivre les étapes de l'installation
Thank you for your comprehension.
************ http://www.secdev.org/projects/scapy/doc/installation.html ************
Utilisation
Remarques générales
- Le caractère "_" désigne le dernier résultat. Par exemple :
>>> a="Hello" >>> str(a) 'Hello' >>> hexdump(_) 0000 48 65 6C 6C 6F Hello
- Pour obtenir de l'aide sur une fonction, utilisez la fonction help(nom_de_la_fonction)
>>> help(sniff) Help on function sniff in module __main__: sniff(count=0, store=1, offline=None, prn=None, lfilter=None, L2socket=None, timeout=None, *arg, **karg) Sniff packets sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets count: number of packets to capture. 0 means infinity store: wether to store sniffed packets or discard them prn: function to apply to each packet. If something is returned, it is displayed. Ex: ex: prn = lambda x: x.summary() lfilter: python function applied to each packet to determine if further action may be done ex: lfilter = lambda x: x.haslayer(Padding) offline: pcap file to read packets from, instead of sniffing them timeout: stop sniffing after a given time (default: None) L2socket: use the provided L2socket
- Pour connaître la liste des paramètres d'une couche et les valeurs par défaut de ces paramètres, utilisez : ls(couche). Pour connaître la liste des couches, utilisez ls() sans paramètre. Enfin, pour lister les paramètres d'une variable (par exemple t1=IP(dst="192.168.182.132")), utilisez ls(t1).
>>> ls(IP) version : BitField = (4) ihl : BitField = (None) tos : XByteField = (0) len : ShortField = (None) id : ShortField = (1) flags : FlagsField = (0) frag : BitField = (0) ttl : ByteField = (64) proto : ByteEnumField = (0) chksum : XShortField = (None) src : Emph = (None) dst : Emph = ('127.0.0.1') options : IPoptionsField = ()
- Pour connaître la liste des commandes disponibles, utilisez la fonction lsc().
>>> lsc() sr : Send and receive packets at layer 3 sr1 : Send packets at layer 3 and return only the first answer srp : Send and receive packets at layer 2 srp1 : Send and receive packets at layer 2 and return only the first answer srloop : Send a packet at layer 3 in loop and print the answer each time srploop : Send a packet at layer 2 in loop and print the answer each time sniff : Sniff packets p0f : Passive OS fingerprinting: which OS emitted this TCP SYN ? arpcachepoison : Poison target's cache with (your MAC,victim's IP) couple send : Send packets at layer 3 sendp : Send packets at layer 2 traceroute : Instant TCP traceroute arping : Send ARP who-has requests to determine which hosts are up ls : List available layers, or infos on a given layer lsc : List user commands queso : Queso OS fingerprinting nmap_fp : nmap fingerprinting report_ports : portscan a target and output a LaTeX table dyndns_add : Send a DNS add message to a nameserver for "name" to have a new "rdata" dyndns_del : Send a DNS delete message to a nameserver for "name" is_promisc : Try to guess if target is in Promisc mode. The target is provided by its ip. promiscping : Send ARP who-has requests to determine which hosts are in promiscuous mode
- Enfin, pour connaître la syntaxe des paramètres propres aux protocoles (src=, dst=, etc.), vous pouvez vous référer à la colonne "abréviation" des tableaux de description des champs dans les paragraphes relatifs aux protocoles, vus dans le paragraphe 2.3.
Initialiser une session
Pour initialiser une nouvelle session, utiliser la commande suivante :
# ./scapy.py -s mysession INFO: Using session [mysession] Welcome to Scapy (1.2.0.2) >>>
Forger des paquets
Scapy permet de forger n’importe quel type de paquet (couche TCP, UDP, IP, etc.). Pour chaque couche, les valeurs qui ne sont pas renseignées manuellement le seront automatiquement. La commande ls(IP) permet de consulter l’attribution automatique de ces valeurs.
>>> ls(IP) version : BitField = (4) ihl : BitField = (None) tos : XByteField = (0) len : ShortField = (None) id : ShortField = (1) flags : FlagsField = (0) frag : BitField = (0) ttl : ByteField = (64) proto : ByteEnumField = (0) chksum : XShortField = (None) src : Emph = (None) dst : Emph = ('127.0.0.1') options : IPoptionsField = ()
Initialisons tout d’abord un nouvel objet :
>>> a=IP()
Celui-ci contient dorénavant des valeurs par défaut :
>>> a.ttl 64 >>> a.src '127.0.0.1'
Il est possible de forcer ces valeurs par défaut :
>>> a.src='192.168.1.13' >>> a.src '192.168.1.13'
Pour consulter toutes les valeurs forcées, il suffit de rappeler l’objet :
>>> a <IP src=192.168.1.13 |>
Certaines valeurs sont dépendantes et donc recalculées. L’exemple ci-dessous illustre ce phénomène (la valeur de a.src par défaut est mise à jour par dépendance de mise à jour de la valeur de a.dst)
>>> a=IP() >>> a.src '127.0.0.1' >>> a.dst='192.168.1.1' >>> a.src '192.168.182.132'
La fonction del( ) permet de détruire tout ou partie d’un objet. L’exemple qui suit montre que la suppression d’une valeur forcée entraîne la réinitialisation de la valeur par défaut :
>>> del(a.dst) >>> a.dst, a.src ('127.0.0.1', '127.0.0.1') >>> a <IP |> >>> del(a) >>> a Traceback (most recent call last): File "<console>", line 1, in ? NameError: name 'a' is not defined
Pour compléter notre paquet, nous pouvons également spécifier les drapeaux TCP comme suit :
>>> a=IP(dst="192.168.1.1") >>> a <IP dst=192.168.1.1 |> >>> b=a/TCP(flags="SF") >>> b <IP frag=0 proto=tcp dst=192.168.1.1 | <TCP flags=FS |>>
Ou, pour une vue plus détaillée :
>>> b.show() ###[ IP ]### version= 4 ihl= 0 tos= 0x0 len= 0 id= 1 flags= frag= 0 ttl= 64 proto= tcp chksum= 0x0 src= 192.168.182.132 dst= 192.168.1.1 options= ###[ TCP ]### sport= ftp_data dport= www seq= 0 ack= 0 dataofs= 0 reserved= 0 flags= FS window= 8192 chksum= 0x0 urgptr= 0 options= {}
Il est également possible de spécifier plusieurs éléments par paramètre. L'exemple suivant montre comment spécifier deux ports de destination :
>>> b.ttl=(10,14) >>> b.dport=[80,443] >>> [k for k in b] [<IP frag=0 ttl=10 proto=tcp dst=192.168.1.1 |<TCP dport=www flags=FS |>>, <IP frag=0 ttl=10 proto=tcp dst=192.168.1.1 |<TCP dport=https flags=FS |>>, <IP frag=0 ttl=11 proto=tcp dst=192.168.1.1 |<TCP dport=www flags=FS |>>, <IP frag=0 ttl=11 proto=tcp dst=192.168.1.1 |<TCP dport=https flags=FS |>>, <IP frag=0 ttl=12 proto=tcp dst=192.168.1.1 |<TCP dport=www flags=FS |>>, <IP frag=0 ttl=12 proto=tcp dst=192.168.1.1 |<TCP dport=https flags=FS |>>, <IP frag=0 ttl=13 proto=tcp dst=192.168.1.1 |<TCP dport=www flags=FS |>>, <IP frag=0 ttl=13 proto=tcp dst=192.168.1.1 |<TCP dport=https flags=FS |>>, <IP frag=0 ttl=14 proto=tcp dst=192.168.1.1 |<TCP dport=www flags=FS |>>, <IP frag=0 ttl=14 proto=tcp dst=192.168.1.1 |<TCP dport=https flags=FS |>>]
Envoyer et recevoir des paquets
La commande send( ) permet d'envoyer des paquets précédemment forgés :
>>> a=IP(dst="192.168.225.1") >>> a <IP dst=192.168.225.1 |> >>> send(a) . Sent 1 packets.
Il existe plusieurs fonctions pour envoyer et recevoir des paquets :
- La fontion sr( ) émet sur la couche 3 (réseau) et reçoit les réponses;
- La fonction sr1( ) émet sur la couche 3 (réseau) et renvoie la première réponse;
- La fonction srp( ) émet sur la couche 2 (liaison) et reçoit les réponses;
- La fonction srp1( ) émet sur la couche 2 (liaison) et renvoie la première réponse.
>>> sr1(IP(dst="192.168.225.1")/ICMP())
Begin emission: .*Finished to send 1 packets.
Received 2 packets, got 1 answers, remaining 0 packets
<IP version=4L ihl=5L tos=0x0 len=28 id=1758 flags= frag=0L ttl=128 proto=icmp chksum=0x1b2c src=192.168.225.1 dst=192.168.182.132 options= |<ICMP type=echo -reply code=0 chksum=0xffff id=0x0 seq=0x0 |<Padding load='\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' >>>
En cas de non réponse :
>>> sr1(IP(dst="192.168.225.2")/ICMP()) Begin emission: .Finished to send 1 packets. ..............................................................^C Received 63 packets, got 0 answers, remaining 1 packets
Il est possible de scanner les hôtes actifs sur un réseau, en exploitant le tableau de résultats comme dans l'exemple ci-dessous :
>>> sr(IP(dst="192.168.0.0/24")/ICMP()) Begin emission: ....*.*.................*.Finished to send 256 packets. ...........^C Received 37 packets, got 3 answers, remaining 253 packets (<Results: TCP:0 UDP:0 ICMP:3 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:253 Other: 0>) >>> res,unans=_ >>> res.summary() IP / ICMP 192.168.182.132 > 192.168.0.10 echo-request 0 ==> IP / ICMP 192.168.0. 10 > 192.168.182.132 echo-reply 0 / Padding IP / ICMP 192.168.182.132 > 192.168.0.13 echo-request 0 ==> IP / ICMP 192.168.0. 13 > 192.168.182.132 echo-reply 0 / Padding IP / ICMP 192.168.182.132 > 192.168.0.254 echo-request 0 ==> IP / ICMP 192.168.0 .254 > 192.168.182.132 echo-reply 0 / Padding
Mode écoute
Le mode d'écoute est assuré par la fonction sniff( ). Elle accepte comme arguments principaux count pour limiter l'écoute à un nombre de paquets, et filter afin de filtrer le type de paquet (TCP, UDP, ICMP, Other).
Sur le serveur, entrez la commande suivante :
>>> sniff(count=5)
Sur le client, effectuez un ping vers le serveur afin de générer du trafic. Scapy passe alors en mode d'écoute. Lorsque le nombre de paquets spécifiés (ici 5) est atteint, Scapy rend la main et affiche un message :
<Sniffed: TCP:1 UDP:0 ICMP:4 Other:0>
Il est alors possible de déchiffrer le résultat intercepté :
>>> a=_ >>> a.summary() Ether / IP / TCP 192.168.182.1:1200 > 192.168.182.132:https A / Padding Ether / IP / ICMP 192.168.182.1 > 192.168.182.132 echo-request 0 / Raw Ether / IP / ICMP 192.168.182.132 > 192.168.182.1 echo-reply 0 / Raw Ether / IP / ICMP 192.168.182.1 > 192.168.182.132 echo-request 0 / Raw Ether / IP / ICMP 192.168.182.132 > 192.168.182.1 echo-reply 0 / Raw
Les fonctions wrpcap( ) et rdpcap( ) permettent respectivement d'écrire et de lire des fichiers de capture.
Conclusion
Scapy est un outil complet qui permet de fabriquer presque n'importe quel type de paquet, ce qui implique également l'émission de paquets malformés, ping de la mort ou autres. C'est pourquoi, même si cet outil connaît certaines limites, il est très utile dans le cadre de campagnes de tests de sécurité d'un réseau.
Par ailleurs, Scapy est doté de fonctionnalités graphiques – non présentées dans le présent document – et qui permettent de représenter les résultats de traceroute en 3D (voir figure suivante : rendu 3D d'un traceroute avec Scapy).
- Backtrack/GUI/Information-Gathering/Network-Analysis/Network-Scanners
- Backtrack/GUI/Information-Gathering/Network-Analysis/Network-Traffic-Analysis
- Backtrack/GUI/Information-Gathering/Network-Analysis/Route-Analysis
- Backtrack/GUI/Privilege-Escalation/Protocol-Analysis/Network-Sniffers
- Backtrack/CLI/usr/bin
- Backtrack/CLI/usr/local/bin
- Network/Packet-forge