Posez votre question Signaler

[Python] Construire un paquet UDP/TCP

darkneurone 39Messages postés 11 mars 2007Date d'inscription - Dernière réponse le 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 !
Lire la suite 

[Python] Construire un paquet UDP/TCP »

9 réponses
Réponse
+0
moins plus
http://www.google.fr/search?q=python+socket&meta=lr%3Dlang_fr
Pour faire de la communication TCP UDP on utilise dans la plupart des langages de programmation ce qu'on appel des sockets...
Ajouter un commentaire
Réponse
+0
moins plus
merci pour ta réponse mais je sais déjà utiliser les sockets ^^ je veux vraiment construire un packet pas à pas.
Ajouter un commentaire
Réponse
+0
moins plus
Bon ben bonne chance ! :)
Qu'est-ce qui motive une telle décision ?
Bonne lecture des RFC correspondantes...
Ajouter un commentaire
Réponse
+0
moins plus
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
+-----------------------------------------------+
Ajouter un commentaire
Réponse
+0
moins plus
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.
Ajouter un commentaire
Réponse
+0
moins plus
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é !
Ajouter un commentaire
Réponse
+0
moins plus
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...
Ajouter un commentaire
Réponse
+0
moins plus
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)
EminoMeneko- 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. :)
Ajouter un commentaire
Ce document intitulé « [Python] Construire un paquet UDP/TCP » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Dossier à la une
Passage au tout numérique : quel coût pour les particuliers ?