美文网首页
【硬件虚拟化第二弹】远离kernel的理想乡

【硬件虚拟化第二弹】远离kernel的理想乡

作者: 看雪学院 | 来源:发表于2018-11-06 18:18 被阅读26次


简介

这个故事描述了如何使用硬件虚拟化(HVM)使得自己的一些hook代码远离内核不容易被其他内核hook所影响并且较难被检测。本文的思路来源于某学校的动态linux内核更新的玩意,代码大量抄自bluepill。

第一章  (Avalon) 阿瓦隆的黎明 

由于驱动牛人越来越多系统控制权的争夺愈演愈烈,内核之中几乎无一块净土。inline hook、ssdt hook等等各种hook充斥着我们幼小的内核。他们有些结构复杂,有些相互关联,有些检测监视,想要重新获得那些控制点的控制权必须花些力气研究那些hook,使得原来很简单的hook变得牵一发而动全身。

现在有硬件虚拟化技术,我们可以换个思路来解决那些问题了…

一、(Avalon)阿瓦隆的构成 

(Avalon) 阿瓦隆的本体为以下几个部分:

1、Avlboot.sys(用于保存刚初始化后还没被hook污染的系统内核方便之后使用)

2、Avalon.sys(用于读取伪内核信息,开启硬件虚拟化加载伪内核)

3、XXX.sys(用户利用Avlboot.sys中所提供的信息进行具体hook操作的程序)

二、(Avalon)阿瓦隆的真相 

本文所介绍的(Avalon) 阿瓦隆是一个基于虚拟化的内核加载框架。其利用硬件虚拟化(HVM)和一块没有被hook污染的内核内存,使得PC中同时运行着两个内核。并且Avalon通过控制sysenter_eip和idt中指向伪内核的相应地址来获得控制权。

简而言之,(Avalon)阿瓦隆就是利用硬件虚拟化(HVM)加载自己的内核架空原内核,使得自己能在不被检测的环境下获得内核的控制权。

实现原理如下图所示:

自己的hook程序在获得伪内核的基地址后,可以通过hookport来处理ssdt,shadow ssdt(strongod需要备份其所hook的ssdt稍微麻烦点,agp什么的只要把地址偏移一下就能用了)。

三、(Avalon)阿瓦隆的应用 

其实我们可以把(Avalon)阿瓦隆看成是一种变相的sysenter hook+idt hook。

由于(Avalon)阿瓦隆基于硬件虚拟化(HVM)使得我们可以架空整个内核,使得内核可以在运行时可以实时的替换。

因为伪内核的所在内存范围不受内存监控,别的程序也无法直接访问,使得我们的伪内核就成了不用考虑其他干扰问题,可以随意hook的安全的理想乡。

这种方式的hook和传统的一些hook相比有着以下优点

1、不在传统的内存监控的范围,较难检测。

2、不干扰系统中原有的hook代码,兼容性较高。

但是同样有一些

缺点

1、无法直接干涉object hook,irp hook等不依赖于内核内存的hook代码

2、整个系统依赖于硬件虚拟化(HVM),对硬件设备有一定要求。

第二章     空想具现化 

一、纯洁的初始化 

首先我们来实现(Avalon)阿瓦隆的初始化,初始化由4个部分组成:内核信息获取、伪内核构造、IDT信息保存、原始SYSENTER_EIP获取。

实现代码如下:

NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) 

...

KrnlCopy();

IDTCopy();

ReadMsrSysenter();

...

}

/*

内核拷贝

*/

VOID KrnlCopy()

{

PVOID Buffer;

ULONG Size;

ULONG RetSize;

PSYSTEM_MODULE_INFORMATION InfoBuffer;

NTSTATUS Status;

PVOID ModuleBase;

ULONG ModuleSize;

Size=0x1000;

do {

Buffer=ExAllocatePool(NonPagedPool,Size);

Status=ZwQuerySystemInformation(SystemModuleInformation,Buffer,Size,&RetSize);

if (Status == STATUS_INFO_LENGTH_MISMATCH)

{

ExFreePool(Buffer);

Size = RetSize;

}

}while(Status == STATUS_INFO_LENGTH_MISMATCH);

InfoBuffer = (PSYSTEM_MODULE_INFORMATION)Buffer;

ModuleBase=(PVOID)(InfoBuffer->ModuleInfo[0].Base);

Orig_krnl=(ULONG)ModuleBase;

DbgPrint("AvlBoot:Orig_krnl Base=%x\n",ModuleBase);

ModuleSize=InfoBuffer->ModuleInfo[0].Size;

makeKernelCopy((ULONG)ModuleBase,ModuleSize);

DbgPrint("AvlBoot:Avl_krnl Base=%x\n",Avl_krnl);

ExFreePool(Buffer);

}

