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

The reversing machine's routines. More...

#include "pch.h"

Functions

BOOLEAN ExecTrapTraverseThroughOsPageTables (PVMM_EPT_PAGE_TABLE EptTable, CR3_TYPE TargetCr3, CR3_TYPE KernelCr3)
 This function gets virtual address and returns its PTE of the virtual address based on the specific cr3 but without switching to the target address.
BOOLEAN ExecTrapEnableExecuteOnlyPages (PVMM_EPT_PAGE_TABLE EptTable)
 Adjust execute-only bits bit of target page-table.
VOID ExecTrapReadRamPhysicalRegions ()
 Read the RAM regions (physical address).
BOOLEAN ExecTrapInitialize ()
 Initialize the exec trap based on service request.
VOID ExecTrapUninitialize ()
 Uinitialize the needed structure for the reversing machine.
VOID ExecTrapRestoreToNormalEptp (VIRTUAL_MACHINE_STATE *VCpu)
 restore to normal EPTP
VOID ExecTrapChangeToUserDisabledMbecEptp (VIRTUAL_MACHINE_STATE *VCpu)
 change to user-disabled MBEC EPTP
VOID ExecTrapChangeToKernelDisabledMbecEptp (VIRTUAL_MACHINE_STATE *VCpu)
 change to kernel-disabled MBEC EPTP
VOID ExecTrapChangeToNormalMbecEptp (VIRTUAL_MACHINE_STATE *VCpu)
 change to normal MBEC EPTP
VOID ExecTrapHandleMoveToAdjustedTrapState (VIRTUAL_MACHINE_STATE *VCpu, DEBUGGER_EVENT_MODE_TYPE TargetMode)
 Restore the execution of the trap to adjusted trap state.
BOOLEAN ExecTrapHandleEptViolationVmexit (VIRTUAL_MACHINE_STATE *VCpu, VMX_EXIT_QUALIFICATION_EPT_VIOLATION *ViolationQualification)
 Handle EPT Violations related to the MBEC hooks.
VOID ExecTrapApplyMbecConfiguratinFromKernelSide (VIRTUAL_MACHINE_STATE *VCpu)
 Apply the MBEC configuration from the kernel side.
VOID ExecTrapHandleCr3Vmexit (VIRTUAL_MACHINE_STATE *VCpu)
 Handle MOV to CR3 vm-exits for hooking mode execution.
BOOLEAN ExecTrapAddProcessToWatchingList (UINT32 ProcessId)
 Add the target process to the watching list.
BOOLEAN ExecTrapRemoveProcessFromWatchingList (UINT32 ProcessId)
 Remove the target process from the watching list.

Detailed Description

The reversing machine's routines.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.4
Date
2023-07-05

Function Documentation

◆ ExecTrapAddProcessToWatchingList()

BOOLEAN ExecTrapAddProcessToWatchingList ( UINT32 ProcessId)

Add the target process to the watching list.

Parameters
ProcessId
Returns
BOOLEAN
791{
792 UINT32 Index;
793 BOOLEAN Result;
794
796
797 Result = InsertionSortInsertItem(&g_ExecTrapState.InterceptionProcessIds[0],
798 &g_ExecTrapState.NumberOfItems,
800 &Index,
801 (UINT64)ProcessId);
802
804
805 return Result;
806}
volatile LONG ExecTrapProcessListLock
The lock for modifying the list of processes for user-mode, kernel-mode execution traps.
Definition ExecTrap.h:33
#define MAXIMUM_NUMBER_OF_PROCESSES_FOR_USER_KERNEL_EXEC_THREAD
maximum number of processes for a simultaneous user-mode, kernel-mode execution trap
Definition ExecTrap.h:23
BOOLEAN InsertionSortInsertItem(UINT64 ArrayPtr[], UINT32 *NumberOfItems, UINT32 MaxNumOfItems, UINT32 *Index, UINT64 Key)
Function to implement insertion sort.
Definition InsertionSort.c:26
VOID SpinlockLock(volatile LONG *Lock)
Tries to get the lock and won't return until successfully get the lock.
Definition Spinlock.c:53
VOID SpinlockUnlock(volatile LONG *Lock)
Release the lock.
Definition Spinlock.c:162
UCHAR BOOLEAN
Definition BasicTypes.h:35
unsigned int UINT32
Definition BasicTypes.h:54
USER_KERNEL_EXECUTION_TRAP_STATE g_ExecTrapState
State of the trap-flag.
Definition GlobalVariables.h:175

