Bon, alors je pars du principe que les modèles OSI – TCP/IP n’ont plus de secret pour vous .
Pour notre petit sniffer il nous faut , comme vous l’avez lu, 2 modules : pcapy et Impacket .
pcapy sert à capturer les pokémons paquets alors que Impacket décapsule/encapsule .
Pour commencer, il faut récupérer les interfaces sur lesquelles on peut écouter .
La fonction findalldevs() est faite pour ça.
On va créer la fonction mesInterfaces()
def mesInterfaces():
try:
interfaces = pcapy.findalldevs()
interfaces.remove(‘any’)
interfaces.remove(‘lo’)
except pcapy.PcapError, e:
#si on a pas les droits, par exemple
interfaces = None
return interfaces
Ensuite, il nous faut créer monReader , qui va lire les paquets.
On va donc créer notre classe EcouteMamanEstPresDeToi qui le contient.
class EcouteMamanEstPresDeToi(Thread):
def __init__(self,monInterface,maxBits,promiscuite,timeOut,onSniffe):
Thread.__init__(self)
self.monInterface = monInterface
self.maxBits = maxBits
self.promiscuite = promiscuite
self.timeOut = timeOut
self.onSniffe = onSniffe
self.monReader = pcapy.open_live(self.monInterface,
self.maxBits,
self.promiscuite,
self.timeOut)
pcapy.open_live prend plusieurs arguments:
self.monInterface = l’interface que l’on veut écouter.
self.maxBits = la taille maximale d’un paquet
self.promiscuite = 0 ou 1, afin de permettre à la carte d’accepter tous les paquets
self.timeOut = va accumuler pendant t ms les paquets, puis les analyser
Ensuite, ce serait bien de savoir dans quel sous réseau on se trouve .
On va ajouter dans notre classe, deux méthodes : reseau() et masque() .
def reseau(self):
return self.monReader.getnet()
def masque(self):
return self.monReader.getmask()
Notre reader contient les méthodes getnet() et getmask() qui renvoient l’adresse réseau et le masque .
Maintenant, il nous faut les IP des paquets .
On va donc rajouter 2 méthodes à notre classe :
def ip_source(self,paquet):
return paquet.get_ip_src()
def ip_dest(self,paquet):
return paquet.get_ip_dst()
paquet désigne la couche 3 : le protocole IP .
Il faut aussi, qu’on sache quel est le protocole de couche 4 du paquet.
Pour ce faire, on va ajouter une méthode : couche4(paquet) .
def couche4(self,segment):
dicoCouche4 = { 6:’TCP’, 17:’UDP’ }
try :
return dicoCouche4[segment.protocol]
except KeyError, e :
return None
segment désigne la couche 4 .
dicoCouche4 est un dictionnaire contenant quelques protocoles de couche 4 et leurs numéros associés.
C’est presque terminé, on a plus qu’à capturer les paquets et lancer les méthodes, le tout dans la méthode run() .
def run(self):
try :
ethernet = Ethernet().decode( self.monReader.next()[1] )
ip = ethernet.child()
print( « IP source : » + str(self.ip_source( ip ) ) )
print( « IP destination : » + str(self.ip_dest( ip ) ) )
couche_4 = ip.child()
print( « Protocole de couche 4 : » + str( self.couche4( couche_4 ) ) )
couche_superieure = couche_4.child()
print( couche_superieure.get_buffer_as_string() )
except:
pass
self.monReader.next() va prendre le prochain paquet, et retourne une liste de 2 éléments : le header ( grâce auquel on aura la taille du paquet, le timestamp,…. ) et le paquet, qui nous intéresse .
On met un try/except vu que l’on désencapsule en partant du principe que la trame sera de type Ethernet : Ethernet().decode() .
child() renvoie la couche supérieure .
Les couches 5,6,7 contiennent les données, donc get_buffer_as_string() les renvoie .
Voilà la code en entier :
#-*- coding:Utf-8 -*-
import pcapy
from impacket.ImpactDecoder import EthDecoder as Ethernet
from threading import Thread
import time
def mesInterfaces():
try:
interfaces = pcapy.findalldevs()
interfaces.remove(‘any’)
interfaces.remove(‘lo’)
except pcapy.PcapError, e:
interfaces = None
return interfaces
class EcouteMamanEstPresDeToi(Thread):
def __init__(self,monInterface,maxBits,promiscuite,timeOut,onSniffe):
Thread.__init__(self)
self.monInterface = monInterface
self.maxBits = maxBits
self.promiscuite = promiscuite
self.timeOut = timeOut
self.onSniffe = onSniffe
self.monReader = pcapy.open_live(self.monInterface,
self.maxBits,
self.promiscuite,
self.timeOut)
print(self.monInterface + » : » + self.reseau() + » : » + self.masque() )
def run(self):
while self.onSniffe:
try :
ethernet = Ethernet().decode( self.monReader.next()[1] )
ip = ethernet.child()
print( « IP source : » + str(self.ip_source( ip ) ) )
print( « IP destination : » + str(self.ip_dest( ip ) ) )
couche_4 = ip.child()
print( « Protocole de couche 4 : » + str( self.couche4( couche_4 ) ) )
couche_superieure = couche_4.child()
print( couche_superieure.get_buffer_as_string() )
except:
pass
def ip_source(self,paquet):
return paquet.get_ip_src()
def ip_dest(self,paquet):
return paquet.get_ip_dst()
def reseau(self):
return self.monReader.getnet()
def masque(self):
return self.monReader.getmask()
def couche4(self,segment):
dicoCouche4 = { 6:’TCP’, 17:’UDP’ }
try :
return dicoCouche4[segment.protocol]
except KeyError, e :
return None
if __name__ == ‘__main__’:
for element in mesInterfaces() :
sniffSniff = EcouteMamanEstPresDeToi(element,1024,0,100,True)
sniffSniff.start()
Voilà, l’article est terminé.
Il y aura peut-être une suite : le GUI de notre sniffer .




Vendredi, juin 13th, 2008, 22 h 15 min | 



1 février 2011 at 15 h 26 min
Bonjour, je voulais tout d’abord te féliciter pour ton site/blog qui est tout simplement très instructif.
Je suis élève-ingénieur actuellement en poste en tant que manager applicatif. Comprendre les failles m’est essentiel.
Tout est explicite est bien formulé. J’ai une petite question qui regroupe un peu tout test tuto « impacket ».
Comment reconstruire un email a partir d’un sniffer?
Je fais un pen-test mais la sécurité n’est pas mon point fort. Pour l’instant je sniffe et j’arp-poisoning. Mais j’aimerai sniffer sur le réseau et reconstituer un mail se baladant avant un serveur exchange et ainsi pouvoir déterminer au mieux la cible.
Si tu as des pistes de reflexion avec impacket, je suis preneur.
Cordialement,
Seb aka ‘sena’