我在C中尝试缓冲区溢出,发现了一个有趣的怪癖:
对于任何给定的数组大小,在SIGABRT崩溃之前,似乎都有一定数量的溢出字节可以写入内存。例如,在下面的代码中,10字节数组可以溢出到26字节,然后在27处崩溃。类似地,一个由20个char
s组成的数组在第41个中止之前可以溢出到40个char
s。
有人能解释为什么会这样吗?此外,SIGABRT是否与"分段故障"相同(或由其引起)?
Mac OS 10.8-Xcode 4.6,clang和lldb。谢谢
#include <stdio.h>
int main(int argc, const char * argv[])
{
char aString[ 10 ];
char aLetter = 'a';
printf("The size of one array slot sizeof( aString[0] ) is %zun", sizeof(aString[0]));
printf("The size of one letter sizeof( aLetter ) is %zun", sizeof(aLetter));
// Overflow the aString array of chars
// lldb claims aString is initialized with values or NULL at all locations
// Substitute i<27 and this code will crash regularly
for (int i=0; i<26; i++) {
aString[i]= aLetter;
}
return 0;
}
编辑-我在反汇编中完成了它,并在for循环后发现了这种保护:
0x100000f27: movq 226(%rip), %rax ; (void *)0x00007fff793f24b0: __stack_chk_guard
0x100000f2e: movq (%rax), %rax
0x100000f31: movq -8(%rbp), %rcx
0x100000f35: cmpq %rcx, %rax
0x100000f38: jne 0x100000f49 ; main + 121 at main.c:26
.
.
.
0x100000f49: callq 0x100000f4e ; symbol stub for: __stack_chk_fail
这是由于mac
操作系统上的堆栈对齐。
这不是什么大新闻,如果你在谷歌上搜索过,你会发现答案:
为什么Mac ABI需要x86-32的16字节堆栈对齐?
很高兴看到您可以在小于16字节的块中毫无副作用地写入堆栈。
如果你多次利用它,你可能会进入一种状态,所有的恶意代码都可能被搁置,你可能在堆栈上跳转执行它。