如何找到缓冲区溢出和内存损坏的地方?

vit*_*.ch 6 c valgrind buffer-overflow memory-corruption

valgrind找不到任何有用的东西.我糊涂了.

Symptomes:

  1. 我的数据被malloc()调用破坏了
  2. 我的函数的返回地址被错误的替换

PS:代码不会出现段错误

目前我通过mmap()+ 替换所有malloc()取得了一些进展mprotect()

sar*_*old 7

您可能正在覆盖堆栈,或者您可能正在覆盖堆.

您可以尝试将标志添加-fstack-protector-all到GCC命令行选项,以要求在程序中构建一些堆栈粉碎报告.这可能会导致它更快失败.

另一种可能性是查看dmesg输出中报告的地址,看看是否无法追踪被破坏的功能/内存:

[68303.941351] broken[13301]: segfault at 7f0061616161 ip 000000000040053d sp 00007fffd4ad3980 error 4 in broken[400000+1000]
Run Code Online (Sandbox Code Playgroud)

readelf -s 将转储符号表,我们可以查找触发问题的函数:

$ readelf -s broken | grep 4005
40: 00000000004005e0     0 FUNC    LOCAL  DEFAULT   13 __do_global_ctors_aux
47: 0000000000400540     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini
57: 0000000000400550   137 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
63: 0000000000400515    42 FUNC    GLOBAL DEFAULT   13 main
Run Code Online (Sandbox Code Playgroud)

main例程是在使用坏指针时执行的例程:

#include <string.h>

void f(const char *s) {
    char buf[4];
    strcpy(buf, s);
    return;
}

int main(int argc, char* argv[]) {
    f("aaaa");
    f("aaaaaaaaaaaaaaaaaaaa");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

main尝试返回C库退出时,它使用存储在堆栈帧中的错误指针.所以看一下所调用的函数main,并且(在这个简单的情况下它很容易)f显然是在整个堆栈框架上乱写的bugger.

如果你要覆盖堆,那么也许你可以试试电围栏.缺点是非常陡峭(大量内存使用),但它可能正是你需要找到问题.


Man*_*edi 2

  1. 修复所有悬空指针、所有缓冲区溢出
  2. 仅在真正需要的地方使用指针

请参阅以下链接::哪些 C/C++ 工具可以检查缓冲区溢出?