/*! @file HostUtils.c @brief Utility functions and structures for the host. @author Satoshi Tanda @copyright Copyright (c) 2020 - , Satoshi Tanda. All rights reserved. */ #include "HostUtils.h" #include "Logger.h" #include "ExtendedPageTables.h" #include "Ia32Utils.h" #include "MemoryAccess.h" /*! @brief Dumps the segment access rights value. @param[in] AccessRights - The segment access rights value to dump. */ static VOID DumpAccessRights ( _In_ UINT64 AccessRights ) { VMX_SEGMENT_ACCESS_RIGHTS rights; rights.Flags = (UINT32)AccessRights; LOG_ERROR(" - Type = %u", rights.Type); LOG_ERROR(" - S = %u", rights.DescriptorType); LOG_ERROR(" - DPL = %u", rights.DescriptorPrivilegeLevel); LOG_ERROR(" - P = %u", rights.Present); LOG_ERROR(" - Reserved1 = %u", rights.Reserved1); LOG_ERROR(" - Available = %u", rights.AvailableBit); LOG_ERROR(" - L = %u", rights.LongMode); LOG_ERROR(" - D/B = %u", rights.DefaultBig); LOG_ERROR(" - G = %u", rights.Granularity); LOG_ERROR(" - Unusable = %u", rights.Unusable); LOG_ERROR(" - Reserved2 = %u", rights.Reserved2); } VOID DumpHostState ( ) { // // 16-Bit Host-State Fields // LOG_ERROR("Host ES Selector = %016llx", VmxRead(VMCS_HOST_ES_SELECTOR)); LOG_ERROR("Host CS Selector = %016llx", VmxRead(VMCS_HOST_CS_SELECTOR)); LOG_ERROR("Host SS Selector = %016llx", VmxRead(VMCS_HOST_SS_SELECTOR)); LOG_ERROR("Host DS Selector = %016llx", VmxRead(VMCS_HOST_DS_SELECTOR)); LOG_ERROR("Host FS Selector = %016llx", VmxRead(VMCS_HOST_FS_SELECTOR)); LOG_ERROR("Host GS Selector = %016llx", VmxRead(VMCS_HOST_GS_SELECTOR)); LOG_ERROR("Host TR Selector = %016llx", VmxRead(VMCS_HOST_TR_SELECTOR)); // // 64-Bit Host-State Fields // LOG_ERROR("Host IA32_PAT = %016llx", VmxRead(VMCS_HOST_PAT)); LOG_ERROR("Host IA32_EFER = %016llx", VmxRead(VMCS_HOST_EFER)); LOG_ERROR("Host IA32_PERF_GLOBAL_CTRL = %016llx", VmxRead(VMCS_HOST_PERF_GLOBAL_CTRL)); // // 32-Bit Host-State Fields // LOG_ERROR("Host IA32_SYSENTER_CS = %016llx", VmxRead(VMCS_HOST_SYSENTER_CS)); // // Natural-Width Host-State Fields // LOG_ERROR("Host CR0 = %016llx", VmxRead(VMCS_HOST_CR0)); LOG_ERROR("Host CR3 = %016llx", VmxRead(VMCS_HOST_CR3)); LOG_ERROR("Host CR4 = %016llx", VmxRead(VMCS_HOST_CR4)); LOG_ERROR("Host FS Base = %016llx", VmxRead(VMCS_HOST_FS_BASE)); LOG_ERROR("Host GS Base = %016llx", VmxRead(VMCS_HOST_GS_BASE)); LOG_ERROR("Host TR base = %016llx", VmxRead(VMCS_HOST_TR_BASE)); LOG_ERROR("Host GDTR base = %016llx", VmxRead(VMCS_HOST_GDTR_BASE)); LOG_ERROR("Host IDTR base = %016llx", VmxRead(VMCS_HOST_IDTR_BASE)); LOG_ERROR("Host IA32_SYSENTER_ESP = %016llx", VmxRead(VMCS_HOST_SYSENTER_ESP)); LOG_ERROR("Host IA32_SYSENTER_EIP = %016llx", VmxRead(VMCS_HOST_SYSENTER_EIP)); LOG_ERROR("Host RSP = %016llx", VmxRead(VMCS_HOST_RSP)); LOG_ERROR("Host RIP = %016llx", VmxRead(VMCS_HOST_RIP)); } VOID DumpGuestState ( ) { // // 16-Bit Guest-State Fields // LOG_ERROR("Guest ES Selector = %016llx", VmxRead(VMCS_GUEST_ES_SELECTOR)); LOG_ERROR("Guest CS Selector = %016llx", VmxRead(VMCS_GUEST_CS_SELECTOR)); LOG_ERROR("Guest SS Selector = %016llx", VmxRead(VMCS_GUEST_SS_SELECTOR)); LOG_ERROR("Guest DS Selector = %016llx", VmxRead(VMCS_GUEST_DS_SELECTOR)); LOG_ERROR("Guest FS Selector = %016llx", VmxRead(VMCS_GUEST_FS_SELECTOR)); LOG_ERROR("Guest GS Selector = %016llx", VmxRead(VMCS_GUEST_GS_SELECTOR)); LOG_ERROR("Guest LDTR Selector = %016llx", VmxRead(VMCS_GUEST_LDTR_SELECTOR)); LOG_ERROR("Guest TR Selector = %016llx", VmxRead(VMCS_GUEST_TR_SELECTOR)); LOG_ERROR("Guest interrupt status = %016llx", VmxRead(VMCS_GUEST_INTERRUPT_STATUS)); LOG_ERROR("PML index = %016llx", VmxRead(VMCS_GUEST_PML_INDEX)); // // 64-Bit Guest-State Fields // LOG_ERROR("VMCS link pointer = %016llx", VmxRead(VMCS_GUEST_VMCS_LINK_POINTER)); LOG_ERROR("Guest IA32_DEBUGCTL = %016llx", VmxRead(VMCS_GUEST_DEBUGCTL)); LOG_ERROR("Guest IA32_PAT = %016llx", VmxRead(VMCS_GUEST_PAT)); LOG_ERROR("Guest IA32_EFER = %016llx", VmxRead(VMCS_GUEST_EFER)); LOG_ERROR("Guest IA32_PERF_GLOBAL_CTRL = %016llx", VmxRead(VMCS_GUEST_PERF_GLOBAL_CTRL)); LOG_ERROR("Guest PDPTE0 = %016llx", VmxRead(VMCS_GUEST_PDPTE0)); LOG_ERROR("Guest PDPTE1 = %016llx", VmxRead(VMCS_GUEST_PDPTE1)); LOG_ERROR("Guest PDPTE2 = %016llx", VmxRead(VMCS_GUEST_PDPTE2)); LOG_ERROR("Guest PDPTE3 = %016llx", VmxRead(VMCS_GUEST_PDPTE3)); LOG_ERROR("Guest IA32_BNDCFGS = %016llx", VmxRead(VMCS_GUEST_BNDCFGS)); LOG_ERROR("Guest IA32_RTIT_CTL = %016llx", VmxRead(VMCS_GUEST_RTIT_CTL)); // // 32-Bit Guest-State Fields // LOG_ERROR("Guest ES Limit = %016llx", VmxRead(VMCS_GUEST_ES_LIMIT)); LOG_ERROR("Guest CS Limit = %016llx", VmxRead(VMCS_GUEST_CS_LIMIT)); LOG_ERROR("Guest SS Limit = %016llx", VmxRead(VMCS_GUEST_SS_LIMIT)); LOG_ERROR("Guest DS Limit = %016llx", VmxRead(VMCS_GUEST_DS_LIMIT)); LOG_ERROR("Guest FS Limit = %016llx", VmxRead(VMCS_GUEST_FS_LIMIT)); LOG_ERROR("Guest GS Limit = %016llx", VmxRead(VMCS_GUEST_GS_LIMIT)); LOG_ERROR("Guest LDTR Limit = %016llx", VmxRead(VMCS_GUEST_LDTR_LIMIT)); LOG_ERROR("Guest TR Limit = %016llx", VmxRead(VMCS_GUEST_TR_LIMIT)); LOG_ERROR("Guest GDTR limit = %016llx", VmxRead(VMCS_GUEST_GDTR_LIMIT)); LOG_ERROR("Guest IDTR limit = %016llx", VmxRead(VMCS_GUEST_IDTR_LIMIT)); LOG_ERROR("Guest ES access rights = %016llx", VmxRead(VMCS_GUEST_ES_ACCESS_RIGHTS)); LOG_ERROR("Guest CS access rights = %016llx", VmxRead(VMCS_GUEST_CS_ACCESS_RIGHTS)); LOG_ERROR("Guest SS access rights = %016llx", VmxRead(VMCS_GUEST_SS_ACCESS_RIGHTS)); LOG_ERROR("Guest DS access rights = %016llx", VmxRead(VMCS_GUEST_DS_ACCESS_RIGHTS)); LOG_ERROR("Guest FS access rights = %016llx", VmxRead(VMCS_GUEST_FS_ACCESS_RIGHTS)); LOG_ERROR("Guest GS access rights = %016llx", VmxRead(VMCS_GUEST_GS_ACCESS_RIGHTS)); LOG_ERROR("Guest LDTR access rights = %016llx", VmxRead(VMCS_GUEST_LDTR_ACCESS_RIGHTS)); LOG_ERROR("Guest TR access rights = %016llx", VmxRead(VMCS_GUEST_TR_ACCESS_RIGHTS)); LOG_ERROR("Guest interruptibility state = %016llx", VmxRead(VMCS_GUEST_INTERRUPTIBILITY_STATE)); LOG_ERROR("Guest activity state = %016llx", VmxRead(VMCS_GUEST_ACTIVITY_STATE)); LOG_ERROR("Guest SMBASE = %016llx", VmxRead(VMCS_GUEST_SMBASE)); LOG_ERROR("Guest IA32_SYSENTER_CS = %016llx", VmxRead(VMCS_GUEST_SYSENTER_CS)); LOG_ERROR("VMX-preemption timer value = %016llx", VmxRead(VMCS_GUEST_VMX_PREEMPTION_TIMER_VALUE)); // // Natural-Width Guest-State Fields // LOG_ERROR("Guest CR0 = %016llx", VmxRead(VMCS_GUEST_CR0)); LOG_ERROR("Guest CR3 = %016llx", VmxRead(VMCS_GUEST_CR3)); LOG_ERROR("Guest CR4 = %016llx", VmxRead(VMCS_GUEST_CR4)); LOG_ERROR("Guest ES Base = %016llx", VmxRead(VMCS_GUEST_ES_BASE)); LOG_ERROR("Guest CS Base = %016llx", VmxRead(VMCS_GUEST_CS_BASE)); LOG_ERROR("Guest SS Base = %016llx", VmxRead(VMCS_GUEST_SS_BASE)); LOG_ERROR("Guest DS Base = %016llx", VmxRead(VMCS_GUEST_DS_BASE)); LOG_ERROR("Guest FS Base = %016llx", VmxRead(VMCS_GUEST_FS_BASE)); LOG_ERROR("Guest GS Base = %016llx", VmxRead(VMCS_GUEST_GS_BASE)); LOG_ERROR("Guest LDTR base = %016llx", VmxRead(VMCS_GUEST_LDTR_BASE)); LOG_ERROR("Guest TR base = %016llx", VmxRead(VMCS_GUEST_TR_BASE)); LOG_ERROR("Guest GDTR base = %016llx", VmxRead(VMCS_GUEST_GDTR_BASE)); LOG_ERROR("Guest IDTR base = %016llx", VmxRead(VMCS_GUEST_IDTR_BASE)); LOG_ERROR("Guest DR7 = %016llx", VmxRead(VMCS_GUEST_DR7)); LOG_ERROR("Guest RSP = %016llx", VmxRead(VMCS_GUEST_RSP)); LOG_ERROR("Guest RIP = %016llx", VmxRead(VMCS_GUEST_RIP)); LOG_ERROR("Guest RFLAGS = %016llx", VmxRead(VMCS_GUEST_RFLAGS)); LOG_ERROR("Guest pending debug exceptions = %016llx", VmxRead(VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS)); LOG_ERROR("Guest IA32_SYSENTER_ESP = %016llx", VmxRead(VMCS_GUEST_SYSENTER_ESP)); LOG_ERROR("Guest IA32_SYSENTER_EIP = %016llx", VmxRead(VMCS_GUEST_SYSENTER_EIP)); } VOID DumpControl ( ) { // // 16-Bit Control Fields // LOG_ERROR("Virtual-processor identifier = %016llx", VmxRead(VMCS_CTRL_VIRTUAL_PROCESSOR_IDENTIFIER)); LOG_ERROR("Posted-interrupt notification vector = %016llx", VmxRead(VMCS_CTRL_POSTED_INTERRUPT_NOTIFICATION_VECTOR)); LOG_ERROR("EPTP index = %016llx", VmxRead(VMCS_CTRL_EPTP_INDEX)); // // 64-Bit Control Fields // LOG_ERROR("Address of I/O bitmap A = %016llx", VmxRead(VMCS_CTRL_IO_BITMAP_A_ADDRESS)); LOG_ERROR("Address of I/O bitmap B = %016llx", VmxRead(VMCS_CTRL_IO_BITMAP_B_ADDRESS)); LOG_ERROR("Address of MSR bitmaps = %016llx", VmxRead(VMCS_CTRL_MSR_BITMAP_ADDRESS)); LOG_ERROR("VM-exit MSR-store address = %016llx", VmxRead(VMCS_CTRL_VMEXIT_MSR_STORE_ADDRESS)); LOG_ERROR("VM-exit MSR-load address = %016llx", VmxRead(VMCS_CTRL_VMEXIT_MSR_LOAD_ADDRESS)); LOG_ERROR("VM-entry MSR-load address = %016llx", VmxRead(VMCS_CTRL_VMENTRY_MSR_LOAD_ADDRESS)); LOG_ERROR("Executive-VMCS pointer = %016llx", VmxRead(VMCS_CTRL_EXECUTIVE_VMCS_POINTER)); LOG_ERROR("PML address = %016llx", VmxRead(VMCS_CTRL_PML_ADDRESS)); LOG_ERROR("TSC offset = %016llx", VmxRead(VMCS_CTRL_TSC_OFFSET)); LOG_ERROR("Virtual-APIC address = %016llx", VmxRead(VMCS_CTRL_VIRTUAL_APIC_ADDRESS)); LOG_ERROR("APIC-access address = %016llx", VmxRead(VMCS_CTRL_APIC_ACCESS_ADDRESS)); LOG_ERROR("Posted-interrupt descriptor address = %016llx", VmxRead(VMCS_CTRL_POSTED_INTERRUPT_DESCRIPTOR_ADDRESS)); LOG_ERROR("VM-function controls = %016llx", VmxRead(VMCS_CTRL_VMFUNC_CONTROLS)); LOG_ERROR("EPT pointer = %016llx", VmxRead(VMCS_CTRL_EPT_POINTER)); LOG_ERROR("EOI-exit bitmap 0 = %016llx", VmxRead(VMCS_CTRL_EOI_EXIT_BITMAP_0)); LOG_ERROR("EOI-exit bitmap 1 = %016llx", VmxRead(VMCS_CTRL_EOI_EXIT_BITMAP_1)); LOG_ERROR("EOI-exit bitmap 2 = %016llx", VmxRead(VMCS_CTRL_EOI_EXIT_BITMAP_2)); LOG_ERROR("EOI-exit bitmap 3 = %016llx", VmxRead(VMCS_CTRL_EOI_EXIT_BITMAP_3)); LOG_ERROR("EPTP-list address = %016llx", VmxRead(VMCS_CTRL_EPT_POINTER_LIST_ADDRESS)); LOG_ERROR("VMREAD-bitmap address = %016llx", VmxRead(VMCS_CTRL_VMREAD_BITMAP_ADDRESS)); LOG_ERROR("VMWRITE-bitmap address = %016llx", VmxRead(VMCS_CTRL_VMWRITE_BITMAP_ADDRESS)); LOG_ERROR("Virtualization-exception information address = %016llx", VmxRead(VMCS_CTRL_VIRTUALIZATION_EXCEPTION_INFORMATION_ADDRESS)); LOG_ERROR("XSS-exiting bitmap = %016llx", VmxRead(VMCS_CTRL_XSS_EXITING_BITMAP)); LOG_ERROR("ENCLS-exiting bitmap = %016llx", VmxRead(VMCS_CTRL_ENCLS_EXITING_BITMAP)); LOG_ERROR("TSC multiplier = %016llx", VmxRead(VMCS_CTRL_TSC_MULTIPLIER)); // // 32-Bit Control Fields // LOG_ERROR("Pin-based VM-execution controls = %016llx", VmxRead(VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS)); LOG_ERROR("Primary processor-based VM-execution controls = %016llx", VmxRead(VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS)); LOG_ERROR("Exception bitmap = %016llx", VmxRead(VMCS_CTRL_EXCEPTION_BITMAP)); LOG_ERROR("Page-fault error-code mask = %016llx", VmxRead(VMCS_CTRL_PAGEFAULT_ERROR_CODE_MASK)); LOG_ERROR("Page-fault error-code match = %016llx", VmxRead(VMCS_CTRL_PAGEFAULT_ERROR_CODE_MATCH)); LOG_ERROR("CR3-target count = %016llx", VmxRead(VMCS_CTRL_CR3_TARGET_COUNT)); LOG_ERROR("VM-exit controls = %016llx", VmxRead(VMCS_CTRL_VMEXIT_CONTROLS)); LOG_ERROR("VM-exit MSR-store count = %016llx", VmxRead(VMCS_CTRL_VMEXIT_MSR_STORE_COUNT)); LOG_ERROR("VM-exit MSR-load count = %016llx", VmxRead(VMCS_CTRL_VMEXIT_MSR_LOAD_COUNT)); LOG_ERROR("VM-entry controls = %016llx", VmxRead(VMCS_CTRL_VMENTRY_CONTROLS)); LOG_ERROR("VM-entry MSR-load count = %016llx", VmxRead(VMCS_CTRL_VMENTRY_MSR_LOAD_COUNT)); LOG_ERROR("VM-entry interruption-information field = %016llx", VmxRead(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD)); LOG_ERROR("VM-entry exception error code = %016llx", VmxRead(VMCS_CTRL_VMENTRY_EXCEPTION_ERROR_CODE)); LOG_ERROR("VM-entry instruction length = %016llx", VmxRead(VMCS_CTRL_VMENTRY_INSTRUCTION_LENGTH)); LOG_ERROR("TPR threshold = %016llx", VmxRead(VMCS_CTRL_TPR_THRESHOLD)); LOG_ERROR("Secondary processor-based VM-execution controls = %016llx", VmxRead(VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS)); LOG_ERROR("PLE_Gap = %016llx", VmxRead(VMCS_CTRL_PLE_GAP)); LOG_ERROR("PLE_Window = %016llx", VmxRead(VMCS_CTRL_PLE_WINDOW)); // // Natural-Width Control Fields // LOG_ERROR("CR0 guest/host mask = %016llx", VmxRead(VMCS_CTRL_CR0_GUEST_HOST_MASK)); LOG_ERROR("CR4 guest/host mask = %016llx", VmxRead(VMCS_CTRL_CR4_GUEST_HOST_MASK)); LOG_ERROR("CR0 read shadow = %016llx", VmxRead(VMCS_CTRL_CR0_READ_SHADOW)); LOG_ERROR("CR4 read shadow = %016llx", VmxRead(VMCS_CTRL_CR4_READ_SHADOW)); LOG_ERROR("CR3-target value 0 = %016llx", VmxRead(VMCS_CTRL_CR3_TARGET_VALUE_0)); LOG_ERROR("CR3-target value 1 = %016llx", VmxRead(VMCS_CTRL_CR3_TARGET_VALUE_1)); LOG_ERROR("CR3-target value 2 = %016llx", VmxRead(VMCS_CTRL_CR3_TARGET_VALUE_2)); LOG_ERROR("CR3-target value 3 = %016llx", VmxRead(VMCS_CTRL_CR3_TARGET_VALUE_3)); } _Use_decl_annotations_ VOID VmxWrite ( VMCS_FIELD Field, UINT64 FieldValue ) { VMX_RESULT result; result = __vmx_vmwrite(Field, FieldValue); if (result != VmxResultOk) { VMX_ERROR_NUMBER vmxErrorStatus; vmxErrorStatus = (result == VmxResultErrorWithStatus) ? (VMX_ERROR_NUMBER)VmxRead(VMCS_VM_INSTRUCTION_ERROR) : 0; if (vmxErrorStatus != VMX_ERROR_VMREAD_VMWRITE_INVALID_COMPONENT) { MV_PANIC(); } } } _Use_decl_annotations_ UINT64 VmxRead ( VMCS_FIELD Field ) { VMX_RESULT result; UINT64 fieldValue; result = __vmx_vmread(Field, &fieldValue); if (result != VmxResultOk) { VMX_ERROR_NUMBER vmxErrorStatus; vmxErrorStatus = (result == VmxResultErrorWithStatus) ? (VMX_ERROR_NUMBER)VmxRead(VMCS_VM_INSTRUCTION_ERROR) : 0; if (vmxErrorStatus != VMX_ERROR_VMREAD_VMWRITE_INVALID_COMPONENT) { MV_PANIC(); } fieldValue = 0; } return fieldValue; } _Use_decl_annotations_ VOID AdvanceGuestInstructionPointer ( GUEST_CONTEXT* GuestContext ) { UINT64 exitInstructionLength; exitInstructionLength = VmxRead(VMCS_VMEXIT_INSTRUCTION_LENGTH); GuestContext->VmcsBasedRegisters.Rip += exitInstructionLength; VmxWrite(VMCS_GUEST_RIP, GuestContext->VmcsBasedRegisters.Rip); } _Use_decl_annotations_ BOOLEAN IsGuestInKernelMode ( ) { VMX_SEGMENT_ACCESS_RIGHTS accessRight; accessRight.Flags = (UINT32)VmxRead(VMCS_GUEST_SS_ACCESS_RIGHTS); return (accessRight.DescriptorPrivilegeLevel == 0); } _Use_decl_annotations_ VOID InjectInterruption ( INTERRUPTION_TYPE InterruptionType, EXCEPTION_VECTOR Vector, BOOLEAN DeliverErrorCode, UINT32 ErrorCode ) { VMENTRY_INTERRUPT_INFORMATION interruptToInject; interruptToInject.Flags = 0; interruptToInject.Valid = TRUE; interruptToInject.InterruptionType = (UINT32)InterruptionType; interruptToInject.Vector = (UINT32)Vector; interruptToInject.DeliverErrorCode = DeliverErrorCode; VmxWrite(VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD, interruptToInject.Flags); if (DeliverErrorCode != FALSE) { VmxWrite(VMCS_CTRL_VMENTRY_EXCEPTION_ERROR_CODE, ErrorCode); } } _Use_decl_annotations_ VOID SwitchGuestPagingMode ( CR0 NewGuestCr0 ) { IA32_EFER_REGISTER guestEfer; IA32_VMX_ENTRY_CTLS_REGISTER vmEntryControls; // // "Enable paging by setting CR0.PG = 1. This causes the processor to set the // IA32_EFER.LMA bit to 1." // See: 9.8.5 Initializing IA-32e Mode // // "The processor always sets IA32_EFER.LMA to CR0.PG & IA32_EFER.LME. // Software cannot directly modify IA32_EFER.LMA; an execution of WRMSR to // the IA32_EFER MSR ignores bit 10 of its source operand." // See: 4.1.1 Three Paging Modes // guestEfer.Flags = VmxRead(VMCS_GUEST_EFER); guestEfer.Ia32EModeActive = (NewGuestCr0.PagingEnable & guestEfer.Ia32EModeEnable); VmxWrite(VMCS_GUEST_EFER, guestEfer.Flags); // // Apply the paging mode change in the VM-entry control VMCS field too. // vmEntryControls.Flags = VmxRead(VMCS_CTRL_VMENTRY_CONTROLS); vmEntryControls.Ia32EModeGuest = guestEfer.Ia32EModeActive; VmxWrite(VMCS_CTRL_VMENTRY_CONTROLS, vmEntryControls.Flags); // // Changing the paging mode results in invalidating TLB. Emulate this by // invalidating combined caches (GVA to HPA translation caches). // InvalidateVpidDerivedCache((UINT16)VmxRead(VMCS_CTRL_VIRTUAL_PROCESSOR_IDENTIFIER)); } _Use_decl_annotations_ CR0 AdjustGuestCr0 ( CR0 Cr0 ) { CR0 newCr0; IA32_VMX_PROCBASED_CTLS2_REGISTER secondaryProcBasedControls; newCr0 = AdjustCr0(Cr0); // // When the UnrestrictedGuest bit is set, ProtectionEnable and PagingEnable // bits are allowed to be zero. Make this adjustment, by setting them 1 only // when the guest did indeed requested them to be 1 (ie, // Cr0.ProtectionEnable == 1) and the FIXED0 MSR indicated them to be 1 (ie, // newCr0.ProtectionEnable == 1). // secondaryProcBasedControls.Flags = VmxRead( VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS); if (secondaryProcBasedControls.UnrestrictedGuest != FALSE) { newCr0.ProtectionEnable &= Cr0.ProtectionEnable; newCr0.PagingEnable &= Cr0.PagingEnable; } return newCr0; } _Use_decl_annotations_ CR4 AdjustGuestCr4 ( CR4 Cr4 ) { return AdjustCr4(Cr4); } _Use_decl_annotations_ UINT64 FindImageBase ( GUEST_CONTEXT* GuestContext, UINT64 GuestVirtualAddress ) { UINT64 imageBase; // // Starting with the page aligned address, and search up IMAGE_DOS_SIGNATURE // every page up to 16MB (0x1000000). Ntoskrnl.exe can be mapped at the page // boundary and not the 64KB boundary unlike other images. // imageBase = (GuestVirtualAddress & ~(PAGE_SIZE - 1)); for (int i = 0; i < 0x1000; i++, imageBase -= PAGE_SIZE) { BOOLEAN ok; UINT16 contents; MEMORY_ACCESS_ERROR_INFORMATION errorInfo; ok = ReadGuestVirtualAddress(GuestContext->Contexts->MemoryAccessContext, TRUE, imageBase, &contents, sizeof(contents), &errorInfo); if (ok == FALSE) { continue; } if (contents == 0x5A4D) { goto Exit; } } imageBase = 0; Exit: return imageBase; } _Use_decl_annotations_ VOID UpdateMsrBitmaps ( MSR_BITMAPS* Bitmaps, IA32_MSR_ADDRESS Msr, OPERATION_TYPE InterOperation, BOOLEAN Intercept ) { IA32_MSR_ADDRESS msrTemp; BOOLEAN highValue; UINT64 byteOffset; UINT64 bitMask; UINT8* msrBitmap; // // MSR must be within either 0x0 - 0x1fff or 0xc0000000 - 0xc0001fff // inclusive, and at least read or write intercept must be specified. // MV_ASSERT((Msr <= 0x1fff) || ((Msr >= 0xc0000000) && (Msr <= 0xc0001fff))); // // Check if the MSR belongs to high bitmaps. // highValue = BooleanFlagOn(Msr, 0xc0000000); // // Computes offsets and bitmaps to update the bitmaps. // msrTemp = (Msr & ~0xc0000000); byteOffset = (msrTemp / CHAR_BIT); bitMask = (1ull << (msrTemp % CHAR_BIT)); // // Select the bitmap to work on. // if (InterOperation == OperationRead) { if (highValue == FALSE) { msrBitmap = Bitmaps->ReadBitmapLow; } else { msrBitmap = Bitmaps->ReadBitmapHigh; } } else { if (highValue == FALSE) { msrBitmap = Bitmaps->WriteBitmapLow; } else { msrBitmap = Bitmaps->WriteBitmapHigh; } } // // Set of clear the bit. // if (Intercept != FALSE) { SetFlag(msrBitmap[byteOffset], bitMask); } else { ClearFlag(msrBitmap[byteOffset], bitMask); } }