【转】两篇关于__security_cookie的介绍

___security_cookie机制,防止栈溢出

从研究底层和汇编以来,已经多次接触到“栈溢出”这个名词了。

这次在汇编码中看到了个不明就里的 ___security_cookie ,查了下,原来是编译器的安全检查机制。转载一篇文章:

首先,security cookie并不是windows系统自带的保护机制,并不是说一个确实存在溢出漏洞的
程序,放到带security cookie保护的环境中,就不能正常溢出了。
那么,到底是什么是security cookie呢?
我觉得从广义上讲,它应该是一种保护栈的机制,提供这种保护的,是程序本身,编译进程序本身的
代码提供的,而不是系统中某个运行在黑暗角落中的线程。
所以,既然是程序自身就带上的,为了不给程序员带来额外的负担,这份工作就交给编译器来完成了。
vc6.0的cl.exe是不带这个功能的,只有vc.net以后面版本的cl.exe才带这个功能,就所谓的/GS选项。
即用vc.net的cl编译器时,/GS选项默认就打开了。
现在,我们知道了这个机制的提供方,那么,这个机制到底是怎么一回事呢?
熟悉函数调用及返回前后的汇编指令的人肯定很清楚,在win32平台,对于stdcall类型的函数调用,
当call指令运行完毕,当前的堆栈结构基本上是这样的:

局变2  ebp-8   低地址
局变1  ebp- 4
ebp  ebp
返回地址 ebp+4
参数1  ebp+8
参数2  ebp+c
参数3  ebp+10
参数4  ebp+14   高地址

第一列是堆栈中存放的dword的内容,第二列是用ebp作为栈地址的索引时,它对应的应该用ebp表示的值,
说得形象一点,ebp中存放着栈的一个地址(栈其实也是一片内存,ebp只是指向其中一个对当前函数内部比较
重要的地址,其实是相当重要),栈的其它位置都是通过这个ebp来寻址的,即我们给函数的第一个形参的
地址,就是ebp+8,第二个就是ebp+c,我们定义的局部变量的地址,第一个局部变量是ebp-4,第二局部变量的
地址就是ebp-8,依此类推。但这也不是一定的,上面说的是理想情况,如果我们在函数里定了一个数组,
如 char buf[8];并且是定义的第一个局部变量,那么它的地址肯定就不是ebp-4,还是ebp-8。所以,数组
比较特殊,结构体也比较特殊,其根本原因是栈是从高地址向低地址生长的,而我们的数组,结构体,
却是从低向高地址生长的,两者矛盾的结果就是寻址上的微妙变化。
当然,这里为了方便说明问题,都默认定义的变量,传入的参数,都是四字节对齐的,并且一个变量一个
双字。你可以把数组理解一个4字节的char,也就是一个双字了。
话说回来,当call运行完毕,当前的堆栈结构已经给出,如果在函数里调用strcpy()往局部变量1 里考入
东西,对长度没有进行检测,那么ebp-4,ebp,ebp+4,还有后面的地址,其所在的内容都会被覆盖掉。这里
溢出就发生了,我们控制住了ret的返回地址,然后...
嗯,为了防止这一切,新的cl编译器的/GS选项加上入所谓的"security cookie",如何加入的?在哪加入的
呢?
先看看加入"security cookie"后的call指令运行完以后,堆栈的变化。

局变2  ebp-c   低地址
局变1  ebp-8
XXXXX  ebp-4
ebp  ebp
返回地址 ebp+4
参数1  ebp+8
参数2  ebp+c
参数3  ebp+10
参数4  ebp+14   高地址

变化很明显,在ebp上面,第一个局部变量的下面,填入的一个新的值,这个值就是所谓的"security cookie"
.按照前面说的溢出过程,ebp- 4的内容被覆盖掉,即security cookie的值被修改,在函数返回,即执行ret
指令前,会call另一个函数,这个函数就是用来对比 ebp-4的值和当时push到栈中的值是不是一样,不一样的
话,就说明溢出了,然后进程被终止。
那么,你大概会产生以下几个问题:
1. 这个security cookie是如何计算出来的?
security cookie是一个双字,也可以说是一个int,其本身是保存在全局变量里的,其创建是编译器在编译
阶段就创建的,然后写入到.data段里,即在PE里就保存了这个值。
但这个值又是变化的,windows装载器完成必要的前期准备工作后(如创建进程,为栈分配内存,等待)
把 EIP设置为PE里的代码入口处,第一个执行的指令就是一个call调用,这个call调用就是用来初始化这个
cookie值的,当然,这段代码也是公开的,但没有关系,这个算法保证这个cookie值是随机的,hacker也
是不能在一个shellcode中可以猜出来的。
具体算法我不打算在此说明,感兴趣的读者可以自己编译一下再反汇编一下看看。

