Android 地址空间随机化(ALSR)缓解技术

出发点

常规的缓冲区溢出利用技术以及其衍生的Ret2libs和ROP利用技术在利用栈缓冲区溢出漏洞进行攻击时,需要事先熟悉被攻击进程的虚拟地址空间布局以便采用硬编码方式布局栈内存。由于操作系统每次加载进程和动态链接库时,基地址都加载到固定虚拟内存地址处,使缓冲区溢出漏洞易于劫持程序流程跳转到布局在栈内存的shellcode,即使开启XN缓解技术,采用ROP也很容易定位到系统库中的gadget,并劫持程序执行流跳转到gadget chain。

基于上述缓冲区溢出漏洞的利用特点,地址空间布局随机化机制(ALSR)将熵引入到进程内存地址空间中,使进程的多个区域(系统调用使用的区域、栈内存空间等)在加载时随机分配虚拟地址空间,这样可以有效的阻止Ret2libs和ROP等利用技术。如果和XN技术结合启用将在最大程度上保护系统不受内存破坏漏洞的攻击。

原理

早期的ASLR技术主要是在进程加载时在进程栈上预先填充随机大小的字节(将栈顶指针减去随机大小字节),从而达到进程基地址加载的地址空间随机化布局,但由于随机化的内存地址区域单一(栈内存),无法应对其他形式的内存攻击,eg,堆缓冲区溢出攻击,并且由于填充的随机字节数太少很容被暴力破解掉,只是在一定程度上缓解了缓冲区溢出漏洞攻击。

随着ASLR技术的逐步完善,ASLR技术趋于成熟。其中PaX的技术方案就是ASLR的成熟代表。PaX通过对内核打补丁的方式,实现了对栈基址、主程序基址和共享库的加载随机化。在进程加载时对栈基址的4-27位进行随机化,对主程序的代码区、静态数据区、堆三个连续区域基地址的12-27位进行随机化,对共享库加载地址的12-27位进行随机化,这样对存在内存破坏的各种内存区域都进行了强随机化,大大降低了缓冲区溢出攻击的成功率。

和PaX不同,TRR通过修改进程加载器的方式来实现ASLR,避免了修改内核,其随机化方法基本和PaX类似。但TRR增加了对GOT表的随机化功能,TRR通过修改进程加载器,在进程加载时将GOT表移动到随机位置,并用二进制代码修改工具修改了代码段PLT中对GOT表的索引使其正确指向GOT,从而实现了对GOT表的随机化。GOT表随机化可以有效的阻止修改GOT表中函数指针指向恶意代码的攻击方式。

android

与其他操作系统一样,Android对ASLR机制的支持也是分阶段完成的,最早在4.0版本引入,仅仅实现了对nmap系统调用所创建的区域(包括动态链接库)的随机化。在4.0.3实现了对空间的随机化,但是动态连接器(linker)本身的随机化并未实现,4.1.1为linker和所有其他的系统二进制文件进行了随机化,目前Android系统已经完全支持了ASLR机制。

ALSR机制有这样的一个特点或者说“缺陷”:当进程启动时,随机化会生效,但如果进程是由一个程序fork而来,则不会再次随机化。使用fork系统调用后,新进程的地址空间布局会和原来的进程完全一样。这种情况在Android上的例子就是Zygote。

Zygote利用fork机制来启动所有应用进程,这些应用程序拥有一个巨大的、共享的、预先填充的虚拟内存地址空间,并利用写时复制技术(copy-on-write)尽可能延迟内存页的复制,从而减少了新进程的内存使用量和创建时间。但同时这样的设计也使Android设备上的任何应用程序都可以泄漏内存地址。

例如,下面是Android中两个由Zygote fork启动的应用程序,

root@hammerhead:/ # cat /proc/1380/maps                                        
4004c000-40051000 r-xp 00000000 b3:19 1424       /system/bin/app_process
40051000-40052000 r--p 00004000 b3:19 1424       /system/bin/app_process
40052000-40053000 rw-p 00005000 b3:19 1424       /system/bin/app_process
40053000-40062000 r-xp 00000000 b3:19 125        /system/bin/linker
40062000-40063000 r--p 0000e000 b3:19 125        /system/bin/linker
40063000-40064000 rw-p 0000f000 b3:19 125        /system/bin/linker
40064000-40067000 rw-p 00000000 00:00 0 
40067000-40068000 r--p 00000000 00:00 0 
40068000-40069000 rw-p 00000000 00:00 0          [anon:libc_malloc]
40069000-4006c000 r-xp 00000000 b3:19 791        /system/lib/liblog.so
4006c000-4006d000 r--p 00002000 b3:19 791        /system/lib/liblog.so
4006d000-4006e000 rw-p 00003000 b3:19 791        /system/lib/liblog.so
4006e000-400b5000 r-xp 00000000 b3:19 711        /system/lib/libc.so
400b5000-400b6000 ---p 00000000 00:00 0 
400b6000-400b8000 r--p 00047000 b3:19 711        /system/lib/libc.so
400b8000-400bb000 rw-p 00049000 b3:19 711        /system/lib/libc.so
400bb000-400c9000 rw-p 00000000 00:00 0 
400c9000-400ca000 r-xp 00000000 b3:19 880        /system/lib/libstdc++.so
......
be91d000-be93e000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

============================================================================

root@hammerhead:/ # cat /proc/1367/maps
4004c000-40051000 r-xp 00000000 b3:19 1424       /system/bin/app_process
40051000-40052000 r--p 00004000 b3:19 1424       /system/bin/app_process
40052000-40053000 rw-p 00005000 b3:19 1424       /system/bin/app_process
40053000-40062000 r-xp 00000000 b3:19 125        /system/bin/linker
40062000-40063000 r--p 0000e000 b3:19 125        /system/bin/linker
40063000-40064000 rw-p 0000f000 b3:19 125        /system/bin/linker
40064000-40067000 rw-p 00000000 00:00 0 
40067000-40068000 r--p 00000000 00:00 0 
40068000-40069000 rw-p 00000000 00:00 0          [anon:libc_malloc]
40069000-4006c000 r-xp 00000000 b3:19 791        /system/lib/liblog.so
4006c000-4006d000 r--p 00002000 b3:19 791        /system/lib/liblog.so
4006d000-4006e000 rw-p 00003000 b3:19 791        /system/lib/liblog.so
4006e000-400b5000 r-xp 00000000 b3:19 711        /system/lib/libc.so
400b5000-400b6000 ---p 00000000 00:00 0 
400b6000-400b8000 r--p 00047000 b3:19 711        /system/lib/libc.so
400b8000-400bb000 rw-p 00049000 b3:19 711        /system/lib/libc.so
400bb000-400c9000 rw-p 00000000 00:00 0 
400c9000-400ca000 r-xp 00000000 b3:19 880        /system/lib/libstdc++.so
......
be91d000-be93e000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

bypass

虽然ASLR机制可以有效地缓解了缓冲区溢出漏洞的利用,但也仅仅是增加了漏洞利用的开发难度,并未能完全防御。下面列出了常用的对抗ASLR技巧:

  • 最简单的方法是利用尚未被随机化的区域,目前Android上已完全随机化,这种方法不适用于Android。

  • 利用堆喷技术使攻击者控制的数据到达内存中可预测的位置。

  • 利用信息泄漏漏洞更加精准有效的获取进程地址空间布局。

  • 利用Android应用进程由Zygote fork启动的特点,可以预先在手机中植入恶意应用程序,并由该程序来泄漏内存地址布局。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值