| 接下来是一些坑爹的代码: /*   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 VMCSn");        return STATUS_INSUFFICIENT_RESOURCES;    }     DbgPrint("VmxInitialize(): OriginaVmxonR VA: 0x%xn", Cpu->Vmx.OriginaVmxonR);    DbgPrint("VmxInitialize(): OriginaVmxonR PA: 0x%llxn", 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 VMCSn");        return STATUS_INSUFFICIENT_RESOURCES;    }     DbgPrint("VmxInitialize(): Vmcs VA: 0x%xn", Cpu->Vmx.OriginalVmcs);    DbgPrint("VmxInitialize(): Vmcs PA: 0x%llxn", Cpu->Vmx.OriginalVmcsPA.QuadPart);     // 开启vmx    if (!NT_SUCCESS (VmxEnable (Cpu->Vmx.OriginaVmxonR)))    {        DbgPrint("VmxInitialize(): Failed to enable Vmxn");        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%08hXn", Status);        VmxDisable();        return Status;    }     DbgPrint("VmxInitialize(): Vmx enabledn");    // 保存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%llxn", 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%llxn", 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%llxn", 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后的运行流向。 (编辑:我爱故事小小网_铜陵站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |