一种防止缓冲区溢出攻击的动态堆栈内存管理方法

文档序号:6388359阅读:637来源:国知局
专利名称:一种防止缓冲区溢出攻击的动态堆栈内存管理方法
技术领域
本发明涉及动态堆栈内存管理方法,防止缓冲区溢出是一种常见的对计算机系统进行攻击的方法。本发明提出了一种动态堆栈内存管理方法,它可以有效地阻止缓冲区溢出攻击。
二.技术背景缓冲区是程序运行时候在计算机内存中存放数据的地方。当程序试图将一段数据写到某一段内存缓冲区中时,如果数据的长度超过缓冲区的长度,就会发生缓冲区溢出。攻击者可以利用这一弱点对计算机进行攻击(参见[1]E.Spafford.The Internet Worm ProgramAnalysis.Computer Communication Review,January 1989)。攻击者把一个超过缓冲区长度的字符串写入到缓冲区。由于写入的超长的字符串覆盖了相邻的存储单元,常常会导致两种结果。一是引起程序运行失败,严重的可导致系统崩溃;另外一种结果就是利用这种漏洞执行恶意指令。如果被攻击的程序在超级用户权限上执行,那么攻击者也可以获得系统超级用户的权限。结果是一个匿名的因特网攻击者往往有机会获得一台主机的部分或全部的控制权。缓冲区溢出攻击已经成为操作系统、数据库,万维网服务器等大型应用程序最普遍的漏洞之一。
现有的解决办法针对上述的问题,目前为止已经存在多种解决办法。和本发明较为接近的主要有两种技术。一是美国IMMUNIX公司的StackGuard技术(参见[2]Crispin Cowan,Steve Beattie,RyarFinnin Day,Calton Pu,Perry Wagle,and Eric Walthinsen,Protecting systems from stacksmashing attacks with StackGuard.Linux Expohttp//www.cse.ogi.edu//~crispin/,May 1999),另一个是日本IBM研究院的Proplice技术(参见[3]Hiroaki Etoh,Gcc extension for protectingapplications from stack smashing attacks,http//www.trl.ibm.com/projects/security/ssp,June2000)。这两种技术都是通过修改C语言的编译器,在生成的目标代码中附加上缓冲区溢出检测功能。其优点是在原来的程序在不需要任何的改动。拿StackGuard技术来说,为了探测是否有攻击者对返回地址进行攻击,当一个新的函数被调用时,它将一个″canary″值(一个单字)放到返回地址的前面。如果当函数返回时,发现这个canary的值被改变了,就证明可能有人正在试图进行缓冲区溢出攻击。程序会立刻响应,并将被攻击的进程的相关信息记录下来,然后终止被攻击的进程。日本IBM研究院的Proplice技术在借鉴了stackguard技术的基础上,重新安排了局部变量的顺序。这样当字符串变量被写入超长的字符串时,别的类型的局部变量的值不会遭到破坏,从而把攻击的危害减少到最小程度。
但是通过分析源程序或分析使用这两种技术编译后的目标程序,攻击者可以确定运行时堆栈具体结构。即攻击者通过分析代码可以确切获得返回地址和分配的局部变量之间的相对偏移。攻击者可以根据运行时候的堆栈结构来改变返回地址的值,但同时并不改变″canary″的值(参见[4]Bulba and Kil3r.Bypassing StackGuard and StackShield,Phrack Magazine56http//www.phrack.org/phrack/56/p56-0x05,May 2000)。从而绕过stackguard技术和Proplice技术对返回地址的保护,有效地实行缓冲区攻击。
三.

发明内容
本发明为了防止攻击者通过分析原程序或者分析编译后的目标程序,确定运行时堆栈结构,对计算机系统实行攻击,提出了一种新的堆栈内存管理方法。从而使攻击者无法准确确定返回地址的位置,无法通过改写返回地址来进行缓冲区溢出攻击。
本发明提出的动态内存管理方法是这样的在计算机程序执行时,每次子过程被调用并分配当前过程的堆栈空间时,象正常情况一样保存调用参数,返回地址。但是保存帧指针和分配局部变量的时候,在帧指针和局部变量起始地址之间分配一段额外内存空间或者在返回地址和帧指针之间额外分配一段额外内存空间。此额外空间的大小在程序执行的时候随机决定。这样堆栈内存中返回地址和局部变量的相对位置无法通过分析源程序或编译后的目标程序得到,可以有效地防止利用堆栈缓冲区溢出来对计算机系统进行攻击。
在分配局部参数内存空间时,在帧指针和局部变量起始地址之间多分配一段内存空间或者在返回地址和帧指针之间多分配一段内存空间。这样局部变量和返回地址之间的相对偏移就增加了一段额外的长度;这段额外长度的具体大小在每次运行开始时通过产生一个随机数获得。
本发明方法中额外长度的内存缓冲区中也可以放入类似StackGuard技术中的″canary″值,从而检测出当前执行程序是否正在被攻击。
如图1所示,本技术在分配局部参数的内存空间的时候,会在基址寄存器和局部变量之间多分配一段内存空间。这样局部变量和返回地址之间的相对偏移就增加了一段额外的长度。为了保证攻击者无法通过分析原程序或编译后的目标程序来推测出这段额外长度,本技术要求这段额外长度在静态分析编译后的目标代码时是未知的。额外长度的具体大小在每次运行的时候通过产生一个随机数获得。因此即使是同一个程序,每次执行的时候这段额外长度的值都会不一样。
由于攻击者无法准确预测出局部变量和返回地址间的相对偏移,无法准确将返回地址的值改向自己的恶意攻击程序。从而很难实施有效地缓冲区溢出攻击。
本发明的额外长度由随机函数发生器子程序来实现。
利用本发明编译完成的计算机目标程序执行时具有上述特征。相应的编译器能产生上述特征的目标程序。
本发明的优点本发明提出的一种新的对返回地址进行保护的方法,它可以同时检测出当前执行程序是否正在被攻击并可以防止被攻击。它的特点是无法通过静态地分析源程序或目标程序来推测获得返回地址和分配的局部变量之间的相对偏移。由于产生的额外的长度是随机的,即使使用动态跟踪工具跟踪执行目标程序,也无法确定下次执行时返回地址和分配的局部变量之间的相对偏移。攻击者由于无法事先知道返回地址的准确位置,无法修改返回地址,从而有效地防止了攻击者利用堆栈缓冲区溢出进行攻击。


图1传统程序运行时堆栈内存结构和使用本技术编译后的程序运行时堆栈内存结构(局部变量和返回地址之间增加了一段随即的长度)的示意2普通的程序执行时的堆栈内存结构图3使用缓冲区攻击后的程序执行时的堆栈内存结构图4使用本发明后堆栈调用时的结构图5一个C程序在启动保护功能前和启动保护功能后编译执行的结果如图5所示一个C程序在启动保护功能前和启动保护功能后编译执行后的结果。我们使用的编译器是公开原码的LINUX GCC。为了观察方便,在每次进入和退出子过程时打印出分配和释放的额外动态空间。在启动堆栈保护后,在程序每次启动执行时产生一个随机数。随机数的值每次执行时都不一样大。每次进入子过程时分配这段额外空间,而退出子过程时释放这段额外空间。当然在实际应用中额外空间的分配和释放都是在后台进行的,没有必要显示出来。
具体实施例方式
上面是本发明的基本原理,可以有多种实现方式。比如可以使用特别的内存设备(包括软件设备和硬件设备)来实现。也可以使用特别的计算机系统来实现。也可以改写编译器来生成具有上述功能的目标程序。总之本原理精神范围内的各种各样的实现方式都应该包括进来。下面举出一个示例来具体说明使用本方法的程序的执行过程。
I.正常程序的执行过程我们以图2为例来说明正常的程序执行流程。我们使用函数foo被函数bar调用的例子来加以说明。假设函数被调用时堆栈帧从高地址向低地址方向增长。图2中函数foo把环境变量ENV_STR的内容使用C语言的库函数getenv得到后,使用C语言的库函数strcpy拷贝到大小为128字节的字符串数组buffer中。foo被调用后,为了保存foo的动态执行环境,下面的信息被保存在堆栈中。

我们下面使用SP来代表堆栈指针,使用FP来代表帧指针,使用RA来代表返回地址。
●函数foo被调用前函数foo被调用前,堆栈指针(SP)指向堆栈帧的最底部,帧指针(FP)指向bar的前一堆栈帧的帧指针变量(FP)。从帧指针(FP)的下一个地址到堆栈指针(SP)之间存放了函数bar的局部变量。
●函数foo被调用后首先在堆栈中保存了foo的调用参数,然后保存了返回bar的返回地址。然后保存了前一帧指针(FP)。最后分配了foo的局部参数。此时堆栈指针(SP)指向最下位。函数foo便可以开始执行了。
●函数foo执行后函数foo执行终了后,按照上记的相反的顺序,堆栈指针(SP)和帧指针(FP)也回到了函数foo被调用前的值。然后返回到foo的返回地址RA指向的程序,继续执行bar部分的程序。
II.典型的缓冲区溢出攻击方式函数foo的堆栈构造很容易从foo的源程序和编译后的目标程序中分析出来。然后按照分析的结果来对执行的程序进行攻击。我们以图3来对攻击过程进行说明。假设攻击者已经改写了环境变量,在字符串拷贝的时候,返回地址被ADDR_X给覆盖了,而局部变量的内容被恶意攻击代码覆盖了。并且ADDR_X指向这段攻击代码。比如函数foo被调用后,会执行strcpy。由于strcpy一般不会检查输入字符串的大小,这样从局部变量一直到RA返回地址部分都被改写。函数foo执行结束后,没有返回到bar程序中继续执行,而是返回到了那段恶意攻击代码处。这样恶意攻击程序就掌握了主动权并开始执行。而且由于前帧指针也被改写了,返回到bar时正确的帧指针也无法正确得到。这样可能会发生不可预测的执行错误。
III.利用动态堆栈内存管理技术来防止缓冲区溢出攻击我们结合图4以函数foo被调用执行时候的堆栈构造过程为例来说明。首先目标程序象正常情况一样保存了调用参数,返回地址和帧指针,但是在分配局部变量的时候,本方法会动
III.利用动态堆栈内存管理技术来防止缓冲区溢出攻击我们结合图4以函数foo被调用执行时候的堆栈构造过程为例来说明。首先目标程序象正常情况一样保存了调用参数,返回地址和帧指针,但是在分配局部变量的时候,本方法会动态地分配比正常的局部变量需要的空间更大的内存空间。比如在图4中分配大小为alpha空间。alpha的具体大小在运行的时候随机动态地决定。(这个大小为alpha的缓冲区也可以被用做它用)。
在增加alpha大小的缓冲区后,帧指针的值可以指向图中虚线,也可以指向图中实线的位置。程序将随之使用不同的办法来查找调用参数和局部变量。使用本发明的堆栈内存管理方法,即使是同一段程序,每次执行的时候局部变量部分分配的额外空间大小可能都不一样。通过分析源程序和编译后的程序无法检测出返回地址的准确位置。因此很难有效地实施堆栈攻击。
可以使用随机函数发生器来产生随机大小的额外缓冲区长度一个具体的随机函数发生器的例子如下所示。
<pre listing-type="program-listing"><![CDATA[  static int randval=0;  RandomGenerator()  {  if(randval==0)  {  srand(time(0));  randval=rand()%100+10;  }  return randval;  }]]></pre>
权利要求
1.一种新型的动态堆栈内存管理方法。其特征是在计算机程序执行时,每次子过程被调用并分配当前过程的堆栈空间时,象正常情况一样保存调用参数,返回地址。但是保存帧指针和分配局部变量的时候,在帧指针和局部变量起始地址之间分配一段额外内存空间或者在返回地址和帧指针之间额外分配一段额外内存空间。此额外空间的大小在程序执行的时候随机决定。这样堆栈内存中返回地址和局部变量的相对位置无法通过分析源程序或编译后的目标程序得到,可以有效地防止利用堆栈缓冲区溢出来对计算机系统进行攻击。
2.由权利要求1所述的一种新型的动态堆栈内存管理方法,其特征是在分配局部参数内存空间时,在帧指针和局部变量起始地址之间多分配一段内存空间或者在返回地址和帧指针之间多分配一段内存空间。这样局部变量和返回地址之间的相对偏移就增加了一段额外的长度;这段额外长度的具体大小在每次运行的时候通过产生一个随机数获得。
3.由权利要求1所述的一种新型的动态堆栈内存管理方法,其特征是其中额外长度的内存缓冲区中也可以放入类似StackGuard技术中的″canary″值,从而检测出当前执行程序是否正在被攻击。
4.由权利要求1所述的一种新型的动态堆栈内存管理方法,其特征是权利要求1中所述的额外长度由随机函数发生器子程序来实现。
5.由权利要求1所述的一种新型的动态堆栈内存管理方法,其特征是计算机目标程序执行时具有上述权利要求1的特征。
6.由权利要求1所述的一种新型的动态堆栈内存管理方法,其特征是相应的编译器能产生权利要求1的特征的目标程序。
全文摘要
本发明公开了一种防止缓冲区溢出攻击的动态堆栈内存管理方法。在计算机程序执行的时候,由于返回地址和局部变量之间的相对位置随机动态地改变,无法改写返回地址,从而可以有效地防止利用缓冲区溢出来对计算机系统进行攻击。本发明包括以下
权利要求
动态堆栈内存管理方法,具有此动态堆栈内存管理特征的目标程序和能产生这种目标程序的编译器,具有此动态堆栈内存管理特征的内存设备(硬件设备或软件设备),具有此动态堆栈内存管理特征的计算机系统。
文档编号G06F1/00GK1564098SQ200410014600
公开日2005年1月12日 申请日期2004年4月9日 优先权日2004年4月9日
发明者龚如宾, 潘金贵 申请人:南京大学
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1