Foro de elhacker.net

Seguridad Informática => Bugs y Exploits => Mensaje iniciado por: c1c4tr1z en 14 Enero 2009, 01:28 am



Título: Deshabilitando protecciones contra Buffer Overflows
Publicado por: c1c4tr1z en 14 Enero 2009, 01:28 am
Cuando es el momento de analizar un programa en busca de vulnerabilidades o simplemente explotarlos bajo GNU/Linux, hay dos simples protecciones que hay que tener en cuanta cuando hablamos  de sistemas con Kernels de versiones 2.6 y mayores, y por sobre todo si están compilados con GCC. Hay mas protecciones como el parche grsecurity o exec-shield (de los que quizás hable mas adelante), hasta existe una protección desde hardware llamado StackGuard.

Virtual Address Space Randomization:

La primera protección es la creación de espacio  de direcciones virtuales aleatorias en el proceso, que van cambiando con cada invocación del proceso. Al cambiar esto, los exploits creados para direcciones absolutas (osea, constantes) serian obsoletos ya que cambian las direcciones con cada ejecución del programa y sus librerías en un rango de 8MB. Esto se aplica solamente a binarios ELF (Executable and Linkable Format).
El método para habilitarlo y deshabilitarlo es simple, voy a demostrar el cambio de direcciones en la memoria con el siguiente código:

Código:
#include <stdio.h>

unsigned long esp(void){
__asm__("movl %esp, %eax");
}

int main(int argc, char *argv[]){
printf("0x%08x\n",esp());
return 0;
}

Este código me daría la dirección exacta de ESP en el momento de la ejecución. Ahora con este código vamos a probar la protección en si del kernel en cuestión. El archivo de sistema que controla esta opción se encuentra en /proc/sys/kernel/randomize_va_space (solo manipulado por un superusuario o root) y podríamos decir que se controla mediante un TRUE (1) o FALSE (0). Entonces, probemos:

Código:
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat /proc/sys/kernel/randomize_va_space 
1
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat > esp.c << _END_
> #include <stdio.h>
>
> unsigned long esp(void){
> __asm__("movl %esp, %eax");
> }
>
> int main(int argc, char *argv[]){
> printf("0x%08x\n",esp());
> return 0;
> }
>
> _END_
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gcc esp.c -o esp
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$  ./esp
0xbfef2448
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
0xbfd48298
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
0xbfa24778
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$

Mediante la habilitación de este "parche" podemos ver que las direcciones van cambiando y haciendo casi imposible saber la dirección virtual de ESP (en este caso..) hasta el momento de la ejecución. Ahora deshabilitemos esta función y veamos que pasa:

Código:
root@c1c4tr1z-desktop:~# echo 0 > /proc/sys/kernel/randomize_va_space
[...]
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat /proc/sys/kernel/randomize_va_space
0
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
0xbffff558
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
0xbffff558
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
0xbffff558
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$

Después de deshabilitar el parche podemos ver que la dirección de ESP es constante en el ejecutable, sin siquiera volver a compilarlo!
Pero no se asusten, como la historia nos ha enseñado! Detras de cada sistema de seguridad hay alguien tratando de romperlo.. [1]

GCC StackGuard (ProPolice) Protection:

Bueno, esta es una proteccion de seguridad implementada en el compilador ultra renombrado y que se encuentra en cada distribución GNU/Linux , hablo de GCC (GNU Compiler Collection). Este compilador viene con un sistema de protección llamado "StackGuard" desarrollado por Immunix y ahora llamado ProPolice [2]. Esta protección detecta un ataque de buffer overflow (siempre en el "stack") creando un valor llamado "Canario" entre los buffers creados y el "frame pointer" (EBP) & "return address" (EIP), entonces cuando un buffer intenta sobreescribir estos valores tiene que de una forma o otra sobreescribir el valor "Canario" y esto sirve como lanzador ("trigger") de la proteccion que da una alerta y toma una acción contra ello, por ejemplo, deteniendo el proceso.
Bueno, vamos a ver como reacciona a un simple overflow como este:

Código:
#include <stdio.h>
#include <string.h>

