
Code source du livre « Violent Python » de TJ O'Connor. Le code a été entièrement converti en Python 3, reformaté pour se conformer aux normes PEP8 et refactorisé afin d'éliminer les problèmes de dépendances liés à l'implémentation de bibliothèques obsolètes.
Code source du livre « Violent Python » de TJ O'Connor. Le code a été entièrement converti en Python 3, reformaté pour être conforme aux normes PEP8 et refactorisé afin d'éliminer les problèmes de dépendances liés à l'implémentation de bibliothèques obsolètes.
Une conversion similaire à celle-ci a été rendue disponible par moi-même sur le code source du livre « Black Hat Python », de Justin Seitz. Allez y jeter un œil ici si vous ne l'avez pas encore fait.
Créez simplement un nouveau répertoire (DIR) pour le projet, créez un nouvel environnement virtuel ou venv pour celui-ci (recommandé), clonez ce dépôt à l'aide de git clone et installez les dépendances avec pip install.
user@host:~/DIR$ git clone https://github.com/EONRaider/violent-python3
user@host:~/DIR$ python3 -m venv venv
user@host:~/DIR$ source venv/bin/activate
(venv) user@host:~/DIR$ pip install -r requirements.txt
optparse, désormais obsolète, a été remplacée par argparse dans l'ensemble du code source. Tout l'analyse des arguments est désormais contenue dans le cadre d'exécution __main__ de chaque fichier. Tous les arguments CLI qui étaient obligatoires pour l'exécution des scripts mais traités comme facultatifs dans le code d'origine sont désormais implémentés comme positionnels. Une invite usage est désormais disponible pour tous les scripts qui utilisent argparse en fournissant un argument -h à la CLI. Laisser les responsabilités d'objet frontière et de contrôleur à l'analyseur CLI n'est certainement pas le meilleur choix en termes d'architecture logicielle, mais a été laissé tel quel par nécessité de conformité à l'intention du codeur original.PEP 8: E722 do not use bare except ont été refactorisées avec des clauses d'exception plus spécifiques.close() sur les objets fichier/base de données ouverts. Pour cette raison, toutes les manipulations de fichiers et de bases de données ont été refactorisées à l'aide de gestionnaires de contexte.# -*- coding: utf-8 -*-) a été supprimée en raison de la normalisation de UTF-8 comme encodage par défaut de Python 3 (remplaçant ASCII de Python 2).Les fichiers non listés ci-dessous peuvent être considérés comme ayant été refactorisés d'une manière ou d'une autre, comme établi dans la section « Remarques ».
chapter01/vuln_scanner.py était structuré de telle sorte qu'un fichier inexistant entraînait une exception OSError au moment de l'exécution. Pour cette raison, la structure de contrôle d'itération qui appelle check_vulns() a été déplacée dans la condition définie dans la fonction principale.chapter02/nmap_scan.py implémentait une fonction principale uniquement pour appeler la bibliothèque obsolète optparse, qui a été remplacée par argparse. Pour cette raison, la fonction principale a été supprimée. Une structure de contrôle d'itération qui faisait partie de l'appel optparse dans le code d'origine était implémentée de telle sorte qu'un nouvel appel à nmap était exécuté pour chaque port scanné. L'itération a été déplacée dans la fonction nmap_scan afin d'éviter de gaspiller des cycles.chapter02/ssh_command.py a vu son code d'initialisation déplacé dans le cadre d'exécution __main__. Les noms des variables utilisées dans la portée externe qui entraient en conflit avec les noms des paramètres des fonctions ont été modifiés. Les informations de l'invite de retour étaient à l'origine encodées et ont maintenant été décodées pour offrir une meilleure lisibilité.Les contributions dans d'autres langues peuvent être consultées ici :
Par simple bon sens, essayez d'abord de discuter du changement que vous souhaitez apporter à ce dépôt via une issue.
chapter02/ssh_brute.py importait pxssh comme une bibliothèque autonome, mais en réalité c'est une bibliothèque sous la bibliothèque pexpect. Le bug a conduit à une ModuleNotFoundError et a été corrigé. Le code lui-même, tel que présenté dans le livre, était parsemé d'erreurs d'indentation qui le rendaient inutilisable et a été ramené à un état fonctionnel.chapter02/ssh_brutekey.py nécessitait un certain nombre de clés pré-générées pour fonctionner ; de plus, le livre indique au lecteur d'acquérir ces clés à une URL qui renvoie actuellement une réponse 403. Pour cette raison, une archive compressée contenant les clés a été ajoutée au sous-répertoire chapter02.chapter02/ssh_botnet.py contenait une instruction d'import inutilisée pour optparse qui a été supprimée. Il semble que ce soit un fragment d'une tentative avortée d'implémenter une CLI pour ce script. Étonnamment, il a été laissé là, même dans la version imprimée du livre. Le code qui initialise le botnet et émet ses commandes a été organisé sous le cadre d'exécution __main__ pour des raisons de normalisation. Les deux commandes envoyées aux bots ont été unifiées pour éviter un nombre inutile de déclarations de retour.chapter02/conficker.py a supprimé l'appel inutilisé à la bibliothèque sys.chapter03/discover_networks.py a dû être réimplémenté au lieu d'être simplement refactorisé. À l'origine, il utilisait non seulement la bibliothèque obsolète mechanize, mais interagissait aussi avec le service WiGLE d'une manière qui n'est plus nécessaire, puisque WiGLE fournit désormais une API. Pour cette raison, le code a été normalisé et une nouvelle fonction wigle_print a été implémentée en utilisant la bibliothèque requests pour envoyer une requête HTTP GET authentifiée à WiGLE. La réponse renvoie un objet JSON qui peut être directement accessible, rendant également inutile l'utilisation de la bibliothèque re. La gestion des exceptions a été ajoutée pour permettre au script de traiter les messages de réponse d'erreur envoyés par l'API. Notez que ce script dépend de winreg, qui ne s'exécute que sur les installations Python de Microsoft Windows et nécessite des privilèges Administrateur pendant l'exécution pour accéder aux clés du Registre. Un compte doit être enregistré sur https://wigle.net/account pour accéder à l'API.chapter03/pdf_read.py utilise désormais la bibliothèque PyPDF4 au lieu de la bibliothèque obsolète PyPDF. Le livre fait référence à un fichier PDF spécifique dans le texte et il a été ajouté au sous-répertoire chapter03.chapter03/exif_fetch.py nécessitait un argument features="html.parser" lors de l'appel au constructeur de l'objet BeautifulSoup. Il a été ajouté à la ligne 15. Ce script ne fonctionne que sur les applications web qui encapsulent les images entre des balises HTML img (une pratique rare sur les applications web modernes qui dépendent fortement de JavaScript).chapter03/skype_parse.py utilise le fichier main.db comme exemple. Il a été ajouté au sous-répertoire chapter03/skype_profile pour plus de commodité.chapter03/firefox_parse.py utilise plusieurs fichiers .sqlite comme exemples. Ils ont été ajoutés au sous-répertoire chapter03/firefox_profile pour plus de commodité.chapter03/iphone_messages.py fait référence à des fichiers de sauvegarde iPhone qui n'ont pas été mis à disposition par l'auteur. Pour cette raison, le code a été refactorisé mais reste non testé.chapter04/geo_ip.py utilisait la bibliothèque obsolète pygeoip. Comme suggéré par son créateur, geoip2 devrait désormais être utilisé. Une tentative a été faite pour garder le code nouvellement implémenté aussi similaire que possible à l'implémentation originale du livre, mais certains changements ont dû être apportés pour s'adapter à la nouvelle structure du paquet geoip2 et à ses attributs. Le fichier de base de données nécessaire pour exécuter le script a été téléchargé depuis MaxMind et mis à disposition dans le répertoire chapter04. Une CLI a également été implémentée à l'aide d'argparse.chapter04/print_direction.py levait une exception UnicodeDecodeError lors de l'ouverture du fichier dans l'implémentation d'origine. Cela a été corrigé en ajoutant un argument rb au gestionnaire de contexte qui gère le fichier.chapter04/find_ddos.py affichait l'adresse source de l'attaque Hivemind comme destination, rendant la sortie inutile. La variable correcte dst est maintenant affichée sur stdout. Le livre fait référence à un fichier appelé traffic.pcap qui n'a pas été mis à disposition par l'auteur, donc le code a été refactorisé mais reste non testé.chapter04/test_domain_flux.py indique que zéro requête sans réponse a été faite lors de l'analyse du fichier pcap fourni par l'auteur. Pour une raison quelconque, les paquets eux-mêmes n'ont pas la valeur du champ DNS Resource Record définie, donc la condition dans la fonction dns_QR_test est toujours évaluée comme fausse. Dans ce cas, la condition évaluant le champ DNSRR a été retirée de la déclaration conditionnelle et tous les paquets UDP ayant le port 53 comme source sont désormais analysés. Cela donne un code moins efficace, mais au moins il produit les résultats comme prévu dans le livre.chapter05/blue_bug.py utilise la bibliothèque PyBluez, qui demande à son tour la bibliothèque BlueZ et les fichiers d'en-tête comme indiqué dans ses instructions d'installation. Ces dépendances doivent être installées avant d'installer PyBluez comme exigence. Sous Linux, cela peut être effectué en exécutant la commande apt install bluetooth libbluetooth-dev. Le code d'origine référence un objet client_sock inexistant qui a été remplacé par phone_sock.chapter05/ftp_sniff.py présentait un défaut logique qui lui faisait afficher un nom d'utilisateur sniffé mais aucun mot de passe en raison d'une mauvaise implémentation d'une instruction if... else. Cela a été corrigé en remplaçant l'instruction conditionnelle par une clause if imbriquée.chapter05/ninja_print.py nécessite la bibliothèque obexftp pour fonctionner. Cette bibliothèque a été écrite pour Python 2 et n'a pas encore été portée ni remplacée par une équivalente à ce jour, donc le code reste tel que écrit par l'auteur dans sa version Python 2.chapter05/__init__.py et chapter06/__init__.py ont été ajoutés pour permettre l'importation des modules depuis chapter05/dup.py et chapter06/anon_browser.py, respectivement.chapter06/anon_proxy.py a été réimplémenté avec la bibliothèque Python 3 MechanicalSoup. Il intègre les modifications qui étaient nécessaires pour proxy_test.py, useragent_test.py et print_cookies.py.chapter06/anon_browser.py a également été réimplémenté avec MechanicalSoup et a subi quelques modifications dans le code. La bibliothèque cookielib a été remplacée par http.cookiejar dans la méthode constructeur de la classe AnonBrowser et le paramètre user_agents accepte désormais une liste de chaînes de caractères au lieu d'un tuple.chapter06/link_parser.py a été refactorisé en utilisant de nouvelles façons de gérer les implémentations de re et bs4.