一种基于QEMU的内核级代码重用型攻击检测方法转让专利

申请号 : CN201510574168.8

文献号 : CN105260659B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 李金库程坤孙聪卢笛姚青松马建峰

申请人 : 西安电子科技大学

摘要 :

本发明公开了一种基于QEMU的内核级代码重用型攻击检测方法,主要解决现有技术依赖硬件或需要修改内核源代码的问题。它通过对QEMU虚拟机管理器的功能模块进行扩展,遍历检测运行在其上的操作系统内核中的每一条指令,从中识别出与控制流程相关的跳转指令,包括ret和间接call指令,通过记录它们的跳转目标地址,然后将这些目标地址与系统正常执行流程中的合法目标地址进行对比来检测系统是否正常执行;同时,它对中断发生时压入栈中的中断返回地址和中断实际返回时使用的返回地址进行对比验证,以判断是否发生了攻击。本发明针对代码重用型攻击均需要改变系统原有执行流程的特点,通过对改变内核执行流程的指令(和地点)进行监测,能有效发现攻击,可用于保护操作系统的安全。

权利要求 :

1.一种基于QEMU的内核级代码重用型攻击检测方法,其特征在于,包括以下步骤:

1)预处理

1.1)创建一个空的临时文件temp_file,并将操作系统内核镜像文件中的内容输出到临时文件temp_file中;

1.2)创建一个记录内核中函数入口地址的文件func_addr_file,从temp_file文件中依次取得内核所有函数的入口地址,并将这些地址写入func_addr_file文件中;

1.3)创建一个记录内核中函数返回地址的文件ret_addr_file,从temp_file文件中依次取得系统中所有有效的函数返回地址,并将这些地址写入ret_addr_file文件中;

2)基于QEMU的跳转指令目标地址的记录和中断流程验证,具体方法如下:

2.1)使用QEMU启动虚拟机内核;

2.2)在QEMU的从客户机指令到主机指令的翻译阶段,取得内核指令中的一条指令I;

2.3)在对指令I进行翻译之前,首先判断是否发生了中断事件,如果发生了中断,则跳转到步骤2.7);

2.4)判断指令I的类型:如果I是间接call指令,则跳转到步骤2.5);如果I是ret指令,则跳转到步骤2.6);否则跳转到步骤2.8);

2.5)对间接call指令I进行如下操作:

2.5a)若文件call_addr.out不存在,则创建记录间接call指令目标地址的文件call_addr.out;

2.5b)在翻译间接call指令I时,对其标志call_flag赋值为1;

2.5c)若此时发生中断,进入中断处理函数时判断call_flag是否为1,若是,则记录中断处理时压栈的返回地址到call_addr.out文件中,然后将call_flag赋值为0,跳转到步骤

2.5e);

2.5d)QEMU跳转到间接call指令的目标地址进行翻译,在翻译之前判断标志call_flag是否为1,若是,则记录翻译块首地址到call_addr.out文件中,即为间接call指令的目标地址,然后将call_flag赋值为0;

2.5e)跳转到步骤2.8);

2.6)对ret指令I进行如下操作:

2.6a)若文件ret_addr.out不存在,则创建记录ret指令的目标地址的文件ret_addr.out;

2.6b)在翻译ret指令I时,对其标志ret_flag赋值为1;

2.6c)若此时发生中断,进入中断处理函数时判断ret_flag是否为1,若是,则记录中断处理时压栈的返回地址到ret_addr.out文件中,然后将ret_flag赋值为0,跳转到步骤

2.6e);

2.6d)QEMU跳转到ret指令的目标地址进行翻译,在翻译之前判断ret_flag是否为1,若是,则记录翻译块首地址到ret_addr.out文件中,即为ret指令的目标地址,然后将ret_flag赋值为0;

2.6e)跳转到步骤2.8);

2.7)对中断进行如下操作:

2.7a)若int_addr.out文件不存在,则创建记录中断信息的文件int_addr.out;

2.7b)若无自定义栈,则初始化栈int_addr,栈顶指针指向第一个位置;

2.7c)在QEMU处理中断的函数中将系统压栈的返回地址同时压入自定义栈int_addr中;

