电脑中堆栈不可执行代码执行攻击

网络安全(19)
文/H3C攻防研究团队
现阶段的安全漏洞种类很多,包括大家熟悉的SQL注入漏洞、缓存溢出漏洞、XSS跨站脚本漏洞等。而栈溢出漏洞作为缓冲区溢出漏洞的一种特定的表现形式,在现实网络环境中比较普遍。本文将从栈溢出漏洞的原理、攻击形式及防护方法等方面进行介绍
一、 栈溢出漏洞的原理
栈溢出(Stack Overflow)是在网络与分布式系统中被广泛利用的一种漏洞类型。在汇编中,以线程为线索的指令执行对函数的调用及局部变量的存取是依靠栈来实现的,黑客可以使用特定的脚本语言,通过网络远程向对外提供业务的服务器进行攻击,利用对栈中数据的填充越界,实现有效的漏洞攻击。下面的例子对该过程进行了详细的描述:
下面这段C代码的vulnerable_func函数用于完成对input字符串的临时存储及对变量isSafe的判断,同时主程序main中,分别对该函数进行正确及错误的参数输入,两相对比可以看出正常调用的栈处理赋值及不正常时的栈溢出情形。函数关键代码如下所示:
int vulnerable_func(char * input)
int isSafe = 0;
char vulnerable_var[16];
strcpy(vulnerable_var, input);
if (isSafe == 0)
printf(&Check error!\n&);
printf(&Check Pass!\n&);
int main(int argc, char* argv[])
vulnerable_func(&Hello World!\n&);
vulnerable_func(&Hello World!AAAAAAAAAAAAAAA&);
通过特定的技术手段,调用查看两种情况下函数调用的栈处理过程,得到的栈参数赋值如图1所示:
地址0013FEFC开始的16个字节为vulnerable_var变量在栈中的存储空间;地址0013FF0C为isSafe变量在栈中的地址;地址0013FF10为main函数EBP在栈中的地址;地址0013FF14为函数返回地址在栈中的存储地址
图1正常栈与溢出栈对比图
进一步分析可知,图1右图中超计划输入的数据覆盖了栈中isSafe变量、EBP和函数返回地址所在内存空间的内容,一般会引发数据混乱或程序崩溃。对于软件开发人员来说,这只是软件开发过程中诸多错误中常见的一种内存越界错误,而对于安全人员来说这可能就意味着一个非常危险的安全漏洞。因为黑客会利用这种漏洞巧妙的构造出攻击输入以跳出原程序的设计逻辑,甚至执行任何攻击者想要执行的代码。
二、 栈溢出漏洞的典型攻击方式
栈溢出漏洞在客户端和服务器上均有可能存在,攻击者主要通过网络以远程方式进行攻击。对于客户端的攻击一般受NAT及防火墙阻隔的影响,需要搭建伪装的服务器通过社会工程学引诱用户访问,在回应用户访问时构造数据进行攻击。传送伪造的数据文件引诱用户打开,以攻击处理软件中的漏洞也很常见,当然在局域网中的直接攻击也广泛存在。对于服务器的攻击则只需直接伪造对服务器访问,在连接或登录后构造报文或数据进行攻击。
黑客在远程利用网络实施栈溢出漏洞攻击时,其攻击报文将通过网络找到特定的服务器主机,并在主机进行函数调用时实施破坏性行为。典型的攻击行为主要有以下三种:
1) 修改相邻数据
仍以前面的演示代码为例,假设此代码为服务器上的安全检查模块的一部分,input为远程用户的登录信息,isSafe为系统中的判断用户关键数据。如果第二次函数调用只修改栈中isSafe变量,就可模拟出一次远程用户的攻击,并绕过对isSafe变量的检查,造成一次非法用户绕过安全检查的成功入侵。由于这种方式受限于系统设计时的诸多因素,实际出现的机会相对较少。
2) 修改函数返回地址
栈溢出更常见的一种利用方式是覆盖漏洞函数的返回地址。若演示代码中input输入足够长时,就会覆盖修改函数vulnerable_fun的返回地址(即图1中地址0012FF14的内容),如果此时输入为精心构造的shellcode(即实现攻击行为的一段机器指令码),准确地修改该返回地址,就可能跳转到shellcode中去执行,攻击者也就可能获取进程对应的权限执行远程植入的指令序列。
3) 修改SEH(Structured Exception Handling)
windows异常处理是windows程序出错后自己处理错误并进行补救的一种机制, 包括SEH、VEH(Vector Exception Hander)、UEF(Unhandled Exception Filter)等技术简单来说,可以想像SEH为栈中的一个单链表,如果函数中使用了__try、__except等异常处理宏,就会在该函数栈帧中压入SEH结点并链接到单链表的头部。发生异常时就会从栈中自顶向底调用SEH链表结点中的异常处理函数。当栈溢出覆盖了后续需要处理的数据或破坏了栈的平衡,均会造成程序运行异常,引发SEH机制调用栈中的异常处理函数。这种情况下,如果SEH链表结点的异常处理函数地址也被覆盖成了shellcode地址或者可以跳转到shellcode的指令地址,一次修改SEH的栈溢出执行任意代码攻击就发生了。由于SEH覆盖的攻击方法比较高效,成为windows上栈溢出的经典攻击方式。
三、 栈溢出漏洞的防护技术
在栈溢出的检查与防范方面,软件开发工具厂商及团体已经做了不少努力,如微软在Visual Studio系列中增加了栈溢出检查的编译选项。合理利用这些带安全特性的开发工具,可以提升系统的安全性,在遭受攻击时检查出程序中的数据溢出中止攻击行为。在操作系统方面,Windows系列操作系统中增加了SEHOP (SEH Overwrite Protection) ,以阻止攻击者通过修改SEH来利用漏洞,增强了系统的安全性,其它操作系统也有类似的机制来提升安全性。硬件方面,64位CPU中引入了NX(No-eXecute)硬件机制。其保护方法的本质,就是在内存中区分数据区与代码区,堆内存与栈内存都是数据区,程序代码部分则为代码区,当攻击使CPU跳转到数据区去执行时,就会异常终止。
对于大量用户已投资的现有软硬件资产,不可能都升级到最新的软硬系统上。即使经济允许,可以绕过防御机制的新漏洞会不断被挖掘与捕获,攻击方法也会推陈出新,成熟的节点软硬件防御机制总是在总结了攻击规律后经过相当长时间推出,因而不能及时对一些新漏洞与新攻击方法生效。所以网络防御措施相当必要,IPS设备就是比较典型的网络防御设备,可以采用各种技术进行针对性更强的防御。
1. 基于漏洞特征的检测
漏洞都有一定的触发条件,对漏洞的攻击过程就是构造外部输入使之既能满足触发条件又能使系统跳出原先逻辑执行攻击者设定动作的过程。显然针对栈溢出漏洞的攻击,也必须达到漏洞的触发条件——注入超过系统逻辑计划存储的数据长度。如前面代码所演示的,对于input输入超过16个字节就能触发演示漏洞。漏洞特征库就是基于已知漏洞的触发条件建立起来的特征信息库,当发现最新的漏洞触发特征,同步动态更新防御设备上的漏洞特征库,基于这个信息库进行网络流量的检测可以有效的发现与阻止针对已知漏洞的攻击,如图2为H3C IPS设备上漏洞库中缓冲区溢出漏洞的部分信息。
图2 H3C IPS T1000A设备上部分缓冲区溢出类漏洞信息
2. 基于攻击特征的检测
漏洞的产生到发现中间有段不确定的时间,有可能是几天也有可能是一年,甚至几年,不少漏洞都是被黑客首先发现并利用进行攻击时,被安全研究机构通过Honey Pot等系统捕获之后分析出来的。因此基于漏洞特征的防御受限于安全机构的漏洞发掘速度与研究范围以及未公布漏洞被利用的广泛程度。为了提高防御性能,有必要基于攻击的特点进行有针对性的防御,如前述修改函数返回地址或修改SEH的攻击方法,栈溢出注入数据的长度与内容随漏洞不同而有所差异,但攻击使用的跳转地址却是常用的、比较固定易用的一些地址。另外shellcode的编写有相当的技术含量,各种平台下的shellcode一般都是尽量重复利用。加上常用的利用模式,使得攻击手法呈现出一定的特征,通过提取这些攻击中频繁出现的利用特征即时更新网络防御设备的攻击特征库,可以有效阻止黑客利用现有手段对各种漏洞(包括未被安全机构发掘的)的攻击。
3. 基于虚拟技术的检测
对于安全性要求很高、需要重点防护的系统,基于漏洞特征与攻击特征的防御难免还有漏网之鱼。就像Honey Pot系统可以用真实的系统做诱饵也可以虚拟一个诱饵系统一样,防御设备也可以虚拟一个跟真实系统相近的系统,用于检测对系统的访问是否存在攻击。以ftp服务器上栈溢出漏洞的防御为例,防御设备最理想的情况是可以虚拟出一个除了数据不同其它均相同的ftp服务器,当服务器被攻破时,系统的服务进程即使不异常中止其现场也会与正常访问的现场不一样。通过在虚拟系统中插入检查点,检查系统某一动作完成后的现场,以及监测进程的运行状态,可以检测出用户每次ftp操作是否含有攻击或攻击是否成功。如果用户的操作没有异常后台再把操作重定向到真实的ftp服务器上去处理,并把真实的数据返回给用户,否则可以直接阻断此用户对真实系统的访问。这样即使是以攻击者首创的未公布攻击方法对未公布漏洞进行攻击,也可以有效检测出来。
4. 基于模糊识别的检测
由于溢出类漏洞的填充数据对于攻击本身是没有意义的,即只是用来占位以达到数据长度的目的,这部分一般会被攻击者以习惯模式填充(如多个字符重复多遍),而这部分数据在正常访问情况下,是外部输入中有意义的部分。另外输入的shellcode和跳转地址部分与正常的输入一般情况下也有差别,基于这些差别可以建立起来模糊识别的模型,用于检测对未知漏洞的攻击。
栈溢出的攻防安全之争中,目前防御一方略占上风。本文提到的保护技术能有效阻止大部分针对栈溢出漏洞的攻击,但是出于性能成本等多方面的考虑,这些技术只被部分采用。另外攻防技术还在不断发展之中,栈溢出漏洞在安全领域还有不小的舞台,值得安全研究与管理人员更多关注。
原文链接:.cn/About_H3C/Company_Publication/IP_Lh/2011/03/Home/Catalog/048_30008_0.htm
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:34859次
积分:1557
积分:1557
排名:千里之外
原创:95篇
转载:199篇2009年7月 总版技术专家分月排行榜第二2009年3月 总版技术专家分月排行榜第二2009年1月 总版技术专家分月排行榜第二2005年7月 总版技术专家分月排行榜第二2005年5月 总版技术专家分月排行榜第二2005年3月 总版技术专家分月排行榜第二
优秀小版主2015年8月优秀小版主2015年9月优秀小版主2015年5月优秀小版主2015年2月论坛优秀版主
2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
2016年8月 VC/MFC大版内专家分月排行榜第二2016年7月 VC/MFC大版内专家分月排行榜第二2016年6月 VC/MFC大版内专家分月排行榜第二2015年6月 VC/MFC大版内专家分月排行榜第二
2016年9月 VC/MFC大版内专家分月排行榜第三2016年4月 VC/MFC大版内专家分月排行榜第三2015年4月 VC/MFC大版内专家分月排行榜第三2012年8月 VC/MFC大版内专家分月排行榜第三
2015年1月 VC/MFC大版内专家分月排行榜第二
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。程序堆栈问题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
程序堆栈问题
上传于||文档简介
&&介​绍​C​语​言​中​涉​及​到​的​一​些​内​存​布​局​问​题
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
你可能喜欢用户态进程在堆栈执行代码时,因为内核在加载该进程的时候,取消了在堆栈上执行代码的权限,因此如果在其上执行代码的话,进程会直接死掉。
接下来是在堆栈执行代码的测试例子,主要思路是给物理内存加上可执行代码的权限。代码如下:
typedef int (*func)(unsigned int);
int hello(unsigned int start)
return 0x61;
int main(void)
unsigned int len = 0;
unsigned char *q = NULL;
unsigned char *p = NULL;
int i = 0;
func qq = NULL;
fd = open("/dev/mem", O_RDWR|O_EXCL|O_SYNC);
if(fd == -1){
printf("open /dev/mem failed!\n");
return -1;
/*通过mmap设置其用可执行权限(PROT_EXEC)*/
q = mmap(NULL, 0xff, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, fd, 0x20000);
if(q == 0){
printf("mmap failed!\n");
p = (unsigned char *)
/*拷贝代码*/
for(i = 0;p[i]!=0xc3;i++){
q[i] = p[i];
printf( "hello:%p:\t%02x\t\n",p+i,p[i]);
printf( "q
:%p:\t%02x\t\n",q+i,q[i]);
q[i] = p[i];
printf( "hello:%p:\t%02x\t\n",p+i,p[i]);
printf( "q
:%p:\t%02x\t\n",q+i,q[i]);
printf( "len = 0x%x before hack\n",len);
qq = (func)q;
len = qq(0);
printf( "len = 0x%x after hack\n",len);
close(fd);
munmap(q, 0xff);
结果如下:
可见,成功执行了该代码。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:13841次
排名:千里之外
原创:57篇
(1)(1)(1)(27)(25)(5)

我要回帖

更多关于 电脑执行代码 的文章

 

随机推荐