论文的选题背景

随着硬件、网络和虚拟化技术的发展,云计算已经成为安全威胁的目标,例如跨虚拟机侧信道攻击(恶意租户通过探测共享资源的状态信息,建立泄漏模型,便可绕过虚拟化提供的隔离性,窃取其它同驻虚拟机的隐私信息),恶意用户利用漏洞获取信息或访问其他Guest虚拟机。在众多虚拟化技术中,hypervisor管理共享资源池,以确保来宾虚拟机能够正常服务并相互隔离。但是,在管理共享硬件资源时,由于虚拟化层的存在和不同的CPU模式(根模式和非根模式),当CPU切换到非根模式并被Guest Machine占用时,hypervisor不能在运行时干预Guest Machine。因此,Guest的执行状态对于hypervisor来说就像一个黑盒,并且hypervisor不能在运行时调解可能的恶意行为。

例如,一些恶意软件,比如病毒、互联网蠕虫、木马和僵尸网络,被用来破坏网络系统,窃取敏感信息,或者控制Guest Machine。它们通常利用库或Windows API调用来执行特权任务,例如网络通信和系统管理。由于这些任务是在虚拟机中执行的,因此hypervisor无法轻易地在运行时从虚拟机外部监视此类恶意活动。

论文的研究思路

综述:本文提出了一种基于硬件辅助的VMI(虚拟机内省)Guest内进程监控机制,它支持监控和管理Guest Machine中的应用程序,例如对于Guest Machine中的进程进行分析。该机制允许将hook函数放置在Guest Machine的目标进程中,并通过hypervisor处理hook调用。为了方便Guest Machine中所需的监视或管理操作,该机制通过修改扩展页表(EPT)来将guest内存空间的访问重定向到hypervisor中受控的、自定义的内存,以便于最小化Guest Machine和Host Machine的切换。

KVM:KVM是基于虚拟化扩展(Intel VT或者AMD-V)的X86硬件的开源的Linux原生的全虚拟化解决方案。KVM是一个Linux内核模块,使得Linux本身变成一个Hypervisor。KVM只模拟CPU和内存。
本文使用Intel VT-x扩展将Guest的内存访问重定向到hypervisor中受控的、自定义的内存空间。本文精心设计和选择了适当的插装步骤和时间点,修改由KVM管理的扩展页表(EPT),以支持内存重定向机制。本文修改了KVM的内存管理机制,使它可以实现上述机制来替换Guest的内存。当一个被hook的guest内存地址执行时,其被替换的内存包含一些额外的指令,这些指令用来收集进程的执行信息。上述机制允许在Guest Machine上以真机的速度执行hook function。并且该机制通过检查执行时间差异以防止目标进程的检测。

特性

高度透明性:本文提出的VMI监控机制位于hypervisor层,而不是在Guest的操作系统中;因此,Guest Machine中的目标进程无法检测到VMI机制的存在。此外,我们还介绍了几种方法来隐藏重定向内存空间的存在,用于存储挂钩函数和数据,以保持透明度。

更好的性能:由于该机制是通过硬件虚拟化扩展(Intel VT-x)实现的,因此它比传统的基于模拟的系统(基于QEMU)更快。此外,与传统的基于硬件协助的分析系统(当Guest Machine访问敏感资源时会陷入VMM 中,VMM 便介入了Guest Machine与硬件资源之间的交互过程,从而可获取CPU、寄存器等设备中的相关底层状态数据,该方法必须在不同VM执行模式之间切换)不同,本文提出的机制,在Guest内执行的拦截不需要Guest和Host的切换,从而降低了开销并提高了性能。

更高的语义:本文收集目标进程的API调用,并且进一步遍历内存中的相关表,以获得API的符号表示和参数,最终提供高级语义和可读性。

虚拟化背景知识

Hardware Assisted Virtualization:在x86架构中,保护环的设计目的是在正确的权限状态下管理程序的执行。通过4个特权环(环0、环1、环2、环3),系统可以有效防止高特权指令以低特权状态执行。但是,由于来宾操作系统被主机操作系统认为是一个通用的应用程序,因此保护环机制拒绝在来宾操作系统中执行特权指令。

Intel提出了Intel VT-x,新增两种模式:
VM root: 即虚拟机管理系统运行模式;
VM non root:即虚拟机运行模式;
VM Exit和VM Entry 用以实现non root和root之间的切换;这种转换被VMCS(VM Control Structure)这个数据结构控制,对每一个虚拟CPU都会对应一个VMCS。

主机操作系统以根模式运行,而客户操作系统以非根模式运行。两种执行模式都支持四个特权环执行,解决了Guest模式下特权指令执行的问题。