2.7d)当QEMU执行中断程序完毕后,调用中断返回指令时,将自定义栈int_addr中的返回地址出栈,与中断返回指令的返回地址相比较,如果二者不同,则报告发生了攻击,并将对比结果不同的返回地址记录到int_addr.out文件中;

2.7e)跳转到步骤2.4);

2.8)如果操作系统内核还有未处理的指令,返回步骤2.2),开始下一条指令的处理;否则结束;

3)跳转指令目标地址验证

在指令翻译的同时,对QEMU记录的跳转指令的目标地址进行验证,检测是否发生了攻击。

2.根据权利要求1所述的基于QEMU的内核级代码重用型攻击检测方法,其特征在于,所述步骤2.4)中,指令I的类型是QEMU通过识别二进制指令的操作码进行判断的。

3.根据权利要求1或2所述的基于QEMU的内核级代码重用型攻击检测方法,其特征在于,所述步骤3)中,跳转指令目标地址验证步骤具体如下:

3.1)读取call_addr.out中的每个新增的目标地址,验证其是否是func_addr_file文件中的函数入口地址,如果不是,则报告发生了攻击;

3.2)读取ret_addr.out中的每个新增的目标地址,验证其是否是ret_addr_file文件中的有效函数返回地址,如果不是,则报告发生了攻击;

3.3)返回到3.1)。

说明书 :

一种基于QEMU的内核级代码重用型攻击检测方法

技术领域

[0001] 本发明属于计算机科学与技术领域,涉及恶意软件的防护,具体是一种基于QEMU的内核级代码重用型攻击检测方法。

背景技术

[0002] 作为一种当代新型的攻击方法,内核级代码重用型攻击不需要注入任何新的代码,仅仅利用(或重用)内核中已有的(合法)代码就能构造完整攻击并从根本上颠覆整个操作系统,它能够逃过内核代码完整性保护机制的防护,给用户计算机系统安全带来了巨大威胁。
[0003] 代码重用型攻击需要两步来完成:(1)攻击者精心选择可用的指令片段,并将它们通过特定的指令(比如ret)串接起来;(2)改变系统原有的执行流程(通过篡改内核执行中的某个控制数据,比如函数指针或函数返回地址),跳转到攻击者选择的首个指令片段,实施攻击。
[0004] 最早的代码重用型攻击是ROP(return-oriented programming)攻击。由于它精心选择的指令片段都以ret指令结尾,其构造的工具集会包含许多ret指令,这在正常的系统中是不合理的。由此,Chen等人[ICISS 2009]提出了一种通过检测系统指令执行流程中ret指令调用的频繁程度,从而发现ROP攻击的技术方法。北卡州立大学的Li等人[ACM EuroSys 2010]通过修改编译器,去除内核中所有的ret指令操作码字节,使攻击者无法找到可用的指令片段构造攻击。而最新的代码重用型攻击变种已经不再依赖于ret指令,而是改为利用类似的跳转指令(比如间接jmp或“pop+jmp”指令)来串接指令片段,更加难以对付。为此,北卡州立大学的Li等人[IEEE TIFS 2011]提出了一种基于编译器的方法,通过修改内核相关指令(比如间接call和ret指令)保护内核中的控制数据(包括函数指针和函数返回地址)来防止代码重用型攻击。EPFL的Kuznetsov等人[OSDI2014]同样提出了一种基于编译器方法,他们对程序中所有的code-pointer进行保护,从而抵御代码重用型攻击。
[0005] 应该说,当前的研究成果对代码重用型攻击的检测已经有一定的效果。但是,已有检测方法大都有技术限制。它们要么需要额外的硬件支持,要么需要修改内核源代码。前者会增加硬件成本且可扩展性较差,而后者对于非开源操作系统内核(比如Windows)则不适用。
[0006] 本发明提出的检测方法是基于QEMU虚拟机管理器完成的。QEMU是一款快速、便捷的动态二进制翻译器,它可以启动虚拟机并支持多种不同的CPU架构。由于QEMU以二进制指令翻译的形式执行,它能够对虚拟机内核执行的每一条指令进行干涉(或介入)。而代码重用型攻击均需要改变系统原有的执行流程(第二步),本发明通过对改变内核执行流程的指令(和地点)进行监测,就可以有效检测和发现攻击。并且,现有检测方法中都没有提供对内核中断流程的检测,而攻击者同样能够通过改变内核中断处理中的流程实施攻击。本发明提供了对于内核中断流程的检测和验证。

