软件栈缓冲区溢出的容错方法转让专利

申请号 : CN201110396474.9

文献号 : CN102521079B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 金海邹德清郑伟德陈刚羌卫中

申请人 : 华中科技大学

摘要 :

本发明提供了一种软件栈缓冲区溢出的容错方法,包括以下步骤:获取容错保护的目标程序,对目标程序的二进制可执行文件进行解析,以识别出目标程序中的函数和函数中栈缓冲区的信息,将动态插桩工具附加到目标程序的所有线程之上,用动态插桩工具拦截目标程序的函数调用和函数返回,判断拦截结果是否为目标程序的函数调用,若是,则用动态插桩工具拦截对栈缓冲区的初始化操作,在目标程序的堆空间中分配堆缓冲区,使其与栈缓冲区映射,将栈缓冲区与堆缓冲区的映射关系保存到映射表中,映射关系包括栈缓冲区的信息和堆缓冲区的信息,用动态插桩工具拦截所有内存访问操作,以获得内存访问操作的虚拟有效地址,本发明实现了对栈缓冲区溢出进行容错。

权利要求 :

1.一种软件栈缓冲区溢出的容错方法,包括如下步骤:获取容错保护的目标程序;

对所述目标程序的二进制可执行文件进行解析,以识别出所述目标程序中的函数和所述函数中栈缓冲区的信息;

将动态插桩工具附加到所述目标程序的所有线程之上;

用所述动态插桩工具拦截所述目标程序的函数调用和函数返回;

判断拦截结果是否为所述目标程序的函数调用;

若所述拦截结果不是所述目标程序的函数调用,则在所述函数返回前,对所述函数映射的堆缓冲区进行回收;

判断所述函数返回是否为所述目标程序的主函数返回;

若所述函数返回为所述目标程序的主函数返回,则流程结束,否则返回所述用所述动态插桩工具拦截所述目标程序的函数调用和函数返回的步骤;

若所述拦截结果是所述目标程序的函数调用,则用所述动态插桩工具拦截对所述栈缓冲区的初始化操作,在所述目标程序的堆空间中分配堆缓冲区,使其与所述栈缓冲区映射;

将所述栈缓冲区与所述堆缓冲区的映射关系保存到映射表中,所述映射关系包括所述栈缓冲区的信息和所述堆缓冲区的信息;

用所述动态插桩工具拦截所有内存访问操作,以获得所述内存访问操作的虚拟有效地址;

将所述虚拟有效地址与所述映射表中所述栈缓冲区的信息进行比较,以判断所述虚拟有效地址是否处于被映射到所述堆缓冲区的栈缓冲区中;

若所述虚拟有效地址处于被映射到所述堆缓冲区的栈缓冲区中,则通过所述动态插装工具将所述虚拟有效地址重定向到所述堆缓冲区中,并返回所述用所述动态插桩工具拦截所有内存访问操作,以获得所述内存访问操作的虚拟有效地址的步骤;

若所述虚拟有效地址不处于被映射到所述堆缓冲区的栈缓冲区中,则不修改所述虚拟有效地址,然后返回所述用所述动态插桩工具拦截所有内存访问操作,以获得所述内存访问操作的虚拟有效地址的步骤。

2.根据权利要求1所述的容错方法,其特征在于,分配所述堆缓冲区时,以所述堆缓冲区为粒度进行随机化排布。

3.根据权利要求1所述的容错方法,其特征在于,所述堆缓冲区的大小为所述函数中栈缓冲区的大小的Q倍,Q为大于1的正整数。

说明书 :

软件栈缓冲区溢出的容错方法

技术领域

[0001] 本发明属于计算机安全领域,具体涉及一种软件栈缓冲区溢出的容错方法。

背景技术