◆ ExecTrapApplyMbecConfiguratinFromKernelSide()

VOID ExecTrapApplyMbecConfiguratinFromKernelSide ( VIRTUAL_MACHINE_STATE * VCpu)

Apply the MBEC configuration from the kernel side.

Parameters
VCpuThe virtual processor's state
Returns
VOID
722{
723 BOOLEAN Result;
724 UINT32 Index;
725
726 //
727 // Acquire the lock for the exec trap process list
728 //
730
731 //
732 // Search the list of processes for the current process's user-execution
733 // trap state
734 //
735 Result = BinarySearchPerformSearchItem(&g_ExecTrapState.InterceptionProcessIds[0],
736 g_ExecTrapState.NumberOfItems,
737 &Index,
738 (UINT64)PsGetCurrentProcessId());
739
740 //
741 // Release the lock for the exec trap process list
742 //
744
745 //
746 // Check whether the procerss is in the list of interceptions or not
747 //
748 if (Result)
749 {
750 //
751 // Enable MBEC to detect execution in user-mode
752 //
754 VCpu->MbecEnabled = TRUE;
755
756 //
757 // Trigger the event
758 //
760 }
761 else if (VCpu->MbecEnabled)
762 {
763 //
764 // In case, the process is changed, we've disable the MBEC
765 //
767 VCpu->MbecEnabled = FALSE;
768 }
769}
BOOLEAN BinarySearchPerformSearchItem(UINT64 ArrayPtr[], UINT32 NumberOfItems, UINT32 *ResultIndex, UINT64 Key)
A utility function to perform the binary search.
Definition BinarySearch.c:46
VOID DispatchEventMode(VIRTUAL_MACHINE_STATE *VCpu, DEBUGGER_EVENT_MODE_TYPE TargetMode)
Handling debugger functions related to user-mode/kernel-mode execution trap events.
Definition Dispatch.c:364
VOID HvSetModeBasedExecutionEnableFlag(BOOLEAN Set)
Set Mode-based Execution Control (MBEC) Enable bit.
Definition Hv.c:721
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113
@ DEBUGGER_EVENT_MODE_TYPE_KERNEL_MODE
Definition Events.h:210
BOOLEAN MbecEnabled
Definition State.h:322

◆ ExecTrapChangeToKernelDisabledMbecEptp()

VOID ExecTrapChangeToKernelDisabledMbecEptp ( VIRTUAL_MACHINE_STATE * VCpu)

change to kernel-disabled MBEC EPTP

Parameters
VCpuThe virtual processor's state
Returns
VOID
542{
543 //
544 // From Intel Manual:
545 // [Bit 2] If the "mode-based execute control for EPT" VM - execution control is 0, execute access;
546 // indicates whether instruction fetches are allowed from the 2-MByte page controlled by this entry.
547 // If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction
548 // fetches are allowed from supervisor - mode linear addresses in the 2 - MByte page controlled by this entry
549 //
550
551 //
552 // Set execute access for PML4s
553 //
554 // for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
555 // {
556 VCpu->EptPageTable->PML4[0].UserModeExecute = TRUE;
557
558 //
559 // We only set the top-level PML4 for intercepting kernel-mode execution
560 //
561 VCpu->EptPageTable->PML4[0].ExecuteAccess = FALSE;
562 // }
563
564 //
565 // Invalidate the EPT cache
566 //
568
569 //
570 // It's not on normal EPTP
571 //
572 VCpu->NotNormalEptp = TRUE;
573}
UCHAR EptInveptSingleContext(_In_ UINT64 EptPointer)
Invalidates a single context in ept cache table.
Definition Invept.c:40
PVMM_EPT_PAGE_TABLE EptPageTable
Definition State.h:364
BOOLEAN NotNormalEptp
Definition State.h:321
EPT_POINTER EptPointer
Definition State.h:363
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

◆ ExecTrapChangeToNormalMbecEptp()

VOID ExecTrapChangeToNormalMbecEptp ( VIRTUAL_MACHINE_STATE * VCpu)

change to normal MBEC EPTP

