基于程序插桩和动态信息验证的栈保护方法与流程

文档序号:15518416发布日期:2018-09-25 18:51阅读:366来源:国知局

本发明属于计算机技术领域,尤其是系统与软件安全领域。本发明提供了一种基于程序插桩和动态信息验证的栈保护方法,用于检查堆栈数据的完整性,保护应用软件。



背景技术:

缓冲区溢出漏洞(bufferoverflow)能够影响运行进程堆栈数据的特点给软件安全带来了严重挑战。因此,保护软件在未知环境下正常运行,检测堆栈数据的完整性以及防止控制流劫持,成为系统与软件安全领域一个仍未完善解决的重要问题。数据完整性检测作为软件保护的一种方式,被广泛接受。程序插桩作为一种基本的测试手段,可以利用其在程序中插入的代码段对堆栈数据的完整性进行检测,防止程序的控制流被恶意劫持。

程序插桩:在保证被检测程序原有逻辑完整性的基础上,在程序中插入用于信息采集的代码段,通过代码段的执行并抛出程序运行的特征数据,通过对这些数据的分析,可以获得程序的控制流和数据流信息,从而实现数据完整性检测的目的。

gcc编译器与gcc插件:gcc编译器作为编译器的一种,主要的工作是将汇编或者高级计算机语言源程序(sourceprogram)作为输入,翻译成目标语言(targetlanguage)机器代码的等价程序。翻译过程包括四个相互关联的步骤:预处理,编译,汇编和链接。gcc插件使开发人员可以向编译器添加新功能,而无需修改编译器本身。gcc的插件功能提供了以下几个优点:1)缩短了构建和测试新功能所需的时间,只需要编译实现新功能所需的代码,即gcc不需要被引导;2)允许开发和维护由于某种原因不适合包含在gcc发行版中的编译器特征;3)简化了需要修改gcc,但没有时间深入到编译器内部的开发人员的工作。

栈保护:栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让恶意代码(以下统一使用shellcode)能够得到执行。当启用栈保护后,函数开始执行的时候会先往栈里插入验证信息(以下统一使用canary),当函数真正返回的时候会验证canary信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将canary信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。

现有的栈保护方法包括以下几种:

1)数据执行保护(dataexecutionprevention,dep)。缓冲区溢出攻击通常在其它程序的内存缓冲区写入可执行的恶意代码,然后诱骗程序执行恶意代码。使用dep的目的是阻止恶意插入代码的执行,其运行机制是,操作系统利用dep标记只包含数据的内存位置为非可执行(no-execute,nx),当应用程序试图从标记为nx的内存位置执行代码时,操作系统的dep逻辑将阻止应用程序这样做,从而达到保护系统防止溢出。

2)基于安全区思想的影子栈(shadowstack)。通过将数组放入该影子栈中来防止对数组的溢出而改写返回地址。

3)基于数据完整性行检测的stackguard。stackguard的做法是在函数栈桢的返回地址之前插入随机值canary,并在函数返回之前检测canary的值是否被篡改,如果canary未被篡改,函数正常退出。否则,程序的控制流导向到错误处理模块执行。

共享库:共享库在程序的链接时候并不像静态库那样在拷贝使用函数的代码,而只是作些标记。然后在程序开始启动运行的时候,动态地加载所需模块。所以,应用程序在运行的时候仍然需要共享库的支持。共享库安装正确后,所有启动的程序将自动使用新的共享库。linux系统下,允许用户:1)更新库,并仍然支持旧的库;2)在执行特定程序时覆盖库中的特定库甚至特定功能。

hook技术:hook中文翻译为“钩子”(以下统一使用hook)。在编程中,hook表示一个可以允许编程者插入自定义程序的地方,通常是打包好的程序中提供的接口。通过hook,开发者可以暂停系统调用,或者通过改变系统调用的参数来改交正常的输出结果,甚至可以中止一个当前运行中的进程并且将控制权转移到自己手上。



技术实现要素:

在现有工作的基础上,本发明的目的在于:提出一种新的基于程序插桩和动态信息验证的栈保护方法,解决现有栈保护方法中的易被破解、性能损耗严重、可部署性差等问题。

本发明的技术方案为:基于程序插桩和动态信息验证的栈保护方法,其特征是实现地址无关的动态共享库、hook关键函数、分配canary缓冲区(randomcanarybuffer,rcb)、实现gcc插件;

本发明具体包括以下步骤:

1)实现地址无关的动态共享库(以下统一使用libmultiguard)、hook关键函数;

