在QEMU中实现基于配件长度的粗粒度CFI安全机制

这是老师布置的大作业,虽然不算难,但从一点没接触过QEMU到成功添加安全机制,遇到一些困难,踩过一些水坑,不过幸好,学到很多。

申明:转载请说明出处。

0X01  参数设置

参数说明:x=5,  y=7,  当配件长度小于5,且连续出现7次时,认为遭受了攻击。

0X02 key points

要完成这个大作业,个人觉得需要做到以下几点:

1、必须要建立起对qemu这个虚拟工具的一个概念,知道他是个什么东西,如果工作的,比如说是把目标主机的代码转换成本地主机代码的这个过程是怎样的,整体概念的建立很重要。

2、要理解qemu的工作原理,特别是它的动态翻译机制,最好是能够熟悉整个动态翻译的流程,他有一个完整的函数调用链,要能够大致知道函数之间是怎么调用的,这些函数分别完成了什么功能。

3、要理解qemu是以TB块为基本粒度进行翻译执行的,以及一定一定要清楚TB块的结构和切分方法,

清楚了TB块将会大大节省你完成安全机制建立的时间,我就是因为没搞懂所以掉到坑里浪费了好长时间。

4、要理解“配件”这一概念,特别是配件长度是什么,什么是配件,这两个概念很关键。

5、好好读代码,qemu里面很多原先定义的变量都可以直接拿来使用,很高效而且准确。

6、好好阅读老师和助教给的资料,每一句话每一个文件都不是摆设。

7、当你发现一条路走不通的时候不要钻牛角尖,要想想能不能换个方法解决问题。

8、要注重交流,这能开拓你的思维。

9、最后,要坚持,虽然是个小白,但是当自己坚持完成一项从没有接触过的任务后,会学到很多,过程越艰辛,成就感越足,共勉。


0X03  原理简述

关于qemu的原理介绍和翻译流程,在这里挂几个写得不错的链接。

1、动态翻译流程:https://stackoverflow.com/questions/20675226/qemu-code-flow-instruction-cache-and-tcg

2cpu_exec的讲解:http://www.hellogcc.org/?p=45

3TCG讲解:http://www.hellogcc.org/?p=46

以上的链接只是讲qemu的工作机制,下面我将结合作业补充几个点:

1、关于TB块的切分:

TB块是qemu翻译执行的基本粒度。如果TB块中有跳转指令,那么TB块一定是以这条跳转指令结尾的,也就是说,如果TB块有跳转指令,那么也只能有一条跳转指令,并且跳转指令一定是在TB块的结尾。但是,值得注意的是,并不是每个TB块都有跳转指令。

2、关于TB块结构中重要的变量:

1)自带的:

tb->icount标志的是一个TB块大小,主要用于判断是不是配件和计算配件长度。


2)打补丁加的:

这些变量在翻译过程中如果检测到跳转指令会标志为1,主要用于标记TB块是否有跳转指令,标记后会方便后续执行过程中对TB块的检测。

3)自己加的:

eflags:这个变量主要是用来标记该TB块是由目标代码翻译来的,而不是系统调用的TB块。

preflag:上一个TB块是否有跳转指令。

picount:上一个TB块的大小。

lenflag:当前TB块是否有跳转指令。

ppflag:前两个TB块是否有跳转指令。


0X04 具体实现

在哪里插入代码完成功能(除了打补丁插入的代码之外,自己加代码的位置):

总体来说,添加的代码会在下面这两条指令和这两条指令之间执行完。

 
1、在tb_find_fast执行过程中,会去寻找翻译好的TB块,如果找寻不到翻译好的TB块,就会调用翻译机制翻译目标代码,其中就包括translate.c文件中的voidgen_intermediate_code()。在这个函数的两层for循环的内层for循环中,会给翻译完的TB块新增一些携带信息,这些信息会伴随着TB块进入执行阶段。这些信息包括:当前TB块是否有跳转指令。上一个TB块是否有跳转指令。上一个TB块的大小。

前两个TB块是否有跳转指令。

2、在tb_find_fas函数和cpu_loop_exec_tb函数之间,我们将会完成是否是配件以及是否遭到攻击(连续出现y=7个配件)的判断。大致思路是将每个TB块当作一个代码片段,判断当前TB块,以及前几个TB块是否有跳转指令,以及两条跳转指令之间的指令条数。比如说,如果当前TB块有跳转指令,上一个TB块也有跳转指令,那么当前TB块的长度就是两条跳转指令之间的指令数目。如果当前TB块有跳转指令,上一个TB块没有跳转指令,但是now-2(上上个TB)有跳转指令,那么当前TB块的长度加上上一个TB块的长度之和就是就是两条跳转指令之间的指令数目。如果两条跳转指令之间的指令数小于x=5,那么就是配件。如果配件连续出现7次及7次以上,就判断遭到了攻击。


3、在cpu_loop_exec_tb() 函数中,会调用cpu_tb_exec() 函数,在cpu_tb_exec函数中会调用函数grin_handle_jmp()grin_handle_jmp()grin_handle_jmp(),这三个函数在粗粒度CFI安全机制开启并且满足配件要求的时候,输出跳转指令的跳转目的地址tmpcpu->env.eip

0X05 检测结果截图

由图可知,图中有一条完整的ret攻击配件链,成功检测到系统收到攻击,粗粒度CFI安全机制添加成功。






猜你喜欢

转载自blog.csdn.net/vivid_moon/article/details/80496580