2010-10-26 25 views
5

tengo la siguiente aplicación C:No se pudo encontrar la función ataques contra la pila usando GDB

#include <stdio.h> 

void smash() 
{ 
    int i; 
    char buffer[16]; 
    for(i = 0; i < 17; i++) // <-- exceeds the limit of the buffer 
    { 
     buffer[i] = i; 
    } 
} 

int main() 
{ 
    printf("Starting\n"); 
    smash(); 
    return 0; 
} 

I-compilado Cruz utilizando la siguiente versión de gcc:

armv5l-linux-gnueabi-gcc -v 
Using built-in specs. 
Target: armv5l-linux-gnueabi 
Configured with: /home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/gcc-4.4.1/gcc-4.4.1/configure --target=armv5l-linux-gnueabi --host=i486-linux-gnu --build=i486-linux-gnu --prefix=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/toolchain --with-sysroot=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/toolchain --with-headers=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/toolchain/include --enable-languages=c,c++ --with-gmp=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/gmp-5.0.0/gmp-host-install --with-mpfr=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/mpfr-2.4.2/mpfr-host-install --disable-nls --disable-libgcj --disable-libmudflap --disable-libssp --disable-libgomp --enable-checking=release --with-system-zlib --with-arch=armv5t --with-gnu-as --with-gnu-ld --enable-shared --enable-symvers=gnu --enable-__cxa_atexit --disable-nls --without-fp --enable-threads 
Thread model: posix 
gcc version 4.4.1 (GCC) 

invoca así:

armv5l-linux-gnueabi-gcc -ggdb3 -fstack-protector-all -O0 test.c 

Cuando se ejecuta en el objetivo, genera:

Starting 
*** stack smashing detected ***: ./a.out terminated 
Aborted (core dumped) 

cargo el volcado de memoria que resulta en GDB produciendo el siguiente traza:

GNU gdb (GDB) 7.0.1 
Copyright (C) 2009 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "--host=i486-linux-gnu --target=armv5l-linux-gnueabi". 
For bug reporting instructions, please see: 
<http://www.gnu.org/software/gdb/bugs/>... 
Reading symbols from /home/andersn/workspace/stacktest/a.out...done. 
Reading symbols from /home/andersn/workspace/stacktest/linux/toolchain/lib/libc.so.6...done. 
Loaded symbols for /home/andersn/workspace/stacktest/linux/toolchain/lib/libc.so.6 
Reading symbols from /home/andersn/workspace/stacktest/linux/toolchain/lib/ld-linux.so.3...done. 
Loaded symbols for /home/andersn/workspace/stacktest/linux/toolchain/lib/ld-linux.so.3 
Reading symbols from /home/andersn/workspace/stacktest/linux/toolchain /lib/libgcc_s.so.1...done. 
Loaded symbols for /home/andersn/workspace/stacktest/linux/toolchain/lib/libgcc_s.so.1 
Core was generated by `./a.out'. 
Program terminated with signal 6, Aborted. 
#0 0x40052d4c in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67 
67 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory. 
    in ../nptl/sysdeps/unix/sysv/linux/raise.c 
(gdb) bt 
#0 0x40052d4c in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67 
#1 0x40054244 in *__GI_abort() at abort.c:92 
#2 0x40054244 in *__GI_abort() at abort.c:92 
#3 0x40054244 in *__GI_abort() at abort.c:92 
#4 0x40054244 in *__GI_abort() at abort.c:92 
#5 0x40054244 in *__GI_abort() at abort.c:92 
#6 0x40054244 in *__GI_abort() at abort.c:92 
... and so on ... 

Ahora, la pregunta: estoy totalmente incapaz de encontrar la función que ha causado la pila rompiendo desde BGF a pesar la función smash() no sobrescribe ningún dato estructural de la pila, solo el protector de pila en sí. ¿Que debería hacer?

+1

Creo que su "y demás" pueden haber omitido alguna información importante. es __GI_abort realmente el final de la pila? – SoapBox

+0

Intenté continuar con la salida de GDB y alcancé el número 11087 antes de darme por vencido ... Todos los cuadros iguales. – anorm

+0

Está corrompiendo explícitamente la pila; no espere que el archivo central tenga marcos de llamada perfectamente encadenados :) –

Respuesta

8

El problema es que la versión de GCC que compiló su libc.so.6 objetivo tiene errores y no emitió los descriptores de desenrollado correctos para __GI_raise. Con las descripciones de desenrollado incorrectas, GDB entra en un bucle mientras desenrolla la pila.

Puede examinar los descriptores relajarse con

readelf -wf /home/andersn/workspace/stacktest/linux/toolchain/lib/libc.so.6 

espero que obtendrá mismo resultado exacto en el GDB de cualquier programa de llamada de aborto, por ejemplo,

#include <stdlib.h> 
void foo() { abort(); } 
int main() { foo(); return 0; } 

Por desgracia, no hay mucho que se pueda hacer, aparte de tratar de construir una versión más reciente de GCC, y luego la reconstrucción de todo el "mundo" con él.

+0

Sí, eso debería ser, en pocas palabras. Sin embargo, puede ser suficiente para reconstruir libc.so con un nuevo compilador. – user434507

+0

Reconstruir solo libc.so.6 puede no ser suficiente: después de todo, no hay garantía de que foo() obtenga el descriptor de desenrollado correcto con el "antiguo" GCC. –

0

¿Ha intentado resolver este reclamo: "../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory." para ver si realmente puede ayudar a resolver los símbolos?

+0

No, no lo he hecho, pero a GDB no le falta información de símbolos en la ubicación determinada, solo el archivo de código fuente para la lista. Sin embargo, intentaré su sugerencia ... Gracias – anorm

+0

Bueno, probé esto sin suerte. GDB mostró la línea fuente en raise.c pero la traza inversa todavía está corrupta. – anorm

2

No es el caso que GDB siempre pueda resolver lo que sucedió con una pila rota incluso con -fstack-protector-all (e incluso con -Wstack-protector para advertir acerca de las funciones con marcos que no estaban protegidos). Example.

En estos casos, el protector de pila ha hecho su trabajo (eliminó una aplicación que funciona mal) pero no le ha hecho ningún favor al depurador. (El ejemplo clásico es un smash de pila donde ha ocurrido una escritura con un paso lo suficientemente grande como para saltar al canario.) En estos casos puede ser necesario realizar una búsqueda binaria a través del código a través de puntos de corte para reducir qué región del código está causando el éxito, luego un solo paso a través del éxito para ver cómo sucedió.

Cuestiones relacionadas