首页
社区
课程
招聘
[原创] 安卓中的 ASLR实现与关闭
发表于: 4小时前 168

[原创] 安卓中的 ASLR实现与关闭

4小时前
168

由 Linux 内核在 2001 年引入的一项内核补丁技术,旨在为防止堆栈指针泄漏引发的重定向攻击。通过 ASLR(Address Space Layout Randomization)随机化内存布局,使得指针偏移难以预测,从而防范攻击。

在最新的 Android 版本中,ASLR 已经做为系统安全的一部分被强制开启。并且不可关闭。各版本 ASLR 对比:

ASLR 的实现在安卓中共分为两部分,分别是内核态与用户态。

ASLR 的开启与关闭由进程的 personality 属性或全局变量 randomize_va_space 控制。当一个进程 execve(init) 启动时,在内核中经由以下链条:

sys_execve -> do_execve -> do_execveat_common -> bprm_execve -> exec_binpr -> search_binary_handler -> load_binary -> load_elf_binary,在 load_elf_binary 装载 ELF 的过程中会设置 PF_RANDOMIZE 标志。

一旦 PF_RANDOMIZE 标志设置成功,后续的二进制程序、共享库、堆、栈内存都将开启随机化。对已经建立完成的内存布局,后续再修改标志也不会重排现有布局。

用户态的 ASLR 是在 Linker 中强制开启的,这是安卓独有的特性。当共享库(so)被 Linker 加载时,在 find_libraries 阶段会将自身以及依赖的库加载顺序随机打乱。

同样在 ReserveAddressSpace 阶段也加入了 ASLR。

在安卓中要做到完全关闭 ASLR,需要将内核态与用户态两层限制都给绕过。

在常规的系统中我们可以直接将 /proc/sys/kernel/randomize_va_space 设置为 0 即可关闭内核态的 ASLR。但是因为安卓 APP 的启动都是由 Zygote 进程孵化而来, 而 Zygote 进程是由 Init 在系统启动较早期启动。通过上面的内核实现分析,我们已经得知进程的 PF_RANDOMIZE 标志一旦被设置,ASLR 将不可关闭。因此,我们只能在 Zygote 启动之前修改,才能实现内核态 ASLR 的关闭。

如此,我们可以借助 Apatch 提供的 post-fs-data 时机来运行脚本,完成对 randomize_va_space 的修改。

不过实测之后,这段脚本并没有生效。经过一番排查,在 Init 进程的启动过程中会将 randomize_va_space 重置为 2。

因此,我们必须在 Init 进程启动的过程中将 randomize_va_space 改回来。通过上面的内核分析,我们知道 PF_RANDOMIZE 标志是在 load_elf_binary 函数中设置的。这样就为我们提供了一个完美的 HOOK 时机,我们可以在 load_elf_binary 函数进入之前将 randomize_va_space 改为 0 。

将这段编译为 KPM 模块,刷进 boot.img。再次启动时将会发现内存段的高位地址已经被固定。


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 4小时前 被lidongyooo编辑 ,原因:
收藏
免费 17
支持
分享
最新回复 (6)
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
安卓的ASLR是残废,不重启libc的地址在进程里面都是一样的
4小时前
0
雪    币: 132
活跃值: (6867)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
Zepp7289 安卓的ASLR是残废,不重启libc的地址在进程里面都是一样的
共享库的关系,zygote 不挂,都是一样
4小时前
0
雪    币: 7
活跃值: (957)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
666
4小时前
0
雪    币: 617
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
Tql
3小时前
0
雪    币: 1929
活跃值: (2411)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
666
3小时前
0
雪    币: 104
活跃值: (7982)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
rbq
3小时前
0
游客
登录 | 注册 方可回帖
返回