Parameters
VCpuThe virtual processor's state
Returns
VOID
583{
584 //
585 // From Intel Manual:
586 // [Bit 2] If the "mode-based execute control for EPT" VM - execution control is 0, execute access;
587 // indicates whether instruction fetches are allowed from the 2-MByte page controlled by this entry.
588 // If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction
589 // fetches are allowed from supervisor - mode linear addresses in the 2 - MByte page controlled by this entry
590 //
591
592 //
593 // Set execute access for PML4s
594 //
595 // for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
596 // {
597 VCpu->EptPageTable->PML4[0].UserModeExecute = TRUE;
598
599 //
600 // We only set the top-level PML4 for intercepting kernel-mode execution
601 //
602 VCpu->EptPageTable->PML4[0].ExecuteAccess = TRUE;
603 // }
604
605 //
606 // Invalidate the EPT cache
607 //
609
610 //
611 // It's not on normal EPTP
612 //
613 VCpu->NotNormalEptp = FALSE;
614}

◆ ExecTrapChangeToUserDisabledMbecEptp()

VOID ExecTrapChangeToUserDisabledMbecEptp ( VIRTUAL_MACHINE_STATE * VCpu)

change to user-disabled MBEC EPTP

Parameters
VCpuThe virtual processor's state
Returns
VOID
501{
502 //
503 // From Intel Manual:
504 // [Bit 2] If the "mode-based execute control for EPT" VM - execution control is 0, execute access;
505 // indicates whether instruction fetches are allowed from the 2-MByte page controlled by this entry.
506 // If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction
507 // fetches are allowed from supervisor - mode linear addresses in the 2 - MByte page controlled by this entry
508 //
509
510 //
511 // Set execute access for PML4s
512 //
513 // for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
514 // {
515 VCpu->EptPageTable->PML4[0].UserModeExecute = FALSE;
516
517 //
518 // We only set the top-level PML4 for intercepting kernel-mode execution
519 //
520 VCpu->EptPageTable->PML4[0].ExecuteAccess = TRUE;
521 // }
522
523 //
524 // Invalidate the EPT cache
525 //
527
528 //
529 // It's not on normal EPTP
530 //
531 VCpu->NotNormalEptp = TRUE;
532}

◆ ExecTrapEnableExecuteOnlyPages()

BOOLEAN ExecTrapEnableExecuteOnlyPages ( PVMM_EPT_PAGE_TABLE EptTable)

Adjust execute-only bits bit of target page-table.

should be called from vmx non-root mode

Parameters
EptTable
Returns
BOOLEAN
257{
258 INT64 RemainingSize = 0;
259 UINT64 CurrentAddress = 0;
260
261 //
262 // *** allow execution of user-mode pages in execute only EPTP ***
263 //
264
265 //
266 // Set execute access for PML4s
267 //
268 for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
269 {
270 //
271 // We only set the top-level PML4 for intercepting user-mode execution
272 //
273 EptTable->PML4[i].UserModeExecute = TRUE;
274 }
275
276 //
277 // Set execute access for PML3s
278 //
279 for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
280 {
281 EptTable->PML3[i].UserModeExecute = TRUE;
282 }
283
284 //
285 // Set execute access for PML2s
286 //
287 for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
288 {
289 for (SIZE_T j = 0; j < VMM_EPT_PML2E_COUNT; j++)
290 {
291 EptTable->PML2[i][j].UserModeExecute = TRUE;
292 }
293 }
294
295 //
296 // *** disallow read or write for certain memory only (not MMIO) EPTP pages ***
297 //
298 for (SIZE_T i = 0; i < MAX_PHYSICAL_RAM_RANGE_COUNT; i++)
299 {
300 if (PhysicalRamRegions[i].RamPhysicalAddress != NULL64_ZERO)
301 {
302 RemainingSize = (INT64)PhysicalRamRegions[i].RamSize;
303 CurrentAddress = PhysicalRamRegions[i].RamPhysicalAddress;
304
305 while (RemainingSize > 0)
306 {
307 //
308 // Get the target entry in EPT table (every entry is 2-MB granularity)
309 //
310 PEPT_PML2_ENTRY EptEntry = EptGetPml2Entry(EptTable, CurrentAddress);
311 EptEntry->WriteAccess = FALSE;
312
313 //
314 // Move to the new address
315 //
316 CurrentAddress += SIZE_2_MB;
317 RemainingSize -= SIZE_2_MB;
318 }
319 }
320 }
321
322 return TRUE;
323}
PEPT_PML2_ENTRY EptGetPml2Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress)
Get the PML2 entry for this physical address.
Definition Ept.c:450
#define SIZE_2_MB
Integer 2MB.
Definition Ept.h:31
#define MAX_PHYSICAL_RAM_RANGE_COUNT
Definition ModeBasedExecHook.h:18
MODE_BASED_RAM_REGIONS PhysicalRamRegions[MAX_PHYSICAL_RAM_RANGE_COUNT]
Definition ModeBasedExecHook.h:39
#define NULL64_ZERO
Definition BasicTypes.h:111
EPT_PDE_2MB * PEPT_PML2_ENTRY
Definition State.h:21
#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_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