等初始化之后,其他部件就可以通过访问Avlboot.sys来获得伪内核的信息和内核原始信息。

二、抄来的虚拟化 

这里先简单的向大家介绍下,Intel vt硬件虚拟化的步骤:

1、检查vt环境

2、开启vt功能

3、填充vt,存储虚拟机状态

4、设定需要拦截项目

5、设定从虚拟机中退出时返回的地址

6、启动虚拟机,等待拦截项目触发

7、拦截项目被触发,进入相关项目的处理例程

8、恢复虚拟机继续运行

接下来是一些坑爹的代码:

/*

Vmx初始化

*/

NTSTATUS NTAPI VmxInitialize (

PCPU Cpu,

PVOID GuestEip,

PVOID GuestEsp

)

{

PHYSICAL_ADDRESS AlignedVmcsPA;

ULONG VaDelta;

NTSTATUS Status;

// 为 VMXON region 申请内存空间

Cpu->Vmx.OriginaVmxonR = MmAllocateContiguousPages(

VMX_VMXONR_SIZE_IN_PAGES, 

&Cpu->Vmx.OriginalVmxonRPA);

if (!Cpu->Vmx.OriginaVmxonR) 

{

DbgPrint("VmxInitialize(): Failed to allocate memory for original VMCS\n");

return STATUS_INSUFFICIENT_RESOURCES;

}

DbgPrint("VmxInitialize(): OriginaVmxonR VA: 0x%x\n", Cpu->Vmx.OriginaVmxonR);

DbgPrint("VmxInitialize(): OriginaVmxonR PA: 0x%llx\n", Cpu->Vmx.OriginalVmxonRPA.QuadPart);

// 为 VMCS 申请内存空间 

Cpu->Vmx.OriginalVmcs = MmAllocateContiguousPages(

VMX_VMCS_SIZE_IN_PAGES, 

&Cpu->Vmx.OriginalVmcsPA);

if (!Cpu->Vmx.OriginalVmcs) 

{

DbgPrint("VmxInitialize(): Failed to allocate memory for original VMCS\n");

return STATUS_INSUFFICIENT_RESOURCES;

}

DbgPrint("VmxInitialize(): Vmcs VA: 0x%x\n", Cpu->Vmx.OriginalVmcs);

DbgPrint("VmxInitialize(): Vmcs PA: 0x%llx\n", Cpu->Vmx.OriginalVmcsPA.QuadPart);

// 开启vmx

if (!NT_SUCCESS (VmxEnable (Cpu->Vmx.OriginaVmxonR)))

{

DbgPrint("VmxInitialize(): Failed to enable Vmx\n");

return STATUS_UNSUCCESSFUL;

}

*((ULONG64 *)(Cpu->Vmx.OriginalVmcs)) = 

(MsrRead (MSR_IA32_VMX_BASIC) & 0xffffffff); //set up vmcs_revision_id      

// 填充VMCS结构

Status = VmxSetupVMCS (Cpu, GuestEip, GuestEsp);

if (!NT_SUCCESS (Status)) 

{

DbgPrint("VmxSetupVMCS() failed with status 0x%08hX\n", Status);

VmxDisable();

return Status;

}

DbgPrint("VmxInitialize(): Vmx enabled\n");

 // 保存EFER

Cpu->Vmx.GuestEFER = MsrRead (MSR_EFER);

DbgPrint("Guest MSR_EFER Read 0x%llx \n", Cpu->Vmx.GuestEFER);

 // 保存控制寄存器

Cpu->Vmx.GuestCR0 = RegGetCr0 ();

Cpu->Vmx.GuestCR3 = RegGetCr3 ();

Cpu->Vmx.GuestCR4 = RegGetCr4 ();

CmCli ();

return STATUS_SUCCESS;

}

