[Python] Construire un paquet UDP/TCP

Fermé
darkneurone Messages postés 39 Date d'inscription dimanche 11 mars 2007 Statut Membre Dernière intervention 12 juin 2008 - 23 mars 2008 à 21:16
EminoMeneko Messages postés 2435 Date d'inscription jeudi 24 janvier 2008 Statut Membre Dernière intervention 23 mai 2018 - 25 mars 2008 à 22:53
Bonsoir à tous !!!

La question est dans le titre ^^ Ca fait pas mal de temps que je cherche sur google des moyens de construire entièrement un paquet UDP (aussi TCP). J'ai déjà trouvé les datagrammes sur internet mais il n'y aucun tutorial pour les fabriquer... surtout en python ! est-ce que quelqu'un connait un site où il y aurait un cours qui explique clairement comment procéder ? une librairie ?

Merci pour votre aide.

Bonne soirée à tous !
A voir également:

8 réponses

EminoMeneko Messages postés 2435 Date d'inscription jeudi 24 janvier 2008 Statut Membre Dernière intervention 23 mai 2018 318
23 mars 2008 à 21:23
https://www.google.fr/search?q=python+socket&meta=lr%3Dlang_fr&gws_rd=ssl
Pour faire de la communication TCP UDP on utilise dans la plupart des langages de programmation ce qu'on appel des sockets...
0
darkneurone Messages postés 39 Date d'inscription dimanche 11 mars 2007 Statut Membre Dernière intervention 12 juin 2008 12
23 mars 2008 à 21:49
merci pour ta réponse mais je sais déjà utiliser les sockets ^^ je veux vraiment construire un packet pas à pas.
0
EminoMeneko Messages postés 2435 Date d'inscription jeudi 24 janvier 2008 Statut Membre Dernière intervention 23 mai 2018 318
24 mars 2008 à 16:41
Bon ben bonne chance ! :)
Qu'est-ce qui motive une telle décision ?
Bonne lecture des RFC correspondantes...
0
darkneurone Messages postés 39 Date d'inscription dimanche 11 mars 2007 Statut Membre Dernière intervention 12 juin 2008 12
24 mars 2008 à 21:18
Merci :)

J'ai trouvé les RFC très instructives ^^ Ce qui me motive, c'est la curiosité de savoir comment ces protocoles fonctionnent ^^ je suis trop curieux peut-être mais c'est pas grave ! J'aimerai bien savoir comment ils sont assemblés/désassemblés, interprétés... etc ^^ j'ai lu pas mal de sujet sur ça, mais ça reste de la théorie ^^ j'aimerai bien faire quelque chose de concret là dessus !

J'ai trouvé ce script sur internet... mais je ne comprends pas tout, est ce que quelqu'un pourrait m'expliquer les points ci-dessous svp ?

-----------------------------------------------------------------------------------------------

"""UDP packets."""

# Copyright 1997, Corporation for National Research Initiatives
# written by Jeremy Hylton, jeremy@cnri.reston.va.us

import inet
import struct
import string

class Packet:

def __init__(self, packet=None, cksum=1):
if packet:
self.__disassemble(packet, cksum)
else:
self.sport = 0
self.dport = 0
self.ulen = 8
self.sum = 0
self.data = ''

def __repr__(self):
begin = "<UDP %d->%d len=%d " % (self.sport, self.dport, self.ulen)
if self.ulen == 8:
rep = begin + "\'\'>"
elif self.ulen < 18:
rep = begin + "%s>" % repr(self.data)
else:
rep = begin + "%s>" % repr(self.data[:10] + '...')
return rep


def assemble(self, cksum=1):
self.ulen = 8 + len(self.data)
begin = struct.pack('hhh', self.sport, self.dport, self.ulen)
packet = begin + '\000\000' + self.data
if cksum:
self.sum = inet.cksum(packet)
packet = begin + struct.pack('h', self.sum) + self.data
self.__packet = inet.udph2net(packet)
return self.__packet

def __disassemble(self, raw_packet, cksum=1):
packet = inet.net2updh(raw_packet)
if cksum and packet[6:8] != '\000\000':
our_cksum = inet.cksum(packet)
if our_cksum != 0:
raise ValueError, packet
elts = map(lambda x:x & 0xffff, struct.unpack('hhhh', packet[:8]))
[self.sport, self.dport, self.ulen, self.sum] = elts
self.data = packet[8:]

-------------------------------------------------------------------------------------

voilà le code ^^

