我遇到了以下问题:当我初始化内核管理程序时,对我来说它是SVM,我从vmrun退出并进入我的SvmExitHandler(这是管理退出代码的调度程序),然后当我尝试调用任何IRQL Passive时level api(假设我正在使用它),我得到一个 BSOD KERNEL_SECURIY_CHECK_FAILURE。
同时,当我使用相同的参数调用相同的 API 时,但在启动 SVM 之前,一切都对我有用。当我使用 SVM 时,如何组织与内核函数的通信?比如我需要在tracing的时候处理每一条指令
extern "C" VMM_STATUS SvmVmexitHandler(PRIVATE_VM_DATA* Private, GUEST_CONTEXT* Context, GUEST_SSE_CONTEXT* SSeContext, GUEST_AVX_CONTEXT* AvxContext)
{
// Load the host state:
__svm_vmload(reinterpret_cast<size_t>(Private->VmmStack.Layout.InitialStack.HostVmcbPa));
// Restore the guest's RAX that was overwritten by host's RAX on #VMEXIT:
Context->Rax = Private->Guest.StateSaveArea.Rax;
VMM_STATUS Status = VMM_STATUS::VMM_CONTINUE;
switch (Private->Guest.ControlArea.ExitCode)
{
case VMEXIT_CPUID:
{
CPUID_REGS Regs = {};
int Function = static_cast<int>(Context->Rax);
int SubLeaf = static_cast<int>(Context->Rcx);
__cpuidex(Regs.Raw, Function, SubLeaf);
switch (Function) {
case CPUID_VMM_SHUTDOWN:
{
// Shutdown was triggered:
Status = VMM_STATUS::VMM_SHUTDOWN;
break;
}
case CPUID::Generic::CPUID_MAXIMUM_FUNCTION_NUMBER_AND_VENDOR_ID:
{
// Vendor = 'Hyper-Bridge' as RBX + RDX + RCX:
Context->Rax = Regs.Regs.Eax;
GetHvCpuName(Context->Rbx, Context->Rcx, Context->Rdx);
break;
}
default:
{
Context->Rax = Regs.Regs.Eax;
Context->Rbx = Regs.Regs.Ebx;
Context->Rcx = Regs.Regs.Ecx;
Context->Rdx = Regs.Regs.Edx;
break;
}
}
break;
}
case VMEXIT_MSR:
{
if ((Context->Rcx & MAXUINT32) == static_cast<unsigned int>(AMD_MSR::MSR_EFER) && Private->Guest.ControlArea.ExitInfo1)
{
EFER Efer = {};
Efer.Value = ((Context->Rdx & MAXUINT32) << 32) | (Context->Rax & MAXUINT32);
if (!Efer.Bitmap.SecureVirtualMachineEnable)
{
InjectEvent(&Private->Guest, INTERRUPT_VECTOR::GeneralProtection, EXCEPTION_VECTOR::FaultTrapException, 0); // #GP (Vector = 13, Type = Exception)
break;
}
Private->Guest.StateSaveArea.Efer = Efer.Value;
}
break;
}
case VMEXIT_VMRUN:
{
InjectEvent(&Private->Guest, INTERRUPT_VECTOR::GeneralProtection, EXCEPTION_VECTOR::FaultTrapException, 0); // #GP (Vector = 13, Type = Exception)
break;
}
case VMEXIT_EXCP_DB://TRACE EXCEPTION BY TF FLAG
{
KdPrint(("RIP %p\n", Private->Guest.StateSaveArea.Rip));
Private->Guest.StateSaveArea.Rax = Context->Rax;
return Status;
}
}
if (Status == VMM_STATUS::VMM_SHUTDOWN)
{
// We should to devirtualize this processor:
Context->Rax = reinterpret_cast<UINT64>(Private) & MAXUINT32; // Low part
Context->Rbx = Private->Guest.ControlArea.NextRip;
Context->Rcx = Private->Guest.StateSaveArea.Rsp;
Context->Rdx = reinterpret_cast<UINT64>(Private) >> 32; // High part
// Load the guest's state:
__svm_vmload(reinterpret_cast<size_t>(Private->VmmStack.Layout.InitialStack.GuestVmcbPa));
// Store the GIF - Global Interrupt Flag:
_disable();
__svm_stgi();
// Disable the SVM by resetting the EFER.SVME bit:
EFER Efer = {};
Efer.Value = __readmsr(static_cast<unsigned long>(AMD_MSR::MSR_EFER));
Efer.Bitmap.SecureVirtualMachineEnable = FALSE;
__writemsr(static_cast<unsigned long>(AMD_MSR::MSR_EFER), Efer.Value);
// Restoring the EFlags:
__writeeflags(Private->Guest.StateSaveArea.Rflags);
}
Private->Guest.StateSaveArea.Rax = Context->Rax;
// Go to the next instruction:
Private->Guest.StateSaveArea.Rip = Private->Guest.ControlArea.NextRip;
return Status;
}
因此,如果我直接访问 ZwWriteFIle API 以便将 RIP 值写入 VMEXIT_EXCP_DB,那么我将崩溃并出现 BSOD,因为实际上当我处于 SVM 中时,所有中断和其他功能都被禁用。我该怎么办?我会很高兴得到任何帮助!
这个问题的完整答案是:不,因为为了进入中断,我的 IRQL 级别会上升,然后在进入 SvmVmexitHandler 后下降,因此我不能在中使用任何依赖于 IRQL 的本机 API它