>>> trame = Ether() >>> trame.show() ###[ Ethernet ]### WARNING: Mac address to reach destination not found. Using broadcast. dst= ff:ff:ff:ff:ff:ff src= 00:00:00:00:00:00 type= 0x9000 >>>
trame.dsp = 'ac:84:c9:db:fb:c0'trame.show()
>>> trame.dst='ac:84:c9:db:fb:c0'
trame.show()#
##[ Ethernet ]### dst= ac:84:c9:db:fb:c0 src= 00:00:00:00:00:00 type= 0x9000
Il est bien sur possible de préciser cette adresse MAC à la création de la trame : <code python>
trame = Ether(dst='ac:84:c9:db:fb:c0')
<
/code>
sendp(trame)
.
Sent 1 packets.
<
/code>
Le point “.” représente un envoi.
La trame Ethernet a été envoyée mais :
Il faut maintenant encapsuler des données d'un protocole des couches supérieures dans cette trame vide.
La commande sendp() permet d'envoyer un paquet créé (forgé) à partir du niveau 2 (couche Ethernet).
La commande send() permet d'envoyer un paquet créé (forgé) à partir du niveau 3 (couche IP). Les informations du niveau 2 (la couche ethernet) sont alors automatiquement renseigné par scapy.
La commande ping qui utilise le protocole ICMP permet :
>>> ping = ICMP() >>> ping.show() ###[ ICMP ]### type= echo-request code= 0 chksum= None id= 0x0 seq= 0x0 >>>
Par défaut, l'instanciation de la classe ICMP() met le type du ping à echo-request.
Page Wikipedia sur le protocole ICMP :
Quelques précisions sur le fonctionnement du protocole ICMP :
Pour envoyer un paquet ICMP, il faut :
Avec Scapy, l'encapsulation entre protocoles se réalise avec l'opérateur / (slash).
trame = Ether() / IP(dst='192.168.1.1') / ICMP()trame.show()
#
##[ Ethernet ]### dst= ac:84:c9:db:fb:c0 src= 00:15:5d:01:c6:02 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.159 dst= 192.168.1.1 \options\ ###[ ICMP ]### type= echo-request code= 0 chksum= None id= 0x0 seq= 0x0
<
/code>
Seule l'adresse IP du destinataire a été renseignée. Cependant Scapy a complété automatiquement les autres champs :
sendp(trame)
.
Sent 1 packets.
<
/code>
Le paquet est envoyé mais aucune réponse n'est reçue. Pour cela il faut utiliser les fonctions suivantes qui permettent d'envoyer la trame et de recevoir la réponse :
>>> rep, non_rep = srp(trame) Begin emission: ..Finished to send 1 packets. .* Received 4 packets, got 1 answers, remaining 0 packets >>> rep <Results: TCP:0 UDP:0 ICMP:1 Other:0> >>> non_rep <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0> >>>
Avec Scapy :
Important pour la suite :
>>> rep[0][1][ICMP].type 0 >>>
Utilisation de la fonction srp1() qui ne renvoie qu'un seul objet, la première réponse : <code python> »> rep = srp1(trame) Begin emission: .Finished to send 1 packets. ..* Received 4 packets, got 1 answers, remaining 0 packets »> rep.show() ###[ Ethernet ]### dst= 00:15:5d:01:c6:02 src= ac:84:c9:db:fb:c0 type= 0x800 ###[ IP ]### version= 4 ihl= 5 tos= 0x0 len= 28 id= 43316 flags= frag= 0 ttl= 64 proto= icmp chksum= 0x4dbc src= 192.168.1.1 dst= 192.168.1.159 \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' »> </code> ====== Créer un datagramme IP contenant un paquet ICMP ====== Si on ne s'intéresse qu'à la partie IP des paquets à gérer, on utilise alors les fonctions suivantes sans s'occuper du niveau 2 Ethernet qui est alors automatiquement renseigné par Scapy : * send() équivalent à sendp(), * sr() équivalent à srp(), * sr1() équivalentes à srp1(). <code python> »> paquet = IP(dst='192.168.1.1') / ICMP() »> rep = sr1(paquet) Begin emission: ..Finished to send 1 packets. .* Received 4 packets, got 1 answers, remaining 0 packets »> rep.show() ###[ IP ]### version= 4 ihl= 5 tos= 0x0 len= 28 id= 43318 flags= frag= 0 ttl= 64 proto= icmp chksum= 0x4dba src= 192.168.1.1 dst= 192.168.1.159 \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' »> </code> ====== Envoi d'un paquet sur un hôte non existant ====== <code python> »> paquet = IP(dst='192.168.1.200') / ICMP() »> rep = sr1(paquet) Begin emission: ……………………………………………..WARNING: Mac address to reach destination not found. Using broadcast. Finished to send 1 packets. …………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………^C Received 371 packets, got 0 answers, remaining 1 packets »> AttributeError: 'NoneType' object has no attribute 'show' »> rep »> </code>
Arrêt de l'envoi (CTRL + C) après quelques secondes et la variable rep est vide.
Il est possible de préciser une limite de temps en secondes à la fonction sr1(). <code python> »> rep = sr1(paquet, timeout=0.5) Begin emission: …………………………………………..WARNING: Mac address to reach destination not found. Using broadcast. Finished to send 1 packets. …………….. Received 67 packets, got 0 answers, remaining 1 packets »> </code>
Pour visualiser les autres paramètres de la fonction sr1() utiliser la commande:
>>> help(sr1)
==== Retour à Python : la bibliothèque Scapy … ====