HyperDbg Debugger
Loading...
Searching...
No Matches
ModeBasedExecHook.c File Reference

Implementation of hooks based on Mode-based execution. More...

#include "pch.h"

Functions

BOOLEAN ModeBasedExecHookDisableUserModeExecution (PVMM_EPT_PAGE_TABLE EptTable)
 Adjust (unset) user-mode execution bit of target page-table.
BOOLEAN ModeBasedExecHookDisableKernelModeExecution (PVMM_EPT_PAGE_TABLE EptTable)
 Adjust (unset) kernel-mode execution bit of target page-table but allow user-mode execution.
BOOLEAN ModeBasedExecHookEnableUsermodeExecution (PVMM_EPT_PAGE_TABLE EptTable)
 Enables user-mode execution bit of target page-table.
VOID ModeBasedExecHookEnableOrDisable (VIRTUAL_MACHINE_STATE *VCpu, UINT32 State)
 Enable/disable MBEC.
BOOLEAN ModeBasedExecHookInitialize ()
 Initialize the needed structure for hooking mode execution.
VOID ModeBasedExecHookUninitialize ()
 Uinitialize the needed structure for hooking mode execution.

Detailed Description

Implementation of hooks based on Mode-based execution.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.2
Date
2023-03-16

Function Documentation

◆ ModeBasedExecHookDisableKernelModeExecution()

BOOLEAN ModeBasedExecHookDisableKernelModeExecution ( PVMM_EPT_PAGE_TABLE EptTable)

Adjust (unset) kernel-mode execution bit of target page-table but allow user-mode execution.

should be called from vmx non-root mode

Parameters
EptTable
Returns
BOOLEAN
68{
69 //
70 // From Intel Manual:
71 // [Bit 2] If the "mode-based execute control for EPT" VM - execution control is 0, execute access;
72 // indicates whether instruction fetches are allowed from the 2-MByte page controlled by this entry.
73 // If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction
74 // fetches are allowed from supervisor - mode linear addresses in the 2 - MByte page controlled by this entry
75 //
76
77 //
78 // Set execute access for PML4s
79 //
80 for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
81 {
82 EptTable->PML4[i].UserModeExecute = TRUE;
83
84 //
85 // We only set the top-level PML4 for intercepting kernel-mode execution
86 //
87 EptTable->PML4[i].ExecuteAccess = FALSE;
88 }
89
90 //
91 // Set execute access for PML3s
92 //
93 for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
94 {
95 EptTable->PML3[i].UserModeExecute = TRUE;
96 }
97
98 //
99 // Set execute access for PML2s
100 //
101 for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
102 {
103 for (SIZE_T j = 0; j < VMM_EPT_PML2E_COUNT; j++)
104 {
105 EptTable->PML2[i][j].UserModeExecute = TRUE;
106 }
107 }
108
109 return TRUE;
110}
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113
#define VMM_EPT_PML4E_COUNT
The number of 512GB PML4 entries in the page table.
Definition State.h:79
#define VMM_EPT_PML3E_COUNT
The number of 1GB PDPT entries in the page table per 512GB PML4 entry.
Definition State.h:85
#define VMM_EPT_PML2E_COUNT
Then number of 2MB Page Directory entries in the page table per 1GB PML3 entry.
Definition State.h:92
EPT_PML4_POINTER PML4[VMM_EPT_PML4E_COUNT]
28.2.2 Describes 512 contiguous 512GB memory regions each with 512 1GB regions.
Definition State.h:111
EPT_PML3_POINTER PML3[VMM_EPT_PML3E_COUNT]
Describes exactly 512 contiguous 1GB memory regions within a our singular 512GB PML4 region.
Definition State.h:125
EPT_PML2_ENTRY PML2[VMM_EPT_PML3E_COUNT][VMM_EPT_PML2E_COUNT]
For each 1GB PML3 entry, create 512 2MB entries to map identity. NOTE: We are using 2MB pages as the ...
Definition State.h:133

◆ ModeBasedExecHookDisableUserModeExecution()

BOOLEAN ModeBasedExecHookDisableUserModeExecution ( PVMM_EPT_PAGE_TABLE EptTable)

Adjust (unset) user-mode execution bit of target page-table.

should be called from vmx non-root mode

Parameters
EptTable
Returns
BOOLEAN
24{
25 //
26 // Set execute access for PML4s
27 //
28 for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
29 {
30 //
31 // We only set the top-level PML4 for intercepting user-mode execution
32 //
33 EptTable->PML4[i].UserModeExecute = FALSE;
34 }
35
36 //
37 // Set execute access for PML3s
38 //
39 for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
40 {
41 EptTable->PML3[i].UserModeExecute = TRUE;
42 }
43
44 //
45 // Set execute access for PML2s
46 //
47 for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
48 {
49 for (SIZE_T j = 0; j < VMM_EPT_PML2E_COUNT; j++)
50 {
51 EptTable->PML2[i][j].UserModeExecute = TRUE;
52 }
53 }
54
55 return TRUE;
56}

◆ ModeBasedExecHookEnableOrDisable()

VOID ModeBasedExecHookEnableOrDisable ( VIRTUAL_MACHINE_STATE * VCpu,
UINT32 State )

Enable/disable MBEC.

Parameters
VCpuThe virtual processor's state
Returns
VOID
190{
191 if (State == 0x0)
192 {
194
195 //
196 // MBEC is not enabled anymore!
197 //
198 VCpu->MbecEnabled = FALSE;
199 }
200 else
201 {
203 }
204}
VOID HvSetModeBasedExecutionEnableFlag(BOOLEAN Set)
Set Mode-based Execution Control (MBEC) Enable bit.
Definition Hv.c:721
BOOLEAN MbecEnabled
Definition State.h:322