2.是什么时候填入到栈里面的?
我们知道了这个 security cookie的计算和初始化过程,那么,它必须在函数调用时写入到ebp-4里面才有用。
所以,过去的不带这种保护的代码,在函数入口处一般是这样的:
push ebp
mov ebp,esp
sub ebp,n   ;这条指令可能不同,不过多数情况下都是这样来为局部变量分配空间的
然后,后面就开始执行我们的代码了,
加入这种保护后,会在sub ebp,n后面,加入一条像这样的指令:
mov     dword ptr [ebp-4],XXX
XXX就是security cookie的值,这个值保存在全局变量里,通过RVA+PE头地址,实际上也可以说成是
绝对地址来引用了。
到这里security cookie的值就写入栈了,然后在函数返回前检测一下就行了。

到了这里,你大概又会产生一个新的问题,
必须为每一个函数调用都写入security cookie进行保护吗?
答案是否定的,要不然我们的程序的执行效率会受到一定的影响,并且可能还不小。
那么,就应该存在一定的规则,什么时候进行这种保护,什么时候不需要。
其依据当然也很简单,有溢出可能的,就加入这种保护,没有溢出可能的,就不加。
那怎么样才算是有溢出可能呢?
这个是编译器进行判断的,像函数里定义了char数组,后面又用字符串操作函数进行了一定的操作,就说明
可能存在溢出。编译器在编译这个函数里的时候就加上security cookie的保护。
当然,这里还有一些其它的很具体的规则,在msdn里有更详细的描述。

还有其它一些问题没有在这里说明,可以把这些问题留给大家
1.有对付security cookie的检测的方法吗?(答案是有的,但好像都不是很优美)
2.有关security异常的异常处理函数
3./safeSEH对 SEH处理的变化

【讨论】_security_cookie的问题

#include <stdlib.h>
void study1()
{
  char str[4];  //标记一
  gets(str);
  printf("你输入的内容是\n%s",str);
 }

int main(int argc, char* argv[])
{
  study1();
  system("PAUSE");
  return 0;
}

不明白的是,在上述"标记一"处,如果str的长度小于等于4,release下为什么没有生成_security_cookie啊?如果长度大于4就会生成_security_cookie,我是在vs 2005下试验的,
求看雪牛牛给解答……

当应用程序启动时,程序的cookie(4字节(dword),无符号整型)被计算出来(伪随机数)并保存在
加载模块的.data节中,在函数的开头这个cookie被拷贝到栈中,位于EBP和返回地址的正前方(位于返
回地址和局部变量的中间)。 

[buffer][cookie][savedEBP][savedEIP]
在函数的结尾处,程序会把这个cookie和保存在.data节中的cookie进行比较。
如果不相等,就说明进程栈被破坏,进程必须被终止。 

为了尽量减少额外的代码行对性能带来的影响,只有当一个函数中包含字符串缓冲区或使用_alloca函数
在栈上分配空间的时候编译器才在栈中保存cookie。另外,当缓冲区至少于5个字节时,在栈中也不保
存cookie。 

在典型的缓冲区溢出中,栈上的返回地址会被数据所覆盖,但在返回地址被覆盖之前,cookie早已经被
覆盖了,因此就导致了exploit的失效(但仍然可以导致拒绝服务),因为在函数的结尾程序会发现cookie
已经被破坏,接着应用程序会被结束。 
时间: 2024-10-03 08:09:57

【转】两篇关于__security_cookie的介绍的相关文章

(转载)两篇很牛的vim使用技巧

读本文之前请注意: 1. 本文的目标是提供一些vim的使用技巧,利用这些技巧可以提高vim的操作效率.部分技巧在vi上也可以使用,但是现在基本上都是用vim了. 2. 本文是整理和总结使用技巧,而非讲解vim入门,因此不会涉及最基本的使用,例如如何上移或下移光标,对此类操作请参阅任何一本vim或者vi教程. 3. 本文阅读对象是了解了vim的基本操作,而希望高效地利用vim进行工作的人.熟练使用vim的人自然不必细读,如果能留下您的宝贵意见,本人将感激不尽. 4. 本文由本人搜集整理,转载请注明

对张子阳先生对委托和事件的两篇文章的读后思考(说得很透,内附故事一篇)