void overflow(char *badbeef){
char buffer[32];
strcpy(buffer, badbeef);
}

int main(int argc, char *argv[]){
overflow(argv[1]);
return 0;
}


Como vemos, hay un buffer de 32 bytes y ni un solo checkeo al hacer la copia de string al buffer. Ya sabemos que tenemos 32 bytes de buffer + EBP +  EIP, pero si la protección esta habilitada no nos permitiría ni pasar de el "frame pointer":
Código:

c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat > vulnerable.c <<_END_
> #include <stdio.h>
> #include <string.h>
>
> void overflow(char *badbeef){
> char buffer[32];
> strcpy(buffer, badbeef);
> }
>
> int main(int argc, char *argv[]){
> overflow(argv[1]);
> return 0;
> }
>
> _END_
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gcc vulnerable.c -o vulnerable
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x32')
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x36#EBP')
*** stack smashing detected ***: ./vulnerable terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7f69138]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7f690f0]
./vulnerable[0x80483fe]
./vulnerable[0x8048421]
[0x41414141]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
08049000-0804a000 rw-p 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
0804a000-0806b000 rw-p 0804a000 00:00 0          [heap]
b7e70000-b7e7a000 r-xp 00000000 08:02 197220     /lib/libgcc_s.so.1
b7e7a000-b7e7b000 rw-p 0000a000 08:02 197220     /lib/libgcc_s.so.1
b7e7b000-b7e7c000 rw-p b7e7b000 00:00 0
b7e7c000-b7fc5000 r-xp 00000000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc5000-b7fc6000 r--p 00149000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc6000-b7fc8000 rw-p 0014a000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc8000-b7fcb000 rw-p b7fc8000 00:00 0
b7fe1000-b7fe3000 rw-p b7fe1000 00:00 0
b7fe3000-b7fe4000 r-xp b7fe3000 00:00 0          [vdso]
b7fe4000-b7ffe000 r-xp 00000000 08:02 196676     /lib/ld-2.7.so
b7ffe000-b8000000 rw-p 00019000 08:02 196676     /lib/ld-2.7.so
bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
Cancelado
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x44#EIP')
*** stack smashing detected ***: ./vulnerable terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7f69138]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7f690f0]
./vulnerable[0x80483fe]
[0x41414141]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
08049000-0804a000 rw-p 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
0804a000-0806b000 rw-p 0804a000 00:00 0          [heap]
b7e70000-b7e7a000 r-xp 00000000 08:02 197220     /lib/libgcc_s.so.1
b7e7a000-b7e7b000 rw-p 0000a000 08:02 197220     /lib/libgcc_s.so.1
b7e7b000-b7e7c000 rw-p b7e7b000 00:00 0
b7e7c000-b7fc5000 r-xp 00000000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc5000-b7fc6000 r--p 00149000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc6000-b7fc8000 rw-p 0014a000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc8000-b7fcb000 rw-p b7fc8000 00:00 0
b7fe1000-b7fe3000 rw-p b7fe1000 00:00 0
b7fe3000-b7fe4000 r-xp b7fe3000 00:00 0          [vdso]
b7fe4000-b7ffe000 r-xp 00000000 08:02 196676     /lib/ld-2.7.so
b7ffe000-b8000000 rw-p 00019000 08:02 196676     /lib/ld-2.7.so
bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
Cancelado

DETECTADO! Si analizamos mas de cerca vemos esto ./vulnerable[0x80483ef], esa direccion nos indica en que momento el programa ejecuta el buffer overflow:

