Ceci est une ancienne révision du document !
>>> 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')
>>> sendp(trame) . Sent 1 packets. >>>
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 >>>
Seule l'adresse IP du destinataire a été renseignée. Cependant Scapy a complété automatiquement les autres champs :
>>> sendp(trame) . Sent 1 packets. >>>
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 :
Il y a une réponse et zéro échec. Ce plus la réponse est un paquet ICMP. Pour visualiser le contenu de la réponse, il suffit de regarder le contenu de la variable rep :
>>> rep.show() 0000 Ether / IP / ICMP 192.168.1.159 > 192.168.1.1 echo-request 0 ==> Ether / IP / ICMP 192.168.1.1 > 192.168.1.159 echo-reply 0 / Padding >>>
La variable rep contient une liste de couples de paquets :
Ici il n'y a qu'un seul couple de paquets puisqu'il n'y a qu'un seul envoi et une seule réponse. La variable rep est une liste et est manipulable comme une liste en python.
Le résultat est un couple (tuple à deux valeurs) :
>>> rep[0] (<Ether type=0x800 |<IP frag=0 proto=icmp dst=192.168.1.1 |<ICMP |>>>, <Ether 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=43315 flags= frag=0 ttl=64 proto=icmp chksum=0x4dbd 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' |>>>>) >>> rep[0][0].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 >>> rep[0][1].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= 43315 flags= frag= 0 ttl= 64 proto= icmp chksum= 0x4dbd 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' >>>
>>> rep[0][1][ICMP].show() ###[ 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' >>>
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 :
>>> 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' >>>
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 :
>>> 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' >>>
>>> 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 >>>
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().
>>> 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 >>>
Pour visualiser les autres paramètres de la fonction sr1() utiliser la commande:
>>> help(sr1)