在OS X上禁用ASLR的文档方法是什么?

30

在OS X 10.9(Mavericks)上,如果您通过调用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);

这是从苹果公司的GDB源代码中逆向工程出来的。

这类未经记录的特性的问题在于它们往往会毫无预兆地消失。根据这个Stack Overflow回答,动态链接器dyld曾经会查询环境变量DYLD_NO_PIE,但在10.9中已经不再使用;类似地,静态链接器显然曾经使用--no-pie选项,但现在已不再使用。

所以有没有一种记录在案的方法来禁用ASLR呢?

(我需要禁用ASLR的原因是为了确保代码测试和调试过程中对对象地址依赖的行为(例如基于地址的哈希表和BIBOP内存管理器)具有重复性。)


1
不,这不是一个可能会被记录的东西。 - uchuugaka
1
@uchuugaka:你说这话的依据是什么? - Gareth Rees
肯定看起来不是打算被覆盖的东西。这就是为什么它会是未记录的。你需要做什么才需要这个? - uchuugaka
1
@uchuugaka:请查看修订后的帖子。 - Gareth Rees
1个回答

49

实际上,仍然存在一个-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

好的,这里有一个PIE标志,让我们验证一下

$ 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

果然PIE标志已经消失:

$ 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

因此,我们使链接器不添加PIE标志,我的Mavericks系统似乎仍然遵守这一规定。

值得一提的是,在/usr/include/mach-o/loader.h中定义和记录了PIE标志,其表示为MH_PIE

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

虽然我无法提供一种文档化的方法来启动没有ASLR的PIE标志二进制文件,但是既然您想测试代码,可能是您自己的代码,那么只需使用-no_pie链接您的测试程序或从您的测试二进制文件中删除PIE标志就应该足够了?


change_mach_o_flags.py set MH_NO_HEAP_EXECUTION bit by default. If you do want to change the PIE flag only, use python change_mach_o_flags.py --executable-heap --no-pie <path_to_mach_o> - youfu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接