/*

开启vmx

*/

NTSTATUS NTAPI VmxEnable (

PVOID VmxonVA

)

{

ULONG cr4;

ULONG64 vmxmsr;

ULONG flags;

PHYSICAL_ADDRESS VmxonPA;

// 设置cr4位,为启用VM模式做准备

set_in_cr4 (X86_CR4_VMXE);

cr4 = get_cr4 ();

DbgPrint("VmxEnable(): CR4 after VmxEnable: 0x%llx\n", cr4);

if (!(cr4 & X86_CR4_VMXE))

return STATUS_NOT_SUPPORTED;

// 检测是否支持vmx

vmxmsr = MsrRead (MSR_IA32_FEATURE_CONTROL);

if (!(vmxmsr & 4)) 

{

DbgPrint("VmxEnable(): VMX is not supported: IA32_FEATURE_CONTROL is 0x%llx\n", vmxmsr);

return STATUS_NOT_SUPPORTED;

}

//bochs的bug,要改IA32_FEATURE_CONTROL的Lock为1

#if bochsdebug

MsrWrite(MSR_IA32_FEATURE_CONTROL,5);

#endif

vmxmsr = MsrRead (MSR_IA32_VMX_BASIC);

*((ULONG64 *) VmxonVA) = (vmxmsr & 0xffffffff); //set up vmcs_revision_id

VmxonPA = MmGetPhysicalAddress (VmxonVA);

DbgPrint("VmxEnable(): VmxonPA:  0x%llx\n", VmxonPA.QuadPart);

//开启VMX

VmxTurnOn(VmxonPA);

flags = RegGetEflags ();

DbgPrint("VmxEnable(): vmcs_revision_id: 0x%x  Eflags: 0x%x \n", vmxmsr, flags);

return STATUS_SUCCESS;

}

/*

进入虚拟机

*/

NTSTATUS NTAPI VmxVirtualize (

PCPU Cpu

)

{

ULONG esp;

if (!Cpu)

return STATUS_INVALID_PARAMETER;

*((PULONG) (g_HostStackBaseAddress + 0x0C00)) = (ULONG) Cpu;

VmxLaunch ();

// never returns

return STATUS_UNSUCCESSFUL;

}

三、蛋疼的拦截处理

sysenter的处理方法:

由于硬件虚拟化(HVM)无法直接拦截sysenter指令,所以只能使用其他方法来获得控制权。

这里有三种方法:

1、在kifastcallentery的头部写入cpuid,int3等利用中断或特权指令进入vm。

2、使用调试寄存器在kifastcallentery下硬件执行中断,利用中断进入vm

3、进入VMM后直接修改guest的sysenter_eip地址,通过控制msr的读写来欺骗其他访问msr的程序。

为了不被内存检测和充分利用调试寄存器,Avalon中我选用了方案3来控制进程执行sysenter后的运行流向。

部分代码:

static BOOLEAN NTAPI VmxDispatchMsrRead (

PCPU Cpu,

PGUEST_REGS GuestRegs,

PNBP_TRAP Trap,

BOOLEAN WillBeAlsoHandledByGuestHv

)