Extended Page Table:维护 GPA->HPA 的映射

Kernel-Based Virtual Machine (KVM) and QEMU :KVM创建了一个“/dev/kvm”设备节点,作为KVM和QEMU之间的通信通道。QEMU创建相应的数据结构,并通过一组ioctl()系统调用与KVM进行通信,KVM创建相应的数据结构并分配资源来初始化一个VM。KVM执行循环继续如下图所示。

一旦QEMU完成I/O任务,它将通知KVM以guest模式执行代码,KVM将接管CPU。当出现QEMU必须处理的外部事件(例如网络数据包的到达或超时事件)时,QEMU将稍后恢复。
KVM将主机状态保存到VMCS,并恢复guest状态,执行VM entry进入guest模式(非root模式)。guest代码在物理CPU上执行。一旦CPU由于中断或页面错误等事件退出guest模式,CPU将切换回host模式(根模式),KVM将在恢复guest执行之前执行必要的处理。如果退出是因为I/O指令或进程队列中的信号,则KVM以用户模式退出到QEMU。

相关工作

MMU Manipulation of Normal Page Table

POSTER: Page table manipulation attack:设法在主内核页表中找到目标页表项(PTE),并修改其属性以规避PTE限制。(未找到论文)
row-hammer-induced bit flips:今天的DRAM单元为了让内存容量更大,所以在物理密度上更紧凑,但这样很难阻止临近的内存单元之间的电子上的互相影响,在足够多的访问次数后可以让某个单元的值从1变成0,或者相反。

但是,本文目标不是修改普通的页表,而是由hypervisor管理的EPT条目。此外,本文不仅修改了现有的EPT条目,而且本文提出的机制还在KVM中创建了新的内存空间,在EPT中创建了新的条目,以存储主机和客户都可以访问的额外监控代码。

SandBox

CWSandbox可以在本机模式或虚拟Windows环境中执行示例,通过API函数挂钩执行API级监控。Cuckoo Sandbox利用虚拟机技术能够在不同的操作系统(例如,Windows和Linux)上运行,并由客户中安装的代理提供高级语义执行信息(例如,API调用跟踪和访问文件的一般行为)。然而,在某些情况下,恶意软件可能会检测到客户代理的存在,以逃避此类监控。Cuckoo和CWSandbox都提供了良好的性能和高语义信息。但是,它们必须安装一个附加的客户代理,并且不能对目标程序透明。因此,它们更适合于监测实验室中的任务,而不是在线或实时监测。

Dual-VM-Based Approach

采用基于双虚拟机方法的VMI系统包括一个客户虚拟机(GVM)和一个安全虚拟机(SVM),它们需要安装相同的操作系统。GVM是运行被监控应用程序的虚拟机,SVM是一个高度安全的机器,安全应用程序运行在SVM上以避免被破坏。SVM中的安全应用程序拦截和监视GVM中目标程序的执行,例如收集系统调用或API调用的信息。

基于双虚拟机的VMI系统需要至少两个虚拟机和修改GVM,并且虚拟机通信和切换会引起额外的开销,修改GVM也可能会增加被监控程序检测的风险。

Emulation-Based Approach

基于模拟器的VMI系统在软件模拟器(如QEMU)中实现,用来拦截二进制翻译的过程,并能够一条指令一条指令地记录Guest Machine的执行流程。这样的设计允许对Guest Machine进行细粒度的跟踪,但获得的指令级信息缺乏高级语义,因此难于理解。此外,二进制转换会导致较高的开销,严重降低性能。

Hardware-Assisted VMI Systems

Mishra等人根据使用的内省方法将该类系统分为五种类型:
1)基于guest OS hook(例如:SIM和Lares)。
2)基于虚拟机状态访问(例如:VMI-IDS 、LibVMI和Maitland)。
3)基于hypercall认证(例如:Collabra)。
4)基于内核调试(例如:DRAKVUF和SPEMS)。
5)基于中断(例如:Nitro)。
但是,本文提出的APIf不属于任何类别。虽然APIf利用了guest OS hooking技术,但APIf不需要修改guest OS。此外,与其他类别的方法相比,APIf不需要额外的特权域(即Domain 0)、hypercall、 debug berk point、系统调用和中断。

系统设计

