C 缓冲区溢出 - 为什么有恒定数量的字节会引发段错误? (Mac OS 10.8 64 位,clang)

标签 c macos clang buffer-overflow lldb

我在 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/

相关文章:

c - 函数参数是结构体,在调用时为其成员赋值

c++ - 生成 alpha 图片轮廓的算法?

c - 安全地直接写入内存地址

c - 如何从main中的函数读取二维数组

macos - PHP 和 AMQP RabbitMQ 消费者

Django send_mail 导致错误 60,Mac OSX 上的操作超时

php - 无法为 OS X 10.9.5 安装 Sphinx : '"/lib/cpp"fails sanity check'

c++ - 没有记录 clang 编译器选项?

c++ - 如何在字段中存储格式字符串并避免格式非文字警告?

c - 使用链接器命令进行 clang 静态分析