发明内容

[0007] 为了弥补现有技术的不足,本发明提出了一种基于QEMU的内核级代码重用型攻击检测方法,该方法用以检测各种内核级代码重用型攻击(及其变种)的行为,保护操作系统的安全。
[0008] 为了实现上述目的,本发明所采用的技术方案包括以下步骤:
[0009] 1)预处理
[0010] 1.1)创建一个空的临时文件temp_file,并将操作系统内核镜像文件中的内容输出到临时文件temp_file中;
[0011] 1.2)创建一个记录内核中函数入口地址的文件func_addr_file,从temp_file文件中依次取得内核所有函数的入口地址,并将这些地址写入func_addr_file文件中;
[0012] 1.3)创建一个记录内核中函数返回地址的文件ret_addr_file,从temp_file文件中依次取得系统中所有有效的函数返回地址,并将这些地址写入ret_addr_file文件中;
[0013] 2)基于QEMU的跳转指令目标地址的记录和中断流程验证
[0014] 3)跳转指令目标地址验证
[0015] 在指令翻译的同时,对QEMU记录的跳转指令的目标地址进行验证,检测是否发生了攻击。
[0016] 本发明进一步的改进在于:
[0017] 所述步骤2)中,基于QEMU的跳转指令目标地址的记录和中断流程验证的具体方法如下:
[0018] 2.1)使用QEMU启动虚拟机内核;
[0019] 2.2)在QEMU的从客户机指令到主机指令的翻译阶段,取得内核指令中的一条指令I;
[0020] 2.3)在对指令I进行翻译之前,首先判断是否发生了中断事件,如果发生了中断,则跳转到步骤2.7);
[0021] 2.4)判断指令I的类型:如果I是间接call指令,则跳转到步骤2.5);如果I是ret指令,则跳转到步骤2.6);否则跳转到步骤2.8);
[0022] 2.5)对间接call指令I进行如下操作:
[0023] 2.5a)若文件call_addr.out不存在,则创建记录间接call指令目标地址的文件call_addr.out;
[0024] 2.5b)在翻译间接call指令I时,对其标志call_flag赋值为1;
[0025] 2.5c)若此时发生中断,进入中断处理函数时判断call_flag是否为1,若是,则记录中断处理时压栈的返回地址到call_addr.out文件中,然后将call_flag赋值为0,跳转到步骤2.5e);
[0026] 2.5d)QEMU跳转到间接call指令的目标地址进行翻译,在翻译之前判断标志call_flag是否为1,若是,则记录翻译块首地址到call_addr.out文件中,即为间接call指令的目标地址,然后将call_flag赋值为0;
[0027] 2.5e)跳转到步骤2.8);
[0028] 2.6)对ret指令I进行如下操作:
[0029] 2.6a)若文件ret_addr.out不存在,则创建记录ret指令的目标地址的文件ret_addr.out;
[0030] 2.6b)在翻译ret指令I时,对其标志ret_flag赋值为1;
[0031] 2.6c)若此时发生中断,进入中断处理函数时判断ret_flag是否为1,若是,则记录中断处理时压栈的返回地址到ret_addr.out文件中,然后将ret_flag赋值为0,跳转到步骤2.6e);
[0032] 2.6d)QEMU跳转到ret指令的目标地址进行翻译,在翻译之前判断ret_flag是否为1,若是,则记录翻译块首地址到ret_addr.out文件中,即为ret指令的目标地址,然后将ret_flag赋值为0;
[0033] 2.6e)跳转到步骤2.8);
[0034] 2.7)对中断进行如下操作:
[0035] 2.7a)若int_addr.out文件不存在,则创建记录中断信息的文件int_addr.out;
[0036] 2.7b)若无自定义栈,则初始化栈int_addr,栈顶指针指向第一个位置;
[0037] 2.7c)在QEMU处理中断的函数中将系统压栈的返回地址同时压入自定义栈int_addr中;
[0038] 2.7d)当QEMU执行中断程序完毕后,调用中断返回指令时,将自定义栈int_addr中的返回地址出栈,与中断返回指令的返回地址相比较,如果二者不同,则报告发生了攻击,并将对比结果不同的返回地址记录到int_addr.out文件中;
[0039] 2.7e)跳转到步骤2.4);
[0040] 2.8)如果操作系统内核还有未处理的指令,返回步骤2.2),开始下一条指令的处理;否则结束。
[0041] 所述步骤2.4)中,指令I的类型是QEMU通过识别二进制指令的操作码进行判断的。
[0042] 所述步骤3)中,跳转指令目标地址验证步骤具体如下:
[0043] 3.1)读取call_addr.out中的每个新增的目标地址,验证其是否是func_addr_file文件中的函数入口地址,如果不是,则报告发生了攻击;
[0044] 3.2)读取ret_addr.out中的每个新增的目标地址,验证其是否是ret_addr_file文件中的有效函数返回地址,如果不是,则报告发生了攻击;
[0045] 3.3)返回到3.1)。
[0046] 本发明与现有的技术相比,具有以下有益效果:
[0047] 1)本发明基于QEMU虚拟机管理器实施,不需要扩展硬件,也不用修改操作系统内核源代码就可以识别、定位和记录所需要检测的跳转指令的目标地址。这种机制相对于已有方法成本低,可扩展性强,且可支持多种操作系统类型(比如非开源操作系统)。通过将记录的目标地址与系统合法的跳转地址进行比较,就能检测出内核级代码重用型攻击,保护操作系统的安全。
[0048] 2)本发明仅在需要翻译跳转指令时增加一次存储操作,即将目的地址记录到文件的操作。它具有性能高效的优点,基于UnixBench的性能测试结果表明,本发明所带来的性能损失约为4%。
[0049] 3)本发明提供了对操作系统内核中绝大部分跳转指令的检测,同时,它提出了当系统发生中断时,对中断处理过程中的返回地址进行检测和验证的方法。QEMU实际上监督了整个操作系统控制流程的跳转过程,所以它能够检测出内核级代码重用型攻击,为操作系统安全提供强有力的保障。