Código:
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gdb -q vulnerable
(gdb) disas 0x80483ef
Dump of assembler code for function overflow:
0x080483c4 <overflow+0>: push   %ebp
0x080483c5 <overflow+1>: mov    %esp,%ebp
0x080483c7 <overflow+3>: sub    $0x48,%esp
0x080483ca <overflow+6>: mov    0x8(%ebp),%eax
0x080483cd <overflow+9>: mov    %eax,-0x34(%ebp)
0x080483d0 <overflow+12>: mov    %gs:0x14,%eax
0x080483d6 <overflow+18>: mov    %eax,-0x4(%ebp)
0x080483d9 <overflow+21>: xor    %eax,%eax
0x080483db <overflow+23>: mov    -0x34(%ebp),%eax
0x080483de <overflow+26>: mov    %eax,0x4(%esp)
0x080483e2 <overflow+30>: lea    -0x24(%ebp),%eax
0x080483e5 <overflow+33>: mov    %eax,(%esp)
[b]0x080483e8 <overflow+36>: call   0x8048320 <strcpy@plt>[/b]
0x080483ed <overflow+41>: mov    -0x4(%ebp),%eax
0x080483f0 <overflow+44>: xor    %gs:0x14,%eax
0x080483f7 <overflow+51>: je     0x80483fe <overflow+58>
0x080483f9 <overflow+53>: call   0x8048330 <__stack_chk_fail@plt>
0x080483fe <overflow+58>: leave
0x080483ff <overflow+59>: ret   
End of assembler dump.

Como vemos detiene el programa en la instrucció leave, que (por lo que entiendo) es la encargada de mover (mov) a %ebp a %esp y sacar (pop) a %ebp de la pila, eso significaria que pretende volver a ESP y con el buffer copiado (call   0x8048320 <strcpy@plt>). Es ahi donde el canario es sobreescrito y se detiene todo el procedimiento despues del checkeo. El checkeo lo hace mediante la funcion __stack_chk_fail().
Ahora vamos a probar el programa _sin_ esta protección. Para eso vamos a compilar el programa con el flag --no-stack-protector:

Código:
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gcc --no-stack-protector vulnerable.c -o vulnerable
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x44#EIP')
Fallo de segmentación
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gdb -q vulnerable
(gdb) r $(perl -e 'print "A"x36 ,"B"x4')
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/c1c4tr1z/Escritorio/vulnerable $(perl -e 'print "A"x36 ,"B"x4')

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) i r eip ebp
eip            0x42424242 0x42424242
ebp            0x41414141 0x41414141
(gdb)

Y sin esta protección pudimos sobreescribir EBP y EIP sin ninguna dificultad, cosa que seria fácil de explotar mas aún si la protección de la cual hable antes esta deshabilitada para poder conseguir la dirección constante de ESP y sobreescribir el flujo del proceso. En sí, yo solo hable de un solo método de protección de esta extensión, que por lo que sé son 5 y se pueden ver en al pagina oficial [2].

Espero que les haya gustado esta pequeña charla, si tienen  alguna pregunta o recalcarme en algo que estuve mal por favor haganlo ya que me estarían ayudando a mi y a los lectores :D porque apenas entro en el mundo de los exploits a nivel de sistema y la *lectura* de códigos en ASM.

Referencias:
[1] Smack the Stack (Advanced Buffer Overflow Methods) - http://www.packetstormsecurity.org/papers/bypass/smackthestack.txt
[2] ProPolice - http://www.trl.ibm.com/projects/security/ssp/


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: AlbertoBSD en 15 Enero 2009, 05:49 am
Muy bien explicado, la verdad me gusto el documento, lastima que en FreeBSD no sea igual aun asi no tengo activada la pila en random.

Ahora:

Código
  1. root@c1c4tr1z-desktop:~# echo 0 > /proc/sys/kernel/randomize_va_space

Cualquiera siendo root puedo desactivar las protecciones  :-X. aun así muy instructivo la verdad.

Saludos.




Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: c1c4tr1z en 15 Enero 2009, 06:30 am
Gracias Anon!
Si, eso fue un error mio, a lo primero fue pensado como un simple post del "porque" a veces los exploits no funcionan por eso el titulo fue "Deshabilitando protecciones contra Buffer Overflows", pero decidí desarrollar un poco mas el texto ;D


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: k-k0 en 15 Enero 2009, 06:34 am
Buen post!... si mal no recuerdo FreeBSD, trae la opcion de evitar overflows por defecto en gcc, no ?


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: c1c4tr1z en 15 Enero 2009, 07:09 am
En realidad por default GCC trae la proteccion habilitada. Supongo que debe ser asi en todos los sistemas *nix..


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: AlbertoBSD en 15 Enero 2009, 07:21 am
No la tiene habilitada, tengo FreeBSD 7.0

