有没有办法 "overload" 或重新实现 __stack_chk_fail?

Is there a way to "overload" or reimplement __stack_chk_fail?

我想在 gcc 中为我在 x86 linux 上构建的 运行 系统启用堆栈保护功能 linux。

我希望如果它检测到堆栈粉碎,它会调用我自己的函数来处理这种情况,或者它会调用我自己的函数实现 __stack_chk_fail,有没有办法做到这一点?

到目前为止,我尝试取消定义 __stack_chk_fail__stack_chk_guard,然后自己定义它们,但它不起作用,并在尝试利用缓冲区溢出时导致分段错误。 这是我所做的一个例子:

    #undef __stack_chk_guard
    #undef __stack_chk_fail
    uintptr_t __stack_chk_guard = 0xdeadbeef;

    void __stack_chk_fail(void)
    {
        printf("Stack smashing detected");
    }

   void foo(void)
   {
    char buffer[2];
    strcpy(buffer, "hello, I am smashing your stack!");
   }

我也试过使用LD_PRELOAD,但是在粉碎堆栈时导致了分段错误,但它也导致了分段错误。

经过一些研究,我发现我可以使用链接器标志 --wrap 来包装 __stack_chk_fail 并按照我的需要插入我自己的处理。

标志将 __stack_chk_fail 的每次调用更改为 __wrap___stack_chk_fail,将 __real___stack_chk_fail 的每次调用更改为 __stack_chk_fail

如果我愿意,我什至可以跳过调用真正的 __stack_chk_fail

下面是名为 test.c:

的文件中的示例代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void __real___stack_chk_fail(void);

void __wrap___stack_chk_fail(void)
{
    printf("our test");
    __real___stack_chk_fail();
}
void func()
{
    char buffer[2];
    strcpy(buffer, "smashhhhhhhhhhhhhhhh");
}
int main(void)
{
    func();
    return 0;
}

编译执行:

gcc -fstack-protector-strong -c test.c
gcc -Wl,--wrap=__stack_chk_fail test.o 

输出将是 "our test",然后是 __stack_chk_fail

的常规行为

更新:

另一种方法是使用标志 --exclude-libs,libssp 从链接过程中排除 libssp 并实现 __stack_chk_failguard_setup(启动 __stack_chk_guard 值的函数) 靠自己