禁用内存地址随机化

42

我正在尝试调试一个使用了许多指针的二进制文件。有时为了快速查找错误并查看输出,我会打印对象的地址及其对应的值,然而,对象的地址是随机的,这破坏了这种快速检查的目的。 是否有一种方法可以临时/永久地禁用这个功能,以便每次运行程序时都获得相同的值。

哎呀,操作系统是 Linux fsttcs1 2.6.32-28-generic #55-Ubuntu SMP Mon Jan 10 23:42:43 UTC 2011 x86_64 GNU/Linux


相关的问题:https://dev59.com/L2gu5IYBdhLWcg3wj3z5 - Ciro Santilli OurBigBook.com
3个回答

51

2
谢谢。这帮我救了一个应用程序的命,所以我给你多加了50块。 - hsanders

45

为了暂时禁用特定程序的ASLR,您可以始终发出以下命令(无需sudo)

setarch `uname -m` -R ./yourProgram

2
我发现在ARM系统(例如树莓派)上,“setarch”命令找到“uname -m”的输出不太可靠。但是,“setarch linux32 -R ./yourProgram”命令效果很好。 - Ben Voigt
12
一种不错的变体是使用命令setarch \uname -m` -R $SHELL`。这会生成一个禁用了ASLR的shell,从该shell运行的任何命令也将禁用ASLR。 - ntc2
哦,不错!我非常喜欢! - Stephen

10
你也可以在UNIX的exec之前通过C源代码来进行编程实现。
如果你查看setarch的源代码(这里是一个源代码),你会发现:

http://code.metager.de/source/xref/linux/utils/util-linux/sys-utils/setarch.c

你可以看到,这归结为一个系统调用(syscall)或函数调用(取决于您的系统定义)。来自setarch.c:
#ifndef HAVE_PERSONALITY
# include <syscall.h>
# define personality(pers) ((long)syscall(SYS_personality, pers))
#endif

在我的CentOS 6 64位系统上,看起来它使用了一个函数(可能调用了上面的相同系统调用)。请查看此片段,来自于/usr/include/sys/personality.h中的包含文件(在setarch源代码中引用为<sys/personality.h>):
/* Set different ABIs (personalities).  */
extern int personality (unsigned long int __persona) __THROW;

从本质上讲,您可以从C代码中调用并设置人格以使用ADDR_NO_RANDOMIZE,然后像setarch一样执行exec。
#include <sys/personality.com>

#ifndef HAVE_PERSONALITY
# include <syscall.h>
# define personality(pers) ((long)syscall(SYS_personality, pers))
#endif

...

void mycode() 
{
   // If requested, turn off the address rand feature right before execing
   if (MyGlobalVar_Turn_Address_Randomization_Off) {
     personality(ADDR_NO_RANDOMIZE);
   } 
   execvp(argv[0], argv); // ... from set-arch.
}

很明显,在进程中你无法关闭地址随机化(除非是动态加载),因此这只会影响到后来的forks和execs。我相信地址随机化标志会被子进程继承?

总之,这就是如何在C源代码中以编程方式关闭地址随机化。如果您不想强制用户手动干预并使用setarch或前面列出的其他解决方案启动,则可能只有这种方法是您的唯一解决方案。

在抱怨关闭此功能会带来安全问题之前,请注意某些共享内存库/工具(例如PickingTools shared memory和一些IBM databases)需要能够关闭内存地址的随机化。


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