/*! @file HostUtils.h @brief Utility functions and structures for the host. @author Satoshi Tanda @copyright Copyright (c) 2020 - , Satoshi Tanda. All rights reserved. */ #pragma once #include "Common.h" #include "Public.h" // // 128bit XMM register (ie, equivalent to __m128 on MSVC). // typedef struct _XMM { UINT8 Value[16]; } XMM; // // Guest General Purpose Registers (GPRs) created on VM-exit from the guest // state and write back to the guest on VM-entry. // typedef struct _GUEST_REGISTERS { XMM Xmm[6]; VOID* Alignment; UINT64 R15; UINT64 R14; UINT64 R13; UINT64 R12; UINT64 R11; UINT64 R10; UINT64 R9; UINT64 R8; UINT64 Rdi; UINT64 Rsi; UINT64 Rbp; UINT64 Rbx; UINT64 Rdx; UINT64 Rcx; UINT64 Rax; } GUEST_REGISTERS; // // The guest registers that are stored in the VMCS as opposed to stack like // ones in the GUEST_REGISTERS structure. // typedef struct _VMCS_BASED_REGISTERS { UINT64 Rip; UINT64 Rsp; RFLAGS Rflags; } VMCS_BASED_REGISTERS; // // State of the guest. // typedef struct _GUEST_CONTEXT { // // Indicates that the processor should continue virtualization. FALSE of // results in disablement of hypervisor with the VMXOFF instruction. See // x64.asm. This value is used as a return value of the HandleVmExit function. // BOOLEAN ContinueVm; // // Collection of pointers passed from the kernel via the host stack. // HYPERVISOR_CONTEXT* Contexts; // // The guest states stored in hypervisor stack. // GUEST_REGISTERS* StackBasedRegisters; // // The guest states stored in the VMCS. // VMCS_BASED_REGISTERS VmcsBasedRegisters; } GUEST_CONTEXT; /*! @brief Dumps host state VMCS fields. */ VOID DumpHostState ( ); /*! @brief Dumps guest state VMCS fields. */ VOID DumpGuestState ( ); /*! @brief Dumps control VMCS fields. */ VOID DumpControl ( ); /*! @brief Writes the value to the VMCS. @param[in] Field - The VMCS field to write the value to. @param[in] FieldValue - The value to write. */ VOID VmxWrite ( _In_ VMCS_FIELD Field, _In_ UINT64 FieldValue ); /*! @brief Read a value from the VMCS. @param[in] Field - The VMCS field to read a value from. @return A value read from the VMCS. 0 is returned when a non-existent VMCS field is requested for read. */ UINT64 VmxRead ( _In_ VMCS_FIELD Field ); /*! @brief Advances the guest's RIP to the address of the next instruction. This implies that the hypervisor completed emulation of the instruction. @param[in,out] GuestContext - The pointer to the guest context. */ VOID AdvanceGuestInstructionPointer ( _Inout_ GUEST_CONTEXT* GuestContext ); /*! @brief Tests whether the guest was at the CPL 0 (kernel-mode) when VM-exit happened. @return TRUE when the guest was at the CPL 0, otherwise FALSE. */ _Must_inspect_result_ BOOLEAN IsGuestInKernelMode ( ); /*! @brief Queues interrupt to occur to the VMCS. @details Generally, this interrupt fires on VM-entry and the guests runs a corresponding exception handler before executing the instruction pointed by Rip. @param[in] InterruptionType - The type of interrupt to inject. @param[in] Vector - The vector number of interrupt to inject. @param[in] DeliverErrorCode - TRUE when the interrupt should have an error code. Whether the interrupt should have an error code is defined by the Intel SDM. See comments in the EXCEPTION_VECTOR definitions for a quick reference. @param[in] ErrorCode - The error code. Not used when DeliverErrorCode is FALSE. */ VOID InjectInterruption ( _In_ INTERRUPTION_TYPE InterruptionType, _In_ EXCEPTION_VECTOR Vector, _In_ BOOLEAN DeliverErrorCode, _In_ UINT32 ErrorCode ); /*! @brief Switches the guest paging mode between 32 and 64bit modes according with CR0 and EFER. @param[in] NewGuestCr0 - The guest CR0 value to check the mode to switch to. */ VOID SwitchGuestPagingMode ( _In_ CR0 NewGuestCr0 ); /*! @brief Returns the CR0 value after the FIXED0 and FIXED1 MSR values are applied for the guest. @param[in] Cr0 - The CR0 value to apply the FIXED0 and FIXED1 MSR values. @return The CR0 value where the FIXED0 and FIXED1 MSR values are applied. */ CR0 AdjustGuestCr0 ( _In_ CR0 Cr0 ); /*! @brief Returns the CR4 value after the FIXED0 and FIXED1 MSR values are applied for the guest. @param[in] Cr4 - The CR4 value to apply the FIXED0 and FIXED1 MSR values. @return The CR4 value where the FIXED0 and FIXED1 MSR values are applied. */ CR4 AdjustGuestCr4 ( _In_ CR4 Cr4 ); /*! @brief Finds the base address of the image to which the specified address belongs. @param[in] GuestContext - The pointer to the guest context. @param[in] GuestVirtualAddress - The guest virtual address to find its image base. @return The base address of the image to which GuestVirtualAddress belongs, or 0 on error. */ UINT64 FindImageBase ( _In_ GUEST_CONTEXT* GuestContext, _In_ UINT64 GuestVirtualAddress ); /*! @brief Updates the MSR bitmap as specified. @param[in] Bitmaps - The pointer to the MSR bitmaps. @param[in,out] Msr - The MSR to change configurations. Must be in the range of 0x0 - 0x1fff or 0xc0000000 - 0xc0001fff. @param[in] InterOperation - The type of operation to change configurations. @param[in] Intercept - TRUE if the hypervisor should intercept the specified type of access. */ VOID UpdateMsrBitmaps ( _Inout_ MSR_BITMAPS* Bitmaps, _In_ IA32_MSR_ADDRESS Msr, _In_ OPERATION_TYPE InterOperation, _In_ BOOLEAN Intercept );