附图说明

[0050] 图1是本发明的流程图。

具体实施方式

[0051] 下面结合附图和实施例对本发明做进一步详细的说明:
[0052] 参照图1,本发明包括预处理与基于QEMU的跳转指令目标地址的记录和中断流程验证,以及跳转指令目标地址的合法性验证。其中,与控制流程相关的跳转指令包括间接call指令、ret指令,通过记录它们的跳转目标地址,然后将这些目标地址和正常系统执行流程当中的目标地址对比来检测系统是否正常执行,是否被攻击。
[0053] 本发明是基于这样一种观测而提出的:无论哪种类型的代码重用型攻击,它们要想实施攻击,必须改变系统原有的执行流程(或控制流程),跳转到攻击者所挑选的首个指令片段才能进行。如果能够对可能改变系统执行流程的地方进行检测(或验证),就可以检测(或阻止)攻击。为此,必须对系统中改变系统控制流程的间接call指令、ret指令和中断流程进行保护。
[0054] 本发明的核心思想是以QEMU虚拟机管理器为平台,使用QEMU虚拟机管理器运行操作系统内核进行检测或验证。由于QEMU基于二进制指令翻译技术实现,系统内核的每一条指令都会在QEMU虚拟机管理器中翻译运行,QEMU能够对虚拟机内核执行的每一条指令进行干涉(或介入)。通过对QEMU虚拟机管理器的功能模块进行修改,遍历检测操作系统内核中每一条指令,从中识别ret指令、间接call指令和中断的翻译方式,然后记录这些指令的跳转目标地址,通过将记录信息与合法信息进行对比,就可以实现对代码重用型攻击的检测。操作系统运行在QEMU启动的虚拟机上,而攻击发生在操作系统上,攻击者不会妨碍QEMU的运行;在QEMU中进行检测不用修改系统内核代码,也就是对任意操作系统,都不需要重新编译就能进行检测。同时,QEMU是一款开源代码的软件,不需要进行大量的代码改动,只需要对QEMU当中关键的地方加入处理代码就能完成对代码重用型攻击的检测。
[0055] 针对跳转目标地址,因为目标地址的值是在系统运行时动态生成并且是变化的,在QEMU进行动态翻译的时候可以进行记录。具体来说,遵照系统中函数调用的流程,当执行间接call指令调用一个函数时,会跳转到下一个QEMU翻译块继续执行,此时翻译块的首地址即是跳转指令的目的地址,从而就能记录间接call指令调用的函数的首地址。同理,ret指令在执行之后也会跳转到下一个翻译块执行指令执行流程,用同样的方式可以记录ret指令的返回地址。
[0056] 将跳转指令的目标地址综合考虑,本发明需要对系统中的间接call指令、ret指令的跳转目标地址进行记录,以便后续进行合法性判断;并对中断发生时压入栈中的中断返回地址和中断实际返回时使用的返回地址进行对比验证,以判断是否发生了攻击。
[0057] 对照图1,本发明详细的操作步骤如下:
[0058] 预处理步骤
[0059] a)创建临时文件temp_file,使用系统自带的代码反汇编命令(比如objdump),将操作系统内核镜像文件中的内容输出到temp_file文件中;
[0060] b)创建文件func_addr_file,将temp_file文件中所有的函数入口地址记录到文件func_addr_file中;
[0061] c)创建文件ret_addr_file,将temp_file文件中所有有效的函数返回地址记录在文件ret_addr_file中(每个有效的返回地址都指向紧挨着某个call指令后面的那条指令)。
[0062] 基于QEMU的跳转指令目标地址的记录和中断流程验证步骤
[0063] d)使用QEMU启动虚拟机内核,读取内核指令进行翻译执行;
[0064] 在QEMU翻译指令的阶段,QEMU并非以单条指令为单位进行翻译,翻译过程分为两步,第一步先将整个系统指令流程以跳转指令为界限进行划分,将整个指令流程划分为不同的指令块,叫做翻译块。这样,每个翻译块都是以一个跳转指令作为结尾,这样的特性使得对地址的获取有了一定的特性。指令流程被分割为翻译块后,QEMU以翻译块作为翻译单元;第二步就是对翻译块中的每一条指令进行翻译。
[0065] e)在QEMU的从客户机指令到主机指令的翻译阶段,取得内核指令中的一条指令I,在翻译之前,首先判断是否发生了中断,如果发生了中断,则执行步骤i);
[0066] f)通过读取指令的操作码,判断指令I的类型:如果I是间接call指令则执行步骤g),如果I是ret指令则执行步骤h),否则执行步骤j);
[0067] g)对间接call指令I进行如下操作:
[0068] g1)若call_addr.out文件不存在,则创建记录间接call指令的目标地址的文件call_addr.out;
[0069] g2)在翻译间接call指令I时,将call_flag赋值为1;
[0070] 步骤g2)中为每个间接call指令在翻译时添加标志以表示间接call指令正在被翻译,每次翻译间接call指令时call_flag都被赋值为1;
[0071] g3)在翻译块继续执行下一块翻译块之前,判断是否发生中断,如果发生中断,则跳转到中断处理函数中判断call_flag是否为1,如果是,则将中断处理时压栈的返回地址记录在文件call_addr.out中(此时中断压栈返回地址即为间接call指令的跳转目的地址),然后将call_flag赋值为0,跳转到步骤g5);
[0072] 步骤g3)中之所以需要判断中断的发生,是因为QEMU在进行动态二进制翻译时,并不是随时都能进行中断,由于翻译需要使用的翻译块分块会非常小,所以QEMU在判断中断时会在每一个翻译块开始翻译时进行中断发生的判断,所以在这里进行跳转指令目标地址的判断需要考虑中断发生的可能性;
[0073] g4)在QEMU翻译下一个翻译块之前,判断call_flag是否为1,如果为1,则将翻译块首地址记录在文件call_addr.out中,然后将call_flag赋值为0;
[0074] g5)跳转到步骤j);
[0075] h)对ret指令I进行如下操作:
[0076] h1)若ret_addr.out文件不存在,则创建记录ret指令的目标地址的文件ret_addr.out;
[0077] h2)在翻译ret指令I时,将ret_flag赋值为1;
[0078] 步骤h2)中为每个ret指令在翻译时添加标志以表示ret指令正在被翻译,每次翻译ret指令时ret_flag都被赋值为1;
[0079] h3)在翻译块继续执行下一块翻译块之前,判断是否发生中断,如果发生中断,则跳转到中断处理函数中判断ret_flag是否为1,如果是,则将中断处理时压栈的返回地址记录在文件ret_addr.out中(此时中断压栈返回地址即ret指令的跳转目标地址),然后将ret_flag赋值为0,跳转到步骤h5);
[0080] 这里进行中断发生的判断的原因和间接call指令一样。
[0081] h4)在QEMU翻译下一个翻译块之前,判断ret_flag是否为1,如果是,则将翻译块首地址记录在文件ret_addr.out中,然后将ret_flag赋值为0;
[0082] h5)跳转到步骤j);
[0083] i)对中断进行如下操作:
[0084] i1)若int_addr.out文件不存在,则创建文件int_addr.out;
[0085] i2)若没有自定义栈,则初始化栈int_addr,并将栈的空间设置为50,栈顶指针指向第一个位置;
[0086] i3)在执行中断函数之前需要将寄存器的值和上下文压栈,其中包括中断返回地址,首先进行判断自定义栈int_addr空间是否已满,如果未满,则将中断返回地址压入自定义栈int_addr,而后栈顶指针自加1;否则(int_addr空间已满)系统报错;
[0087] i4)当中断函数执行完毕之后,系统调用中断返回函数来返回发生中断的地方继续执行,将调用中断处理函数时栈顶记录的中断返回地址弹出,同时将记录在自定义栈int_addr中的中断返回地址取出,判断中断返回函数使用的返回地址和自定义栈int_addr中记录的返回地址是否一致;如果两者不一致,则可知中断流程中的返回地址被篡改,报告发生了攻击,并将两个不同的返回地址输出到文件int_addr.out中;
[0088] i5)跳转到步骤f);
[0089] j)如果操作系统指令集中还有未处理的指令,返回步骤e),开始下一条指令的处理;否则指令翻译阶段结束。
[0090] 跳转指令目标地址验证步骤
[0091] k)在指令翻译的同时,对QEMU记录的跳转指令的目标地址进行验证,检测是否发生了攻击:
[0092] k1)对间接call指令目标地址的验证:读取call_addr.out中的每一个新增的跳转目标地址,验证其是否是func_addr_file文件中的函数入口地址,如果不是,则报告发生了攻击;
[0093] k2)对ret指令目标地址的验证:读取ret_addr.out中的每一个新增的返回目标地址,验证其是否是ret_addr_file文件中的有效函数返回地址,如果不是,则报告发生了攻击。
[0094] 本发明的性能效果可以通过以下实验进一步说明:
[0095] 实验条件:
[0096] 将本发明实现到QEMU虚拟机管理器中。本发明利用QEMU1.5.0版本对Linux3.11.1版本的内核进行代码重用型攻击的检测,通过修改QEMU的源代码实现该功能。
[0097] 实验内容:
[0098] 选用性能测试工具UnixBench,分别对原始QEMU启动系统内核和添加了本发明功能的QEMU启动系统内核进行性能测试,以得出本发明所带来的性能损失。各测试三次,求平均值。
[0099] 结果分析:
[0100] 基于UnixBench的性能测试结果表明,本所带来的性能损失约为4%。总体上,本发明具有性能高效的优点。
[0101] 以上内容仅为说明本发明的技术思想,不能以此限定本发明的保护范围,凡是按照本发明提出的技术思想,在技术方案基础上所做的任何改动,均落入本发明权利要求书的保护范围之内。