如何从ELF文件中禁用地址随机化(ASLR)?

4

已解决: 解决方案是调用personality(0x40000)。请参阅下面的评论以获取详细信息。

ASLR标志位于ELF文件中的哪里?我需要禁用特定库(.so)的ASLR。 我尝试使用objdump,但我找不到如何这样做。

我不能使用/proc,因为它似乎在我的Android 4.4.4上无法工作, 所以我正在尝试修改二进制文件。

编辑: 我已经编译了以下内容:

#include <stdio.h>

void* getEIP()
{
    return __builtin_return_address(0) - 0x5;
}

int main(int argc, char** argv)
{
    printf("EIP located at: %p\n", getEIP());
    return 0;
}

不带ASLR (PIE):

arm-linux-androideabi-gcc.exe code.c -o noPIE --sysroot=%NDK%\platforms\android-3\arch-arm

使用ASLR(PIE):

arm-linux-androideabi-gcc.exe -fPIE -pie code.c -o withPIE --sysroot=%NDK%\platforms\android-3\arch-arm

即使如此,noPIE二进制文件确实没有被随机化:

# cat /proc/sys/kernel/randomize_va_space
2

1
据我所知,ASLR标志不驻留在ELF文件内。它是内核的动态属性。因此,如果您无法使用/proc/,我认为您就陷入了困境。顺便说一句,我的想法可能是完全错误的!请参见这个。而且,ASLR是地址空间的进程范围属性,因此仅为一个特定的libfoo.so更改它是没有任何意义的。 - Basile Starynkevitch
也许我应该提一下 - 我不能使用/proc,因为它在我的Android 4.4上不起作用。 它根本没有真正禁用ASLR。 对我起作用的是编译时禁用ASLR。 你知道有什么解决方法吗? - John
请编辑您的问题,解释您如何在没有ASLR的情况下进行编译... - Basile Starynkevitch
我使用了-fPIE和-pie,我认为其中一个仅生成位置无关代码,另一个则设置ASLR标志? - John
2个回答

3
我需要禁用特定库(.so)的ASLR功能。 您无法这样做(因为ASLR不驻留在ELF文件中,而是内核的属性)。 您可以为给定进程禁用随机化。 setarch -R 可以帮助您实现这一点。请参阅此处了解更多信息。

这个有效。我在我的Android设备上没有setarch,因此我使用了personality:http://man7.org/linux/man-pages/man2/personality.2.html 我没有找到任何禁用ASLR的宏,所以我像Basile Starynkevitch在Ubuntu上建议的那样使用了strace,并发现它传递了0x40000。 - John

1

我认为ASLR在两种情况下都发生了。另请参见this

但在第一种情况(noPIE二进制文件)中,可执行文件本身具有固定地址;但是所有调用 mmap(2) 而没有 MAP_FIXED 的内容都是随机化的,包括共享库的加载。

在第二种情况(PIE二进制文件)中,即使是可执行文件本身也会被execve(2) 加载到某个随机地址上(当然还有共享库,稍后由ld-linux(8) 在 ELF 文件中作为“解释器”进行映射)。

你可以通过 strace(1) 来检查这两个执行的情况。
ASLR 是内核状态的一部分。改变它以 mmap 特定共享对象没有任何意义,但是,正如Employed Russian answered所回答的那样,你可以使用 setarch -R 禁用进程及其未来子进程的 ASLR(也许包括你的父 shell 和它的所有子进程)。

如果可能且非零,则不会有调用 mmap 映射到第一个参数指定的地址。 - Timothy Baldwin

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