No puedo sobrescribir EIP (Linux)

Iniciado por zhynar_X, 26 Diciembre 2007, 16:42 PM

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

M3st4ng

Hola,

Aún no he conseguido que se ejecute la dirección del RET sobreescrita. No sé si será por ele compilador gcc, he estado dando vueltas por google y la verdad no sé por dónde pueden ir los tiros.
Voy a intentar exponer el problema  a ver si a alguien le ha pasado.
Este es el código vulnerable:


#include <stdio.h>
#include <string.h>

void copiar(char* b)
{
        char buffer[16];
        strcpy(buffer,b);
}


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

}


La variable "buffer" es de 16bytes.
Ejecuto el gdb y pongo un break en la funcion "copirar"

(gdb) list
4 void copiar(char* b)
5 {
6 char buffer[16];
7 strcpy(buffer,b);
8 }
9
10
11 int main(int argc, char** argv)
12 {
13 copiar(argv[1]);
(gdb) break 6
(gdb) run $(perl -e 'print "A"x32')


Antes de ejecutar el strcpy miro la pila:
La direccion de la variable "buffer" en la funcion copiar es 0xbffff67c

(gdb) print &buffer
$1 = (char (*)[16]) 0xbffff67c


La direccíon de retorno a el main es 0x080483f4:

(gdb) disass main
Dump of assembler code for function main:
   0x080483de <+0>: push   %ebp
   0x080483df <+1>: mov    %esp,%ebp
   0x080483e1 <+3>: sub    $0x4,%esp
   0x080483e4 <+6>: mov    0xc(%ebp),%eax
   0x080483e7 <+9>: add    $0x4,%eax
   0x080483ea <+12>: mov    (%eax),%eax
   0x080483ec <+14>: mov    %eax,(%esp)
   0x080483ef <+17>: call   0x80483c4 <copiar>
   0x080483f4 <+22>: mov    $0x0,%eax
   0x080483f9 <+27>: leave 
   0x080483fa <+28>: ret   
End of assembler dump.


Ahora observo la pila en el breakpoint

esp            0xbffff674 0xbffff674
ebp            0xbffff68c 0xbffff68c


En la direccion 0xbffff67c comienza la varible "buffer" y en la direccion 0xbffff690 el RET


(gdb) x/50x $esp
0xbffff674: 0x00287ff4 0x08048410 0xbffff698 0x0015e985
0xbffff684: 0x0011eac0 0x0804841b 0xbffff698  0x080483f4
0xbffff694: 0xbffff89a          0xbffff718 0x00145ce7 0x00000002
0xbffff6a4: 0xbffff744  0xbffff750 0xb7fff848 0xbffff7b8
0xbffff6b4: 0xffffffff        0x0012cff4 0x0804822c 0x00000001
0xbffff6c4: 0xbffff700 0x0011e096 0x0012dad0 0xb7fffb28
0xbffff6d4: 0x00287ff4 0x00000000 0x00000000 0xbffff718
0xbffff6e4: 0x084b7a07 0xdf1f6378 0x00000000 0x00000000
0xbffff6f4: 0x00000000 0x00000002 0x08048310 0x00000000
0xbffff704: 0x00123cf0 0x00145c0b 0x0012cff4 0x00000002
0xbffff714: 0x08048310 0x00000000 0x08048331 0x080483de
0xbffff724: 0x00000002 0xbffff744 0x08048410 0x08048400
0xbffff734: 0x0011eac0 0xbffff73c


Sigo ejecutando:


(gdb) next
8 }
(gdb) x/50x $esp
0xbffff674: 0xbffff67c 0xbffff89a         0x41414141 0x41414141
0xbffff684: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff694: 0x41414141 0x41414141 0x00145c00 0x00000002
0xbffff6a4: 0xbffff744  0xbffff750         0xb7fff848 0xbffff7b8
0xbffff6b4: 0xffffffff        0x0012cff4 0x0804822c 0x00000001
0xbffff6c4: 0xbffff700 0x0011e096 0x0012dad0 0xb7fffb28
0xbffff6d4: 0x00287ff4 0x00000000 0x00000000 0xbffff718
0xbffff6e4: 0x084b7a07 0xdf1f6378 0x00000000 0x00000000
0xbffff6f4: 0x00000000 0x00000002 0x08048310 0x00000000
0xbffff704: 0x00123cf0 0x00145c0b 0x0012cff4 0x00000002
0xbffff714: 0x08048310 0x00000000 0x08048331 0x080483de
0xbffff724: 0x00000002 0xbffff744 0x08048410 0x08048400
0xbffff734: 0x0011eac0 0xbffff73c


