Installation de scapy sur Ubuntu
sudo apt-get install python-scapy
Obtenir de l'aide sur les commandes scapy
Pour connaitre la liste des commandes scapy
>>> lsc() arpcachepoison : Poison target's cache with (your MAC,victim's IP) couple arping : Send ARP who-has requests to determine which hosts are up bind_layers : Bind 2 layers on some specific fields' values corrupt_bits : Flip a given percentage or number of bits from a string corrupt_bytes : Corrupt a given percentage or number of bytes from a string defrag : defrag(plist) -> ([not fragmented], [defragmented], defragment : defrag(plist) -> plist defragmented as much as possible 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" etherleak : Exploit Etherleak flaw fragment : Fragment a big IP datagram fuzz : Transform a layer into a fuzzy layer by replacing some default values by random objects getmacbyip : Return MAC address corresponding to a given IP address hexdiff : Show differences between 2 binary strings hexdump : -- hexedit : -- is_promisc : Try to guess if target is in Promisc mode. The target is provided by its ip. linehexdump : -- ls : List available layers, or infos on a given layer promiscping : Send ARP who-has requests to determine which hosts are in promiscuous mode rdpcap : Read a pcap file and return a packet list send : Send packets at layer 3 sendp : Send packets at layer 2 sendpfast : Send packets at layer 2 using tcpreplay for performance sniff : Sniff packets split_layers : Split 2 layers previously bound sr : Send and receive packets at layer 3 sr1 : Send packets at layer 3 and return only the first answer srbt : send and receive using a bluetooth socket srbt1 : send and receive 1 packet using a bluetooth socket srflood : Flood and receive packets at layer 3 srloop : Send a packet at layer 3 in loop and print the answer each time srp : Send and receive packets at layer 2 srp1 : Send and receive packets at layer 2 and return only the first answer srpflood : Flood and receive packets at layer 2 srploop : Send a packet at layer 2 in loop and print the answer each time traceroute : Instant TCP traceroute tshark : Sniff packets and print them calling pkt.show(), a bit like text wireshark wireshark : Run wireshark on a list of packets wrpcap : Write a list of packets to a pcap file >>>
Voir tous les objets que Scapy peut manipuler
ls() ARP : ARP ... IP : IP ...
=> Il existe donc un objet IP dont le contenu peut être connu via ls(IP)
>>> 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 : PacketListField = ([])
>>>
Aide sur la commande send qui permet d'envoyer un paquet forgé à partir du niveau 3 (couche IP). Ceci veut dire que le niveau 2 (la couche ethernet) a été renseigné par scapy automatiquement :
thierry@PC1:~/Bureau/data/testScapy$ scapy
Welcome to Scapy (2.2.0)
>>> help(send)
Help on function send in module scapy.sendrecv:
send(x, inter=0, loop=0, count=None, verbose=None, realtime=None, *args, **kargs)
Send packets at layer 3
send(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None
Aide sur la commande sendp qui permet d'envoyer un paquet forgé à partir du niveau 2 (couche Ethernet):
thierry@PC1:~$ scapy
INFO: Can't import python gnuplot wrapper . Won't be able to plot.
INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().
WARNING: No route found for IPv6 destination :: (no default route?)
Welcome to Scapy (2.2.0)
>>> help(sendp)
Help on function sendp in module scapy.sendrecv:
sendp(x, inter=0, loop=0, iface=None, iface_hint=None, count=None, verbose=None, realtime=None, *args, **kargs)
Send packets at layer 2
sendp(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None
Création d'un paquet
On voit ci-dessous les valeutrs par défaut.
De plus, certaines valeurs sont recalculées, comme l'IP source suite à la définition de l'IP destination :
>>> a=IP() >>> a.ttl 64 >>> a.src '127.0.0.1' >>> a.dst='192.168.1.2' >>> a.src '192.168.1.10' >>>
Création d'un paquet ping vers www.google.fr
Trois méthodes :
- soit on crée le paquet à partir du niveau Ethernet en précisant que celui-ci contient un paquet IP à destination www.google.fr, lui même contenant un paquet ICMP echo-request, et envoie via srp
- soit on crée le paquet à partir du niveau IP en précisant que la destination est www.google.fr, puis en précisant que ce paquet IP contient une charge un paquet ICMP echo-request, et envoi via sr,
- soit on crée le paquet avec la méthode ICMP().
Cas de la construction de la trame à partir du niveau Ethernet. La fonction pour envoyer un tel paquet est alors srp.
#!/usr/bin/python
from scapy.all import *
# creation du paquet IP a destination de www.google.fr, ce paquet IP contenant un ICMP
pck=Ether()/IP(dst='www.google.fr')/ICMP()
# Affichage de ce paquet : affiche son contenu Ethernet, IP et ICMP
print "--- pck.show():"
pck.show()
L'exécution de ce script donne :
WARNING: No route found for IPv6 destination :: (no default route?)
--- pck.show():
###[ Ethernet ]###
dst = 94:fe:f4:ac:d0:51
src = 00:24:21:b5:e6:46
type = 0x800
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = icmp
chksum = None
src = 192.168.1.2
dst = Net('www.google.fr')
\options \
###[ ICMP ]###
type = echo-request
code = 0
chksum = None
id = 0x0
seq = 0x0
Explications :
Scapy signale qu'il ne peut joindre www.google.fr via IPv6 étant donné que ma box ne supporte pas IPv6.
Scapy a complété automatiquement la couche 2 pour ce qui concerne l'adresse MAC de l'émetteur et l'adresse MAC du destinataire :
adresse MAC de l'émetteur : l'adresse MAC de mon PC
adresse MAC du destinataire : l'adresse MAC de ma box côté LAN.
A présent on envoie ce paquet en utilisant rep,norep=srp(pck). rep contient les paquet émis avec la réponse. norep contient les paquets qui n'auraient pas obtenu de réponse.
Compléter donc le script ainsi :
#envoi du paquet construit a partir du niveau IP, send permet l'envoi du paquet mais ne permet pas de recuperer la reponse a ce paquet
print "--- envoi du paquet sans lire la reponse"
sendp(pck)
print "--- envoi du paquet avec lecture de la reponse via la commande srp"
rep,norep=srp(pck)
print "--- Affichage de la reponse, uniquement la partie ICMP pour la destination " + str(pck.dst)
rep[0][1][ICMP].show()
Ce qui donne:
--- envoi du paquet sans lire la reponse
.
Sent 1 packets.
--- envoi du paquet avec lecture de la reponse via la commande srp
Begin emission:
Finished to send 1 packets.
*
Received 1 packets, got 1 answers, remaining 0 packets
--- Affichage de la reponse, uniquement la partie ICMP pour la destination 94:fe:f4:ac:d0:51
###[ 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'
Cas de la construction de la trame à partir du niveau IP comme montré ci-dessous. La fonction pour envoyer un tel paquet est alors sr.
#!/usr/bin/python
from scapy.all import *
# creation du paquet IP a destination de www.google.fr, ce paquet IP contenant un ICMP
pck=IP(dst='www.google.fr')/ICMP()/"Hello"
# Affichage de ce paquet : affiche son contenu IP et son contenu ICMP
print "--- pck.show():"
pck.show()
# Affichage de ce paquet mais uniquement sa partie ICMP
print "--- pck[ICMP].show():"
pck[ICMP].show()
#envoi du paquet construit a partir du niveau IP, send permet l'envoi du paquet mais ne permet pas de recuperer la reponse a ce paquet
print "--- envoi du paquet sans lire la reponse"
send(pck)
print "--- envoi du paquet avec lecture de la reponse via la commande sr"
rep,norep=sr(pck)
print "--- Affichage de la reponse, uniquement la partie ICMP pour la destination " + str(pck.dst)
rep[0][1][ICMP].show()
Ce qui donne:
WARNING: No route found for IPv6 destination :: (no default route?)
--- pck.show():
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = icmp
chksum = None
src = 192.168.1.2
dst = Net('www.google.fr')
\options \
###[ ICMP ]###
type = echo-request
code = 0
chksum = None
id = 0x0
seq = 0x0
###[ Raw ]###
load = 'Hello'
--- pck[ICMP].show():
###[ ICMP ]###
type = echo-request
code = 0
chksum = None
id = 0x0
seq = 0x0
###[ Raw ]###
load = 'Hello'
--- envoi du paquet sans lire la reponse
.
Sent 1 packets.
--- envoi du paquet avec lecture de la reponse via la commande sr
Begin emission:
.Finished to send 1 packets.
*
Received 2 packets, got 1 answers, remaining 0 packets
--- Affichage de la reponse, uniquement la partie ICMP pour la destination Net('www.google.fr')
###[ ICMP ]###
type = echo-reply
code = 0
chksum = 0xdc2d
id = 0x0
seq = 0x0
###[ Raw ]###
load = 'Hello'
###[ Padding ]###
load = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Bibliographie
http://fr.openclassrooms.com/informatique/cours/manipulez-les-paquets-reseau-avec-scapy
