2010-10-26 98 views
5

找到堆栈溢出功能,我有以下的C应用程序:无法使用GDB

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) 

调用像这样:

#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; 
} 

我用gcc以下版本的交叉编译

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

当在目标上运行时,它输出:

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

我加载在gdb所产生的核心转储,得到以下回溯:

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

现在的问题: 我完全无法找到导致堆栈GDB砸即使函数smash()函数不会覆盖堆栈的任何结构数据,只会覆盖堆栈保护器本身。我该怎么办?

+1

我认为你的“等”可能已经省略了一些重要的信息。是__GI_abort真的是堆栈的底部? – SoapBox 2010-10-26 14:58:59

+0

我试着继续GDB输出,并在我放弃之前达到了#11087 ....所有相同的帧。 – anorm 2010-10-26 15:01:46

+0

你明确地破坏了堆栈 - 不要指望核心文件有整齐的链接调用框架然后:) – 2010-10-26 15:25:00

回答

8

问题是,编译你的目标libc.so.6的GCC版本有问题,并且没有为__GI_raise发出正确的展开描述符。使用不正确的展开描述符时,GDB会在展开堆栈时进入循环。

您可以

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

检查开卷描述我想你会在GDB从任何程序调用中断,例如得到完全相同的结果

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

不幸的是,没有比试图建立GCC的新版本,然后重建整个“世界”与它什么可以做,其他。

+0

是的,应该是这样,简而言之。但是,用新编译器重新编译libc.so可能就足够了。 – user434507 2010-10-27 03:07:44

+0

刚刚重建libc.so.6可能还不够:毕竟,不能保证foo()会得到正确的“旧”GCC展开描述符。 – 2010-10-27 03:55:18

0

您是否尝试解决此投诉:“../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.”以查看实际能否解决符号会有所帮助?

+0

不,我没有,但GDB不遗漏给定位置的符号信息,只有列表的源代码文件。然而,我会尝试你的建议...谢谢 – anorm 2010-10-26 15:00:19

+0

嗯,我试过这个没有运气。 GDB在raise.c中显示了源代码行,但回溯仍然是错误的。 – anorm 2010-10-26 15:06:23

2

即使使用-fstack-protector-all(甚至使用-Wstack-protector来警告未受保护的帧的函数),GDB也不能总是发现被捣毁的堆栈发生了什么。 Example

在这些情况下,堆栈保护器已经完成了它的工作(杀死了一个行为异常的应用程序),但还没有完成调试器的任何好处。 (典型的例子是堆栈粉碎,其中写入发生的次数足以跳过金丝雀。)在这些情况下,可能有必要通过断点对代码进行二进制搜索以缩小代码的哪个区域造成的结果粉碎,然后通过粉碎单步骤,看看它是如何发生的。