2)实现基于gcc的multiguard插件(以下统一使用multiguard),插入放置、检查canary以及错误处理的代码段;

进一步:

步骤1)中,地址无关的动态共享库主要有两部分作用:功能函数的实现和关键函数的重写。共享库中的功能函数主要负责rcb的分配与设置、canary的生成与更新等。共享库重写部分库函数的目的在于:在linux操作系统的动态链接库中,ld_preload作为一个环境变量,可以影响程序的运行时的链接(runtimelinker),它允许用户定义在程序运行前优先加载的动态链接库。链接器(loader)在进行动态链接的时候,会将有相同符号名的符号覆盖成ld_preload指定的.so文件中的符号。基于此,可以通过自己.so库中的函数替换原来库里有的函数,从而达到hook的目的。以得到的共享库为基础,通过改写的进程创建函数pthread_create,在main函数调用之前,分配canary缓冲区,设置线程局部存储区(threadlocalstorage,tls)偏移,保存rcb入口地址、大小以及索引信息。rcb分配完毕后,canary生成函数按照缓冲区的大小随机生成非重复的canaries,顺序放置于rcb中。

步骤2)中,以步骤1)得到的存有多个不同canaries的缓冲区为基础,源代码通过gcc编译器进行编译时,开启multiguard选项,在不影响程序原本语义的情况下,插入放置、检查canary以及错误处理的代码段。放置指令主要通过tls偏移中保存的canary缓冲区入口地址和当前索引信息,获取canary,放置到当前函数栈桢的返回地址之前,每个函数栈桢上保存的canary值均不相同。检查指令主要负责从tls偏移中取出当前canary,比较其与栈上保存的canary是否一致,如果一致则判断程序未受到攻击,函数正常退出。否则,系统判断程序受到攻击,错误处理指令将程序的控制流导向错误处理模块。

通过采用以上技术方案,本发明具有以下优点:

1.适用性广泛:本发明是通过gcc插件以及一个共享库来工作的,对于有安全需求的软件,尤其是商业软件,只需在gcc编译时开启multiguard保护选项,编译后的软件在运行时加载此共享库,就能达到保护软件的目的。同时,根据不同的需求,不同软件可以定制适合自身的共享库。

2.可部署性强:本发明的保护机制向后兼容了传统栈保护方法,开启multiguard保护的模块和传统模块间能够正常工作。本发明插桩是对汇编程序插入功能代码段,期间不依赖任何硬件处理器特性,可部署在绝大部分硬件处理器架构之上,可部署性强。

3.程序性能损耗低:本发明在设计上力图最大限度的遵循传统的栈保护框架,仅监控有限的函数,使得受保护程序执行速度损耗非常的低。

附图说明

图1为本发明实施例的基于程序插桩和动态信息验证的栈保护方法的部署图

图2为本发明实施例的基于程序插桩和动态信息验证的栈保护方法的程序插桩图。

图3为本发明实施例的基于程序插桩和动态信息验证的栈保护方法的工作原理图。

图4为本发明实施例的基于程序插桩和动态信息验证的栈保护方法的工作流程图。

图5为本发明实施例的基于程序插桩和动态信息验证的栈保护方法的验证信息更新图。

具体实施方式

本发明方法首先编写动态共享库libmultiguard.so,包含被重写的库函数和功能函数。重写库函数的目的是在函数调用时,额外执行用户自定义的行为,pthread_create、fork函数被重写后,在创建进程时,同时分配了用户指定的canary缓冲区,缓冲区的入口地址、大小以及索引信息保存在tls中;功能函数包含canary的生成与放置、canary缓冲区的擦除。同时,本发明方法实现了一个gcc插件multiguard,用于在源程序编译时插入放置、检查canary以及错误处理的代码段,每个函数发生调用时,动态地从canary缓冲区中取canary,并将其压栈到该函数栈桢的返回地址之前8个字节,函数调用结束时,检查与错误处理指令检查栈上保存的canary是否与canary缓冲区中的值一致,如果一致,函数正常返回,否则,程序控制流导向错误处理模块。动态库libmultiguard.so和multiguard插件的工作方式为:源程序在gcc编译器进行编译时,开启multiguard选项,得到插桩过的可执行程序,程序通过ld_preload加载libmultiguard.so,这样程序在调用pthread_create函数或者fork函数时,就调用了libmultiguard.so中改写过的函数,进程或子进程被创建的同时,分配了canary缓冲区、随机生成了多个canaries并放置到缓冲区中。然后,系统调用main函数,程序开始执行,随着函数的调用,每个函数均在栈上有一个栈桢,multiguard插件插入到每个函数中的代码段,在函数发生调用时,从canary缓冲区中取出canary压到函数返回地址之前;在函数调用结束时,校验canary是否被篡改,做相应处理。本发明方法通过共享库libmultiguard.so和multiguard插件,动态校验栈上数据的完整性,从而起到保护软件的作用,也能有效防止暴力破解canary。