Como vemos el RET (direccion 0xbffff690) se ha sobreescrito. Y como me pasaba en el comentario anterioir despues de escribir todas las "A", en byte siguiente lo sobre con ceros (ha pasado de 0x00145ce7 a 0x00145c00).

En el siguiente paso el programa "casca" pero sin que el EIP ejecute el RET:

Program received signal SIGSEGV, Segmentation fault.
0x080483dd in copiar (b=No se puede acceder a la memoria en la dirección 0x41414149
) at ejemplo.c:8
8 }
(gdb) info r
eax            0xbffff67c -1073744260
ecx            0x0 0
edx            0x21 33
ebx            0x287ff4 2654196
esp            0xbffff690 0xbffff690
ebp            0x41414141 0x41414141
esi            0x0 0
edi            0x0 0
eip            0x80483dd 0x80483dd <copiar+25>
eflags         0x10246 [ PF ZF IF RF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51


La dirección donde se queda es el RET de la funcion copiar: eip            0x80483dd   0x80483dd <copiar+25>



(gdb) disass copiar
Dump of assembler code for function copiar:
   0x080483c4 <+0>: push   %ebp
   0x080483c5 <+1>: mov    %esp,%ebp
   0x080483c7 <+3>: sub    $0x18,%esp
   0x080483ca <+6>: mov    0x8(%ebp),%eax
   0x080483cd <+9>: mov    %eax,0x4(%esp)
   0x080483d1 <+13>: lea    -0x10(%ebp),%eax
   0x080483d4 <+16>: mov    %eax,(%esp)
   0x080483d7 <+19>: call   0x80482f4 <strcpy@plt>
   0x080483dc <+24>: leave 
=> 0x080483dd <+25>: ret   
End of assembler dump.


Me podeis echar una mano.?? Gracias

braulio--

Me imagino que habrás deshabilitado las protecciones contra buffer overflow no?

M3st4ng

Si, si, esta compilado asii:

gcc -g -fno-stack-protector -mpreferred-stack-boundary=2 -ggdb ejemplo.c

Graicas

braulio--

A mí me paso esto durante un tiempo y también me parecía inexplicable. Prueba con un buffer mayor y pásale un argumento de aproximadamente el doble del buffer.

M3st4ng

Hola,

Gracias por contestar. He probado con un buffer de 500 y 1000 "A" como parámetro y tampoco me ha funcionado.
Además, he probado a compilar el gcc-3.4.6 y tampoco funciona. No sé es una cosa rara rara.
Os dejo el traceo del gdb


(gdb) print &buffer
$1 = (char (*)[16]) 0xbffff2ac
(gdb) s
8 }
(gdb) x/100x $esp
0xbffff2a4: 0xbffff2ac 0xbffff4be 0x41414141 0x41414141
0xbffff2b4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff2c4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff2d4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff2e4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff2f4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff304: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff314: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff324: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff334: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff344: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff354: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff364: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff374: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff384: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff394: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3a4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3b4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3c4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3d4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3e4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff3f4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff404: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff414: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffff424: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x0804837d in copiar (b=No se puede acceder a la memoria en la dirección 0x41414149
) at ejemplo.c:8
8 }
(gdb) info r
eax            0xbffff2ac -1073745236
ecx            0x0 0
edx            0x3e9 1001
ebx            0x287ff4 2654196
esp            0xbffff2c0 0xbffff2c0
ebp            0x41414141 0x41414141
esi            0x0 0
edi            0x0 0
eip            0x804837d 0x804837d <copiar+25>
eflags         0x10246 [ PF ZF IF RF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51
(gdb) s

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb) info r
El programa no tiene registros ahora.
(gdb) info s
No stack.