图4描述了使用阴影叶页面的VMI监控系统的工作流程,文章设计的基本原理是使用一次插桩来替换即将发生的模式切换。当guest中的一个任务(即进程)即将执行一条指令(GVA)时,GVA经过PD和PT的翻译。在插桩时,PT条目被修改为映射到阴影叶页面,来替换原始页面。当被hook的地址(GVA)被CPU以guest模式访问时,MMU/EPT将重定向guest进程的执行,并且CPU访问阴影页上的指令/数据时不需要额外的guest/host切换。而为了保证系统的性能和透明度,成本限制在一次性修改。

图5展示了VMI监控系统的系统图。在QEMU中的VMI Process Handler从命令行界面接收到目标进程名之后,它将监视目标进程的激活。一旦目标进程处于活动状态,VMI Process Handler就发送一个ioctl信号来启用VMI MMU Modifier和VMI Log Handler。MMU Modifier创建自定义阴影叶页面并修改地址转换,以便目标进程的hook地址的执行被重定向到自定义阴影叶页面。 VMI Log Handler管理日志缓冲区的操作,该缓冲区用于存储来自客户机的数据(例如分析应用程序中的API调用信息)。

VMI Process Handler

1.第一个任务是获取目标进程(图5第一步),通过访问guest kernel来获取当前的进程列表,目的是获取到目标进程的CR3注册值。如果列表中不包含目标进程,Process Handler模块会挂起等待。
2.第二个任务是在KVM Exit Handler设计插桩(第二步)。当在guest虚拟机衍生(spawn)一个新进程时,进程上下文切换设置CR3的值(CR3_Change),并且CPU通过VM EIXT退出到KVM(VMM)。而对于Process Handler来说,这是检查目标进程的激活和定位目标APIs地址的好时机。
3.第三个任务是找到目标API的GVA,并将地址发送给MMU Modifier。
由于地址空间布局随机化(ASLR)的广泛应用,因此还需要完成在每次重启之后,定位目标进程的GVA。为了分析应用程序,需要找到目标api的DLL文件的基址(例如,LoadLibraryA的地址),并结合基址和偏移量来获得目标APIs的GVA。

VMI MMU Modifier

VMI MMU Modifier负责在主机中分配必要的内存空间并修改EPT。(第三步)MMU Modifier通过kzalloc()分配所需的内存空间(第四步),包括阴影叶页面(用于存储inline hooking的克隆页面)、日志缓冲区(用于存储客户信息)和配置文件缓冲区(用于存储hook代码),然后将这些主机内内存空间(HPA)映射到guest内存空间(GVA)。
对于EPT修改,MMU Modifier首先使用目标进程的CR3值和目标GVA来定位PT的入口地址。通过修改这个PT的值,MMU Modifier将GVA重定向到阴影叶页面。在这些页面上,本文使用inline hooking的方法部署API hooks(P-Code)来拦截APIf中API的执行。

VMI Log Handler