◆ ExecTrapHandleCr3Vmexit()

VOID ExecTrapHandleCr3Vmexit ( VIRTUAL_MACHINE_STATE * VCpu)

Handle MOV to CR3 vm-exits for hooking mode execution.

Parameters
VCpuThe virtual processor's state
Returns
VOID
779{
781}
VOID ExecTrapApplyMbecConfiguratinFromKernelSide(VIRTUAL_MACHINE_STATE *VCpu)
Apply the MBEC configuration from the kernel side.
Definition ExecTrap.c:721

◆ ExecTrapHandleEptViolationVmexit()

BOOLEAN ExecTrapHandleEptViolationVmexit ( VIRTUAL_MACHINE_STATE * VCpu,
VMX_EXIT_QUALIFICATION_EPT_VIOLATION * ViolationQualification )

Handle EPT Violations related to the MBEC hooks.

Parameters
VCpuThe virtual processor's state
ViolationQualification
Returns
BOOLEAN
657{
658 //
659 // Check if this mechanism is use or not
660 //
662 {
663 return FALSE;
664 }
665
666 if (!ViolationQualification->EptExecutableForUserMode && ViolationQualification->ExecuteAccess)
667 {
668 //
669 // For test purposes
670 //
671 // LogInfo("Reached to the user-mode of the process (0x%x) is executed address: %llx", PsGetCurrentProcessId(), VCpu->LastVmexitRip);
672
673 //
674 // Suppress the RIP increment
675 //
677
678 //
679 // Trigger the event
680 //
682 }
683 else if (!ViolationQualification->EptExecutable && ViolationQualification->ExecuteAccess)
684 {
685 //
686 // For test purposes
687 //
688 // LogInfo("Reached to the kernel-mode of the process (0x%x) is executed address: %llx", PsGetCurrentProcessId(), VCpu->LastVmexitRip);
689
690 //
691 // Suppress the RIP increment
692 //
694
695 //
696 // Trigger the event
697 //
699 }
700 else
701 {
702 //
703 // Unexpected violation
704 //
705 return FALSE;
706 }
707
708 //
709 // It successfully handled by MBEC hooks
710 //
711 return TRUE;
712}
VOID HvSuppressRipIncrement(VIRTUAL_MACHINE_STATE *VCpu)
Suppress the incrementation of RIP.
Definition Hv.c:320
@ DEBUGGER_EVENT_MODE_TYPE_USER_MODE
Definition Events.h:209
BOOLEAN g_ExecTrapInitialized
Showes whether the execution trap handler is allowed to trigger an event or not.
Definition GlobalVariables.h:162

◆ ExecTrapHandleMoveToAdjustedTrapState()

VOID ExecTrapHandleMoveToAdjustedTrapState ( VIRTUAL_MACHINE_STATE * VCpu,
DEBUGGER_EVENT_MODE_TYPE TargetMode )

Restore the execution of the trap to adjusted trap state.