[0002] 当前对栈缓冲区溢出问题,存在一些解决方案来防止利用栈缓冲区溢出执行来未经授权的代码,主要分为静态检测和动态保护两类方法。静态检测方法主要有基于源代码的静态检测和基于目标代码的检测。ITS、Splint和MOPS是静态分析方法的3种代表性工具。这一类方法能识别出与漏洞库函数相关的部分缓冲区溢出、格式化串溢出和文件系统中的竞争条件漏洞。动态保护是指在程序运行过程中进行动态的防范,阻止攻击者在栈缓冲区溢出后将函数返回地址修改成恶意代码并加以运行。StackGuard、StackShield、和随机地址空间分配是这一类方法的代表。StackGuard通过修改编译器,在函数返回地址前面添加一个检测标记值。当函数返回时,如果发现检测标记值发生变化,则推断堆栈正被人试图攻击,程序进程将会中断。StackShield通过修改编译器,创建一个特别的表来储存函数的返回地址的一份拷贝。它在受保护的函数的开头和结尾分别添加一段代码,开头处的代码被用来将函数返回地址拷贝到这个特殊的表中,而结尾的代码被用来将返回地址从表中拷贝回堆栈。随机地址空间分配方法是通过修改操作系统内核,在程序装载时,对栈段、共享库段映射等线性区的基址进行随机化,防止攻击者定位攻击代码位置,达到阻止溢出攻击的目的。
[0003] 然而,上述方法在解决栈缓冲区溢出时还有较大不足。静态检测方法有高误报率和高漏报率的问题。而动态保护方案只能防止利用栈缓冲区溢出来执行未经授权的代码,只保证安全性,而不能对栈缓冲区溢出进行容错,不能保证程序执行的正确性及可靠性。另外在实现上,上述方法要求的条件强,需要得到程序的源代码,并用修改过的编译器对程序的源代码进行重新编译。

发明内容

[0004] 本发明的目的在于提供一种软件栈缓冲区溢出的容错方法,其在软件运行时,利用动态插桩技术将栈缓冲区映射为堆缓冲区,实现对栈缓冲区溢出进行容错,同时使得发生栈缓冲区溢出错误的软件能够正确的继续运行下去,且不需要得到程序源代码,也不需要修改编译器。
[0005] 本发明是通过以下技术方案实现的:
[0006] 一种软件栈缓冲区溢出的容错方法,包括如下步骤:获取容错保护的目标程序,对目标程序的二进制可执行文件进行解析,以识别出目标程序中的函数和函数中栈缓冲区的信息,将动态插桩工具附加到目标程序的所有线程之上,用动态插桩工具拦截目标程序的函数调用和函数返回,判断拦截结果是否为目标程序的函数调用,若拦截结果是目标程序的函数调用,则用动态插桩工具拦截对栈缓冲区的初始化操作,在目标程序的堆空间中分配堆缓冲区,使其与栈缓冲区映射,将栈缓冲区与堆缓冲区的映射关系保存到映射表中,映射关系包括栈缓冲区的信息和堆缓冲区的信息,用动态插桩工具拦截所有内存访问操作,以获得内存访问操作的虚拟有效地址,将虚拟有效地址与映射表中栈缓冲区的信息进行比较,以判断虚拟有效地址是否处于被映射到堆缓冲区的栈缓冲区中,若虚拟有效地址处于被映射到堆缓冲区的栈缓冲区中,则通过动态插装工具将虚拟有效地址重定向到堆缓冲区中,并返回用动态插桩工具拦截所有内存访问操作,以获得内存访问操作的虚拟有效地址的步骤。
[0007] 本发明还包括步骤:若拦截结果是目标程序的函数调用,则在函数返回前,对函数映射的堆缓冲区进行回收,判断函数返回是否为目标程序的主函数返回,若函数返回为目标程序的主函数返回,则流程结束,否则返回用动态插桩工具拦截目标程序的函数调用和函数返回的步骤。
[0008] 本发明还包括步骤:若虚拟有效地址不处于被映射到堆缓冲区的栈缓冲区中,则不修改虚拟有效地址,然后返回用动态插桩工具拦截目标程序的函数调用和函数返回的步骤。
[0009] 分配堆缓冲区时,以堆缓冲区为粒度进行随机化排布。
[0010] 堆缓冲区的大小为栈缓冲区的大小的Q倍,Q为大于1的正整数。
[0011] 本发明具有以下优点:
[0012] (1)本发明能够对栈缓冲区溢出提供容错保护。不仅能够在栈缓冲区溢出发生时保护函数返回地址不被修改,还使得溢出不会造成栈缓冲区之间互相覆盖,既保证了安全性又能保证程序行为的正确性。
[0013] (2)本方法只要求得到程序的二进制可执行文件,不需要对程序的源代码进行重新编译。
[0014] (3)本方法能够动态的附加到程序的线程上,对其提供栈缓冲区溢出的容错保护,不需要时可以动态的撤销保护,灵活性较高。

