Un traceroute roots en Python avec Scapy

Scapy est un package de Python bien connu dans le monde du hacking. Il permet d’interagir à bas niveau avec une interface réseau, c’est-à-dire de déterminer les octets qu’elle émet et de récupérer ceux qu’elle reçoit.
Scapy peut donc notamment être utilisé pour forger des trames et/ou paquets sur un réseau. Cela peut permettre de se livrer à des activités que la morale réprouve, comme l’ARP cache poisoning et autres joyeusetés. A l’inverse, comme nous le recommanderons, cela peut permettre de s’adonner à des activités tout à fait respectables, comme le diagnostic.
Scapy, pour sniffer, spoofer et autres
Dans tous les cas, se mettre à Scapy permet de se former au fonctionnement de réseaux en commençant par là où il faut commencer chaque fois qu’on prétend réellement apprendre quelque chose dans quel que domaine, c’est-à-dire à la base. C’est cette finalité pédagogique que poursuit cet article, à l’attention de tous ceux qui n’ont jamais mis le nez dans le réseau. Il présente comment réaliser une version simplifiée d’un outil qui figure inévitablement dans la boite à outils de tout hacker, à savoir traceroute.
Continuer la lecture de « Un traceroute roots en Python avec Scapy »
Un traceroute roots en Python avec Scapy

Les opérateurs étoile (* et **) en Python

En Python, chacun sait que l’opérateur * permet d’effectuer une multiplication sur des opérandes numériques, ou à répéter un opérande quelconque, tandis que l’opérateur ** permet d’effectuer une élévation à une puissance quelconque d’un opérande numérique :
print (2*3)
print (2*'Hello, world!')
print (2**3)
6
Hello, world!Hello, world!
8
Ce qui est moins connu, car elle est assez mal documentée, c’est la possibilité d’utiliser ces opérateurs pour du déballage (unpacking) d’itérables divers en vue de constituer un autre itérable. Par exemple :
x = ['A', 'B']
y = ('C', 'D')
z = [*x, *y]
print (z)
['A', 'B', 'C', 'D']
Comment est-il possible d’utiliser ces opérateurs de cette manière ? Et pour quoi faire ? L’exploration de la documentation de Python permet de constater qu’ils peuvent servir dans deux circonstances : pour créer des itérables, et pour fournir des arguments à une fonction. Explications…
Mise à jour du 19/05/2018 : Mention de notations supplémentaires pour créer un itérable à partir d’un autre.
Continuer la lecture de « Les opérateurs étoile (* et **) en Python »
Les opérateurs étoile (* et **) en Python

Syntaxes avancées (car ramassées) en Python

Il y a mille manières d’exprimer ce qu’on désire en langage naturel, et il en va de même avec un langage de programmation.
Certaines fomulations peuvent être clairement plus laconiques que d’autres, et d’aucuns considèrent que c’est démontrer sa maîtrise du langage que de les maîtriser. Toutefois, si jouer à ce petit jeu de la syntaxe ramassée permet d’économiser sur l’écriture, il ne permet certainement pas d’économiser sur la lecture, du moins tant que celui qui doit lire n’a pas appris à écrire pareillement.
Pour aider dans cet apprentissage, cet article évolutif se propose de recenser les syntaxes ramassées qu’un développeur peut rencontrer en lisant du code en Python (version 3.6.4), à condition qu’elles présentent une véritable utilité.
Pour l’heure, on trouvera des explications suivantes… :
L’article sera enrichi au fil des découvertes réalisées au fil de lectures. Ces mises à jour seront signalées.
Mise à jour du 08/03/2018 :
  • rappel de la typologie (et corrections !) ;
  • extraire une plage d’éléments d’une séquence (slicing).
Continuer la lecture de « Syntaxes avancées (car ramassées) en Python »
Syntaxes avancées (car ramassées) en Python

Paramètres et décorateurs de fonction en Python

Python permet d’écrire des fonctions comportant de nombreux paramètres qui peuvent avoir des mines des plus patibulaire, surtout si elles sont par ailleurs assorties de décorateurs. Par exemple :
def g (h):
	def k (prompt, *words, **complements):
		if complements['computer'] == 'Atari':
			complements['computer'] = 'Amiga'
		h (prompt, *words, **complements)
	return k
@g
def f (prompt, *words, **complements):
	for key, value in complements.items ():
		print (prompt + ':', ' '.join (words), value)
f ('HAL speaking', 'I', 'love', 'the', computer='Atari', drink='coffee')
HAL speaking: I love the Amiga
HAL speaking: I love the coffee
Il est important de ne pas se laisser abuser par cette apparente complexité. Maîtriser les différentes catégories de paramètres qu’il est possible d’utiliser est essentiel pour exploiter le potentiel de l’écriture de fonctions en Python au quotidien. Quant aux décorateurs, il est sans doute bien moins fréquent d’y avoir recours, mais comme ils peuvent se rencontrer, il est bon de savoir commment ils fonctionnent.
Continuer la lecture de « Paramètres et décorateurs de fonction en Python »
Paramètres et décorateurs de fonction en Python

Comment marche réellement la fonction super () de Python

La méthode super () de Python a inspiré un bon nombre d’explications. Toutefois, il apparaît qu’aussi sophistiquées qu’elles soient, elles sont toutes désespérement superficielles.
Je ne parle pas de celles qui le sont d’évidence, comme cette vidéo. L’auteur est bien gentil, mais sa présentation de super() se limite à assimiler la fonction à un moyen de déléguer un appel à la méthode __init__ () (par ailleurs, tout à fait improprement assimilée à un constructeur, comme si __new__ () n’existait pas…) surchargée dans une classe C à sa version dans une classe parent A. Autrement dit, à appeller A.__init__ () depuis C.__init__ (). Mais dans l’exemple, C hérite non seulement de A, mais aussi de B. Dès lors, les questions des commentateurs fusent : pourquoi B.__init__ () n’est-elle pas appelée ? Sincèrement, avant de publier une explication sur un sujet technique, son auteur devrait s’assurer qu’il maîtrise son sujet. Comme il le dit, « The super keyword is a little bit confusing in Python. It’s been confusing for decades now and it’s going to continue to be confusing as we move into the future. It’s just something that’s confusing ». Tu m’étonnes! surtout après avoir entendu sa prétendue explication…
Non. Je parle d’explications d’auteurs qui ont pignon sur rue, comme Python’s super() considered super! de Raymond Hettinger, à laquelle renvoie la documentation de super(), ou encore celle d’Alex Martelli, Anna Ravenscroft et Steve Holden dans leur Python in a Nutshell. Le moins qu’on puisse dire, c’est qu’on ne ressort pas illuminé de ces lectures. Sans doute, on comprend que super() permet de jouer avec le Method Resolution Order (MRO), mais quand a savoir exactement comment, c’est une autre affaire. Tout le monde se contente de terminer en recommandant d’utiliser systématiquement super() à tous les niveaux le hiérarchie des appels, et pour le reste renvoie sur l’algorithme C3, présenté comme abscons.
Bref, tout comme peu de personnes semblent avoir compris que JavaScript est un langage orienté objet à base de prototypes (et non de classes !), y’en a-t-il seulement qui ont compris comment la fonction super() de Python fonctionne vraiment ? Sérieusement, il y a de quoi nourrir de sérieuses inquiétudes quant au niveau d’exigence des développeurs désormais. Plus personne ne se donne la peine d’aller au fond des choses, ou quoi ?
On va donc arrêter de plaisanter, et expliquer sérieusement…
Continuer la lecture de « Comment marche réellement la fonction super () de Python »
Comment marche réellement la fonction super () de Python