Parameters
VCpuThe virtual processor's state
IsUserModeWhether the execution event caused by a switch from kernel-to-user or otherwise user-to-kernel
Returns
VOID
626{
627 if (TargetMode == DEBUGGER_EVENT_MODE_TYPE_USER_MODE)
628 {
629 //
630 // Change EPT to kernel disabled
631 //
633 }
634 else if (TargetMode == DEBUGGER_EVENT_MODE_TYPE_KERNEL_MODE)
635 {
636 //
637 // Change EPT to user disabled
638 //
640 }
641 else
642 {
643 LogError("Err, Invalid target mode for execution trap: %x", TargetMode);
644 }
645}
VOID ExecTrapChangeToKernelDisabledMbecEptp(VIRTUAL_MACHINE_STATE *VCpu)
change to kernel-disabled MBEC EPTP
Definition ExecTrap.c:541
VOID ExecTrapChangeToUserDisabledMbecEptp(VIRTUAL_MACHINE_STATE *VCpu)
change to user-disabled MBEC EPTP
Definition ExecTrap.c:500
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113

◆ ExecTrapInitialize()

BOOLEAN ExecTrapInitialize ( )

Initialize the exec trap based on service request.

Returns
BOOLEAN
370{
371 //
372 // Check if the exec trap is already initialized
373 //
375 {
376 //
377 // Already initialized
378 //
379 return TRUE;
380 }
381
382 //
383 // Check if MBEC supported by this processors
384 //
385 if (!g_CompatibilityCheck.ModeBasedExecutionSupport)
386 {
387 LogInfo("Your processor doesn't support Mode-Based Execution Controls (MBEC), which is a needed feature for this functionality :(\n"
388 "MBEC is available on processors starting from the 7th generation (Kaby Lake) and onwards");
389 return FALSE;
390 }
391
392 //
393 // Call the function responsible for initializing Mode-based hooks
394 //
396 {
397 //
398 // The initialization was not successful
399 //
400 return FALSE;
401 }
402
403 //
404 // Change EPT on all core's to a MBEC supported EPTP
405 // (No longer needed as the starting phase of the process uses EPT hooks)
406 //
408
409 //
410 // Indicate that the reversing machine is initialized
411 // It should be initialized here BEFORE broadcasting mov 2 cr3 exiting
412 // because an EPT violation might be thrown before we enabled it from
413 // here
414 //
416
417 //
418 // Enable Mode-based execution control by broadcasting MOV to CR3 exiting
419 //
421
422 return TRUE;
423}
BOOLEAN ModeBasedExecHookInitialize()
Initialize the needed structure for hooking mode execution.
Definition ModeBasedExecHook.c:213
#define LogInfo(format,...)
Define log variables.
Definition HyperDbgHyperLogIntrinsics.h:71
IMPORT_EXPORT_VMM VOID BroadcastEnableMovToCr3ExitingOnAllProcessors()
routines for debugging threads (enable mov-to-cr3 exiting)
Definition Broadcast.c:436
VOID BroadcastChangeToMbecSupportedEptpOnAllProcessors()
routines for changing EPTP to an MBEC supported EPTP
Definition Broadcast.c:447
COMPATIBILITY_CHECKS_STATUS g_CompatibilityCheck
Different attributes and compatibility checks of the current processor.
Definition GlobalVariables.h:26

◆ ExecTrapReadRamPhysicalRegions()

VOID ExecTrapReadRamPhysicalRegions ( )

Read the RAM regions (physical address).

Returns
VOID
332{
333 PHYSICAL_ADDRESS Address;
334 LONGLONG Size;
335 UINT32 Count = 0;
336 PPHYSICAL_MEMORY_RANGE PhysicalMemoryRanges = NULL;
337
338 //
339 // Read the RAM regions (BIOS) gives these details to Windows
340 //
341 PhysicalMemoryRanges = MmGetPhysicalMemoryRanges();
342
343 do
344 {
345 Address.QuadPart = PhysicalMemoryRanges[Count].BaseAddress.QuadPart;
346 Size = PhysicalMemoryRanges[Count].NumberOfBytes.QuadPart;
347
348 if (!Address.QuadPart && !Size)
349 {
350 break;
351 }
352
353 // LogInfo("RAM Range, from: %llx to %llx", Address.QuadPart, Address.QuadPart + Size);
354
355 PhysicalRamRegions[Count].RamPhysicalAddress = Address.QuadPart;
356 PhysicalRamRegions[Count].RamSize = Size;
357
358 } while (++Count < MAX_PHYSICAL_RAM_RANGE_COUNT);
359
360 ExFreePool(PhysicalMemoryRanges);
361}
NULL()
Definition test-case-generator.py:530

◆ ExecTrapRemoveProcessFromWatchingList()

BOOLEAN ExecTrapRemoveProcessFromWatchingList ( UINT32 ProcessId)

