全文摘要
本发明公开一种虚拟机自省中的语义重构改进方法及系统,包括:获取目标虚拟机内核结构体中各个关键成员对应偏移量的所有候选项,并基于成员属性制定相关约束条件;目标虚拟机启动前,在VMM中透明修改其特定内核函数的指令代码,截获目标虚拟机中系统事件,以触发获取内核结构体中各个关键成员对应偏移量的操作;目标虚拟机启动过程中产生系统事件时,引发VM‑EXIT陷入至VMM,在VMM中基于所制定的约束条件对各个关键成员的偏移量候选项进行筛选;偏移量获取完毕后,在VMM中恢复对目标虚拟机中特定内核函数的修改,使目标虚拟机中的系统事件不再引发VM‑EXIT,并将所得偏移量提供给VMI应用程序完成目标虚拟机高层语义的重构。本发明通用性及可移植性强、执行效率高、自动化程度高。
主设计要求
1.一种虚拟机自省中的语义重构改进方法,其特征在于,包括以下步骤:步骤1:获取目标虚拟机内核结构体中各个关键成员对应偏移量的所有候选项,并基于各个关键成员自身的属性制定相关约束条件;步骤2:目标虚拟机启动前,在VMM中透明修改其特定内核函数的指令代码,截获目标虚拟机中系统事件,以触发获取内核结构体中各个关键成员对应偏移量的操作;步骤3:目标虚拟机启动过程中产生系统事件时,引发VM-EXIT陷入至VMM,在VMM中基于所制定的约束条件对各个关键成员的偏移量候选项进行筛选;步骤4:判断是否已获取全部所需偏移量,若已获取完毕,则执行步骤5,若尚未获取完毕,则进行相关模拟操作后返回步骤3;步骤5:在VMM中恢复对目标虚拟机中特定内核函数的修改,使目标虚拟机中产生系统事件时不再引发VM-EXIT,并将所得偏移量提供给VMI应用程序完成目标虚拟机高层语义的重构;所述内核结构体中关键成员为内核结构体中具有特定意义,不会因目标虚拟机内核版本不同而发生变化的成员,包括进程结构体中的进程链表结点tasks,进程号pid,进程名称comm,进程内存结构体mm,进程页目录基地址mm.pgd,进程代码段起始地址mm.start_code及进程代码段结束地址mm.end_code,及内核模块结构体中的模块名称name,模块核心代码段起始地址module_core及模块核心代码段长度core_text_size。
设计方案
1.一种虚拟机自省中的语义重构改进方法,其特征在于,包括以下步骤:
步骤1:获取目标虚拟机内核结构体中各个关键成员对应偏移量的所有候选项,并基于各个关键成员自身的属性制定相关约束条件;
步骤2:目标虚拟机启动前,在VMM中透明修改其特定内核函数的指令代码,截获目标虚拟机中系统事件,以触发获取内核结构体中各个关键成员对应偏移量的操作;
步骤3:目标虚拟机启动过程中产生系统事件时,引发VM-EXIT陷入至VMM,在VMM中基于所制定的约束条件对各个关键成员的偏移量候选项进行筛选;
步骤4:判断是否已获取全部所需偏移量,若已获取完毕,则执行步骤5,若尚未获取完毕,则进行相关模拟操作后返回步骤3;
步骤5:在VMM中恢复对目标虚拟机中特定内核函数的修改,使目标虚拟机中产生系统事件时不再引发VM-EXIT,并将所得偏移量提供给VMI应用程序完成目标虚拟机高层语义的重构;
所述内核结构体中关键成员为内核结构体中具有特定意义,不会因目标虚拟机内核版本不同而发生变化的成员,包括进程结构体中的进程链表结点tasks,进程号pid,进程名称comm,进程内存结构体mm,进程页目录基地址mm.pgd,进程代码段起始地址mm.start_code及进程代码段结束地址mm.end_code,及内核模块结构体中的模块名称name,模块核心代码段起始地址module_core及模块核心代码段长度core_text_size。
2.根据权利要求1所述的虚拟机自省中的语义重构改进方法,其特征在于,所述目标虚拟机内核结构体中各个关键成员对应偏移量的所有候选项根据内核结构体各个关键成员的数据类型及结构体字节对齐原则获取。
3.根据权利要求1所述的虚拟机自省中的语义重构改进方法,其特征在于,所述特定内核函数包括进程\/线程创建时需调用的内核函数do_fork(),及其消亡时需调用的内核函数release_task(),以及内核模块加载并初始化时调用的内核函数do_one_initcall()。
4.根据权利要求1所述的虚拟机自省中的语义重构改进方法,其特征在于,所述系统事件包括虚拟机中进程\/线程的创建\/消亡事件,及内核模块的加载事件;所述内核模块的加载包括模块实例的创建与初始化过程。
5.根据权利要求1所述的虚拟机自省中的语义重构改进方法,其特征在于,所述步骤2具体包括:
步骤2.1:在目标虚拟机外部挂载其镜像,得到目标虚拟机的内核符号表,从内核符号表中读取内核函数do_fork()、release_task()及do_one_initcall()的入口地址;
步骤2.2:在目标虚拟机启动之前,在VMM层将上述内核函数头部的函数栈帧维护指令替换为可陷入敏感指令VMCALL;
步骤2.3:目标虚拟机启动过程中产生所述系统事件时,均会调用所述特定内核函数,从而执行敏感指令VMCALL陷入至VMM中。
6.根据权利要求1所述的虚拟机自省中的语义重构改进方法,其特征在于,所述步骤3中在VMM中基于所制定的约束条件对各个关键成员的偏移量候选项进行筛选包括:筛选目标虚拟机进程结构体中特定成员偏移量候选项和筛选目标虚拟机模块结构体中特定成员偏移量候选项;
所述筛选目标虚拟机进程结构体中特定成员偏移量候选项的具体步骤包括:
步骤a1):目标虚拟机陷入VMM中后,根据虚拟机退出原因及目标虚拟机指令寄存器的值判断是否为进程\/线程的创建\/消亡事件,若是则执行步骤a2),否则执行步骤a7);
步骤a2):判断该进程结构体成员的所有偏移量候选项中是否仅有一个成员,若是则说明已获取该成员的正确偏移量,无需再次筛选,执行步骤a7),否则执行步骤a3);
步骤a3):获取目标虚拟机中当前进程task_struct结构体的首地址ts_addr;
步骤a4):从该成员的所有偏移量候选项中依次顺序获取一个候选偏移量candi_offset,若已获取完毕,则执行步骤a7),否则执行步骤a5);
步骤a5):获取目标虚拟机当前进程结构体首地址candi_offset偏移处的内容;
步骤a6):判断该偏移处的内容是否符合基于该成员属性制定的约束条件,若符合则直接返回步骤a4),否则从该成员的所有偏移量候选项中删除此候选偏移量candi_offset,并返回步骤a4);
步骤a7):完成了对该成员偏移量候选项的一次筛选过程,结束;
所述筛选目标虚拟机模块结构体中特定成员偏移量候选项的具体步骤包括:
步骤b1):目标虚拟机陷入VMM中后,根据虚拟机退出原因及目标虚拟机指令寄存器的值判断是否为调用内核函数do_one_initcall()引发的退出,若是则执行步骤b2),否则执行步骤b8);
步骤b2):判断当前事件是否为内核模块加载事件,若是则执行步骤b3),否则执行步骤b8);
步骤b3):判断该模块结构体成员的所有偏移量候选项中是否仅有一个成员,若是则说明已获取该成员的正确偏移量,无需再次筛选,执行步骤b8),否则执行步骤b4);
步骤b4):获取目标虚拟机当前模块结构体中list成员的地址mlist_addr;
步骤b5):从该成员的所有偏移量候选项中依次顺序获取一个候选偏移量candi_offset,若已获取完毕则执行步骤b8),否则执行步骤b6);
步骤b6):获取目标虚拟机mlist_addr偏移candi_offset处的内容;
步骤b7):判断该偏移处的内容是否符合基于该成员属性制定的约束条件,若符合则直接返回步骤b5),否则从该成员的所有偏移量候选项中删除此候选偏移量candi_offset,并返回步骤b5);
步骤b8):完成了对该成员偏移量候选项的一次筛选过程,结束。
7.根据权利要求1所述的虚拟机自省中的语义重构改进方法,其特征在于,所述步骤4中执行相关模拟操作具体为:在VMM中模拟所述特定内核函数do_fork()、release_task()及do_one_initcall()的函数栈帧维护操作,随后执行VM-ENTRY返回目标虚拟机完成上述内核函数的正常执行流程。
8.根据权利要求1所述的虚拟机自省中的语义重构改进方法,其特征在于,所述高层语义包括目标虚拟机进程级语义信息及内核模块级语义信息。
设计说明书
技术领域
本发明涉及虚拟机技术领域,具体为一种虚拟机自省中的语义重构改进方法及系统。
背景技术
虚拟机自省(Virtual Machine Introspection,简称VMI)是一种在虚拟机外部获取目标虚拟机信息并对其运行状态进行监控分析的方法。VMI基于虚拟化技术,利用虚拟机监视器(Virtual Machine Monitor, 简称VMM)的高特权级与强隔离性,能够实现安全软件与恶意软件的分离,具有隔离性、自省性与干预性,在恶意软件分析、入侵检测、内核完整性保护等多方面发挥了重要作用。VMI在实现过程中面临的核心问题之一是语义鸿沟,即在目标虚拟机外部获取的底层状态与其代表的操作系统级语义的分离。将得到的二进制底层数据转化为可理解的高层语义的过程即为语义重构。
语义重构是VMI技术的关键步骤,现有的语义重构方法根据其依赖的条件可分为以下几类:(1)基于目标虚拟机。该类方法可直接在目标虚拟机内部获取高层语义信息,或在目标虚拟机中加载内核模块,获取内核结构体中关键成员的偏移量以在虚拟机外部完成语义重构。(2)基于安全虚拟机。此类方法借助安全虚拟机实现语义重构,如在安全虚拟机中同步模拟待监控进程的执行以获取目标虚拟机的进程信息,或在安全虚拟机中训练得到可在目标虚拟机外部执行语义重构的代码。(3)基于内核源码或内存转储文件。该类方法通过分析目标虚拟机的内核源代码或内存转储文件得到相关语义信息。
上述方法均存在实现过程与目标虚拟机内核版本相关的问题,对于不同内核版本的目标虚拟机,第一类方法需要再次访问目标虚拟机获取语义或偏移量信息,且可能因不具备权限或源码缺失等情况而无法加载内核模块,导致自省无法实施;第二类方法需要配置安装与目标虚拟机内核版本一致的安全虚拟机完成自省,对自省环境的要求高,且性能损耗较大;第三类方法则需要重新分析内核源码,其需解析及搜索的信息较多,自省效率低,且分析内存转储文件无法获取运行状态目标虚拟机的信息。云计算环境下往往存在着多个内核版本不同的虚拟机,上述限制使得目前的语义重构方法通用性及可移植性差、执行效率不高、自动化程度低。
发明内容
针对上述问题,本发明的目的在于提供一种虚拟机自省中的语义重构改进方法及系统,能够在目标虚拟机外部自动获取其内核结构体中关键成员的偏移量以实现语义重构,而不需要访问目标虚拟机,无需引入安全虚拟机或分析内核源代码,解决现有语义重构方法通用性及可移植性差、执行效率不高、自动化程度低的问题。技术方案如下:
一种虚拟机自省中的语义重构改进系统,包括陷入点初始化模块、偏移量获取模块和恢复模块;
所述陷入点初始化模块在目标虚拟机启动前,在VMM中透明替换其内核函数do_fork()、release_task()及do_one_initcall()头部的函数栈帧维护指令为可陷入敏感指令VMCALL,使目标虚拟机中进程\/线程的创建\/消亡行为及内核模块加载行为能够产生VM-EXIT陷入至VMM中,以此触发偏移量获取模块的相关操作;
所述偏移量获取模块在VMM中,基于由内核结构体关键成员自身属性制定的约束条件,删除所有不满足对应约束条件的偏移量候选项,完成内核结构体关键成员对应偏移量候选项的筛选过程;
所述恢复模块判断是否已获取全部所需偏移量,若尚未获取完毕,则进行相关模拟操作后执行VM-ENTRY返回目标虚拟机完成内核函数的正常执行流程,否则恢复对目标虚拟机内核函数do_fork()、release_task()及do_one_initcall()的修改,使其相关行为不再陷入至VMM中,并将所得偏移量提供给VMI应用程序完成目标虚拟机的语义重构。
一种虚拟机自省中的语义重构改进方法,包括以下步骤:
步骤1:获取目标虚拟机内核结构体中各个关键成员对应偏移量的所有候选项,并基于各个关键成员自身的属性制定相关约束条件;
步骤2:目标虚拟机启动前,在VMM中透明修改其特定内核函数的指令代码,截获目标虚拟机中系统事件,以触发获取内核结构体中各个关键成员对应偏移量的操作;
步骤3:目标虚拟机启动过程中产生系统事件时,引发VM-EXIT陷入至VMM,在VMM中基于所制定的约束条件对各个关键成员的偏移量候选项进行筛选;
步骤4:判断是否已获取全部所需偏移量,若已获取完毕,则执行步骤5,若尚未获取完毕,则进行相关模拟操作后返回步骤3;
步骤5:在VMM中恢复对目标虚拟机中特定内核函数的修改,使目标虚拟机中产生系统事件时不再引发VM-EXIT,并将所得偏移量提供给VMI应用程序完成目标虚拟机高层语义的重构。
进一步的,所述内核结构体中关键成员为内核结构体中具有特定意义,不会因目标虚拟机内核版本不同而发生变化的成员,包括进程结构体中的进程链表结点tasks,进程号pid,进程名称comm,进程内存结构体mm,进程页目录基地址mm.pgd,进程代码段起始地址mm.start_code及进程代码段结束地址mm.end_code,及内核模块结构体中的模块名称name,模块核心代码段起始地址module_core及模块核心代码段长度core_text_size。
更进一步的,所述目标虚拟机内核结构体中各个关键成员对应偏移量的所有候选项根据内核结构体各个关键成员的数据类型及结构体字节对齐原则获取。
更进一步的,所述特定内核函数包括进程\/线程创建时需调用的内核函数do_fork(),及其消亡时需调用的内核函数release_task(),以及内核模块加载并初始化时调用的内核函数do_one_initcall()。
更进一步的,所述系统事件包括虚拟机中进程\/线程的创建\/消亡事件,及内核模块的加载事件;所述内核模块的加载包括模块实例的创建与初始化过程。
更进一步的,所述步骤2具体包括:
步骤2.1:在目标虚拟机外部挂载其镜像,得到目标虚拟机的内核符号表,从内核符号表中读取内核函数do_fork()、release_task()及do_one_initcall()的入口地址;
步骤2.2:在目标虚拟机启动之前,在VMM层将上述内核函数头部的函数栈帧维护指令替换为可陷入敏感指令VMCALL;
步骤2.3:目标虚拟机启动过程中产生所述系统事件时,均会调用所述特定内核函数,从而执行敏感指令VMCALL陷入至VMM中。
更进一步的,所述步骤3中在VMM中基于所制定的约束条件对各个关键成员的偏移量候选项进行筛选包括:筛选目标虚拟机进程结构体中特定成员偏移量候选项和筛选目标虚拟机模块结构体中特定成员偏移量候选项;
所述筛选目标虚拟机进程结构体中特定成员偏移量候选项的具体步骤包括:
步骤a1):目标虚拟机陷入VMM中后,根据虚拟机退出原因及目标虚拟机指令寄存器的值判断是否为进程\/线程的创建\/消亡事件,若是则执行步骤a2),否则执行步骤a7);
步骤a2):判断该进程结构体成员的所有偏移量候选项中是否仅有一个成员,若是则说明已获取该成员的正确偏移量,无需再次筛选,执行步骤a7),否则执行步骤a3);
步骤a3):获取目标虚拟机中当前进程task_struct结构体的首地址ts_addr;
步骤a4):从该成员的所有偏移量候选项中依次顺序获取一个候选偏移量candi_offset,若已获取完毕,则执行步骤a7),否则执行步骤a5);
步骤a5):获取目标虚拟机当前进程结构体首地址candi_offset偏移处的内容;
步骤a6):判断该偏移处的内容是否符合基于该成员属性制定的约束条件,若符合则直接返回步骤a4),否则从该成员的所有偏移量候选项中删除此候选偏移量candi_offset,并返回步骤a4);
步骤a7):完成了对该成员偏移量候选项的一次筛选过程,结束;
所述筛选目标虚拟机模块结构体中特定成员偏移量候选项的具体步骤包括:
步骤b1):目标虚拟机陷入VMM中后,根据虚拟机退出原因及目标虚拟机指令寄存器的值判断是否为调用内核函数do_one_initcall()引发的退出,若是则执行步骤b2),否则执行步骤b8);
步骤b2):判断当前事件是否为内核模块加载事件,若是则执行步骤b3),否则执行步骤b8);
步骤b3):判断该模块结构体成员的所有偏移量候选项中是否仅有一个成员,若是则说明已获取该成员的正确偏移量,无需再次筛选,执行步骤b8),否则执行步骤b4);
步骤b4):获取目标虚拟机当前模块结构体中list成员的地址mlist_addr;
步骤b5):从该成员的所有偏移量候选项中依次顺序获取一个候选偏移量candi_offset,若已获取完毕则执行步骤b8),否则执行步骤b6);
步骤b6):获取目标虚拟机mlist_addr偏移candi_offset处的内容;
步骤b7):判断该偏移处的内容是否符合基于该成员属性制定的约束条件,若符合则直接返回步骤b5),否则从该成员的所有偏移量候选项中删除此候选偏移量candi_offset,并返回步骤b5);
步骤b 8):完成了对该成员偏移量候选项的一次筛选过程,结束。
更进一步的,所述步骤4中执行相关模拟操作具体为:在VMM中模拟所述特定内核函数do_fork()、release_task()及do_one_initcall()的函数栈帧维护操作,随后执行VM-ENTRY返回目标虚拟机完成上述内核函数的正常执行流程。
更进一步的,所述高层语义包括目标虚拟机进程级语义信息及内核模块级语义信息。
本发明的有益效果是:
(1)通用性:在未知目标虚拟机内核版本的前提下,本发明可自动获取目标虚拟机内核结构体中关键成员的偏移量信息,该过程无需访问目标虚拟机,对目标虚拟机无侵入性,无需额外引入安全虚拟机,具有通用性及可移植性;
(2)高效性:本发明在目标虚拟机启动阶段完成其内核结构体关键成员偏移量的获取,对目标虚拟机启动阶段引入的性能开销低,执行效率高;
(3)可靠性:本发明基于内核结构体关键成员自身属性获取对应偏移量,实现过程不依赖特定内核源码,目标虚拟机内核源码的修改不会影响所得结果的正确性与可靠性;
(4)可扩展性:本发明采用的语义重构方式,可用于重构目标虚拟机中的其他信息,包括但不限于文件信息,网络连接信息等。
附图说明
图1是虚拟机自省中的语义重构改进系统总体架构图。
图2是目标虚拟机事件监控原理示意图。
图3是获取目标虚拟机进程结构体中某特定成员偏移量的算法伪代码。
图4是筛选目标虚拟机进程结构体中某特定成员偏移量候选项的流程图。
图5是筛选目标虚拟机模块结构体中某特定成员偏移量候选项的流程图。
具体实施方式
下面结合附图和具体实施例对本发明做进一步详细说明。图1描述了虚拟机自省中的语义重构改进系统的总体架构图,包括陷入点初始化模块、偏移量获取模块和恢复模块。
陷入点初始化模块在目标虚拟机启动前,在VMM中透明替换目标虚拟机中内核函数do_fork()、release_task()及do_one_initcall()头部的函数栈帧维护指令为可陷入敏感指令VMCALL,使目标虚拟机中进程\/线程的创建\/消亡行为及内核模块加载行为能够产生VM-EXIT陷入至VMM中,以此触发偏移量获取模块的相关操作。
图2描述了所述陷入点初始化模块的原理示意图,以进程创建事件为例进行说明:
Linux中用户进程的创建可通过系统调用fork()、clone()和vfork()实现,其对应的服务例程分别为sys_fork()、sys_clone()和sys_vfork(),这三个函数最终都会调用内核函数do_fork()实现具体创建工作,内核线程的创建同样需调用函数do_fork()。因此截获进程\/线程创建事件的具体步骤为:
1):在目标虚拟机外部挂载其镜像,得到目标虚拟机的内核符号表,从内核符号表中读取内核函数do_fork()的入口地址;
2):在目标虚拟机启动之前,在VMM层将内核函数do_fork()头部的函数栈帧维护指令替换为可陷入敏感指令VMCALL;
3):目标虚拟机启动过程中产生进程\/线程的创建事件时,均会调用内核函数do_fork(),执行敏感指令VMCALL陷入至VMM中。
类似地,进程\/线程的消亡可通过多个系统调用实现,其对应的服务例程均会调用内核函数release_task()释放待消亡进程的进程描述符。内核模块的加载包括模块实例的创建与初始化过程,不同内核版本下模块实例创建过程的内核函数调用流程存在差异,但模块实例创建完毕后均需通过内核函数do_one_initcall()完成模块的初始化工作,类似地替换函数release_task()及do_one_initcall()的头部指令截获进程\/线程消亡及内核模块加载事件。
偏移量获取模块在VMM中,基于由内核结构体关键成员自身属性制定的约束条件,删除所有不满足对应约束条件的偏移量候选项,完成内核结构体关键成员对应偏移量候选项的筛选过程。
恢复模块判断是否已获取全部所需偏移量,若尚未获取完毕,则进行相关模拟操作后执行VM-ENTRY返回目标虚拟机完成内核函数的正常执行流程,否则恢复对目标虚拟机内核函数do_fork()、release_task()及do_one_initcall()的修改,使其相关行为不再陷入至VMM中,并将所得偏移量提供给VMI应用程序完成目标虚拟机的语义重构。
虚拟机自省中的语义重构改进方法包括以下步骤:
步骤1:获取目标虚拟机内核结构体中各个关键成员对应偏移量的所有候选项,并基于各个关键成员自身的属性制定相关约束条件。
内核结构体中关键成员为内核结构体中具有特定意义,不会因目标虚拟机内核版本不同而发生变化的成员,包括进程结构体中的进程链表结点tasks,进程号pid,进程名称comm,进程内存结构体mm,进程页目录基地址mm.pgd,进程代码段起始地址mm.start_code及进程代码段结束地址mm.end_code,及内核模块结构体中的模块名称name,模块核心代码段起始地址module_core及模块核心代码段长度core_text_size。
获取内核结构体中各个关键成员对应偏移量的所有候选项具体为:根据内核结构体各个关键成员的数据类型及结构体字节对齐原则,获取各个成员对应偏移量的所有候选项。
图3描述了获取目标虚拟机进程结构体中某特定成员偏移量的算法伪代码,其中包括:
第一阶段:获取该成员的所有偏移量候选项;
具体的,以成员pid为例,说明获取目标虚拟机进程结构体中某特定成员的所有偏移量候选项candi_offset_list的方式:
成员pid的candi_offset_list由该成员的数据类型及结构体的字节对齐原则得到。内核使用4字节的int类型存储进程的pid,根据结构体的字节对齐原则可知,成员pid相对于task_struct结构体起始地址的偏移量必须是4的倍数。由于目标虚拟机内核源码可能会被修改,因此从0开始到task_struct结构体大小的范围内,每增加4字节的值均可能为pid成员的偏移量,将这些值均作为成员pid的偏移量候选项添加至candi_offset_list中。获取其他成员对应的所有偏移量候选项的过程类似。
第二阶段:基于该成员的约束条件筛选其所有偏移量候选项,删除不满足约束条件的偏移量候选项,迭代执行此过程直至该成员对应的偏移量候选项仅有一个,此时说明已成功获取该结构体成员对应的偏移量。
具体的,进程结构体中各个关键成员的约束条件据其自身属性制定,所制定的约束条件不由内核源码的修改而变化。各个成员的约束条件可以但不限于依据如下属性进行制定:
成员tasks:tasks成员为进程链表结点,在未遭受内核Rootkit攻击的情况下,tasks所在链表的成员数目应与目标虚拟机中真实进程总数一致;
成员pid:pid成员作为各个进程的进程号,具有标识进程的作用,因此各个进程的pid均唯一,即对不同进程实例而言,其pid值必须不同;
成员comm:comm成员用于描述进程名称,因此其每个字符的ASCII码均在可显示字符的ASCII码范围内,且该字符数组的内容不可为空,并以字符’\\0’结尾;
成员mm:mm成员用于管理进程的虚拟地址空间,内核线程的mm成员为0,用户进程mm成员的值则与active_mm成员的内容一致;
成员pgd:mm_struct结构体中成员pgd用于存储进程的页目录基地址,该值对应的物理地址会被载入CR3寄存器,用于实现遍历进程页表进行地址翻译的功能,pgd的值与CR3寄存器的值仅相差一个page_offset,32位下page_offset为0xc0000000,64位下则为0xffffffff80000000;
成员start_code及end_code:进程代码段在内存中的起始地址与结束地址分别存储在结构体mm_struct中的start_code及end_code域中,每个体系结构为代码段制定了一个特定的起始地址,x86架构下始于0x08048000,x86_64下则为0x400000,且代码段位于进程虚拟地址的用户空间,其所在页面的权限为只读与可执行。
步骤2:目标虚拟机启动前,在VMM中透明修改其特定内核函数的指令代码,截获目标虚拟机中系统事件,以触发获取内核结构体中各个关键成员对应偏移量的操作。
所述特定内核函数为进程\/线程创建时需调用的内核函数do_fork()及其消亡时需调用的内核函数release_task(),以及内核模块加载并初始化时调用的内核函数do_one_initcall()。
步骤2.1:在目标虚拟机外部挂载其镜像,得到目标虚拟机的内核符号表,从内核符号表中读取内核函数do_fork()、release_task()及do_one_initcall()的入口地址;
步骤2.2:在目标虚拟机启动之前,在VMM层将上述内核函数头部的函数栈帧维护指令替换为可陷入敏感指令VMCALL;
步骤2.3:目标虚拟机启动过程中产生所述系统事件时,均会调用所述特定内核函数,从而执行敏感指令VMCALL陷入至VMM中。
步骤3:目标虚拟机启动过程中产生系统事件时,引发VM-EXIT陷入至VMM,在VMM中基于所制定的约束条件对各个关键成员的偏移量候选项进行筛选。
图4描述了筛选目标虚拟机进程结构体中某特定成员偏移量候选项的流程图,步骤如下:
1)目标虚拟机陷入VMM中后,根据虚拟机退出原因及目标虚拟机指令寄存器的值判断是否为进程\/线程的创建\/消亡事件,若是则执行步骤2),否则执行步骤7);
2)判断该进程结构体成员的所有偏移量候选项中是否仅有一个成员,若是则说明已获取该成员的正确偏移量,无需再次筛选,执行步骤7),否则执行步骤3);
3)获取目标虚拟机中当前进程task_struct结构体的首地址ts_addr,具体地:目标虚拟机退出时处于内核态,目标虚拟机的内核栈栈顶指针保存在VCPU的堆栈段寄存器ESP中。以32位Linux操作系统为例,其进程内核栈栈帧和thread_info结构体存放在一块独立8K大小的内存区域,因此屏蔽ESP的低13位即可以得到thread_info结构体的地址,并进一步得到目标虚拟机当前进程task_struct结构体的首地址ts_addr;
4)从该成员的所有偏移量候选项中依次顺序获取一个候选偏移量candi_offset,若已获取完毕则执行步骤7),否则执行步骤5);
5)获取目标虚拟机当前进程结构体首地址candi_offset偏移处的内容,考虑到内存虚拟化,从内存中读取该偏移处的内容需经历两次地址转换,即客户机虚拟地址(GuestVirtual Address, GVA)->客户机物理地址(Guest Physical Address,GPA)->宿主机物理地址(Host Physical Address,HPA)的转换;
6)判断该偏移处的内容是否符合基于该成员属性制定的约束条件,若符合则直接返回步骤4),否则从该成员的所有偏移量候选项中删除此候选偏移量candi_offset,并返回步骤4);
7)完成了对该成员偏移量候选项的一次筛选过程,结束。
图5描述了筛选目标虚拟机模块结构体中某特定成员偏移量候选项的流程图,步骤如下:
1)目标虚拟机陷入VMM中后,根据虚拟机退出原因及目标虚拟机指令寄存器的值判断是否为调用内核函数do_one_initcall()引发的退出,若是则执行步骤2),否则执行步骤8);
2)判断当前事件是否为内核模块加载事件,具体地:目标虚拟机启动过程中函数do_one_initcall()会被多次调用以完成内核多个子系统的初始化,而该过程中内核模块的加载则通过modprobe实现,因此获取当前调用函数do_one_initcall()的进程信息可判断当前事件是否为内核模块加载事件;
3)判断该模块结构体成员的所有偏移量候选项中是否仅有一个成员,若是则说明已获取该成员的正确偏移量,无需再次筛选,执行步骤8),否则执行步骤4),具体地:与进程结构体成员类似,基于成员数据类型及结构体字节对齐原则获取模块结构体中各个关键成员的candi_offset_list。不同的是:因模块链表头结点的地址已导出至内核符号表,故可直接获取模块结构体中各关键成员相对于其链表成员list的偏移量以重构模块语义,由于内核源码可能会被修改,因此需遍历成员list地址前后模块结构体大小的空间以获取所有可能的偏移量。
4)获取目标虚拟机当前模块结构体中list成员的地址mlist_addr,具体地:内核调用函数do_one_initcall()实现模块的初始化时,该模块实体已添加至全局模块链表头部,因此可读取全局模块链表头结点next域的内容得到当前模块结构体中list成员的地址mlist_addr;
5)从该成员的所有偏移量候选项中依次顺序获取一个候选偏移量candi_offset,若已获取完毕则执行步骤8),否则执行步骤6);
6)获取目标虚拟机mlist_addr偏移candi_offset处的内容;
7)判断该偏移处的内容是否符合基于该成员属性制定的约束条件,若符合则直接返回步骤5),否则从该成员的所有偏移量候选项中删除此候选偏移量candi_offset,并返回步骤5);具体地,所述模块结构体中关键成员的约束条件可以但不限于依据如下属性进行制定:
成员name:该成员约束条件与进程结构体中comm成员类似,不再赘述;
成员module_core:模块的二进制数据分为初始化部分及核心部分,module_core成员保存其核心部分代码及数据的起始地址,该起始地址为页对齐,且所在页面权限为可执行,其初始化部分的起始地址具有同样属性,但内核模块初始化过程中调用do_one_initcall()时,该函数的参数则为模块初始化函数的地址,即模块初始化部分代码及数据的起始地址;
成员core_text_size:该成员保存内核模块核心部分可执行代码的长度,其内容为页面大小的整数倍;
8)完成了对该成员偏移量候选项的一次筛选过程,结束。
步骤4:判断是否已获取全部所需偏移量,若已获取完毕,则执行步骤5,若尚未获取完毕,则进行相关模拟操作后返回步骤3。
判断是否已获取全部所需偏移量具体为:判断所述内核结构体中各个关键成员对应的偏移量候选项是否均只有一个,若是则说明已获取全部所需偏移量,否则为尚未获取完毕。执行相关模拟操作具体为:在VMM中模拟所述特定内核函数do_fork()、release_task()及do_one_initcall()的函数栈帧维护操作,随后执行VM-ENTRY返回目标虚拟机完成上述内核函数的正常执行流程。
步骤5:在VMM中恢复对目标虚拟机中特定内核函数的修改,使目标虚拟机中产生系统事件时不再引发VM-EXIT,并将所得偏移量提供给VMI应用程序完成目标虚拟机高层语义的重构。高层语义包括目标虚拟机进程级语义信息及内核模块级语义信息。
设计图
相关信息详情
申请码:申请号:CN201910047669.9
申请日:2019-01-18
公开号:CN109857520A
公开日:2019-06-07
国家:CN
国家/省市:90(成都)
授权编号:CN109857520B
授权时间:20200107
主分类号:G06F9/455
专利分类号:G06F9/455;G06F11/30
范畴分类:40B;
申请人:四川大学
第一申请人:四川大学
申请人地址:610065 四川省成都市武侯区一环路南一段24号
发明人:陈兴蜀;蔡梦娟;王伟;金鑫;王启旭
第一发明人:陈兴蜀
当前权利人:四川大学
代理人:裴娟
代理机构:51284
代理机构编号:成都信博专利代理有限责任公司
优先权:关键词:当前状态:审核中
类型名称:外观设计