1. 概述
在前面安全编码实践中我们介绍过GS编译选项和缓存溢出,以及数据保护DEP。首先,缓存溢出的直接后果就是可能导致恶意代码的远程执行,于是编译器提供了GS保护。但是,GS选项有自身的局限,存在若干方法可以绕过GS选项的保护。于是进一步,操作系统提供了数据执行保护,即DEP,以及与之对应的NXCOMPAT编译选项。
那么是不是现在我们就可以高枕无忧了?在安全领域中,系统的攻防是一个不断发展进化的过程。DEP提出后,就出现了针对DEP的Ret2libc攻击手段。这一点我们曾在介绍DEP的安全编码实践文章的最后简单提及过。
ASLR(Address Space Layout Randomization),地址空间格局的随机化,就是用来防范Ret2libc攻击手段的另一个重要的安全特性。那么,什么是Ret2libc攻击,ASLR的原理是什么,开发人员如何使用这个安全特性,就是我们这篇文章要探讨的内容。
2. DEP和Ret2libc攻击
2.1 DEP对堆栈溢出的保护
在栈溢出介绍中提及到Windows体系结构下函数堆栈布局(地址从高向低)如下:
调用参数 |
返回地址 |
EBP上层函数堆栈基址 |
异常处理代码入口地址 (如果函数设置异常处理) |
局部变量 |
表1:Windows系统的函数堆栈结构
如果发生堆栈溢出,恶意代码通过覆盖在堆栈(stack)上的局部变量,从而修改函数的返回地址,而导致恶意代码执行。下面是这类攻击方式的堆栈结构的一个典型例子。
调用参数 |
覆盖方向—> |
恶意代码 |
返回地址 |
恶意代码的入口地址 |
|
EBP上层函数堆栈基址 |
溢出的变量覆盖区域,往往包括必要的填充字节 |
|
异常处理代码入口地址 (如果函数设置异常处理) |
||
局部变量 |
表2:堆栈溢出时的堆栈结构
当DEP保护机制被使用后,由于恶意代码是存放在系统的数据页面(堆栈页面上),那么函数返回时,指令寄存器EIP将跳转到恶意代码的入口地址。此时该页面是非可执行的(non-executable),于是DEP就会触发系统异常而导致程序中止。
2.2 Ret2libc攻击