下面结合本发明的相关说明图与具体实施:intel-x86架构和linux系统上基于程序插桩和动态信息验证的栈保护方法的实现做进一步说明。

第一步:编写libmultiguard.so的c++源文件。主要包括功能函数和被改写的库函数。功能函数主要有:

功能函数renew_canary生成canary的方法是读取linux系统下的/dev/random文件,利用系统当前系统的熵池来计算出固定一定数量的随机比特,然后将这些比特作为字节流返回。_multi_start_routine函数负责为rcb分配内存空间,获取线程的tls地址,初始化与rcb相关的tls中的条目。

重写的库函数主要包括:

函数pthread_create的重写主要添加了rcb的分配、tls相关条目的初始化工作,这一工作通过_multi_start_routine函数实现。重写的fork函数中额外调用了thread_cab_free和update_canaries两个函数。fork函数调用结束后,在子进程中,除调用fork函数的线程外,其他线程的rcb均被thread_cab_free函数清空,重新建立tid_tls_map。然后,update_canaries函数负责重新为rcb赋值,刷新canaries。longjmp和setjmp函数作为非局部跳转语句,可以在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。此时,如果multiguard栈保护机制如果不做处理,函数即使未受攻击,canary校验仍会出错。改写的longjmp函数额外做了如下工作:获取跳转后栈顶指针,调用_multi_unwind_rcb函数,弹出栈上当前栈顶指针所指向位置下面的所有canaries,使得rcb中的索引与栈上每个函数栈桢保存的canary一一对应。

第二步:以得到的动态共享库为基础,实现基于gcc编译器的multiguard插件。从v4.5.1开始,gcc增加了对在整个翻译过程中使用的各种中间语言(il)之上操作的插件来扩展编译流水线的支持。gcc流水线包括三个不同的组件,即前端,中端和后端,将输入转换为generic,gimple和rtlil。generic是一种由每个前端生成的语言无关的表示,它用来作为解析器和优化器之间的接口,gimple和rtl用于优化程序。multiguard被注册为rtl优化过程,并在vartrack过程之后由gcc加载。将multiguard放在rtl优化管道中的第一个原因是确保大多数重要的优化已经执行,因此,multiguard的插桩代码不会被添加到无关的代码中。此外,以这种方式,能确保所有执行特定功能的注入指令保持在其适当位置,并且不会在以后的过程中被优化。

multiguard在tls中保存了rcb的起始地址、大小以及索引。在x86-64体系结构下,tls中从0x2a0到0x2b8的偏移作为保留区域未被使用,由于寄存器fs偏移0的位置保存了tls地址,multiguard将fs偏移0x2a0的位置保存rcb基址,fs偏移0x2b0的位置保存了rcb大小,fs偏移0x2b8的位置保存了multiguard下canary的值。同时,为了确保与当前glibc版本兼容,fs偏移0x28的位置保留了传统stackguard机制下的canary。下面详细介绍multiguard插入的指令及其作用:

(1)pushr13

(2)pushr14

(3)mov%fs:0x2a0,%r13

(4)mov%fs:0x2a8,%r14

(5)mov(%r13,%r14,8)%rax

(6)mov%rax,-0x8(%rbp)

(7)incq%fs:0x2a8

(8)pop%r14

(9)pop%r13

(10)xor%fs:0x2b8,%rcx

(11)decq%fs:0x2a8

指令(1)至(4)中寄存器r13用于保存rcb基址,r14用于保存rcb的索引;指令(5)读取rcb当前索引指向的canary到寄存器rax中;指令(6)将取出的canary压到栈上;指令(7)将rcb的索引值加一;指令(8)至(9)将寄存器r14,r13弹出;指令(10)校验栈上保存的canary是否被篡改。其中指令(1)至(5)在插桩代码段中负责读取rcb中的canary,指令(10)负责canary完整性的校验工作,错误处理任务交由__stack_chk_fail函数处理。

综上,本发明可以有效地解决传统的canary保护机制中所有函数的校验信息相同、易被暴力破解的缺陷,显著提高了软件的安全性。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1