Android 防止数据执行(XN)缓解技术

出发点

当缓冲区溢出发生后,成功利用还需解决两个问题:1)在内存中部署“邪恶代码”。2)定位部署好的“邪恶代码”入口点,劫持PC指向该地址。在早期由于操作系统还未引入ALSR机制,部署“邪恶代码”的问题很容易解决,比如,把“邪恶代码”直接部署到缓冲区中,溢出后劫持PC指向精确计算好的缓冲区基址开始执行:
这里写图片描述

究其根源,是计算机冯·诺依曼体系结构中没有对数据和代码进行区分,允许同一内存块中代码和数据共享存在,CPU也傻傻分不清楚只是按照PC寄存器指向的内存位置获取数据当作代码进行执行。

后来设计的另外一种计算机体系结构—哈弗体系结构,从物理上将存储代码和数据的内存分离开,可以很好的缓解缓冲区溢出攻击,但目前的计算机仍采用冯·诺依曼体系结构,只有极少数系统完全采用哈弗体系结构。这是因为冯·诺依曼体系结构有一个很好的特性,因为数据和代码在同一内存块中共存,使得计算机可以从磁盘上加载程序并执行,软件升级也变得更为容易,从通用计算机的便利性要求看,这个特性是极其重要的。

防止数据执行缓解技术就是在这样的背景下被设计出来的,现代设备通过硬件和软件结合的方法,标记数据所在的内存不可执行,在部分上使数据和代码分离,这样在保持便利性的同时缓解了缓冲区溢出攻击。

原理

早在2000和2002年,PaX团队的popacs在i386平台上发明了两种防止数据执行的技术,由于当时的i386平台还不支持在页表中将内存标记为不可执行(这是现在防止数据执行技术的基础),所以这两种技术使用了一些平时很少用到的硬件特性。

2000年,PaX发布了名为PAGEEXEC的技术,它使用了CPU中的TLB(快表)缓存机制来阻止CPU对数据的执行。2002年,PaX又发布了名为SEGMEXEC的技术,它使用i386系列处理器中的段机制,将用户空间内存分成数据和代码两部分:
这里写图片描述
当CPU试图从内存的数据存储区域取指令时,会引起缺页错误使内核阻止数据执行并终止该进程。

现在设备都采用硬件和软件相结合的方法来防止数据执行,这要得益于CPU在硬件层面添加了对防止数据执行的支持特性。只不过不同的平台在术语上会有些差异,ARM在AMD64系列处理器中首先引入NX(Never Execute)的硬件特性。此后,Intel在奔腾4系列处理器中引入了XD(Execute Disable Bit)。ARM则从ARMv6架构开始支持XN(Execute Never)。

为了配合硬件特性,操作系统在软件层面对内存页表数据结构添加了一个特殊标识位NX/XD,来标识该内存页是否允许执行指令,CPU在取指令执行时会检查该标志位,当试图在标识不可执行的内存页中执行指令时,会产生一个CPU执行错误,然后提交给操作系统内核,内核向产生该错误的进程发送一个信号来终止其执行。

Android

和其他缓解技术一样,防止数据执行在Android也是分阶段完成的。

在Android 1.5发布时,Linux内核就已经有了这个缓解技术,不过Android系统中的二进制可执行文件在编译时并未开启对这个特性的支持。

2010年5月5日,编号为2915cc3的commit加入这个特性。

后来发布的Android 2.2(冻酸奶)并未使用这个保护机制。

直到下一个版本Android 2.3(姜饼)发布时,才最终将这个缓解技术用在终端设备上,不过Android 2.3只是部分实现了这个缓解技术,其中栈是不可执行,但堆仍是可执行的。

自2010年6月发布的Android NDK 4b版启用来这个缓解机制后,所有的AOSP和NDK都默认启用这一编译选项,下面是NDK 9b编译后各个内存区域的情况:

这里写图片描述

bypass

虽然XN机制可以有效地缓解了缓冲区溢出漏洞的利用,但其真正的威力还是需要和ASLR技术结合才能发挥出来,单一使用很容易被bypass,下面是对抗该技术的一些技巧:

  • 最简单的方法是在内存中找到一块可定位地址的内存块,并且该内存块包含可执行数据。目前Android已经找不到满足条件的内存区域,该技巧不适合Android。

  • 利用Ret2Lib(Return-to-library technique)技术。核心思想是直接利用进程中各种动态链接库中的函数(比如Glibc中的system函数)完成攻击,这些连接库包含了第三方库以及操作系统提供的C运行库,它们天生就是可执行的。

  • 利用ROP(Retrun-Oriented-Programming)技术。核心思想是利用内存中现有函数代码中的指令片段( gadget)串联起来构成完整的攻击载荷链。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值