{

...

switch (ecx) {

case MSR_IA32_SYSENTER_CS:

MsrValue.QuadPart = VmxRead (GUEST_SYSENTER_CS);

break;

case MSR_IA32_SYSENTER_ESP:

MsrValue.QuadPart = VmxRead (GUEST_SYSENTER_ESP);

break;

case MSR_IA32_SYSENTER_EIP:

MsrValue.QuadPart = Avlkrnlinfo->SysenterAddr;

...

}

idt重定向处理方法:

1、idt地址欺骗

2、idt模拟投递

第一种是指方案拦截sidt,lidt指令填充一份伪造的idt地址误导访问者(由系统投递相对稳定)。

第二种是指方案模拟idt的处理过程自己写程序投递idt。

因为方案一需要使用反汇编引擎分析具体的保存地址体积过大,所以本版的Avalon使用第二种方案即idt模拟投递。

部分代码:

static BOOLEAN NTAPI VmxDispatchException (

PCPU Cpu,

PGUEST_REGS GuestRegs,

PNBP_TRAP Trap,

BOOLEAN WillBeAlsoHandledByGuestHv

)

{

...

//SETP 7. SET EIP

if((uIntrInfo & 0xff) == 1){

 ComPrint("VmxDispatchException():#BD hit  /n");

 VmxWrite(GUEST_RIP,Avlkrnlinfo->Fake_IDTMap[0]);

}

else if ((uIntrInfo & 0xff) == 3){

 ComPrint("VmxDispatchException():#BP hit /n");

 VmxWrite(GUEST_RIP,Avlkrnlinfo->Fake_IDTMap[1]);}

...

}

第三章     理想乡的黄昏

一、(Avalon)阿瓦隆的检测 

对于基于硬件虚拟化(HVM)的程序,首先想到的方法必然就是直接检测和对抗硬件虚拟化。

对硬件虚拟化的检测主要有:efer的检测,vme的检测。

对于处理了中断的vmm还能通过计算中断前后的时间差来判断自身是否在虚拟机中。

当然针对Avalon还有其他的检测方法(此处省略xx字)

二、未来的更新 

Avalon才刚刚开始功能并不完善,还有好多功能想加进去:

1、将内核移入EPT(NPT)让你完全看不到

2、 和ring3程序交互…

3、其他隐藏功能

总结

Avalon只是硬件虚拟化应用的冰山一角,还有更多的应用等待着我们去探索,小弟的水平有限以后还要向各位高手多多请教继续努力学习。

断章(坑爹的饼)

该bin测试环境如下:

bochs2.4.5

windows xp sp3

注意:这个bin只是个简单的样品,真机上运行必蓝,且只针对ring0的中断,ring3有3处bug未修复。

附件的内容(bin+source+bin=饼+豆沙+饼):

avlboot.sys

avalonreader(读取avlboot信息的源码)

avalon_vt.sys

原文作者:三寸法师

原文链接:https://bbs.pediy.com/thread-134692.htm

转载请注明:转自看雪学院

更多阅读:

1、[原创] PEDIY-JD CTF 2018 Windows CrackMe 题目及设计思路

2、[原创]觉醒之战Ⅰ:洞察HW程序员的脑洞

3、[原创]几种常见的注入姿势

4、[翻译]StaDynA:解决Android APP安全分析中的动态代码更新问题

相关文章

  • 【硬件虚拟化第二弹】远离kernel的理想乡

    简介 这个故事描述了如何使用硬件虚拟化(HVM)使得自己的一些hook代码远离内核不容易被其他内核hook所影响并...

  • 安装Linux时报错This kernel requires a

    主要内容如下:问题原因解法硬件虚拟化 问题 VMware安装 Linux时 报错如下:This kernel re...

  • qemu-kvm

    qemu-kvm kernel-based-virtual Hypervisor基于虚拟化扩展的x86硬件的开源l...

  • Linux操作系统概述

    Unix把硬件虚拟成了软件。 operating system/kernel【内核】:1、驱动底层硬件2、将硬件抽...

  • 虚拟化技术

    虚拟化技术 分类 按虚拟对象 操作系统虚拟化 平台虚拟化 按方案 软件虚拟化 硬件虚拟化 虚拟机管理器 虚拟化技术...

  • Linux 基础4

    操作系统基础 计算机同时运行多个程序需要协调器--内核 内核kernel: 管理硬件资源,并且将硬件资源虚拟成其他...

  • KVM虚拟化

    kvm实验 环境准备,我这里使用虚拟机进行模拟,先设定好虚拟化 进入系统查看是否支持虚拟化 KVM:Kernel-...

  • Docker概念理解

    容器技术 简单介绍 容器技术又称为容器虚拟化 首先是一种虚拟化技术 虚拟化技术包括硬件虚拟化 半虚拟化 操作系统虚...

  • Centos7系统KVM虚拟化安装方式(2)--yum安装

    0x0配置kvm环境,需要cpu支持intel VT等硬件虚拟化功能。 如图有输出表示已经开启硬件虚拟化的相关功能...

  • RHEL/CentOS6(6.6)虚拟化(1)

    一. 什么是虚拟化和迁移 1.1 什么是虚拟化 大多数虚拟化的实现都是使用能控制硬件的hypervisor,软件层...

网友评论

      本文标题:【硬件虚拟化第二弹】远离kernel的理想乡

      本文链接:https://www.haomeiwen.com/subject/bkouxqtx.html