栈溢出笔记1.12 栈Cookie

来源:互联网 发布:linux中录入历史字符 编辑:程序博客网 时间:2024/06/05 20:35

栈Cookie,也叫安全Cookie。我们先来看一看栈Cookie的实现机制,使用的程序为1.2节中的example_2,重点在函数get_print()部分。还记得在1.2节中我们为了演示栈溢出,去掉了编译设置中的“缓冲区安全检查(GS)”选项,我们先看看未启用该选项时的get_print()函数代码:
这里写图片描述
图78 未启用GS的get_print()函数代码

然后,启用该选项,看启用该选项之后的get_print()函数代码:
这里写图片描述
图79 启用GS的get_print()函数代码

函数开头部分和结尾部分多了上面标注的几行代码,结尾还多了一个函数调用。先看看开头多出来的三行代码:

/*****************************************************************************/MOV     EAX,DWORD PTR DS:[416000]XOR     EAX,EBPMOV DWORD PTR SS:[EBP-4],EAX/*****************************************************************************/

这三行代码的操作是从取数据段0x416000处的值,然后与当前的EBP进行异或操作,并将结果保存到栈中EBP-4的位置,回想1.1中的图,EBP-4的位置应该就是保存的EBP上面的那个(即紧邻EBP)。也就是说,这段代码往保存的EBP和局部变量区中间插入了一个值,现在栈变成了这个样子:
这里写图片描述
图80 加Cookie之后的栈

接下来看结尾多出来的三行代码:

/*****************************************************************************/MOV     ECX,DWORD PTR SS:[EBP-4]XOR     ECX,EBPCALL    example_.00411014/*****************************************************************************/

操作是将保存的Cookie值取处到ECX,然后再与当前EBP异或,然后调用example_.00411014函数。这是做什么呢?EBP是没有变化的,因此,若保存的Cookie值也没有变化,则与EBP异或将为原值(即从DS:[416000]取出来的值)。所以,example_.00411014应该是一个检查Cookie是否发生变化的函数,通过ECX的值来判断Cookie值是否被修改,从而做一些操作。

究竟是做什么操作,我们不再往下跟,但从1.2节中程序的表现来看,应该是引发了一个异常。
这就是Cookie的工作原理了,在栈上的局部变量区和保存的返回地址(EIP)之间保存一个值,如果发生了栈溢出,则该值会被修改,从而验证不通过,引发栈溢出异常。这个Cookie是通过保存于数据段中的一个值与EBP异或得到的。

下面,我们在开启了GS时的栈中看一看该Cookie值(输入10个A,不超过缓冲区大小):
这里写图片描述
图81 Cookie值

这就是位于EBP和局部变量之间的Cookie值。

我们重启程序再来看一看:
这里写图片描述
图82 Cookie值

它的值变了!这说明DS:[416000]处的值是一个随机值,每次运行程序都不同。这样,使得Cookie值难以预测。但好消息是,它的位置是固定的。因此,Cookie的作用相当明确,就是保护下面的返回地址不被修改。

启用了栈Cookie之后,会进行Cookie值的检查,因此,绕过的方法之一,就是绕过检查的步骤。这种方法实际上我们前面已经用到了,由于栈Cookie检查在函数最后,因此提前引起一次异常,利用SEH就可以绕过Cookie的检查。当然,依据具体的程序,还有很多其它的方式,具体请看这篇专门讲栈Cookie的文章:Defeating the Stack Based Buffer Overflow Prevention Mechanism of Microsoft Windows 2003 Server, David Litchfield。

0 0
原创粉丝点击