◆ ModeBasedExecHookEnableUsermodeExecution()

BOOLEAN ModeBasedExecHookEnableUsermodeExecution ( PVMM_EPT_PAGE_TABLE EptTable)

Enables user-mode execution bit of target page-table.

Parameters
EptTable
Returns
BOOLEAN
120{
122
123 //
124 // Set execute access for PML4s
125 //
126 for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
127 {
128 //
129 // We only set the top-level PML4 for intercepting user-mode execution
130 //
131 EptTable->PML4[i].UserModeExecute = TRUE;
132 }
133
134 //
135 // Set execute access for PML3s
136 //
137 for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
138 {
139 EptTable->PML3[i].UserModeExecute = TRUE;
140 }
141
142 //
143 // Set execute access for PML2s
144 //
145 for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
146 {
147 for (SIZE_T j = 0; j < VMM_EPT_PML2E_COUNT; j++)
148 {
149 EptTable->PML2[i][j].UserModeExecute = TRUE;
150
151 //
152 // If the PML2 entry is not a large page, we should set execute access for PML1s
153 // It usually happens when the PML2 entry is not a large page and is previously
154 // used for an EPT hook, so, it has PML1 entries
155 //
156 if (!EptTable->PML2[i][j].LargePage)
157 {
158 //
159 // Shift to the left to get the PFN
160 //
161 MemoryMapperReadMemorySafeByPhysicalAddress(EptTable->PML2[i][j].PageFrameNumber << 12, (UINT64)Pml1Entries, PAGE_SIZE);
162
163 //
164 // Set execute access for PML1s
165 //
166 for (SIZE_T k = 0; k < VMM_EPT_PML1E_COUNT; k++)
167 {
168 Pml1Entries[k].UserModeExecute = TRUE;
169 }
170
171 //
172 // Write back the PML1 entries to the EPT page table
173 //
174 MemoryMapperWriteMemorySafeByPhysicalAddress(EptTable->PML2[i][j].PageFrameNumber << 12, (UINT64)Pml1Entries, PAGE_SIZE);
175 }
176 }
177 }
178
179 return TRUE;
180}
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperWriteMemorySafeByPhysicalAddress(_Inout_ UINT64 DestinationPa, _In_ UINT64 Source, _In_ SIZE_T SizeToWrite)
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperReadMemorySafeByPhysicalAddress(_In_ UINT64 PaAddressToRead, _Inout_ UINT64 BufferToSaveMemory, _In_ SIZE_T SizeToRead)
EPT_PTE EPT_PML1_ENTRY
Definition State.h:23
#define VMM_EPT_PML1E_COUNT
Then number of 4096 byte Page Table entries in the page table per 2MB PML2 entry when dynamically spl...
Definition State.h:99
#define PAGE_SIZE
Size of each page (4096 bytes).
Definition common.h:80

◆ ModeBasedExecHookInitialize()

BOOLEAN ModeBasedExecHookInitialize ( )

Initialize the needed structure for hooking mode execution.

should be called from vmx non-root mode

Returns
BOOLEAN
214{
215 ULONG ProcessorsCount;
216
217 //
218 // Get number of processors
219 //
220 ProcessorsCount = KeQueryActiveProcessorCount(0);
221
222 //
223 // Check if MBEC supported by this processors
224 //
225 if (!g_CompatibilityCheck.ModeBasedExecutionSupport)
226 {
227 return FALSE;
228 }
229
230 //
231 // Check if execute-only feature is supported on this processor or not
232 //
233 if (!g_CompatibilityCheck.ExecuteOnlySupport)
234 {
235 return FALSE;
236 }
237
238 //
239 // Check if it's already initialized or not
240 //
242 {
243 return FALSE;
244 }
245
246 //
247 // Enable EPT user-mode execution bit for the target EPTP
248 //
249 for (SIZE_T i = 0; i < ProcessorsCount; i++)
250 {
252 }
253
254 //
255 // Invalidate ALL context on all cores (not necessary here because we will change
256 // it later but let's respect memory primitives)
257 //
259
260 //
261 // Indicate that MBEC is initialized
262 //
264
265 return TRUE;
266}
BOOLEAN ModeBasedExecHookEnableUsermodeExecution(PVMM_EPT_PAGE_TABLE EptTable)
Enables user-mode execution bit of target page-table.
Definition ModeBasedExecHook.c:119
unsigned long ULONG
Definition BasicTypes.h:31
VOID BroadcastNotifyAllToInvalidateEptAllCores()
routines to notify to invalidate their ept on all cores
Definition Broadcast.c:119
VIRTUAL_MACHINE_STATE * g_GuestState
Save the state and variables related to virtualization on each to logical core.
Definition GlobalVariables.h:38
BOOLEAN g_ModeBasedExecutionControlState
Enable interception of Cr3 for Mode-based Execution detection.
Definition GlobalVariables.h:106
COMPATIBILITY_CHECKS_STATUS g_CompatibilityCheck
Different attributes and compatibility checks of the current processor.
Definition GlobalVariables.h:26

◆ ModeBasedExecHookUninitialize()

VOID ModeBasedExecHookUninitialize ( )

Uinitialize the needed structure for hooking mode execution.

should be called from vmx non-root mode

Returns
VOID
276{
277 //
278 // Broadcast to disable MBEC on all cores
279 //
281
282 //
283 // Indicate that MBEC is disabled
284 //
286}
VOID BroadcasDisableMbecOnAllProcessors()
routines for disabling MBEC
Definition Broadcast.c:469