les points que je ne comprends pas :
- L'intérêt de la fonction __repr__
PS : j'ai compris qu'en fonction de la longueur de quelque chose... (ulen = u length / u = ?)... quoiqu'il en soit... si ulen = 8, ça retourne : <UDP *chiffre*->*chiffre* len=*chiffre* '' *à partir du 10eme char, on met la suite*>
Je comprends bien les fonctions... mais l'intérêt... pas compris ^^

- pareil pour la fonction assemble :S
PS : j'ai compris que ça calcul la longueur du truc encore... ^^ on format begin en structure, en insérant certaines données... alors pourquoi mettre 'hhh' déjà ^^ on concatène begin avec le string ''\000\000' et data... pourquoi mettre '\000\000 lol ^^
Ce que je pense : c'est qu'on construit le paquet selon le datagramme UDP, parce qu'on insère d'abord ce qu'on a mit dans begin... (seulement je ne sais pas à quoi ça sert ^^) et on ajoute '\000\000... lol et à la fin on rajoute e "data". Donc peut-être que c'est ça... enfin comme vous pouvez le constater, j'ai beaucoup de mal ^^ surtout quand je ne sais pas à quoi correspond tout ça !
Ensuite, on calcul la taille du paquet... on ajoute encore des données... mais je ne sais pas encore à quoi ça sert ^^ à quoi correspond cet ajout...

Sinon, on peut remarquer qu'il fait appel à la fonction udph2net du module inet... et avant à cksum... voilà les deux fonctions (elles se trouvent dans inet.py) :

def cksum(s):
if len(s) & 1:
s = s + '\0'
words = array.array('h', s)
sum = 0
for word in words:
sum = sum + (word & 0xffff)
hi = sum >> 16
lo = sum & 0xffff
sum = hi + lo
sum = sum + (sum >> 16)
return (~sum) & 0xffff

def gets(s):
return struct.unpack('h', s)[0] & 0xffff

def mks(h):
return struct.pack('h', h)

def udph2net(s):
sp = htons(gets(s[0:2]))
dp = htons(gets(s[2:4]))
len = htons(gets(s[4:6]))
return mks(sp) + mks(dp) + mks(len) + s[6:]

############################################

Voilà à quoi sert la fonction htons :
Convert 16-bit positive integers from host to network byte order. On machines where the host byte order is the same as network byte order, this is a no-op; otherwise, it performs a 2-byte swap operation.

Ces fonctions ont été.... la cerise sur le gâteau ! ^^ Je ne vois pas l'intérêt de faire len(s) & 1. Pourquoi mettre & 1 ? ça renvois toujours "vrai" non ?

Voilà, félicitation si vous avez lu mon post en entier !! et un grand merci à tout ceux qui pourront m'aider. Faut dire que pour l'instant... ça reste très flou pour moi tout ça !

PS : voilà le datagramme d'un paquet UDP

<-----------------32bits----------------------->
+-----------------------+-----------------------+
| Port Source | Port Destination |
+-----------------------+-----------------------+
| Longueur UDP | Somme de ctrl (message)
+-----------------------+-----------------------+
... Données
+-----------------------------------------------+
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
EminoMeneko Messages postés 2435 Date d'inscription jeudi 24 janvier 2008 Statut Membre Dernière intervention 23 mai 2018 318
25 mars 2008 à 16:34
Amuse toi bien moi j'ai de la fumée qui sors des oreilles ! ^^

sport et dport ça doit être source port et destination port si ça peut t'aider...
je connais pas le python mais il semble que la fonction assemble créer le paquet et disassemble le déballe.
Tu sais comment ça marche je pense.
Bonne chance.
0
darkneurone Messages postés 39 Date d'inscription dimanche 11 mars 2007 Statut Membre Dernière intervention 12 juin 2008 12
25 mars 2008 à 17:52
Merci pour tes encouragements !

Effectivement, ça doit être source port et destination port mais je vois pas ces deux variables sont initialisées à 0 ^^ C'est assez bizarre ! Mais bon, je persévère ! je tente de comprendre petit à petit ce code mais c'est assez compliqué !
0
EminoMeneko Messages postés 2435 Date d'inscription jeudi 24 janvier 2008 Statut Membre Dernière intervention 23 mai 2018 318
25 mars 2008 à 19:28
Utilise les balises de code quand tu en envoi sur le forum ça aide...