Lo que me parece raro es el mensaje:

Program received signal SIGSEGV, Segmentation fault.
0x0804837d in copiar (b=No se puede acceder a la memoria en la dirección 0x41414149

Gracias por la ayuda.

braulio--

Pues ya ni idea, tendré que desempolvar el hacking a nivel binario y probaré mañana a ver. De todas formas me parece muy extraño que la dirección que te dé sea "0x41414149".

Me parece que lo del null-byte no tiene nada que ver en absoluto.

AlbertoBSD

Podrias poner el disas main de tu binario porfa.

Saludos!!!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

M3st4ng

Y sin porfa lo pongo....



(gdb) list
4 void copiar(char* b)
5 {
6 char buffer[500];
7 strcpy(buffer,b);
8 }
9
10
11 int main(int argc, char** argv)
12 {
13 copiar(argv[1]);
(gdb)
14     return 0;
15
16 }
(gdb) disass main
Dump of assembler code for function main:
   0x08048384 <+0>: push   %ebp
   0x08048385 <+1>: mov    %esp,%ebp
   0x08048387 <+3>: sub    $0x4,%esp
   0x0804838a <+6>: mov    0xc(%ebp),%eax
   0x0804838d <+9>: add    $0x4,%eax
   0x08048390 <+12>: mov    (%eax),%eax
   0x08048392 <+14>: mov    %eax,(%esp)
   0x08048395 <+17>: call   0x8048364 <copiar>
   0x0804839a <+22>: mov    $0x0,%eax
   0x0804839f <+27>: leave 
   0x080483a0 <+28>: ret   
End of assembler dump.
(gdb) disass copiar
Dump of assembler code for function copiar:
   0x08048364 <+0>: push   %ebp
   0x08048365 <+1>: mov    %esp,%ebp
   0x08048367 <+3>: sub    $0x208,%esp
   0x0804836d <+9>: mov    0x8(%ebp),%eax
   0x08048370 <+12>: mov    %eax,0x4(%esp)
   0x08048374 <+16>: lea    -0x200(%ebp),%eax
   0x0804837a <+22>: mov    %eax,(%esp)
   0x0804837d <+25>: call   0x80482b8 <strcpy@plt>
   0x08048382 <+30>: leave 
   0x08048383 <+31>: ret   
End of assembler dump


La dirección  0x41414149 corresponde a la de la variable "b":

Program received signal SIGSEGV, Segmentation fault.
0x08048383 in copiar (b=No se puede acceder a la memoria en la dirección 0x41414149
) at ejemplo.c:8
8 }
(gdb) print &b
$2 = (char **) 0x41414149


Gracias por la ayuda!

M3st4ng

Hola!

Lo que no acabo de entender es por qué  cuando se escribe la varible "b" de la funcion copiar da este casque, es una valor que está debajo del RET en la pila... ¿puede algo que ver la instrucción "ret" del copiar?
Otra cosa que no acabo de ver es lo del byte-null, si pudiera evitar que se introdujera ese byte null no me llegaria a fallar.... ¿siempre que se introcen carácteres en la pila se pone este valor al final de la cadena?

Gracias!

M3st4ng

Hola!

Ya he conseguido que se intente ejecutar el RET sobreescrito. Por lo visto gcc activa un flag para desactivar la ejecución en la pila. Este mecanismo se desactiva usando en parámetro "-z execstack" a la hora de compilar.

Salu2!