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

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

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

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

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

三、蛋疼的拦截处理

sysenter的处理方法:

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

这里有三种方法:

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

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

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

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

(编辑:文山站长网)

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

推荐文章
    热点阅读