2

我在 C 中试验缓冲区溢出,发现了一个有趣的怪癖:

对于任何给定的数组大小,似乎有一定数量的溢出字节可以在 SIGABRT 崩溃之前写入内存。例如,在下面的代码中,10 字节数组可以溢出到 26 字节,然后在 27 处崩溃。类似地,一个 20char秒的数组可以char在 41 号中止之前溢出到 40 秒。

谁能解释这是为什么?此外,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
4

1 回答 1

3

这是由于macos 上的堆栈对齐。

这不是什么大新闻,如果你用谷歌搜索过,你会找到答案:

为什么 Mac ABI 要求 x86-32 的 16 字节堆栈对齐?


很高兴看到您实际上可以在小于 16 字节的块中写入堆栈而没有副作用。

如果您多次利用它,您可能会进入一种可以放下所有恶意代码的状态,并且您可以在堆栈上跳转执行它。

于 2013-02-23T08:37:14.910 回答