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:
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:
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:
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!