29

在 OS X 10.9 (Mavericks) 上,如果您通过调用和传递 undocumented 属性来启动进程,则可以禁用单个进程的地址空间布局随机化。像这样:posix_spawn()0x100

extern char **environ;
pid_t pid;
posix_spawnattr_t attr;

posix_spawnattr_init(&attr);
posix_spawnattr_setflags(&attr, 0x100);
posix_spawn(&pid, argv[0], NULL, &attr, argv, environ);

(这是从Apple 的 GDB 来源逆向工程的。)

像这样的未记录功能的问题在于它们往往会在没有通知的情况下消失。根据this Stack Overflow answer the dynamic linker dyldused to identify the environment variable DYLD_NO_PIE,但这在 10.9 中不起作用;同样,静态链接器显然曾经采用过一个--no-pie选项,但现在情况已不再如此。

那么有记录的方法来禁用 ASLR 吗?

(我需要禁用 ASLR 的原因是为了在测试和调试时确保行为取决于对象地址的代码的可重复性,例如基于地址的哈希表和基于 BIBOP 的内存管理器。)

4

1 回答 1

46

实际上,仍然有一个-no_pie链接器标志,但您可能认为它实际上被称为--no-pie.

让我们有一个小测试程序:

#include <stdio.h>

const char *test = "test";

int main() {
  printf("%p\n", (void*)test);
  return 0;
}

并首先像往常一样编译:

cc -o test-pie test-pie.c

并检查标志

$ otool -hv test-pie
test-pie:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL LIB64     EXECUTE    16       1376   NOUNDEFS DYLDLINK TWOLEVEL PIE

好吧,里面有一个PIEflag,让我们验证一下

$ for x in $(seq 1 5); do echo -n "$x "; ./test-pie; done
1 0x10a447f96
2 0x10e3cbf96
3 0x1005daf96
4 0x10df50f96
5 0x104e63f96

这看起来很随意。

现在,让我们告诉链接器我们不想PIE使用-Wl,-no_pie

cc -o test-nopie test-pie.c -Wl,-no_pie

果然PIEflag不见了:

$ otool -hv test-nopie
test-pie:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL LIB64     EXECUTE    16       1376   NOUNDEFS DYLDLINK TWOLEVEL

并测试:

$ for x in $(seq 1 5); do echo -n "$x "; ./test-nopie; done
1 0x100000f96
2 0x100000f96
3 0x100000f96
4 0x100000f96
5 0x100000f96

所以我们让链接器不加PIEflag,我的小牛系统好像还是遵守的。

FWIW,该PIE标志被定义并记录/usr/include/mach-o/loader.hMH_PIE.

互联网上有很多工具可以从现有二进制文件中清除 PIE 标志,例如http://src.chromium.org/svn/trunk/src/build/mac/change_mach_o_flags.py

虽然我无法为您提供在PIE没有 ASLR 的情况下启动 -flaged 二进制文件的记录方法,但由于您想测试代码(可能是您自己的代码),只需将您的测试程序与测试二进制文件-no_pie中的标志链接或删除PIE就足够了?

于 2014-06-14T12:05:15.320 回答