Código
  1. Anon@localhost % uname -a
  2. FreeBSD  7.0-RELEASE FreeBSD 7.0-RELEASE #6: Sat Dec 27 08:13:05 CST 2008     root@:/usr/src/sys/i386/compile/VGN-N350  i386
  3.  

Tiene por defecto el gcc 4.2.1

Código
  1. Anon@localhost % gcc -v
  2. Using built-in specs.
  3. Target: i386-undermydesk-freebsd
  4. Configured with: FreeBSD/i386 system compiler
  5. Thread model: posix
  6. gcc version 4.2.1 20070719  [FreeBSD]

Y yo compile por aparte el 3.4.6

Código
  1. Anon@localhost % gcc34 -v
  2. Reading specs from /usr/local/lib/gcc/i386-portbld-freebsd7.0/3.4.6/gcc/i386-portbld-freebsd7.0/3.4.6/specs
  3. Configured with: ./..//gcc-3.4.6/configure --disable-nls --with-system-zlib --with-libiconv-prefix=/usr/local --program-suffix=34 --libdir=/usr/local/lib/gcc/i386-portbld-freebsd7.0/3.4.6 --with-gxx-include-dir=/usr/local/lib/gcc/i386-portbld-freebsd7.0/3.4.6/include/c++/ --prefix=/usr/local --mandir=/usr/local/man --infodir=/usr/local/info/gcc34 i386-portbld-freebsd7.0
  4. Thread model: posix
  5. gcc version 3.4.6 [FreeBSD]
  6.  

Y nada de proteccionista por defecto.

Una cosa que puedo hacer es por defecto desactivar la ejecución en la pila. Esa es una proteccion mas, sin embargo muchas veces con el return into libc no sirve de mucho.

Saludos.


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: k-k0 en 15 Enero 2009, 07:26 am
hace un tiempo cuando probe FreeBSD, recuerdo que traia en gcc una opcion por defecto para evitar posibles overflows, pero sinceramente no me acuerdo cual era esa proteccion ...


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: c1c4tr1z en 15 Enero 2009, 15:31 pm
Yo tampoco parezco tener las protecciones cuando miro los headers de configuración:
Código
  1. c1c4tr1z@c1c4tr1z-desktop:~$ gcc -v
  2. Usando especificaciones internas.
  3. Objetivo: i486-linux-gnu
  4. Configurado con: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
  5. Modelo de hilos: posix
  6. gcc versión 4.2.4 (Ubuntu 4.2.4-1ubuntu3)
  7.  
Pero aun así viene por default, quizás simplemente en Ubuntu o los sabores Debian. Si tenes algo de tiempo, podrías probar el código de ejemplo? Así de paso tenemos mas información..


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: k-k0 en 16 Enero 2009, 04:22 am
uname -a
Código:
Linux localhost 2.6.27-ARCH #1 SMP PREEMPT Sun Dec 21 09:31:10 UTC 2008 i686 Intel(R) Core(TM) Duo CPU T2350 @ 1.86GHz GenuineIntel GNU/Linux

gcc -v
Código:
Usando especificaciones internas.
Objetivo: i686-pc-linux-gnu
Configurado con: ../configure --prefix=/usr --enable-shared --enable-languages=c,c++,fortran,objc,obj-c++,treelang --enable-threads=posix --mandir=/usr/share/man --infodir=/usr/share/info --enable-__cxa_atexit --disable-multilib --libdir=/usr/lib --libexecdir=/usr/lib --enable-clocale=gnu --disable-libstdcxx-pch --with-tune=generic
Modelo de hilos: posix
gcc versión 4.3.2 (GCC)

En un rato cuando termine de meter mano a unas librerias pruebo el codigo y lo posteo ...



Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: c1c4tr1z en 16 Enero 2009, 18:57 pm
@k-k0: Ok, gracias k-k0.

