法律状态公告日
法律状态信息
法律状态
2017-09-29
授权
授权
2015-09-30
实质审查的生效 IPC(主分类):G06F21/57 申请日:20150616
实质审查的生效
2015-09-02
公开
公开
技术领域
本发明属于应用程序技术领域,尤其涉及一种针对虚函数表劫持攻击的防 御方法。
背景技术
内存破坏漏洞(memory corruption bugs)广泛存在于使用C/C++等低级语言 编写的程序中,栈溢出、堆溢出、释放后重用等漏洞均属于内存破坏漏洞。攻 击者利用此类漏洞,可以控制应用程序内存中的数据、代码,改变程序行为甚 至劫持程序的控制流。
现有技术中有以下两种处理方式:
VTGuard:VTGuard是部署在IE浏览器中的一项虚函数表保护技术。其基 本思想是:在每个虚函数表中插入一个私密的cookie,并在虚函数被调用时进行 检查,当前表中的cookie和对应的cookie是否一致,如果不一致则会禁止此次 调用。该方案能够有效减少虚函数表重用攻击,但对虚函数表破坏和虚函数表 注入攻击无效。
SafeDispatch:SafeDispatch是基于编译器的虚函数表劫持攻击防御方案,它 首先对整个程序的类关系进行分析,推断出程序中有效的虚函数表集合及虚函 数集合;接着在虚函数被调用时进行安全校验,检查当前虚函数及虚函数表是 否在有效集合中,若不在则禁止此次调用。对于虚函数的检查,将带来7%的额 外开销;对于虚函数表的检查,将带来30%的额外开销,且对虚函数表破坏攻 击无效。
DieHard:DieHard提供了自定义的内存分配器,在进行内存分配时实现随 机化及隔离。该技术方案在某种程度上对虚函数表劫持攻击有效,但存在不确 定性。
但是上述方案中,均存在以下缺陷:有效性:VTGuard、SafeDispatch、DIeHard 均无法保证对所有类型的虚函数表劫持攻击进行有效防护;二进制兼容: VTGuard、SafeDispatch以及DieHard均不二进制兼容,即需要源代码。而在实 际中获取目标保护程序的源码是极其困难的;系统开销:SafeDispatch所带来的 系统开销(%7与%30)使其很难应用于实际中。
发明内容
为解决上述问题,本发明提供一种针对虚函数表劫持攻击的防御方法。本发 明基于二进制重写技术,不需要源码即可完成部署;且能够有效防护程序中的 重要对象,不受虚函数表劫持攻击的影响;而本发明所带来的系统开销也在可 接受范围之内。
本发明的针对虚函数表劫持攻击的防御方法,其包括:
步骤一、构建有效虚函数表集合和有效虚函数集合;有效虚函数表集合用 于存储虚函数表指针,虚函数表指针指向虚函数表;有效虚函数集合用于存储 虚函数表,虚函数表用于存储虚函数指针,虚函数指针指向虚函数;
步骤二、确定可执行程序中可能被虚函数表劫持攻击、需要被保护的对象 和对象中的虚函数,分析得到虚函数数据的读取地址和虚函数的调用地址;其 中,虚函数数据包括:虚函数表指针和虚函数表;同一个对象的不同虚函数数 据采用相同读取地址,且虚函数数据中的虚函数表指针和虚函数表采用相同读 取地址;
步骤三、在可执行程序的运行过程中,采用动态二进制插装方式,在虚函 数数据的读取地址处插装备份回调函数,在虚函数的调用地址处插装校验回调 函数;
步骤四、当可执行程序执行到某个对象X的虚函数数据对应的备份回调函 数时,在该备份回调函数中,将对象X的虚函数表指针及其指向的虚函数表进 行备份,其中虚函数表指针备份到有效虚函数表集合中,虚函数表备份到有效 虚函数集合中;
步骤五、当可执行程序执行到某个虚函数对应的校验回调函数时,在校验 回调函数中,检查被调用的虚函数所在的虚函数表的虚函数表指针Y是否在有 效虚函数表集合中;
若虚函数表指针Y不在有效虚函数表集合中,则校验失败、拒绝调用虚函 数,并立即终止该可执行程序;
若虚函数表指针Y在有效虚函数表集合中,则根据备份的有效虚函数表集 合和有效虚函数集合,找到虚函数表指针Y指向的虚函数表Z;判断被调用的 虚函数指针是否在虚函数表Z中,若在则校验成功,运行可执行程序调用虚函 数,否则校验失败、拒绝调用虚函数,并终止该可执行程序。
进一步的,步骤四中备份后将备份数据所在的内存页的访问属性修改为只 读。
有益效果:
本发明通过二进制插装技术,在对象实例化时插装代码对虚函数表指针及 虚函数表进行备份;在对象的虚函数被调用时,依据当前虚函数表指针和虚函 数指针与原有值进行比对以判断是否能够进行调用。通过这种方式,本发明在 二进制层面对虚函数表进行了防护,有效保护对象不受虚函数表劫持攻击的影 响。
附图说明
图1(a)为本发明的针对虚函数表劫持攻击的防御方法示意图;
图1(b)为本发明的备份数据示意图;
图1(c)为本发明的校验过程流程图;
图2为可执行程序调用虚函数的代码示意图;
图3(a)为本发明的实施例中对象d的类结构;
图3(b)为本发明的实施例中对象d的虚函数表内存布局。
具体实施方式
PE文件中有多个对象,其中部分对象的虚函数表易受到攻击者的攻击,夺 取程序的控制流,执行危险代码,影响系统安全。
本发明技术方案如图1(a)所示。首先,对待保护的PE文件进行预分析,得 到需要保护对象的虚函数表的生成处及虚函数的调用处;接下来,在生成处及 虚函数调用处进行插装,添加对目标程序的防护。为了对目标程序进行插装, 需要通过预分析得到:1.虚函数表生成位置,以便进行插装进行数据备份;2.虚 函数调用位置,以便进行插装在调用时做安全验证。目前有多种针对二进制文 件的分析方法可以实现这个目标,包括自动分析平台、静态分析、动态分析等。
本发明的针对虚函数表劫持攻击的防御方法,其包括:
步骤一、构建有效虚函数表集合和有效虚函数集合;有效虚函数表集合用 于存储虚函数表指针,虚函数表指针指向虚函数表;有效虚函数集合用于存储 虚函数表,虚函数表用于存储虚函数指针,虚函数指针指向虚函数。
步骤二、确定可执行程序中可能被虚函数表劫持攻击、需要被保护的对象 和对象中的虚函数,分析得到虚函数数据的读取地址和虚函数的调用地址;其 中,虚函数数据包括:虚函数表指针和虚函数表;同一个对象的不同虚函数数 据采用相同读取地址,且虚函数数据中的虚函数表指针和虚函数表采用相同读 取地址;
其中获得虚函数调用地址的方式为:
通过网络获得攻击代码,修改攻击代码对虚函数指针或虚函数表指针的赋 值语句,在可执行程序调用虚函数且该虚函数在被修改后的攻击代码攻击时, 可执行程序报错,则可执行程序报错时可执行程序所执行的指令地址即为虚函 数的调用位置。
获得虚函数数据的读取地址的方式为:
在可执行程序中分析虚函数调用时的代码,追踪该虚函数所属对象的数据 流以确定对象的虚函数数据的读取位置。
步骤三、在可执行程序的运行过程中,采用动态二进制插装方式,在虚函 数数据的读取地址处插装备份回调函数,在虚函数的调用地址处插装校验回调 函数。
步骤四、当可执行程序执行到某个对象X的虚函数数据对应的备份回调函 数时,在该备份回调函数中,将对象X的虚函数表指针及其指向的虚函数表进 行备份,其中虚函数表指针备份到有效虚函数表集合中,虚函数表备份到有效 虚函数集合中。
步骤五、当可执行程序执行到某个虚函数对应的校验回调函数时,在校验 回调函数中,检查被调用的虚函数所在的虚函数表的虚函数表指针Y是否在有 效虚函数表集合中;
若虚函数表指针Y不在有效虚函数表集合中,则校验失败、拒绝调用虚函 数,并立即终止该可执行程序;
若虚函数表指针Y在有效虚函数表集合中,则根据备份的有效虚函数表集 合和有效虚函数集合,找到虚函数表指针Y指向的虚函数表Z;判断被调用的 虚函数指针是否在虚函数表Z中,若在则校验成功,运行可执行程序调用虚函 数,否则校验失败、拒绝调用虚函数,并终止该可执行程序。
进一步的,步骤四中备份后将备份数据所在的内存页的访问属性修改为只 读。
图2中给出了对某程序反编译后(Intel语法)得到的调用虚函数的过程。 在程序中调用虚函数包括三步:第一步为获得调用该虚函数的对象地址,然后 获取该对象首地址处所存储的虚函数表地址(该虚函数表在内存中的起始地址), 最终根据调用指令获得被调用的虚函数在虚函数表中的偏移量,根据该偏移量 去调用该虚函数。其中,若该对象存在虚函数表,则其虚函数表位于该独享的 前端。其中eax寄存器中存放的为对象首地址,ecx寄存器为虚函数表指针,其 值为虚函数表的地址。从调用过程可以看出,无论虚函数表指针被篡改(虚函 数表注入/重用攻击)或是虚函数表(虚函数表破坏攻击)被篡改,都将使得程 序控制流完整性遭到破坏。
现假设通过预分析阶段得知,某对象在完成虚函数表的分配后将虚函数表 地址(虚函数指针)存入eax寄存器中,此时的代码位置为set_address;在 call_address1….call_addres10处存在该对象的虚函数调用,调用指令为cal [ecx+14c]、call[ecx+20c]等。
在set_address地址处进行插装。备份寄存器eax中存储的虚函数表指针,并 依次备份被调用的虚函数指针。被调用的虚函数指针可以通过调用指令获得其 位于虚函数表中的位置,例如call[ecx+14c],则意味着在虚函数表中偏移量为14c 处的虚函数被调用,需要进行备份。将所有备份的被调用的虚函数指针,称为 有效虚函数表集合。虚函数表指针及虚函数指针备份在新申请的内存页中,当 备份操作完成后,将当前页的属性设为只读。
有效性分析:本发明在虚函数调用时会对虚函数表指针进行校验,因此能 够有效防御虚函数表重用攻击及虚函数表注入攻击;而对调用的虚函数指针的 备份则保证了程序不受虚函数表破坏攻击的影响。同时,本发明将数据备份在 内存的只读页中。在本发明所定义的威胁模型下,尽管攻击者扫描到了备份数 据,也无法进行篡改。
上述虚函数表(virtual table,简称虚表或vtable):C++的动态多态是由虚函 数(Vitrual Function)实现的。每个含有虚函数的类都有一张虚函数表,表中的 每一项是一个虚函数的地址,虚函数表解决了继承、覆盖的问题。
虚函数表劫持攻击(vtable hijacking attack)指通过篡改虚函数表或虚函数表 指针(指向虚函数表的指针,其值为虚函数表起始地址),而达到劫持程序控制 流目的的一类攻击。
对于被防护程序,本发明假设:被防护程序为PE格式文件;二进制文件没 有进行代码混淆;程序由gcc、visual C++等主流编译器生成。
对象虚函数表内存布局:当使用父类的指针操作一个子类的时候,虚函数 表就像一张地图,指明了实际应该调用的函数。通过遍历表中的函数指针,便 可以调用相应的虚函数。图3(a)展示了对象d的类结构,图3(b)描述了对象d的 虚函数表内存布局,从图中可以看出,每个父类有自己的虚表,子类的虚函数 被放到了第一个父类(以声明顺序决定)的虚表中;被子类覆盖的虚函数放在 虚表中原父类虚函数的位置,没有被覆盖的函数不变;如图3(b),对象的虚函数 表指针位于对象内存布局中靠前的位置;图3(a)中Base1中依次声明了f()、g()、 h()三个虚函数,由图3(b)中Base1的虚函数表可以看出,虚函数按照其声明 顺序放于表中;图3(a)Derive类类图,该类为多重继承且子类覆盖了父类的一个 虚函数f();(b)Derive类对象d的内存布局,虚函数表指针位于对象实例中靠 前的位置,它指向该对象的各个虚函数表,父类虚函数表中的f()的位置被替换 成了子类的函数指针。
虚函数表劫持攻击的主要方式包括:
1.虚函数表破坏(vtable corruption):攻击者覆盖虚函数表中存储的虚函数 指针来达到攻击目的。
2.虚函数表注入(vtable injection):攻击者覆盖虚函数表指针,令该指针指 向由攻击者构造的虚函数表。这种方式可靠且高效,是攻击者最常采用的攻击 方法。
3.虚函数表重用(vtable reuse):攻击者覆盖虚函数表指针,令该指针指向 内存中已存在的虚函数表。此种方式利用难度高且并不稳定,目前并未在实际 攻击中出现
二进制插装是指在二进制层面对程序进行修改,通过增加、删除、修改代 码,达到增加功能、监视程序运行等目的。
本发明假设攻击者满足以下条件:
1.攻击者能够读取全内存,从而攻击者能够进行信息泄露攻击(information leakage attacks),并绕过ASLR(Adress space layout randomization,通过对内存堆、 栈等线性区布局的随机化,增加攻击者预测目的地址的难度,防止攻击者直接 定位攻击代码位置的防御手段)等防御机制;
2.攻击者能够在所有可写内存页进行写操作,从而攻击者能够修改函数返 回地址、虚函数表指针等重要数据,达到改变程序执行流的目的;
3.攻击者无法直接读取、写入寄存器;
上述假设已足够严格,满足真实世界中利用内存破坏漏洞所进行攻击时的 条件;同时,利用内存破坏漏洞,攻击者也能够实现上述条件。
当然,本发明还可有其他多种实施例,在不背离本发明精神及其实质的情 况下,熟悉本领域的技术人员当可根据本发明作出各种相应的改变和变形,但 这些相应的改变和变形都应属于本发明所附的权利要求的保护范围。
机译: H-IoT一种针对异构物联网的分布式拒绝服务攻击的防御方法及其系统
机译: 一种针对目标受害者防御服务攻击的全自动方法
机译: 防御会话劫持攻击的方法及防火墙