附图说明

[0015] 图1是本发明软件栈缓冲区溢出的容错方法的流程图。

具体实施方式

[0016] 下面结合附图和具体实施方式对本发明做进一步说明。
[0017] 如图1所示,本发明方法包括以下几个步骤:
[0018] (1)获取容错保护的目标程序;
[0019] (2)对容错保护的目标程序二进制可执行文件进行目标代码解析或调试信息解析,识别出目标程序中的函数的集合F和函数中栈缓冲区的信息的集合I。F={f1,f2,...,fn},其中n为目标程序所包含函数的个数,fi代表一个函数。定义fi中所包含的缓冲区的信息集合为Bi={b1,b2,...,bm},bj代表一个栈缓冲区的信息。bj是一个二元组{bj.o,bj.l},bj.o是栈缓冲区的起始偏移地址,bj.l是栈缓冲区的长度,栈缓冲区的信息的集合[0020] (3)将动态插桩工具附加到目标程序的所有线程之上;
[0021] (4)动态插桩工具拦截目标程序的函数调用和函数返回;
[0022] (5)判断拦截结果是否为函数调用,如果是,则转入步骤(6),否则转入步骤(12);
[0023] (6)用动态插桩工具拦截被调用的函数fi所包含的栈缓冲区Bi={b1,b2,...,bm}的初始化操作,在堆空间中分配堆缓冲区hbj与栈缓冲区bj映射。hbj的长度是bj.l×Q,堆缓冲区利用Q倍的冗余对溢出进行容错,防止溢出时覆盖其他缓冲区,Q值由用户指定,且为大于1的正整数,其值越大则发生溢出时缓冲区互相覆盖的概率越小,容错成功的几率越高。堆缓冲区分配时以缓冲区为粒度进行随机化排布,通过打乱各缓冲区之间的相对位置来加强安全性;
[0024] (7)将栈缓冲区bj的信息二元组{bj.o,bjl}与堆缓冲区hbj的起始偏移地址hbj.o合并成一个三元组{bj.o,bj.l,hbj.o},表示堆缓冲区hbj与栈缓冲区bj的映射关系,将该三元组保存到一个映射表中。通过维护该映射表,可得到栈缓冲区与堆缓冲区的映射信息。
[0025] (8)函数fi执行过程中,用动态插桩工具拦截fi的所有内存访问操作,获得内存访问操作虚拟有效地址EA。
[0026] (9)将虚拟有效地址EA与映射表中包含的栈缓冲区的信息进行比较,以判断虚拟有效地址是否处于被映射到堆缓冲区的栈缓冲区中。如果满足条件则转入步骤(10),否则转入步骤(11);
[0027] (10)利用动态插桩代码将虚拟有效地址EA修改为hbj.o+bj.l*Q/2,即把内存访问虚拟有效地址重定向到EA所在栈缓冲区映射的堆缓冲区中,这样,如果目标程序对缓冲区的写操作发生溢出,只会覆盖堆缓冲区中的冗余部分,不会影响程序的正确执行,也不会产生覆盖函数返回地址的安全问题,然后返回步骤(8);
[0028] (11)对虚拟有效地址EA不做修改,然后返回转入步骤(8);
[0029] (12)函数返回前,对该函数(记为fi)映射的堆缓冲区进行回收,即,如果映射表中的三元组{bj.o,bj.l,hbj.o}满足{bj.o,bj.l}∈Bi,则释放起始偏移地址为hbj.o的堆缓冲区,并在映射表删除该三元组;
[0030] (13)判断返回的函数fi是否是目标程序的主函数返回,如是,则流程结束,否则返回步骤(4)。