我有一些关于Stack Guard和SSP保护的问题。第一个问题是关于Stack Guard及其三种类型的金丝雀,如果我是正确的 - 终结者,随机和随机XOR。
1)我想知道,如何在x86 Linux系统上禁用Stack Guard?在我读到的某个地方,使用此命令可以实现,使用gcc' -disable-stackguard-randomization '进行编译时,它与此命令相同对于启用' -enable-stackguard-randomization ',两者都不起作用。如果需要,我的gcc版本是4.8.2。
2)关于Stack guard的下一个问题,当我能够启用/禁用它时,我该如何设置,我想使用哪种类型的金丝雀?我读到的,默认情况下使用终结器金丝雀,随机我必须用' -enable-stackguard-randomization '编译,但随机XOR怎么样? (或使用null 0x00000000)
3)关于SSP(ProPolice),我知道,对于随机的金丝雀,我必须使用' fstack-protector-all ' ,但终结者怎么样,默认情况下与Stack Guard相同?
4)最后一个,如果有人,可以告诉我,我可以在内存中找到随机金丝雀。例如,我有这个场景 - 编译的C程序,如' gcc -g example.c -o example -fstack-protector-all ',所以使用随机的canaries。让我们说,我可以在每次执行后获得金丝雀的地址。所以期待,我有: Canary = 0x1ae3f900 。从不同的论文中,我得到一些信息,该金丝雀位于.bss段。所以我使用readelf获取.bss段的地址:' readelf -a ./example | grep bss '。它是080456c9。在gdb中我设置了一些断点,以获取金丝雀的地址,但是当我检查.bss地址x / 20x 0x080456c9时,我看到的只是0x00000000地址,但是 金丝雀无处可去。另外,我检查了 __ stack_chk_fail ,如果没有,但结果相同,我无法在那里看到它。我从PLT / GOT获得了stack_chk_fail的地址。
提前感谢您的回答和时间。
答案 0 :(得分:2)
Stack Smashing Protection(SSP)是对StackGuard的改进。 SSP最初是在gcc 4.1中实现的。
我想知道,如何在x86 Linux系统上禁用Stack Guard?
使用-fno-stack-protector
禁用用户界面SSP。
--disable-stackguard-randomization
和--enable-stackguard-randomization
是glibc源代码的构建选项。
何时可以启用/禁用它,如何设置,哪种类型的 我想用金丝雀吗?
据我所知,这在gcc中是不可配置的。从glibc 2.10开始,堆栈Canary是在名为_dl_setup_stack_chk_guard
的函数中生成的。这是its code的一部分:
if (dl_random == NULL)
{
ret.bytes[sizeof (ret) - 1] = 255;
ret.bytes[sizeof (ret) - 2] = '\n';
}
else
{
memcpy (ret.bytes, dl_random, sizeof (ret));
ret.num &= ~(uintptr_t) 0xff;
}
dl_random
保留AT_RANDOM
的辅助向量入口的地址,该地址是内核在创建进程时初始化的16字节随机值。如果您在未初始化AT_RANDOM
的内核或仿真器上运行,则检查dl_random == NULL
为true,并且使用的canary是终止符值,其第一个和第二个最高有效字节被初始化为255和\n
。所有其他字节均为零。通常AT_RANDOM
由内核初始化,因此AT_RANDOM
的至少7个有效字节被复制。金丝雀的最后一个字节设置为零。
因此,如果要使用特定方法生成金丝雀,则可以更改此代码并构建自己的glibc。
作为替代方法,@ PeterCordes在注释中建议将金丝雀值写入%%fs:0x28
函数顶部的内存位置main
(请参见下面的代码),并恢复运行时-从main
返回之前生成的金丝雀。
关于SSP(ProPolice),我知道,对于随机金丝雀,我必须编译 与“ fstack-protector-all”一起使用,但是终止符与 默认情况下在Stack Guard中?
-fstack-protector
选项的所有变体都使用SSP。这些不会影响金丝雀的生成方式。
最后一个,如果你们中的任何一个可以告诉我,在哪里我可以找到随机的 金丝雀在记忆中。
金丝雀是在流程启动的早期动态生成的;您不能使用readelf
来获得金丝雀。根据{{3}}的文章,在为i386进行编译时,可以使用以下代码来获取canary:
int read_canary()
{
int val = 0;
__asm__("movl %%gs:0x14, %0;"
: "=r"(val)
:
:);
return val;
}
,对于x86_64:
long read_canary()
{
long val = 0;
__asm__("movq %%fs:0x28, %0;"
: "=r"(val)
:
:);
return val;
}