Remove the target process from the watching list.

Parameters
ProcessId
Returns
BOOLEAN
816{
817 UINT32 Index;
818 BOOLEAN Result;
819
821
822 Result = BinarySearchPerformSearchItem(&g_ExecTrapState.InterceptionProcessIds[0],
823 g_ExecTrapState.NumberOfItems,
824 &Index,
825 (UINT64)ProcessId);
826
827 if (Result)
828 {
829 Result = InsertionSortDeleteItem(&g_ExecTrapState.InterceptionProcessIds[0],
830 &g_ExecTrapState.NumberOfItems,
831 Index);
832 }
833
835
836 return Result;
837}
BOOLEAN InsertionSortDeleteItem(UINT64 ArrayPtr[], UINT32 *NumberOfItems, UINT32 Index)
Function to implement insertion sort.
Definition InsertionSort.c:69

◆ ExecTrapRestoreToNormalEptp()

VOID ExecTrapRestoreToNormalEptp ( VIRTUAL_MACHINE_STATE * VCpu)

restore to normal EPTP

Parameters
VCpuThe virtual processor's state
Returns
VOID
481{
482 //
483 // Change EPTP
484 //
485 VmxVmwrite64(VMCS_CTRL_EPT_POINTER, VCpu->EptPointer.AsUInt);
486
487 //
488 // It's on normal EPTP
489 //
490 VCpu->NotNormalEptp = FALSE;
491}
UCHAR VmxVmwrite64(size_t Field, UINT64 FieldValue)
VMX VMWRITE instruction (64-bit).
Definition PlatformIntrinsicsVmx.c:273

◆ ExecTrapTraverseThroughOsPageTables()

BOOLEAN ExecTrapTraverseThroughOsPageTables ( PVMM_EPT_PAGE_TABLE EptTable,
CR3_TYPE TargetCr3,
CR3_TYPE KernelCr3 )

This function gets virtual address and returns its PTE of the virtual address based on the specific cr3 but without switching to the target address.

the TargetCr3 should be kernel cr3 as we will use it to translate kernel addresses so the kernel functions to translate addresses should be mapped; thus, don't pass a KPTI meltdown user cr3 to this function

