我在 C 语言中尝试缓冲区溢出,发现了一个有趣的怪癖:
对于任何给定的数组大小,似乎有一定数量的溢出字节可以在 SIGABRT 崩溃之前写入内存。例如,在下面的代码中,10 字节数组可以溢出到 26 字节,然后在 27 处崩溃。同样,20 个 char 的数组可以溢出到 40 个 char直到 41 日中止。
谁能解释一下这是为什么吗?另外,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 %zu\n", sizeof(aString[0]));
printf("The size of one letter sizeof( aLetter ) is %zu\n", sizeof(aLetter));
// Overflow the aString array of chars
// lldb claims aString is initialized with values \0 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
操作系统上的堆栈对齐造成的。
这不是什么大新闻,如果你用谷歌搜索一下,你会找到答案:
Why does the Mac ABI require 16-byte stack alignment for x86-32?
很高兴看到您实际上可以以小于 16 字节的 block 写入堆栈,而不会产生任何副作用。
如果您多次利用它,您可能会进入一种状态,所有恶意代码都可以被放下,并且您可以在堆栈上跳转执行它。
关于C 缓冲区溢出 - 为什么有恒定数量的字节会引发段错误? (Mac OS 10.8 64 位,clang),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15038582/