Deshabilitando protecciones contra Buffer Overflows

Iniciado por c1c4tr1z, 14 Enero 2009, 01:28 AM

0 Miembros y 1 Visitante están viendo este tema.

NewLog

#10
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

Vuelvo a editar: Aquí tenéis el artículo de phrack. Must read!
Artículo

Además he encontrado otro pdf muy bueno donde se explica la teoria de las protecciones y como saltarselas:
Artículo

c1c4tr1z

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

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.



AlbertoBSD

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 ?
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

c1c4tr1z

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 (bash) [Seleccionar]

c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ldd vulnerable |grep linux-gate
linux-gate.so.1 =>  (0xb7fe3000)
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 (bash) [Seleccionar]
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ objdump -T vulnerable

vulnerable:     file format elf32-i386

DYNAMIC SYMBOL TABLE:
00000000  w   D  *UND* 00000000              __gmon_start__
00000000      DF *UND* 000001b2  GLIBC_2.0   __libc_start_main
00000000      DF *UND* 00000024  GLIBC_2.0   strcpy
00000000      DF *UND* 00000020  GLIBC_2.4   __stack_chk_fail
080484ec g    DO .rodata 00000004  Base        _IO_stdin_used


c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ nm vulnerable |grep U
         U __libc_start_main@@GLIBC_2.0
         U __stack_chk_fail@@GLIBC_2.4
         U strcpy@@GLIBC_2.0
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ objdump -d vulnerable --section=.plt |tail -n 4
08048330 <__stack_chk_fail@plt>:
8048330: ff 25 f4 95 04 08    jmp    *0x80495f4
8048336: 68 18 00 00 00        push   $0x18
804833b: e9 b0 ff ff ff        jmp    80482f0 <_init+0x30>
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 (bash) [Seleccionar]
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gdb -q vulnerable
(gdb) r $(perl -e 'print "A"x40')
Starting program: /home/c1c4tr1z/Escritorio/vulnerable $(perl -e 'print "A"x40')
*** stack smashing detected ***: /home/c1c4tr1z/Escritorio/vulnerable terminated

[...]

Program received signal SIGABRT, Aborted.
0xb7fe3410 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fe3410 in __kernel_vsyscall ()
#1  0xb7ea7085 in raise () from /lib/tls/i686/cmov/libc.so.6
#2  0xb7ea8a01 in abort () from /lib/tls/i686/cmov/libc.so.6
#3  0xb7edfb7c in ?? () from /lib/tls/i686/cmov/libc.so.6
#4  0xb7f69138 in __fortify_fail () from /lib/tls/i686/cmov/libc.so.6
#5  0xb7f690f0 in __stack_chk_fail () from /lib/tls/i686/cmov/libc.so.6
#6  0x080483fe in overflow ()
#7  0x08048400 in overflow ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) disas 0xb7fe3410
Dump of assembler code for function __kernel_vsyscall:
0xb7fe3400 <__kernel_vsyscall+0>: push   %ecx
0xb7fe3401 <__kernel_vsyscall+1>: push   %edx
0xb7fe3402 <__kernel_vsyscall+2>: push   %ebp
0xb7fe3403 <__kernel_vsyscall+3>: mov    %esp,%ebp
0xb7fe3405 <__kernel_vsyscall+5>: sysenter
0xb7fe3407 <__kernel_vsyscall+7>: nop   
0xb7fe3408 <__kernel_vsyscall+8>: nop   
0xb7fe3409 <__kernel_vsyscall+9>: nop   
0xb7fe340a <__kernel_vsyscall+10>: nop   
0xb7fe340b <__kernel_vsyscall+11>: nop   
0xb7fe340c <__kernel_vsyscall+12>: nop   
0xb7fe340d <__kernel_vsyscall+13>: nop   
0xb7fe340e <__kernel_vsyscall+14>: jmp    0xb7fe3403 <__kernel_vsyscall+3>
0xb7fe3410 <__kernel_vsyscall+16>: pop    %ebp
0xb7fe3411 <__kernel_vsyscall+17>: pop    %edx
0xb7fe3412 <__kernel_vsyscall+18>: pop    %ecx
0xb7fe3413 <__kernel_vsyscall+19>: ret   
End of assembler dump.
(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!




rmdma()

(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]


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

(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)

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

(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..

Ivanchuk

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.
Sólo quien practica lo absurdo puede lograr lo imposible.

Join us @ http://foro.h-sec.org