Parameters
VaVirtual Address
LevelPMLx
TargetCr3user/kernel cr3 of target process
KernelCr3kernel cr3 of target process
Returns
PVOID virtual address of PTE based on cr3
30{
31 CR3_TYPE Cr3;
32 UINT64 TempCr3;
33 PUINT64 Cr3Va;
34 PUINT64 PdptVa;
35 PUINT64 PdVa;
36 PUINT64 PtVa;
37 BOOLEAN IsLargePage = FALSE;
38 CR3_TYPE CurrentProcessCr3 = {0};
39
40 //
41 // Move to guest process as we're currently in system cr3
42 //
43 CurrentProcessCr3 = SwitchToProcessMemoryLayoutByCr3(KernelCr3);
44
45 Cr3.Flags = TargetCr3.Flags;
46
47 //
48 // Cr3 should be shifted 12 to the left because it's PFN
49 //
50 TempCr3 = Cr3.Fields.PageFrameNumber << 12;
51
52 PVOID EptPmlEntry4 = EptGetPml1OrPml2Entry(EptTable, Cr3.Fields.PageFrameNumber << 12, &IsLargePage);
53
54 if (EptPmlEntry4 != NULL)
55 {
56 if (IsLargePage)
57 {
58 ((PEPT_PML2_ENTRY)EptPmlEntry4)->ReadAccess = TRUE;
59 ((PEPT_PML2_ENTRY)EptPmlEntry4)->WriteAccess = TRUE;
60 }
61 else
62 {
63 ((PEPT_PML1_ENTRY)EptPmlEntry4)->ReadAccess = TRUE;
64 ((PEPT_PML1_ENTRY)EptPmlEntry4)->WriteAccess = TRUE;
65 }
66 }
67 else
68 {
69 LogInfo("null address");
70 }
71
72 //
73 // we need VA of Cr3, not PA
74 //
75 Cr3Va = (UINT64 *)PhysicalAddressToVirtualAddress(TempCr3);
76
77 //
78 // Check for invalid address
79 //
80 if (Cr3Va == NULL)
81 {
82 //
83 // Restore the original process
84 //
85 SwitchToPreviousProcess(CurrentProcessCr3);
86
87 return FALSE;
88 }
89
90 for (SIZE_T i = 0; i < 512; i++)
91 {
92 // LogInfo("Address of Cr3Va: %llx", Cr3Va);
93
94 PPAGE_ENTRY Pml4e = (PAGE_ENTRY *)&Cr3Va[i];
95
96 if (Pml4e->Fields.Present)
97 {
98 // LogInfo("PML4[%d] = %llx", i, Pml4e->Fields.PageFrameNumber);
99
100 IsLargePage = FALSE;
101 EptPmlEntry4 = EptGetPml1OrPml2Entry(EptTable, Pml4e->Fields.PageFrameNumber << 12, &IsLargePage);
102
103 if (EptPmlEntry4 != NULL)
104 {
105 if (IsLargePage)
106 {
107 ((PEPT_PML2_ENTRY)EptPmlEntry4)->ReadAccess = TRUE;
108 ((PEPT_PML2_ENTRY)EptPmlEntry4)->WriteAccess = TRUE;
109 }
110 else
111 {
112 ((PEPT_PML1_ENTRY)EptPmlEntry4)->ReadAccess = TRUE;
113 ((PEPT_PML1_ENTRY)EptPmlEntry4)->WriteAccess = TRUE;
114 }
115 }
116 else
117 {
118 LogInfo("null address");
119 }
120
121 PdptVa = (UINT64 *)PhysicalAddressToVirtualAddress(Pml4e->Fields.PageFrameNumber << 12);
122
123 //
124 // Check for invalid address
125 //
126 if (PdptVa != NULL)
127 {
128 for (SIZE_T j = 0; j < 512; j++)
129 {
130 // LogInfo("Address of PdptVa: %llx", PdptVa);
131
132 PPAGE_ENTRY Pdpte = (PAGE_ENTRY *)&PdptVa[j];
133
134 if (Pdpte->Fields.Present)
135 {
136 // LogInfo("PML3[%d] = %llx", j, Pdpte->Fields.PageFrameNumber);
137
138 IsLargePage = FALSE;
139 PVOID EptPmlEntry3 = EptGetPml1OrPml2Entry(EptTable, Pdpte->Fields.PageFrameNumber << 12, &IsLargePage);
140
141 if (EptPmlEntry3 != NULL)
142 {
143 if (IsLargePage)
144 {
145 ((PEPT_PML2_ENTRY)EptPmlEntry3)->ReadAccess = TRUE;
146 ((PEPT_PML2_ENTRY)EptPmlEntry3)->WriteAccess = TRUE;
147 }
148 else
149 {
150 ((PEPT_PML1_ENTRY)EptPmlEntry3)->ReadAccess = TRUE;
151 ((PEPT_PML1_ENTRY)EptPmlEntry3)->WriteAccess = TRUE;
152 }
153 }
154 else
155 {
156 LogInfo("null address");
157 }
158
159 if (Pdpte->Fields.LargePage)
160 {
161 continue;
162 }
163
164 PdVa = (UINT64 *)PhysicalAddressToVirtualAddress(Pdpte->Fields.PageFrameNumber << 12);
165
166 //
167 // Check for invalid address
168 //
169 if (PdVa != NULL)
170 {
171 for (SIZE_T k = 0; k < 512; k++)
172 {
173 // LogInfo("Address of PdVa: %llx", PdVa);
174
175 if (PdVa == (PUINT64)0xfffffffffffffe00)
176 {
177 continue;
178 }
179
180 PPAGE_ENTRY Pde = (PAGE_ENTRY *)&PdVa[k];
181
182 if (Pde->Fields.Present)
183 {
184 // LogInfo("PML2[%d] = %llx", k, Pde->Fields.PageFrameNumber);
185
186 IsLargePage = FALSE;
187 PVOID EptPmlEntry2 = EptGetPml1OrPml2Entry(EptTable, Pde->Fields.PageFrameNumber << 12, &IsLargePage);
188
189 if (EptPmlEntry2 != NULL)
190 {
191 if (IsLargePage)
192 {
193 ((PEPT_PML2_ENTRY)EptPmlEntry2)->ReadAccess = TRUE;
194 ((PEPT_PML2_ENTRY)EptPmlEntry2)->WriteAccess = TRUE;
195 }
196 else
197 {
198 ((PEPT_PML1_ENTRY)EptPmlEntry2)->ReadAccess = TRUE;
199 ((PEPT_PML1_ENTRY)EptPmlEntry2)->WriteAccess = TRUE;
200 }
201 }
202 else
203 {
204 LogInfo("null address");
205 }
206
207 if (Pde->Fields.LargePage)
208 {
209 continue;
210 }
211
212 PtVa = (UINT64 *)PhysicalAddressToVirtualAddress(Pde->Fields.PageFrameNumber << 12);
213
214 //
215 // Check for invalid address
216 //
217 if (PtVa != NULL)
218 {
219 for (SIZE_T l = 0; l < 512; l++)
220 {
221 // LogInfo("Address of PtVa: %llx", PtVa);
222
223 // PPAGE_ENTRY Pt = &PtVa[l];
224
225 /* if (Pt->Fields.Present)
226 {
227 // LogInfo("PML1[%d] = %llx", l, Pt->Fields.PageFrameNumber);
228 }*/
229 }
230 }
231 }
232 }
233 }
234 }
235 }
236 }
237 }
238 }
239
240 //
241 // Restore the original process
242 //
243 SwitchToPreviousProcess(CurrentProcessCr3);
244
245 return TRUE;
246}
PVOID EptGetPml1OrPml2Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress, BOOLEAN *IsLargePage)
Get the PML1 entry for this physical address if the large page is available then large page of Pml2 i...
Definition Ept.c:394
struct _PAGE_ENTRY PAGE_ENTRY
Page Entries.
struct _PAGE_ENTRY * PPAGE_ENTRY
void * PVOID
Definition BasicTypes.h:56
struct _CR3_TYPE CR3_TYPE
CR3 Structure.
IMPORT_EXPORT_VMM VOID SwitchToPreviousProcess(_In_ CR3_TYPE PreviousProcess)
IMPORT_EXPORT_VMM UINT64 PhysicalAddressToVirtualAddress(_In_ UINT64 PhysicalAddress)
IMPORT_EXPORT_VMM CR3_TYPE SwitchToProcessMemoryLayoutByCr3(_In_ CR3_TYPE TargetCr3)
EPT_PTE * PEPT_PML1_ENTRY
Definition State.h:23
UINT64 Flags
Definition BasicTypes.h:239
UINT64 PageFrameNumber
Definition BasicTypes.h:244
struct _CR3_TYPE::@244034060255073137115274324157111341233214336223::@234224113264105317012146222243166211041242274101 Fields
UINT64 LargePage
Definition MemoryMapper.h:88
UINT64 Present
Definition MemoryMapper.h:81
struct _PAGE_ENTRY::@376376202121063303120064260270315140365371076130::@103064255274005116234107103217043340214273361203 Fields
UINT64 PageFrameNumber
Definition MemoryMapper.h:91