@Anon: Estoy en duda por la posibilidad de que no este el parche por default. Asi que dejo el link (http://www.trl.ibm.com/projects/security/ssp/freebsd51/protector-fbsd-5.1-3.patch) parche para FreeBSD (y su checksum (http://www.trl.ibm.com/projects/security/ssp/freebsd51/protector-fbsd-5.1-3.patch.md5)) por las dudas.

Saludos!


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: NewLog en 19 Enero 2009, 18:45 pm
Muy buen texto!

En mi Debian (Kernel 2.6.18-6-686) el gcc tampoco viene con la protección por defecto.

Hay alguna manera de hackear la última protección?

Edito:Aquí tenéis un pdf original escrito por Immunix sobre el StackGuard Protection. En ese mismo documento comentan que en el número 10(¿56?) de phrack se explica como hackear la protección.
Documento (http://mirror-fpt-telecom.fpt.net/gcc/summit/2003/Stackguard.pdf)

Vuelvo a editar: Aquí tenéis el artículo de phrack. Must read!
Artículo (http://www.phrack.com/issues.html?issue=56&id=5#article)

Además he encontrado otro pdf muy bueno donde se explica la teoria de las protecciones y como saltarselas:
Artículo (http://www.coresecurity.com/files/attachments/StackGuard.pdf)


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: c1c4tr1z en 20 Enero 2009, 18:14 pm
Muchas gracias NewLog!
Muy buena información. Aunque esta desactualizada sirve para varias ideas.

En cuanto a las protecciones de StackGuard encontré lo siguiente:

Defeating compiler-level buffer overflow protection (http://usenix.org/publications/login/2005-06/pdfs/alexander0506.pdf)

En cuánto a la protección del parche del VA, encontré varias técnicas para hacer un bypass:

  • RET2ESP: Este es el mas común. Se trata de conseguir la dirección en hexadecimal de la llamada jmp %esp o call %esp
  • RET2EAX: Se puede realizar este método cuando se usa a EAX para retornar un valor
  • RET2RET: Se trata de utilizar una dirección anteriormente guardada en el stack como un potencial RET.
  • RET2RET: Esta técnica me costo un poco comprenderla. Necesitamos realizar una técnica similar a la anterior pero necesitamos que antes del retorno se encuentre un POP que nos permita pasar a otro argumento para almacenar el shellcode.

Estoy viendo un poco mas afondo este tema, asi que dentro de poco aparezco con mas información si el tiempo me lo permite  ;D.


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: AlbertoBSD en 20 Enero 2009, 19:05 pm
Perfecto, yo me los practicare bajo linux, en esta semana que me lo instale, también voy a instalar el windows, para testear algunas vulnerabilidades bajo el.

Saludos.


Que esto no estaba en Bugs y exploits ?


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: c1c4tr1z en 23 Enero 2009, 07:21 am
Si Anon, estaba en "Bugs y Exploits" pero lo movieron.



Bueno, estuve investigando un poco y encontré al representante (mejor dicho ayudante) de esta protección. Su nombre es linux-gate.so.1 y es una librería compartida que no se presenta en el sistema, sino que reside en el kernel.
Voy a usar el mismo programa vulnerable del articulo principal, compilado con la protección. Para saber si el programa usa la librería voy a usar el comando ldd:

Código
  1. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ldd vulnerable |grep linux-gate
  2. linux-gate.so.1 =>  (0xb7fe3000)
  3. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$

Y bueno, uno de los checkeos mas importantes lo hace la misma función __stack_chk_fail que forma parte de glibc:
Código
  1. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ objdump -T vulnerable
  2.  
  3. vulnerable:     file format elf32-i386
  4.  
  5. DYNAMIC SYMBOL TABLE:
  6. 00000000  w   D  *UND* 00000000              __gmon_start__
  7. 00000000      DF *UND* 000001b2  GLIBC_2.0   __libc_start_main
  8. 00000000      DF *UND* 00000024  GLIBC_2.0   strcpy
  9. 00000000      DF *UND* 00000020  GLIBC_2.4   __stack_chk_fail
  10. 080484ec g    DO .rodata 00000004  Base        _IO_stdin_used
  11.  
  12.  
  13. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ nm vulnerable |grep U
  14.         U __libc_start_main@@GLIBC_2.0
  15.         U __stack_chk_fail@@GLIBC_2.4
  16.         U strcpy@@GLIBC_2.0
  17. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ objdump -d vulnerable --section=.plt |tail -n 4
  18. 08048330 <__stack_chk_fail@plt>:
  19. 8048330: ff 25 f4 95 04 08     jmp    *0x80495f4
  20. 8048336: 68 18 00 00 00       push   $0x18
  21. 804833b: e9 b0 ff ff ff       jmp    80482f0 <_init+0x30>
  22. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$

Pero que parece llamar a la función mas importante si se produce un buffer overflow, que es __kernel_vsyscall. Entonces corremos de nuevo gdb y vemos la función:

Código
  1. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gdb -q vulnerable
  2. (gdb) r $(perl -e 'print "A"x40')
  3. Starting program: /home/c1c4tr1z/Escritorio/vulnerable $(perl -e 'print "A"x40')
  4. *** stack smashing detected ***: /home/c1c4tr1z/Escritorio/vulnerable terminated
  5.  
  6. [...]
  7.  
  8. Program received signal SIGABRT, Aborted.
  9. 0xb7fe3410 in __kernel_vsyscall ()
  10. (gdb) bt
  11. #0  0xb7fe3410 in __kernel_vsyscall ()
  12. #1  0xb7ea7085 in raise () from /lib/tls/i686/cmov/libc.so.6
  13. #2  0xb7ea8a01 in abort () from /lib/tls/i686/cmov/libc.so.6
  14. #3  0xb7edfb7c in ?? () from /lib/tls/i686/cmov/libc.so.6
  15. #4  0xb7f69138 in __fortify_fail () from /lib/tls/i686/cmov/libc.so.6
  16. #5  0xb7f690f0 in __stack_chk_fail () from /lib/tls/i686/cmov/libc.so.6
  17. #6  0x080483fe in overflow ()
  18. #7  0x08048400 in overflow ()
  19. Backtrace stopped: previous frame inner to this frame (corrupt stack?)
  20. (gdb) disas 0xb7fe3410
  21. Dump of assembler code for function __kernel_vsyscall:
  22. 0xb7fe3400 <__kernel_vsyscall+0>: push   %ecx
  23. 0xb7fe3401 <__kernel_vsyscall+1>: push   %edx
  24. 0xb7fe3402 <__kernel_vsyscall+2>: push   %ebp
  25. 0xb7fe3403 <__kernel_vsyscall+3>: mov    %esp,%ebp
  26. 0xb7fe3405 <__kernel_vsyscall+5>: sysenter
  27. 0xb7fe3407 <__kernel_vsyscall+7>: nop    
  28. 0xb7fe3408 <__kernel_vsyscall+8>: nop    
  29. 0xb7fe3409 <__kernel_vsyscall+9>: nop    
  30. 0xb7fe340a <__kernel_vsyscall+10>: nop    
  31. 0xb7fe340b <__kernel_vsyscall+11>: nop    
  32. 0xb7fe340c <__kernel_vsyscall+12>: nop    
  33. 0xb7fe340d <__kernel_vsyscall+13>: nop    
  34. 0xb7fe340e <__kernel_vsyscall+14>: jmp    0xb7fe3403 <__kernel_vsyscall+3>
  35. 0xb7fe3410 <__kernel_vsyscall+16>: pop    %ebp
  36. 0xb7fe3411 <__kernel_vsyscall+17>: pop    %edx
  37. 0xb7fe3412 <__kernel_vsyscall+18>: pop    %ecx
  38. 0xb7fe3413 <__kernel_vsyscall+19>: ret    
  39. End of assembler dump.
  40. (gdb)

Al parecer y por lo que he leído, esta función encuentra la manera mas "rápida" de hacer una llamada dependiendo del procesador y de la versión del kernel (>=2.6), determinando si usar sysenter/sysexit o int 0x80 para hacer llamadas.

Bueno, leyendo las listas de correo de linux.kernel me encontré con una simplificada pero buena explicación de como actúa el protector. Lo que hace la protección es seleccionar diferentes funciones (dependiendo si presentan buffers mayores de 8 bytes) y colocan un valor "canario" al principio de la función antes de la dirección de retorno. Antes de terminar la función y usar RET se compara el "canario" (__stack_chk_fail) con el valor de referencia, si sufre un cambio es una alerta de un posible buffer overflow.

Hay otra función que voy a checkear mas tarde que es __fortify_fail(), pero no puedo encontrar mucha información sobre ello. Estas son cosas que voy leyendo/entendiendo hasta ahora.

Saludos!


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: plAnadecU en 10 Marzo 2009, 21:09 pm
En este thread estoy intentado descubrir como saltarse esta protección.

http://foro.elhacker.net/bugs_y_exploits/saltarse_protecciones_gcc_stackchkfail_fortify-t248049.0.html


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: rmdma() en 13 Febrero 2012, 12:33 pm
Código:
(gdb) r $(perl -e 'print "A"x[b]42[/b] , "B"x4')
The program being debugged has been started already.
Start it from the beginning? (y o n) y
Starting program: /home/cebanc/vuln $(perl -e 'print "A"x42 , "B"x4')

Program received signal SIGSEGV, Segmentation fault.
0x08004242 in ?? ()
(gdb) i r
eax            0xbffff280 -1073745280
ecx            0x0 0
edx            0xbffff54f -1073744561
ebx            0x28bff4 2670580
esp            0xbffff2b0 0xbffff2b0
[b]ebp            0x42424141 0x42424141[/b]
esi            0x0 0
edi            0x0 0
[b]eip            0x8004242 0x8004242[/b]

-------------------------------------------------------------------------

Código:
(gdb) r $(perl -e 'print "A"x[b]44 [/b], "B"x4')
The program being debugged has been started already.
Start it from the beginning? (y o n) y
Starting program: /home/cebanc/vuln $(perl -e 'print "A"x44 , "B"x4')

Program received signal SIGSEGV, Segmentation fault.
0x080483dd in overflow ()
(gdb) i r
eax            0xbffff280 -1073745280
ecx            0x0 0
edx            0xbffff54f -1073744561
ebx            0x28bff4 2670580
esp            0xbffff2ac 0xbffff2ac
[b]ebp            0x41414141 0x41414141[/b]
esi            0x0 0
edi            0x0 0
[b]eip            0x80483dd 0x80483dd <overflow+25>[/b]
(gdb)
--------------------------------------------------------------------
Código:
(gdb) r $(perl -e 'print "A"x[b]43[/b] , "B"x4')
The program being debugged has been started already.
Start it from the beginning? (y o n) y
Starting program: /home/cebanc/vuln $(perl -e 'print "A"x43 , "B"x4')

Program received signal SIGSEGV, Segmentation fault.
0x00424242 in ?? ()
(gdb) i r
eax            0xbffff280 -1073745280
ecx            0x0 0
edx            0xbffff54f -1073744561
ebx            0x28bff4 2670580
esp            0xbffff2b0 0xbffff2b0
[b]ebp            0x42414141 0x42414141[/b]
esi            0x0 0
edi            0x0 0
[b]eip            0x424242 0x424242[/b]
(gdb)

mi pregunta es, que es lo q esta pasando? por que eip derrepente tiene una direccion menor de lo normal y por que me sobrescribe alos 46 en vez d en los 40 que os sobrescribe a vosotros, alguien me puede hacer un dibujo de como estaria el stack al principio de ejecucion y despues de ser sobrescrito todo x favor, en la teoria lo entiendo o me da la sensacion de que lo e entendido pero llego a la practica y zass nose..


Título: Re: Deshabilitando protecciones contra Buffer Overflows
Publicado por: Ivanchuk en 15 Febrero 2012, 22:10 pm
Tendrias que poner el desensamblado de tu funcion. Para mi debe ser por la alineacion de 16 bytes de la pila, pero no estoy seguro. argv es mas grande y las direcciones de las variables locales se corren (mas abajo), y capaz que sp se te paso a la siguiente alineacion.