Pour faire un sniffer, rien de plus simple normalement en Python !
Sous linux, il est possible de lancer un RawSocket qui capture tout le traffic.
Sauf que bien évidemment ce n'est pas aussi simple sous OSX !
Pour sniffer j'ai utilisé Scapy pour Python3 (pour l'installer, taper dans un terminal "pip3 install scapy-python3" si vous avez pip3, ou suivez ces instructions : https://github.com/phaethon/scapy). De plus les fonctions de Scapy que j'utilise nécessitent libdnet qu'on peut make ou installer avec macports (ou tout autre gestionnaire de paquets, mais je préfère de loin macports).
Cependant lors de l'import de certaines fonctions de Scapy, si vous utilisez la version de Python installée par .pkg depuis le site officiel, et non celle de MacPorts, il ne trouve pas une bibliothèque appelée libdnet, et il faut alors copier
- /opt/local/lib/libdnet.1.dylib
/opt/local/lib/libdnet.a
/opt/local/lib/libdnet.dylib
(normalement ils sont au même endroit chez vous, sinon vous pouvez toujours utiliser "port contents libdnet") dans un dossier où find_library() (la fonction Python qui cherche les bibliothèques C) regarde, comme /usr/local/lib.
Pour tester si votre installation fonctionne, tapez dans un terminal :
sudo python3
from scapy.all import sniff
sniff(count=1, prn = lambda x: x.show())
Et normalement le premier paquet qui passe par là devrait s'afficher sous vos yeux ébahis. Ce n'est pas grave s'il y a quelques avertissements, du moment que le paquet s'affiche.
On n'a pas encore fini, il faut mettre un filtre : filter = "tcp port 5555" est le mieux pour Dofus en utilisant bien sûr le port 5555.
Maintenant si vous voulez faire quelque chose avec les paquets, il faut spécifier une fonction prn qui sera exécutée sur chaque paquet reçu correspondant au filtre (comme dans l'exemple).
On peut aussi ajouter une fonction de filtre avec le paramètre lfilter, un timeout avec le paramètre timeout, et une fonction qui arrête la commande si elle renvoie True à un paquet en utilisant le paramètre stop_filter.
Cependant, je n'utiliserai pas forcément ces paramètres, vu qu'on peut le faire avec prn et des exceptions.
Ce n'est toujours pas fini, parce qu'on doit sélectionner les paquets contenant des données (champ data dans Wireshark). Pour cela, il suffit d'utiliser le paramètre lfilter avec lambda x: x.haslayer(Raw), en ayant exécuté from scapy.all import Raw.
Il faut aussi un buffer au cas où les messages se retrouvent sur plusieurs paquets.
Fait (presque) proprement, ça donne :
from scapy.all import sniff
from scapy.all import Raw
class Data():
def __init__(self,data=bytes()):
self.data = data
self.pos = 0
def __len__(self):
return len(self.data)
def __iadd__(self,by):
self.data += by
return self
def verif(self,l):
if len(self)<self.pos+l:
raise IndexError(self.pos,l,len(self))
def end(self):
self.data = self.data[self.pos:]
self.pos = 0
def read(self,l):
self.verif(l)
pos=self.pos
self.pos+=l
return self.data[pos:pos+l]
class Msg():
def __init__(self,buf):
self.b = True
try:
header = int.from_bytes(buf.read(2),'big')
lenData = int.from_bytes(buf.read(header&3),'big')
self.id=header>>2
self.data=Data(buf.read(lenData))
except IndexError:
buf.pos=0
self.b = False
else:
buf.end()
def __bool__(self):
return self.b
def raw(pa):
return bytes(pa.getlayer(Raw))
def recoit(pa,buf,action):
buf+=raw(pa)
msg = Msg(buf)
while msg:
action(msg)
msg = Msg(buf)
def launch(action):
print('Sniffeur démarré !\nctrl+c pour arrêter')
buf=Data()
sniff(filter='tcp port 5555',lfilter = lambda p: p.haslayer(Raw),prn=lambda p: recoit(p,buf,action))
print('\nSniffeur interrompu !')
def action(msg):
#l'action qu'on veut exécuter sur le message
pass
Pour vous amuser, vous pouvez lancer :
sudo python3 -i {chemin vers Sniffer Dofus.py}
puis
launch(lambda m: print(m.id))
et ça vous affichera en temps réel les id des paquets envoyés et reçus. Pour différencier les paquets reçus et envoyés, il faudra manipuler les paquets avec scapy, mais je vous laisse regarder la documentation.
Bonne chance !!!
J'ai complété ce tuto avec un autre sur les bibliothèques pixel, pour ceux qui veulent faire des bots pixel qui sniffent le réseau pour récupérer des variables : [Python3] Comment faire un bot pixel portable !