在没有标准库的情况下实现自定义堆栈金丝雀处理

Implement custom stack canary handling without the standard library

我正在尝试在没有标准库的情况下手动实现堆栈金丝雀。因此,我在 OSDev wiki 的 this guide 的帮助下创建了一个简单的 PoC。文章建议一个简单的实现必须提供 __stack_chk_guard 变量和 __stack_chk_fail() 处理程序。

然而,当我使用 GCC 编译并提供 -fstack-protector-all 标志时,可执行文件根本不包含任何堆栈金丝雀检查。我缺少什么让 GCC 包含堆栈金丝雀逻辑?

gcc -Wall -nostdlib -nodefaultlibs -fstack-protector-all -g -m64 -o poc main.c customlib.h

main.c

#include "customlib.h"

#define STACK_CHK_GUARD (0xDEADBEEFFFFFFFF & ~0xFF)
uintptr_t __stack_chk_guard = STACK_CHK_GUARD;

__attribute__((noreturn)) void __stack_chk_fail()
{
    __exit(123);
    while(1);
}

int main()
{
    __attribute__((unused)) char buffer[16];

    for (size_t index = 0; index < 32; index++)
    {
        buffer[index] = 'A';
    }

    return 0;
}

customlib.h

这段代码大部分是无关紧要的,只是程序可以正确编译和链接所必需的。

typedef unsigned long int size_t;
typedef unsigned long int uintptr_t;

size_t __syscall(size_t arg1, size_t arg2, size_t arg3, size_t arg4, size_t arg5, size_t arg6)
{
    asm("int [=12=]x80\n"
        : "=a"(arg1)
        : "a"(arg1), "b"(arg2), "c"(arg3), "d"(arg4), "S"(arg5), "D"(arg6));
    return arg1;
}

void _exit(int exit_code)
{
    __syscall(1, exit_code, 0, 0, 0, 0);
    while(1);
}

extern int main();

void _start()
{
    main();
    _exit(0);
}

GCC 版本 10.2.0,Linux 5.10.36-2-MANJARO GNU/Linux

它看起来像 Arch gcc 包(Manjaro 包基于它)is turning off -fstack-protector when building without the standard library (Done for Arch bug 64270)。

这种行为显然也存在于 Gentoo 中。

我没试过这个,但我相信你应该能够使用 gcc -dumpspecs 将 GCC 规范转储到一个文件中,只保留部分 *cc1_options,删除 %{nostdlib|nodefaultlibs|ffreestanding:-fno-stack-protector}从它,并通过 gcc -specs=your_spec_file.

将其传递给 gcc

或者,您可以在删除此补丁的情况下重建 gcc 包。