接下来是一些坑爹的代码:
- /*
- 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后的运行流向。 (编辑:威海站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|