Source Code Read: SimpleVisor Pinback: vt
从驱动入口 DriverEntry 开始读:
首先做了一个 power state callback,之后加载 hypervisor
hypervisor 加载的逻辑在函数 ShvLoad 中,剩下的阅读都从这个函数出发。
首先需要让所有的 LP(Logic Processor) 进入 VMX root 模式
ShvLoad
ShvOsRunCallbackOnProcessors(ShvVpLoadCallback, &callbackContext);
KeGenericCallDpc // callback
ShvOsDpcRoutine // callback
ShvVpLoadCallback // 在这个函数中cpu 被 hyperjacked,~返回后就是unload和清理了~
// do cleanup:
// ShvVmxCleanup, KeSignalCallDpcSynchronize, KeSignalCallDpcDone
ShvVpLoadCallback
ShvVmxProbe // 检查 VMX root mode 是否支持
PSHV_VP_DATA vpData // 初始化vpData,代表一个~LP~的数据结构
vpData->SystemDirectoryTableBase = Context->Cr3; // TODO: 看注释,什么是PML4
ShvVpInitialize(vpData) // 初始化VP
if (ShvIsOurHypervisorPresent() == FALSE) // 通过cpuid检查当前hypervisor是否初始化成功
// ~此时cpuid应该已经被hook~
InterlockedIncrement(Context->InitCount); // 增加初始化成功的LP计数, This CPU is hyperjacked!
ShvVpInitialize(Data)
ShvOsPrepareProcessor // dump,只在uefi时有用
ShvCaptureSpecialRegisters(&Data->SpecialRegisters); // 初始化vpData的SpecialRegisters:
// cr0, cr3, cr4, debug_ctl, msr_gs_base,
// kernel_dr7, gdtr.limit, idtr.limit, tr, ldtr
ShvOsCaptureContext(&Data->ContextFrame);
RtlCaptureContext(ContextRecord); // windows提供的函数:
// Retrieves a context record in the context of the caller.
status = ShvVmxLaunchOnVp(Data); // 如果EFLAGS_ALIGN_CHECK没有set,为当前处理器初始化VMX
ShvVmxLaunchOnVp(VpData)
VpData->MsrData[i].QuadPart = readmsr(MSR_IA32_VMX_BASIC + i); // 初始化VMX相关的一系列MSRs
ShvVmxMtrrInitialize(VpData); // 初始化 MTRR (Memory Type Range Registers) 相关的一系列MSRs,
// 这似乎是为了EPT准备的。
ShvVmxEptInitialize // 初始化 EPT structures
ShvVmxEnterRootModeOnVp(VpData) // Attempt to enter VMX root mode on this processor.
ShvVmxSetupVmcsForVp(VpData); // 初始化 VMCS,包括guest和host state,大多数“可选监控项”都在这里面
ShvVmxLaunch()
vmlaunch // 这里不该返回了,返回就是失败了,后面是失败处理
// 如果成功rip会指向 ShvVpRestoreAfterLaunch
failureCode = (INT32)ShvVmxRead(VM_INSTRUCTION_ERROR);
vmoff
ShvVmxEnterRootModeOnVp(VpData)
// - 做一些 check
// - 写 revision ID到VmxOn和vmcs里面
// - 设置一些physical addresses
// - 奇怪的掩码方式设置CR0和cr4
__vmx_on // Enable VMX Root Mode
__vmx_vmclear // Clear the state of the VMCS, setting it to Inactive
__vmx_vmptrld // Load the VMCS, setting its state to Active
// 至此 VMX Root Mode is enabled, with an active VMCS.
==== 重要的数据结构 ====
typedef struct _SHV_VP_DATA
{
union
{
DECLSPEC_ALIGN(PAGE_SIZE) UINT8 ShvStackLimit[KERNEL_STACK_SIZE];
struct
{
SHV_SPECIAL_REGISTERS SpecialRegisters;
CONTEXT ContextFrame;
UINT64 SystemDirectoryTableBase;
LARGE_INTEGER MsrData[17];
SHV_MTRR_RANGE MtrrData[16];
UINT64 VmxOnPhysicalAddress;
UINT64 VmcsPhysicalAddress;
UINT64 MsrBitmapPhysicalAddress;
UINT64 EptPml4PhysicalAddress;
UINT32 EptControls;
};
};
DECLSPEC_ALIGN(PAGE_SIZE) UINT8 MsrBitmap[PAGE_SIZE];
DECLSPEC_ALIGN(PAGE_SIZE) VMX_EPML4E Epml4[PML4E_ENTRY_COUNT];
DECLSPEC_ALIGN(PAGE_SIZE) VMX_PDPTE Epdpt[PDPTE_ENTRY_COUNT];
DECLSPEC_ALIGN(PAGE_SIZE) VMX_LARGE_PDE Epde[PDPTE_ENTRY_COUNT][PDE_ENTRY_COUNT];
DECLSPEC_ALIGN(PAGE_SIZE) VMX_VMCS VmxOn;
DECLSPEC_ALIGN(PAGE_SIZE) VMX_VMCS Vmcs;
} SHV_VP_DATA, *PSHV_VP_DATA;