mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-20 14:35:07 +00:00
366 lines
15 KiB
C
366 lines
15 KiB
C
/**
|
|
* @file State.h
|
|
* @author Sina Karvandi (sina@hyperdbg.org)
|
|
* @brief Model-Specific Registers definitions
|
|
*
|
|
* @version 0.2
|
|
* @date 2022-12-01
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
#pragma once
|
|
|
|
//////////////////////////////////////////////////
|
|
// typedefs //
|
|
//////////////////////////////////////////////////
|
|
|
|
typedef EPT_PML4E EPT_PML4_POINTER, *PEPT_PML4_POINTER;
|
|
typedef EPT_PDPTE EPT_PML3_POINTER, *PEPT_PML3_POINTER;
|
|
typedef EPT_PDPTE_1GB EPT_PML3_ENTRY, *PEPT_PML3_ENTRY;
|
|
typedef EPT_PDE_2MB EPT_PML2_ENTRY, *PEPT_PML2_ENTRY;
|
|
typedef EPT_PDE EPT_PML2_POINTER, *PEPT_PML2_POINTER;
|
|
typedef EPT_PTE EPT_PML1_ENTRY, *PEPT_PML1_ENTRY;
|
|
|
|
//////////////////////////////////////////////////
|
|
// Constants //
|
|
//////////////////////////////////////////////////
|
|
|
|
/**
|
|
* @brief Pending External Interrupts Buffer Capacity
|
|
*
|
|
*/
|
|
#define PENDING_INTERRUPTS_BUFFER_CAPACITY 64
|
|
|
|
/**
|
|
* @brief Maximum number of hidden breakpoints in a page
|
|
*
|
|
*/
|
|
#define MaximumHiddenBreakpointsOnPage 40
|
|
|
|
//////////////////////////////////////////////////
|
|
// Enums //
|
|
//////////////////////////////////////////////////
|
|
|
|
/**
|
|
* @brief Types of actions for NMI broadcasting
|
|
*
|
|
*/
|
|
typedef enum _NMI_BROADCAST_ACTION_TYPE
|
|
{
|
|
NMI_BROADCAST_ACTION_NONE = 0,
|
|
NMI_BROADCAST_ACTION_TEST,
|
|
NMI_BROADCAST_ACTION_REQUEST,
|
|
NMI_BROADCAST_ACTION_INVALIDATE_EPT_CACHE_SINGLE_CONTEXT,
|
|
NMI_BROADCAST_ACTION_INVALIDATE_EPT_CACHE_ALL_CONTEXTS,
|
|
|
|
} NMI_BROADCAST_ACTION_TYPE;
|
|
|
|
/**
|
|
* @brief Types of last violation happened to EPT hook
|
|
*
|
|
*/
|
|
typedef enum _EPT_HOOKED_LAST_VIOLATION
|
|
{
|
|
EPT_HOOKED_LAST_VIOLATION_READ = 1,
|
|
EPT_HOOKED_LAST_VIOLATION_WRITE = 2,
|
|
EPT_HOOKED_LAST_VIOLATION_EXEC = 3
|
|
|
|
} EPT_HOOKED_LAST_VIOLATION;
|
|
|
|
//////////////////////////////////////////////////
|
|
// Memory Layout //
|
|
//////////////////////////////////////////////////
|
|
|
|
/**
|
|
* @brief The number of 512GB PML4 entries in the page table
|
|
*
|
|
*/
|
|
#define VMM_EPT_PML4E_COUNT 512
|
|
|
|
/**
|
|
* @brief The number of 1GB PDPT entries in the page table per 512GB PML4 entry
|
|
*
|
|
*/
|
|
#define VMM_EPT_PML3E_COUNT 512
|
|
|
|
/**
|
|
* @brief Then number of 2MB Page Directory entries in the page table per 1GB
|
|
* PML3 entry
|
|
*
|
|
*/
|
|
#define VMM_EPT_PML2E_COUNT 512
|
|
|
|
/**
|
|
* @brief Then number of 4096 byte Page Table entries in the page table per 2MB PML2
|
|
* entry when dynamically split
|
|
*
|
|
*/
|
|
#define VMM_EPT_PML1E_COUNT 512
|
|
|
|
/**
|
|
* @brief Structure for saving EPT Table
|
|
*
|
|
*/
|
|
typedef struct _VMM_EPT_PAGE_TABLE
|
|
{
|
|
/**
|
|
* @brief 28.2.2 Describes 512 contiguous 512GB memory regions each with 512 1GB regions.
|
|
*/
|
|
DECLSPEC_ALIGN(PAGE_SIZE)
|
|
EPT_PML4_POINTER PML4[VMM_EPT_PML4E_COUNT];
|
|
|
|
/**
|
|
* @brief Describes exactly 512 contiguous 1GB memory regions within a our singular 512GB PML4 region
|
|
* (This entry is used to support the entire address space).
|
|
* @details The reason why there is a minus one here is that the original PML3 is described in the next field.
|
|
*/
|
|
DECLSPEC_ALIGN(PAGE_SIZE)
|
|
EPT_PML3_ENTRY PML3_RSVD[VMM_EPT_PML4E_COUNT - 1][VMM_EPT_PML3E_COUNT];
|
|
|
|
/**
|
|
* @brief Describes exactly 512 contiguous 1GB memory regions within a our singular 512GB PML4 region.
|
|
*/
|
|
DECLSPEC_ALIGN(PAGE_SIZE)
|
|
EPT_PML3_POINTER PML3[VMM_EPT_PML3E_COUNT];
|
|
|
|
/**
|
|
* @brief For each 1GB PML3 entry, create 512 2MB entries to map identity.
|
|
* NOTE: We are using 2MB pages as the smallest paging size in our map, so we do not manage individual 4096 byte pages.
|
|
* Therefore, we do not allocate any PML1 (4096 byte) paging structures.
|
|
*/
|
|
DECLSPEC_ALIGN(PAGE_SIZE)
|
|
EPT_PML2_ENTRY PML2[VMM_EPT_PML3E_COUNT][VMM_EPT_PML2E_COUNT];
|
|
|
|
/**
|
|
* @brief Tracks dynamic 2MB->4KB splits for this EPT table.
|
|
* NOTE: Each item stores a direct VA to the split PML1 page and the corresponding PML2 entry it services.
|
|
*
|
|
*/
|
|
LIST_ENTRY DynamicSplitList;
|
|
|
|
} VMM_EPT_PAGE_TABLE, *PVMM_EPT_PAGE_TABLE;
|
|
|
|
//////////////////////////////////////////////////
|
|
// Structure //
|
|
//////////////////////////////////////////////////
|
|
|
|
/**
|
|
* @brief The status of transparency of each core after and before VMX
|
|
*
|
|
*/
|
|
typedef struct _VM_EXIT_TRANSPARENCY
|
|
{
|
|
UINT64 PreviousTimeStampCounter;
|
|
|
|
HANDLE ThreadId;
|
|
UINT64 RevealedTimeStampCounterByRdtsc;
|
|
BOOLEAN CpuidAfterRdtscDetected;
|
|
|
|
} VM_EXIT_TRANSPARENCY, *PVM_EXIT_TRANSPARENCY;
|
|
|
|
/**
|
|
* @brief Save the state of core in the case of VMXOFF
|
|
*
|
|
*/
|
|
typedef struct _VMX_VMXOFF_STATE
|
|
{
|
|
BOOLEAN IsVmxoffExecuted; // Shows whether the VMXOFF executed or not
|
|
UINT64 GuestRip; // Rip address of guest to return
|
|
UINT64 GuestRsp; // Rsp address of guest to return
|
|
|
|
} VMX_VMXOFF_STATE, *PVMX_VMXOFF_STATE;
|
|
|
|
/**
|
|
* @brief Structure to save the state of each hooked pages
|
|
*
|
|
*/
|
|
typedef struct _EPT_HOOKED_PAGE_DETAIL
|
|
{
|
|
DECLSPEC_ALIGN(PAGE_SIZE)
|
|
CHAR FakePageContents[PAGE_SIZE];
|
|
|
|
/**
|
|
* @brief Linked list entries for each page hook.
|
|
*/
|
|
LIST_ENTRY PageHookList;
|
|
|
|
/**
|
|
* @brief The virtual address from the caller perspective view (cr3)
|
|
*/
|
|
UINT64 VirtualAddress;
|
|
|
|
/**
|
|
* @brief The virtual address of it's entry on g_EptHook2sDetourListHead
|
|
* this way we can de-allocate the list whenever the hook is finished
|
|
*/
|
|
UINT64 AddressOfEptHook2sDetourListEntry;
|
|
|
|
/**
|
|
* @brief The base address of the page. Used to find this structure in the list of page hooks
|
|
* when a hook is hit.
|
|
*/
|
|
SIZE_T PhysicalBaseAddress;
|
|
|
|
/**
|
|
* @brief Start address of the target physical address.
|
|
*/
|
|
SIZE_T StartOfTargetPhysicalAddress;
|
|
|
|
/**
|
|
* @brief End address of the target physical address.
|
|
*/
|
|
SIZE_T EndOfTargetPhysicalAddress;
|
|
|
|
/**
|
|
* @brief Tag used for notifying the caller.
|
|
*/
|
|
UINT64 HookingTag;
|
|
|
|
/**
|
|
* @brief The base address of the page with fake contents. Used to swap page with fake contents
|
|
* when a hook is hit.
|
|
*/
|
|
SIZE_T PhysicalBaseAddressOfFakePageContents;
|
|
|
|
/**
|
|
* @brief The original page entry. Will be copied back when the hook is removed
|
|
* from the page.
|
|
*/
|
|
EPT_PML1_ENTRY OriginalEntry;
|
|
|
|
/**
|
|
* @brief The original page entry. Will be copied back when the hook is remove from the page.
|
|
*/
|
|
EPT_PML1_ENTRY ChangedEntry;
|
|
|
|
/**
|
|
* @brief The buffer of the trampoline function which is used in the inline hook.
|
|
*/
|
|
PCHAR Trampoline;
|
|
|
|
/**
|
|
* @brief This field shows whether the hook contains a hidden hook for execution or not
|
|
*/
|
|
BOOLEAN IsExecutionHook;
|
|
|
|
/**
|
|
* @brief If TRUE shows that this is the information about
|
|
* a hidden breakpoint command (not a monitor or hidden detours)
|
|
*/
|
|
BOOLEAN IsHiddenBreakpoint;
|
|
|
|
/**
|
|
* @brief This field shows whether the hook is for MMIO shadowing or not
|
|
*/
|
|
BOOLEAN IsMmioShadowing;
|
|
|
|
/**
|
|
* @brief Temporary context for the post event monitors
|
|
* It shows the context of the last address that triggered the hook
|
|
* Note: Only used for read/write trigger events
|
|
*/
|
|
EPT_HOOKS_CONTEXT LastContextState;
|
|
|
|
/**
|
|
* @brief This field shows whether the hook should call the post event trigger
|
|
* after restoring the state or not
|
|
*/
|
|
BOOLEAN IsPostEventTriggerAllowed;
|
|
|
|
/**
|
|
* @brief This field shows the last violation happened to this EPT hook
|
|
*/
|
|
EPT_HOOKED_LAST_VIOLATION LastViolation;
|
|
|
|
/**
|
|
* @brief Address of hooked pages (multiple breakpoints on a single page)
|
|
* this is only used in hidden breakpoints (not hidden detours)
|
|
*/
|
|
UINT64 BreakpointAddresses[MaximumHiddenBreakpointsOnPage];
|
|
|
|
/**
|
|
* @brief Character that was previously used in BreakpointAddresses
|
|
* this is only used in hidden breakpoints (not hidden detours)
|
|
*/
|
|
CHAR PreviousBytesOnBreakpointAddresses[MaximumHiddenBreakpointsOnPage];
|
|
|
|
/**
|
|
* @brief Count of breakpoints (multiple breakpoints on a single page)
|
|
* this is only used in hidden breakpoints (not hidden detours)
|
|
*/
|
|
UINT64 CountOfBreakpoints;
|
|
|
|
} EPT_HOOKED_PAGE_DETAIL, *PEPT_HOOKED_PAGE_DETAIL;
|
|
|
|
/**
|
|
* @brief The status of NMI broadcasting in VMX
|
|
*
|
|
*/
|
|
typedef struct _NMI_BROADCASTING_STATE
|
|
{
|
|
volatile NMI_BROADCAST_ACTION_TYPE NmiBroadcastAction; // The broadcast action for NMI
|
|
|
|
} NMI_BROADCASTING_STATE, *PNMI_BROADCASTING_STATE;
|
|
|
|
/**
|
|
* @brief The status of each core after and before VMX
|
|
*
|
|
*/
|
|
typedef struct _VIRTUAL_MACHINE_STATE
|
|
{
|
|
BOOLEAN IsOnVmxRootMode; // Detects whether the current logical core is on Executing on VMX Root Mode
|
|
BOOLEAN IncrementRip; // Checks whether it has to redo the previous instruction or not (it used mainly in Ept routines)
|
|
BOOLEAN HasLaunched; // Indicate whether the core is virtualized or not
|
|
BOOLEAN IgnoreMtfUnset; // Indicate whether the core should ignore unsetting the MTF or not
|
|
BOOLEAN WaitForImmediateVmexit; // Whether the current core is waiting for an immediate vm-exit or not
|
|
BOOLEAN EnableExternalInterruptsOnContinue; // Whether to enable external interrupts on the continue or not
|
|
BOOLEAN EnableExternalInterruptsOnContinueMtf; // Whether to enable external interrupts on the continue state of MTF or not
|
|
BOOLEAN InstrumentationStepInMtf; // Instrumentation step in MTF or not (used for single stepping with MTF)
|
|
BOOLEAN IgnoreOneMtf; // Ignore (mark as handled) for one MTF
|
|
BOOLEAN NotNormalEptp; // Indicate that the target processor is on the normal EPTP or not
|
|
BOOLEAN MbecEnabled; // Indicate that the target processor is on MBEC-enabled mode or not
|
|
PUINT64 PmlBufferAddress; // Address of buffer used for dirty logging
|
|
BOOLEAN Test; // Used for test purposes
|
|
UINT64 TestNumber; // Used for test purposes (Number)
|
|
GUEST_REGS * Regs; // The virtual processor's general-purpose registers
|
|
GUEST_XMM_REGS * XmmRegs; // The virtual processor's XMM registers
|
|
UINT32 CoreId; // The core's unique identifier
|
|
UINT32 ExitReason; // The core's exit reason
|
|
UINT32 ExitQualification; // The core's exit qualification
|
|
UINT64 LastVmexitRip; // RIP in the current VM-exit
|
|
UINT64 VmxonRegionPhysicalAddress; // Vmxon region physical address
|
|
UINT64 VmxonRegionVirtualAddress; // VMXON region virtual address
|
|
UINT64 VmcsRegionPhysicalAddress; // VMCS region physical address
|
|
UINT64 VmcsRegionVirtualAddress; // VMCS region virtual address
|
|
UINT64 VmmStack; // Stack for VMM in VM-Exit State
|
|
UINT64 MsrBitmapVirtualAddress; // Msr Bitmap Virtual Address
|
|
UINT64 MsrBitmapPhysicalAddress; // Msr Bitmap Physical Address
|
|
UINT64 IoBitmapVirtualAddressA; // I/O Bitmap Virtual Address (A)
|
|
UINT64 IoBitmapPhysicalAddressA; // I/O Bitmap Physical Address (A)
|
|
UINT64 IoBitmapVirtualAddressB; // I/O Bitmap Virtual Address (B)
|
|
UINT64 IoBitmapPhysicalAddressB; // I/O Bitmap Physical Address (B)
|
|
UINT32 QueuedNmi; // Queued NMIs
|
|
UINT32 PendingExternalInterrupts[PENDING_INTERRUPTS_BUFFER_CAPACITY]; // This list holds a buffer for external-interrupts that are in pending state due to the external-interrupt
|
|
// blocking and waits for interrupt-window exiting
|
|
// From hvpp :
|
|
// Pending interrupt queue (FIFO).
|
|
// Make storage for up-to 64 pending interrupts.
|
|
// In practice I haven't seen more than 2 pending interrupts.
|
|
VMX_VMXOFF_STATE VmxoffState; // Shows the vmxoff state of the guest
|
|
NMI_BROADCASTING_STATE NmiBroadcastingState; // Shows the state of NMI broadcasting
|
|
VM_EXIT_TRANSPARENCY TransparencyState; // The state of the debugger in transparent-mode
|
|
PEPT_HOOKED_PAGE_DETAIL MtfEptHookRestorePoint; // It shows the detail of the hooked paged that should be restore in MTF vm-exit
|
|
UINT8 LastExceptionOccurredInHost; // The vector of last exception occurred in host
|
|
UINT64 HostIdt; // host Interrupt Descriptor Table (actual type is SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64*)
|
|
UINT64 HostGdt; // host Global Descriptor Table (actual type is SEGMENT_DESCRIPTOR_32* or SEGMENT_DESCRIPTOR_64*)
|
|
UINT64 HostTss; // host Task State Segment (actual type is TASK_STATE_SEGMENT_64*)
|
|
UINT64 HostInterruptStack; // host interrupt RSP
|
|
|
|
//
|
|
// EPT Descriptors
|
|
//
|
|
EPT_POINTER EptPointer; // Extended-Page-Table Pointer
|
|
PVMM_EPT_PAGE_TABLE EptPageTable; // Details of core-specific page-table
|
|
|
|
} VIRTUAL_MACHINE_STATE, *PVIRTUAL_MACHINE_STATE;
|