◆ ExecTrapUninitialize()

VOID ExecTrapUninitialize ( )

Uinitialize the needed structure for the reversing machine.

should be called from vmx non-root mode

Returns
VOID
433{
434 //
435 // Check if it's already initialized
436 //
438 {
439 return;
440 }
441
442 //
443 // Indicate that the uninitialization phase started
444 //
446
447 //
448 // Disable MOV to CR3 exiting
449 //
451
452 //
453 // Restore to normal EPTP
454 //
456
457 //
458 // Uninitialize the mode-based execution controls
459 //
461
462 //
463 // Indicate that the execution traps are disabled
464 //
466
467 //
468 // Indicate that the uninitialization phase finished
469 //
471}
VOID ModeBasedExecHookUninitialize()
Uinitialize the needed structure for hooking mode execution.
Definition ModeBasedExecHook.c:275
IMPORT_EXPORT_VMM VOID BroadcastDisableMovToCr3ExitingOnAllProcessors()
routines for debugging threads (disable mov-to-cr3 exiting)
Definition Broadcast.c:491
VOID BroadcastRestoreToNormalEptpOnAllProcessors()
routines for restoring EPTP to normal EPTP
Definition Broadcast.c:458
BOOLEAN g_ExecTrapUnInitializationStarted
Showes whether the uninitialization of the exec trap is started or not.
Definition GlobalVariables.h:169