加入收藏 | 设为首页 | 会员中心 | 我要投稿 温州站长网 (https://www.52wenzhou.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 资源网站 > 空间 > 正文

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

发布时间:2018-12-29 15:42:31 所属栏目:空间 来源:三寸法师
导读:简介 这个故事描述了如何使用硬件虚拟化(HVM)使得自己的一些hook代码远离内核不容易被其他内核hook所影响并且较难被检测。本文的思路来源于某学校的动态linux内核更新的玩意,代码大量抄自bluepill。 第一章 (Avalon) 阿瓦隆的黎明 由于驱动牛人越来越多系

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

  1. /* 
  2.   Vmx初始化 
  3. */ 
  4. NTSTATUS NTAPI VmxInitialize ( 
  5.    PCPU Cpu, 
  6.    PVOID GuestEip, 
  7.    PVOID GuestEsp 
  8.    PHYSICAL_ADDRESS AlignedVmcsPA; 
  9.    ULONG VaDelta; 
  10.    NTSTATUS Status; 
  11.  
  12.  
  13.    // 为 VMXON region 申请内存空间 
  14.    Cpu->Vmx.OriginaVmxonR = MmAllocateContiguousPages( 
  15.        VMX_VMXONR_SIZE_IN_PAGES,  
  16.        &Cpu->Vmx.OriginalVmxonRPA); 
  17.    if (!Cpu->Vmx.OriginaVmxonR)  
  18.    { 
  19.  DbgPrint("VmxInitialize(): Failed to allocate memory for original VMCSn"); 
  20.        return STATUS_INSUFFICIENT_RESOURCES; 
  21.    } 
  22.  
  23.    DbgPrint("VmxInitialize(): OriginaVmxonR VA: 0x%xn", Cpu->Vmx.OriginaVmxonR); 
  24.    DbgPrint("VmxInitialize(): OriginaVmxonR PA: 0x%llxn", Cpu->Vmx.OriginalVmxonRPA.QuadPart); 
  25.  
  26.    // 为 VMCS 申请内存空间  
  27.    Cpu->Vmx.OriginalVmcs = MmAllocateContiguousPages( 
  28.        VMX_VMCS_SIZE_IN_PAGES,  
  29.        &Cpu->Vmx.OriginalVmcsPA); 
  30.    if (!Cpu->Vmx.OriginalVmcs)  
  31.    { 
  32.  DbgPrint("VmxInitialize(): Failed to allocate memory for original VMCSn"); 
  33.        return STATUS_INSUFFICIENT_RESOURCES; 
  34.    } 
  35.  
  36.    DbgPrint("VmxInitialize(): Vmcs VA: 0x%xn", Cpu->Vmx.OriginalVmcs); 
  37.    DbgPrint("VmxInitialize(): Vmcs PA: 0x%llxn", Cpu->Vmx.OriginalVmcsPA.QuadPart); 
  38.  
  39.    // 开启vmx 
  40.    if (!NT_SUCCESS (VmxEnable (Cpu->Vmx.OriginaVmxonR))) 
  41.    { 
  42.        DbgPrint("VmxInitialize(): Failed to enable Vmxn"); 
  43.        return STATUS_UNSUCCESSFUL; 
  44.    } 
  45.  
  46.    *((ULONG64 *)(Cpu->Vmx.OriginalVmcs)) =  
  47.        (MsrRead (MSR_IA32_VMX_BASIC) & 0xffffffff); //set up vmcs_revision_id       
  48.  
  49.    // 填充VMCS结构 
  50. Status = VmxSetupVMCS (Cpu, GuestEip, GuestEsp); 
  51.    if (!NT_SUCCESS (Status))  
  52.    { 
  53.        DbgPrint("VmxSetupVMCS() failed with status 0x%08hXn", Status); 
  54.        VmxDisable(); 
  55.        return Status; 
  56.    } 
  57.  
  58.    DbgPrint("VmxInitialize(): Vmx enabledn"); 
  59.  
  60.   // 保存EFER 
  61.    Cpu->Vmx.GuestEFER = MsrRead (MSR_EFER); 
  62.    DbgPrint("Guest MSR_EFER Read 0x%llx n", Cpu->Vmx.GuestEFER); 
  63.  
  64.   // 保存控制寄存器 
  65.    Cpu->Vmx.GuestCR0 = RegGetCr0 (); 
  66.    Cpu->Vmx.GuestCR3 = RegGetCr3 (); 
  67.    Cpu->Vmx.GuestCR4 = RegGetCr4 (); 
  68.  
  69.    CmCli (); 
  70.    return STATUS_SUCCESS; 
  71.  
  72.  
  73.  
  74. /* 
  75.   开启vmx 
  76. */ 
  77. NTSTATUS NTAPI VmxEnable ( 
  78.    PVOID VmxonVA 
  79.    ULONG cr4; 
  80.    ULONG64 vmxmsr; 
  81.    ULONG flags; 
  82.    PHYSICAL_ADDRESS VmxonPA; 
  83.  
  84. // 设置cr4位,为启用VM模式做准备 
  85.    set_in_cr4 (X86_CR4_VMXE); 
  86.    cr4 = get_cr4 (); 
  87.    DbgPrint("VmxEnable(): CR4 after VmxEnable: 0x%llxn", cr4); 
  88.    if (!(cr4 & X86_CR4_VMXE)) 
  89.        return STATUS_NOT_SUPPORTED; 
  90.  
  91. // 检测是否支持vmx 
  92.    vmxmsr = MsrRead (MSR_IA32_FEATURE_CONTROL); 
  93.    if (!(vmxmsr & 4))  
  94.    { 
  95.        DbgPrint("VmxEnable(): VMX is not supported: IA32_FEATURE_CONTROL is 0x%llxn", vmxmsr); 
  96.        return STATUS_NOT_SUPPORTED; 
  97.    } 
  98.  
  99. //bochs的bug,要改IA32_FEATURE_CONTROL的Lock为1 
  100. #if bochsdebug 
  101. MsrWrite(MSR_IA32_FEATURE_CONTROL,5); 
  102.    #endif 
  103.  
  104.    vmxmsr = MsrRead (MSR_IA32_VMX_BASIC); 
  105.    *((ULONG64 *) VmxonVA) = (vmxmsr & 0xffffffff);       //set up vmcs_revision_id 
  106.    VmxonPA = MmGetPhysicalAddress (VmxonVA); 
  107.  
  108.    DbgPrint("VmxEnable(): VmxonPA:  0x%llxn", VmxonPA.QuadPart); 
  109.  
  110. //开启VMX 
  111. VmxTurnOn(VmxonPA); 
  112.    flags = RegGetEflags (); 
  113.    DbgPrint("VmxEnable(): vmcs_revision_id: 0x%x  Eflags: 0x%x n", vmxmsr, flags); 
  114.  
  115.    return STATUS_SUCCESS; 
  116.  
  117.  
  118.  
  119. /* 
  120.   进入虚拟机 
  121. */ 
  122. NTSTATUS NTAPI VmxVirtualize ( 
  123.  PCPU Cpu 
  124.  
  125.    ULONG esp; 
  126.    if (!Cpu) 
  127.        return STATUS_INVALID_PARAMETER; 
  128.  
  129. *((PULONG) (g_HostStackBaseAddress + 0x0C00)) = (ULONG) Cpu; 
  130.            
  131.    VmxLaunch (); 
  132.  
  133.    // never returns 
  134.  
  135.    return STATUS_UNSUCCESSFUL; 

三、蛋疼的拦截处理

sysenter的处理方法:

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

这里有三种方法:

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

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

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

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

(编辑:温州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读