Bon j'ai essayé de commenter et mais comme je connais pas la syntaxe Python t'y fie pas de trop mais inspire toi en au pire...
Au fait tu as le droit de formater un minimum son code source avec la fonctionnalité qui va bien.
Comme ça....

"""UDP packets."""

# Copyright 1997, Corporation for National Research Initiatives
# written by Jeremy Hylton, jeremy@cnri.reston.va.us

import inet
import struct
import string

class Packet:

# Fonction d'initialisation de l'objet
def __init__(self, packet=None, cksum=1):
	if packet:
		# Si on a un pasuet on le désassemble ?
		self.__disassemble(packet, cksum)
	else:
		# Sinon  on initialise des valeurs
		self.sport = 0
		self.dport = 0
		self.ulen = 8
		self.sum = 0
		self.data = ''

def __repr__(self):
	# On affiche les ports source et destination puis la longueur du paquet.
	begin = "<UDP %d->%d len=%d " % (self.sport, self.dport, self.ulen)
	# Si la longueur du paquet courant vaut 8 on concatène avec "''>"
	if self.ulen == 8:
		rep = begin + "\'\'>"
	# Si inférieur à 18 on ajoure une chaine mais je sais pas quoi
	elif self.ulen < 18:
		rep = begin + "%s>" % repr(self.data)
	else:
	# sinon je sais pas trop... xD
		rep = begin + "%s>" % repr(self.data[:10] + '...')

	return rep


def assemble(self, cksum=1): # checksum initialisé à 1 par défaut.
	# On ajoute 8 à la taille de la donnée "surement on a un entête de 8 caractères/octets/bits"
	self.ulen = 8 + len(self.data)
	# On inscrit les données du paquet dans l'entête...
	begin = struct.pack('hhh', self.sport, self.dport, self.ulen)
	packet = begin + '\000\000' + self.data
	# MAJ du code ce contrôle
	if cksum:
		self.sum = inet.cksum(packet)
	# Ajout de la donnée dans le paquet
	packet = begin + struct.pack('h', self.sum) + self.data
	self.__packet = inet.udph2net(packet)
	return self.__packet

def __disassemble(self, raw_packet, cksum=1):
	# convertion d'une IP vers un nom DNS je crois
	packet = inet.net2updh(raw_packet)
	# Comprend pas cette syntaxe...
	if cksum and packet[6:8] != '\000\000':
		our_cksum = inet.cksum(packet)
	# Levée d'une exception si les CRC ne correspondent pas.
	if our_cksum != 0:
		raise ValueError, packet
	# Je comprends plus
	elts = map(lambda x:x & 0xffff, struct.unpack('hhhh', packet[:8]))
	[self.sport, self.dport, self.ulen, self.sum] = elts
	self.data = packet[8:]


Retrouve ce code coloré et indenté (je sais pas où se limite un if etc en Python) plus bas.
http://pastebin.com/m10e3546d lien valable un mois...

Bonne chance.
Je voulais apprendre le Python mais pas trop le temps...
0
darkneurone Messages postés 39 Date d'inscription dimanche 11 mars 2007 Statut Membre Dernière intervention 12 juin 2008 12
25 mars 2008 à 21:14
Merci pour tes commentaires et pour le code ! :)

Ca éclaircit quelques points... Mais il y a toujours des trucs qui me semblent bizarre ou incompréhensible comme l'ajout de 'hhh' dans le header ^^ Dans un autre script, pour un paquet ICMP, j'ai vu que l'auteur ajoutait 'bbHHh' !

En ce qui concerne les instructions conditionnelles sur la taille du paquet, je crois qu'elle peut varier en fonction de l'ip... ipv6 ou ipv4 ^^ Mais je ne suis sûr de rien ^^

Mais ce qui reste flou, c'est vraiment le pourquoi de la chose ^^ pourquoi est ce qu'il ajoute telle valeur ? etc... c'est vraiment pas simple !

Merci en tout cas pour ton aide ^^ j'espère que tes oreilles n'ont pas trop fumées ! :o)
0
EminoMeneko Messages postés 2435 Date d'inscription jeudi 24 janvier 2008 Statut Membre Dernière intervention 23 mai 2018 318
25 mars 2008 à 22:53
D'après ce que tu dit il semblerait que ces hhh ne soient pas un hasard. Reste à savoir à quoi cela correspond.

Maintenant j'ai pas vu IPv6 des masses, mais il me semble que (logiquement ça colle aussi) les adresses IPv6 sont plus lourdes en taille donc oui la taille change.
Pour le reste je sais pas. :)
0