在 android 4.0.3 上禁用 ASLR

逆向工程 调试 安卓
2021-06-20 04:41:09

我希望共享库始终加载在 Android 4.0.3 上的相同地址。

我似乎无法使用以下方法禁用 ASLR:

echo 0 > /proc/sys/kernel/randomize_va_space

跑步

cat /proc/sys/kernel/randomize_va_space

确实显示 0,但在启动应用程序后,共享库总是(仍然)加载到不同的地址。

编辑:

启动使用命令加载共享对象的活动时会看到上述行为

am start -n <activity>

OTOH,当尝试使用用 C 编写的小型本机进程时,当 ASLR 被禁用时,相同的共享库会被加载到相同的地址

echo 0 > /proc/sys/kernel/randomize_va_space

或者

sysctl -w kernel.randomize_va_space=0

我已经使用 android-ndk-r7c 工具链 arm-linux-androideabi-4.4.3 编译了应用程序,没有任何特殊的编译器开关(例如 -fPIE 或 -pie)。

我也尝试过类似这里描述的东西,但共享库仍然在不同的地址加载 - 我猜不能在 Android 上禁用每个进程的 ASLR。

由于缺少 SYS_personality,我没有设法从 util-linux 交叉编译 setarch.c。

编辑2:

进一步的调查取得了部分成功。这就是我所做的,结果是通过“am start -n”启动的应用程序主要在两个不同的地址上加载共享库:

  1. 使用其中一种方法将 ASLR 设置为禁用状态,
  2. 杀死“/system/bin/servicemanager”进程(kill -9 PID)——这也应该关闭zygote并完成UI,
  3. 等待 servicemanager、zygote 和 UI 重新启动 - init.rc 处理这个,
  4. 尝试启动/终止/启动我的应用程序

在 20 多个启动和终止序列之后,我的应用程序总是在一个或另一个内存地址上加载共享库。怎么来的?不知道!

尽管如此,这应该对调试共享库有很大帮助,因为共享库通常连续多次加载到一个地址上,然后在接下来的几次加载到另一个地址,并访问第一个地址。

1个回答

实际上,ASLR 依赖于体系结构。我没有设法从 Android 获得源代码,但我查看了 Linux 内核的各种 ARM 实现。

在 ARM64 中,我发现了一个完全有效的 ASLR 实现(在arch/arm64/kernel/process.c):

unsigned long arch_align_stack(unsigned long sp)
{
  if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
     sp -= get_random_int() & ~PAGE_MASK;
  return sp & ~0xf;
}

static unsigned long randomize_base(unsigned long base)
{
  unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
  return randomize_range(base, range_end, 0) ? : base;
}

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
  return randomize_base(mm->brk);
}

unsigned long randomize_et_dyn(unsigned long base)
{
  return randomize_base(base);
}

但是,看着arch/arm/kernel/process.c,ASLR 似乎根本不会触发 ASLR,除了:

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
   unsigned long range_end = mm->brk + 0x02000000;
   return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
}

这个ARM版的Linux好像没有考虑randomize_va_space到控制ASLR的触发

取而代之的是,控制它的唯一方法似乎是进程个性标志(它们是进程范围的而不是系统范围的):

    $> setarch `uname -m` -R elf_exec

如果我能掌握 Android 内核源代码,我可能会说更多。