第一篇 C#中的委托和事件 第二篇 C#中的委托和事件(续) 首先,张子阳先生的这是两篇关于委托和事件间关系的文章,是目前为止我读过的介绍委托和事件以及异步调用最简明清晰文章,作者通过非常有节奏的"标题"->"问题"->"思路"->"实现"->"讲解"的结构,分步骤一步一步地将委托和事件的实现.应用与原理阐述得非常清楚,并且在行文期间将自己有趣的思考过程通过生动的语言表达了出来,使人

对张子扬显示的两篇委托和事件说得很透文章读后的思考

第一篇 C#中的委托和事件 http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-in-CSharp.aspx 第二篇 C#中的委托和事件(续) http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-Advanced.aspx 这是两篇目前为止,我读过的介绍委托和事件以及异步调用最简明清晰文章,作者通过非常有节奏的"标题"->&q

iOS开发UI篇—常见的项目文件介绍

iOS开发UI篇—常见的项目文件介绍 一.项目文件结构示意图 二.文件介绍 1.products文件夹:主要用于mac电脑开发的可执行文件,ios开发用不到这个文件 2.frameworks文件夹主要用来放依赖的框架 3.test文件夹是用来做单元测试的 4.常用的文件夹(项目名称文件夹) (1)XXXinfo.plist文件(在该项目中为  01-常见文件-Info.plist) 1)简单说明 是配置文件,该文件对工程做一些运行期的配置,非常重要,不能删除. 在旧版本xcode创建的工程中,这

iOS开发UI篇—常见的项目文件介绍 - 文顶顶

原文  http://www.cnblogs.com/wendingding/p/3766249.html iOS开发UI篇—常见的项目文件介绍 一.项目文件结构示意图 二.文件介绍 1.products文件夹:主要用于mac电脑开发的可执行文件,ios开发用不到这个文件 2.frameworks文件夹主要用来放依赖的框架 3.test文件夹是用来做单元测试的 4.常用的文件夹(项目名称文件夹) (1)XXXinfo.plist文件(在该项目中为  01-常见文件-Info.plist) 1)简

张量漫谈(前两篇)

文档下载: 张量漫谈_第一篇 张量漫谈_第二篇 最初的目的是为了供大一高等代数复习之用,他们学习这部分使用的教材是<高等线性代数学>,关于张量的这部分书本上的错误和不自然的地方很多,由于缺乏资料,索性自己写一份讲义.预计三篇,这是前两篇,最后一篇预计讨论一般模的张量,同样,最后一篇短期内也不会更新. 附原文摘要:张量为什么要如此定义? 这或许是一个让人头疼的问题. 因为其复杂的而多样定义让人感到困惑. 简单的定义无法抓到本质, 复杂的定义缺乏解释. 更为关键的是, 似乎在目力所及的范围内也很难

使用余弦定理计算两篇文章的相似性

使用余弦定理计算两篇文章的相似性:(方法论,细致易懂版) http://blog.csdn.net/dearwind153/article/details/52316151 python 实现(代码): http://outofmemory.cn/code-snippet/35172/match-text-release (结巴分词下载及安装:http://www.cnblogs.com/kaituorensheng/p/3595879.html) java 实现(代码+方法描述): https

两篇波兰地区重金属污染地区土壤微生物多样性的研究

环境微生物(包括方兴未艾的肠道微生物)在不同的系统中发挥着的生态作用逐渐被意识到,我们对环境微生物实际上仍旧知之甚少,其多样性问题仍旧是一个非常基础和重要的课题.这次读的两篇文章都是关于波兰地区重金属污染地区的土壤微生物研究. 文献一: Chodak M., Go??biewski M., Morawska-P?oskonka J., Kuduk K. & Niklińska M. 2013. Diversity of microorganisms from forest soils diffe

【转】《胡侃学习(理论)计算机》前后篇及两篇补充

今天推荐的是篇老帖,南京大学sir先生的<胡侃>以及后来的两篇补充帖子.算算是十几年前的帖子了,我知道帖子出自南京大学的BBS,百度了一下,却没有翻到原文.不过百度到了一大堆不负责任的转帖,我想我这也不算是抄袭了吧.当年有一位我很尊敬的学长给我推荐的这篇文章,让我受益匪浅(学长当年年轻气盛因为这事还吃过不少亏,他自己一直很内疚). 这几篇帖子适用于学习计算机理论,对于大学本科想要好好学计算机的同学,或者是工作后想要系统的学习计算机及数学理论的同学很有帮助. ==========转载需要分隔线=