VMI Log Handler管理日志缓冲区的操作,它有效的提供了客户机和主机机器之间的通道。配置文件缓冲区中的P-code在日志缓冲区中读写数据。当KVM执行常规VM EXIT时, VMI Log Handler以环形缓冲区的方式处理数据并将其转储到跟踪文件中,以便缓冲区管理不会产生任何额外的模式切换。

  1. 允许guest mode下访问in-host profiling code。
    为了使主机内分析代码能够以客户模式访问,分析系统首先在主机内核中为目标进程创建一个可执行页面。然后,它执行一个反向MMU地址转换,将host物理地址映射到一个未使用的guest虚拟地址。
  2. 将GVA重定向到定制的阴影页。
    图6显示了通过修改EPT而实现的地址重定向的简化示例。假设一个4KB的页面(在GVA #P321中)包含了原始的目标API操作码(指令A到Z)。通过使用CR3的值,在MMU转换后,这个页面的地址被转换为一个HPA帧(#F123) 。在VMI MMU Modifier介入后,一开始的内存映射( #P321 → #F123)被修改为了(#P321 → #F456)
  3. 在影子页上设置API hook 处理。
    通过本文系统修改后使用的内存布局模板:首先,一个函数(指令A到Z,通常Z是RET)位于#P321,本文的设计提供了两个插桩点,分别位于A和Z之前,因此我们可以在调用函数之前运行一段P-code(α1 到 αm),也可以在函数返回之前调用另一段P-code(β1 到 βn)。一开始阴影页#F456是#F123的克隆。然后,我们重新排列指令(A - Z)和两个P-code(α1到α和β1到βn),并使用三个额外的JMP指令和一个额外的profile buffer (#F999)。因此执行顺序变成了α1到αm,A到Z,β1到βn。

图7(a)显示了LoadLibraryA在kernel32.dll中的操作码。带有灰色背景的指令将被重写以将控制权转移到P-code。图7(b)所示为hook后的代码和指令的执行顺序,其应与图7(a)相同。在本例中,分析代码(没有显示在图中)记录了API名称、参数和返回值。此外,为了不影响原始的执行序列,本文使用系统堆栈(通过PUSH/POP指令)在输入分析代码之前保存原始寄存器值,并在分析完成后恢复值。

Target Process State Retrieval

检索首先扫描来宾内核调试器块(KDBG),然后访问PsActiveProcessHead,它是执行进程(EPROCESS)数据结构的双循环链表的头。EPROCESS结构是一个进程描述符,它包含有关进程的关键信息,如CR3值、PID和进程名。通过遍历EPROCESS列表检索进程状态信息。用户只需为监控系统指定目标进程名,就可以自动获取此信息(例如CR3)。图8说明了目标进程状态检索的过程。

Enabling In-Host Code Access in the Guest Mode

在主机内核中为目标进程创建了一个可执行页面,该页面可以通过反向MMU地址转换访问。首先通过PML4/PDPT/PD的遍历序列定位PT表。然后在目标进程中找到一个未使用的内存地址,并为该地址在PT上创建一个可执行页表项。生成了一个两阶段的地址映射,即从GPA到HPA(在Host中)和从GVA到GPA(在Guest中),以方便访问。

API Hook Handlings

要hook一个目标API,我们必须获得它的客户虚拟地址(GVA),并将hook处理程序存储在一个阴影叶页面中。在前面解释了目标API的GVA和阴影页的HPA之间的映射。如前所述,现代操作系统使用地址空间布局随机化(ASLR),它随机安排进程的敏感数据区域(如堆栈、堆)的地址空间,以阻止某些类型的攻击。因此必须动态地找到目标API的地址,以便正确地hook目标API.
一个虚拟地址由一个虚拟基地地址和一个相对地址组成。基地地址在系统重新启动时动态分配。相对地址是固定的,作为相对偏移量工作。在本文的系统中,基地地址是通过扫描系统默认进程的DLL导出表来找到相应的DLL基地地址,然后结合相对地址(固定偏移量)来动态定位目标API的地址。

MMU Redirection Instrumentation Point

本系统以第5次EPT Violation为检测时间点,修改EPT进行重定向。此外,由于一个进程的EPT上的API地址转换是唯一的和排他的,因此对一个进程的EPT修改不影响虚拟环境中其他进程的API地址转换。该特性还允许我们执行目标监视,并避免干扰其他进程。

Implementation of Windows API Profiling System

通过包含高级语义信息的API执行记录来记录客户进程的行为。本文从Microsoft MSDN中挑选了了四个操作类别中的几个api。

  • File I/O
    本文选择了与I/O相关的api,比如用于创建、读取、写入、复制和删除文件的api。
  • Process Management
    为了监控进程级别的恶意软件活动,本文选择了用于进程创建、启动和执行的api。
  • Library Invocation
    本文选择LoadLibrary()作为目标api之一,因为恶意程序经常通过动态链接加载自己提供的库。
  • Registry Access
    本文选择注册表搜索、打开、创建、关闭和删除的api,以监控恶意软件对系统配置的更改。

为了提供高语义,分析系统在分析缓冲区中放置额外的代码,以进一步获取API调用参数和从目标进程堆栈返回的值。此外,由于一些参数是指针(如字符串对象和文件句柄),本文的分析代码支持进一步将它们解析为实际值,以使生成的分析文件更易于阅读。分析代码将调用API的API名称、参数(在堆栈中)和返回值(在RAX寄存器中)记录到日志缓冲区。分析代码在x64汇编中编程实现。日志数据以十六进制格式存储。图11是日志缓冲区中的API调用跟踪的一个示例。

Transparency

通常,透明性并不意味着对目标进程隐藏虚拟化环境的存在,而是隐藏监视机制的存在。本文采取了一些措施来确保监视系统对客户机器中的目标进程而言是透明的。

  1. 隐藏Hooking Functions
    通常,inline hooking是通过修改程序来实现的。比较程序文件本身(例如,exe、dll)是一个简单但有用的方法来检测本身是否被修改。但是,本文通过修改EPT来部署API hook,而不是直接修改程序文件。因此,这种检测方法是无效的。
    API hook也可以通过内存完整性检查来检测。通常,hook WriteprocessMemory和ReadProcessMemory的APIs并伪造它们的参数和返回值可以防止检测。例如,如果恶意软件试图通过使用ReadProcessMemory读取指定的内存部分来检查内存完整性,我们可以hook该函数并使用原始程序替换读取缓冲区的内容,以避免被检测到。
  2. 隐藏EPT修改
    因为客户机无法访问EPT,所以目标进程既不能访问EPT,也不知道对EPT的任何修改。本文的系统只使用常规的EPT_VIOLATION执行一次性插装;因为没有发生其他VM exit,所以目标进程不能识别这样的检测。
  3. 处理时间
    恶意软件可以读取计时器并计算执行时间。如果时间超过了某个阈值,恶意软件可能会认为存在监控系统。恶意软件可以使用RDTSC指令来确定执行时间是否超过阈值。RDTSC指令读取TSC寄存器并将值写入EAX和EDX寄存器。本文的系统可以拦截RDTSC指令,通过伪造EAX和EDX的值来误导恶意软件。

论文的应用评估

结果评估

运行环境 :2.5 GHz Intel i5双核CPU 8GB RAM,主机操作系统为Ubuntu 14.04,内核为Linux 3.16.0。虚拟机为配置一个单核虚拟CPU和2GB RAM的Windows 7 64-bit SP1。

代码大小:间接跳转操作占用2条指令;用于收集参数和日志数据的分析代码使用了49到73条指令;
除分析代码之外,需要3个跳转操作来连接阴影叶页面和配置文件缓冲区;因此,hook目标API的整个开销在55到79条指令之间。

性能测试:使用PerformanceTest 8.0进行性能测试,并与Cuckoo进行比较。在所有的基准测试中,APIf产生的开销很低(在0.0%到7.38%之间)。磁盘顺序写(Disk Sequential Write)和磁盘随机读写(Disk Random R/W)开销最高,大概为7.38%。内存操作的开销在0.92%到3.84%之间;CPU操作的开销在0.0%到4.52%之间。结果表明,本文所提出的系统在CPU和I/O操作上的开销很小。

调用Hooked APIs的延迟:表IV显示了1000次挂钩API调用的初始运行时间的平均值和延迟。时延范围为30到100 us。LoadLibrary API调用引起的时间延迟小于1us,表中没有显示。用于文件操作的api平均花费的时间最多(76.59 us)。一些注册表api会显著影响性能,而持续访问Windows注册表可能导致沉重的系统I/O,并且在系统中访问许多日志缓冲区,从而降低性能。但是可以通过优化缓冲机制来改进这一点。因而分析代码产生的延迟非常小。

一个实例:在Windows中,当用户试图登录时,会调用LogonUser()函数。用户输入用户名和明文密码。如果登录成功,用户将收到一个指定用户帐户凭据的访问令牌,或者在大多数情况下创建一个在指定用户上下文中运行的进程。在本次实验中hook此函数来记录用户的用户名和密码。下图展示了当用户输入用户名和密码(test/test)时,分析代码会在日志缓冲区中记录登录的信息。

一些讨论

可移植性:本文提议的VMI监视机制是hypervisor可移植的,因为所有的实现都是独立于KVM的。用户可以将该监控机制迁移到不同的虚拟化环境中,只需满足以下需求:

  • 修改页表项来改变地址转换。 Intel VT-x定义了上述页表结构和地址转换原理。因此,任何与Intel VT-x扩展兼容的管理程序都可以使用本文提出的机制。
  • 创建阴影页。所有管理程序都可以分配具有写/可执行访问权限的内存空间。
  • 了解guest OS的内核结构。在Windows中使用客户内核结构EPROCESS来构造一个活动进程列表。如果不同操作系统中的相关结构(例如Linux中的struct_t结构)已知,本文的监控机制可以应用于不同的客户操作系统。

总之,如果管理程序与x86/64硬件辅助虚拟化兼容,就可以实现上述所有需求。因此,所提出的监控机制在很大程度上具有可移植性

总结

虚拟化是云计算的核心组件,为客户提供不同硬件和软件服务之间的隔离。虽然当前虚拟机监控程序的设计侧重于虚拟机之间的资源共享和管理,但随着越来越多的企业接受虚拟化环境,它缺乏适当的安全保证机制。每天都有新的威胁出现,而最新的威胁之一就是跨虚拟机的Cache侧信道攻击。本文设计并开发了一个MMU重定向机制,该机制拦截客户虚拟机中API调用的执行,以支持运行时安全监控和分析。基于所提出的MMU重定向机制,本文在QEMU/KVM上实现了一个具有三个重要属性的分析系统原型:最小化VM转换开销、对guest虚拟机的透明性和高层语义数据记录。实验结果表明,本文的分析系统产生的系统开销不超过7.38%,执行单个api的延迟不超过100us。本文所实现的可靠性能允许对Windows API调用进行实时监控和分析。