From cfb3640a88049bb2a85d315abf6c577da9122deb Mon Sep 17 00:00:00 2001 From: lhodges1 Date: Sat, 26 Aug 2023 22:07:06 +1000 Subject: [PATCH] page table walking stuff started --- driver/driver.c | 2 + driver/driver.vcxproj | 2 + driver/driver.vcxproj.filters | 6 + driver/integrity.h | 2 + driver/ioctl.c | 1 + driver/pool.c | 191 +++++++++++++++ driver/pool.h | 432 ++++++++++++++++++++++++++++++++++ 7 files changed, 636 insertions(+) create mode 100644 driver/pool.c create mode 100644 driver/pool.h diff --git a/driver/driver.c b/driver/driver.c index d004a43..cccb0b3 100644 --- a/driver/driver.c +++ b/driver/driver.c @@ -108,6 +108,8 @@ NTSTATUS DriverEntry( config.protected_process_eprocess = NULL; config.protected_process_id = NULL; + WalkKernelPageTables(); + status = IoCreateDevice( DriverObject, NULL, diff --git a/driver/driver.vcxproj b/driver/driver.vcxproj index 41ba82e..8076d3f 100644 --- a/driver/driver.vcxproj +++ b/driver/driver.vcxproj @@ -133,6 +133,7 @@ + @@ -144,6 +145,7 @@ + diff --git a/driver/driver.vcxproj.filters b/driver/driver.vcxproj.filters index 99aeb6d..434a2cd 100644 --- a/driver/driver.vcxproj.filters +++ b/driver/driver.vcxproj.filters @@ -48,6 +48,9 @@ Source Files + + Source Files + @@ -77,6 +80,9 @@ Header Files + + Header Files + diff --git a/driver/integrity.h b/driver/integrity.h index cf8c053..baaef7f 100644 --- a/driver/integrity.h +++ b/driver/integrity.h @@ -5,6 +5,8 @@ #define POOL_TAG_INTEGRITY 'intg' +VOID WalkKernelPageTables(); + NTSTATUS CopyDriverExecutableRegions( _In_ PIRP Irp ); diff --git a/driver/ioctl.c b/driver/ioctl.c index 39799c8..1b0b3f5 100644 --- a/driver/ioctl.c +++ b/driver/ioctl.c @@ -6,6 +6,7 @@ #include "modules.h" #include "driver.h" #include "callbacks.h" +#include "pool.h" #include "integrity.h" #include "hv.h" diff --git a/driver/pool.c b/driver/pool.c new file mode 100644 index 0000000..ef67993 --- /dev/null +++ b/driver/pool.c @@ -0,0 +1,191 @@ +#include "pool.h" + +#include "common.h" + +#include + +PKDDEBUGGER_DATA64 GetGlobalDebuggerData() +{ + CONTEXT context = { 0 }; + PDUMP_HEADER dump_header = { 0 }; + UINT64 thread_state; + PKDDEBUGGER_DATA64 debugger_data = NULL; + + context.ContextFlags = CONTEXT_FULL; + + RtlCaptureContext( &context ); + + dump_header = ExAllocatePool2( POOL_FLAG_NON_PAGED, DUMP_BLOCK_SIZE, POOL_DUMP_BLOCK_TAG ); + + if ( !dump_header ) + goto end; + + KeCapturePersistentThreadState( + &context, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + dump_header + ); + + debugger_data = ( PKDDEBUGGER_DATA64 )ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( KDDEBUGGER_DATA64 ), POOL_DEBUGGER_DATA_TAG ); + + if ( !debugger_data ) + goto end; + + RtlCopyMemory( debugger_data, dump_header->KdDebuggerDataBlock, sizeof( KDDEBUGGER_DATA64 )); + +end: + + if ( dump_header ) + ExFreePoolWithTag( dump_header, POOL_DUMP_BLOCK_TAG ); + + return debugger_data; +} + +VOID WalkKernelPageTables() +{ + CR3 cr3; + PML4E pml4_base; + PML4E pml4_entry; + PDPTE pdpt_base; + PDPTE pdpt_entry; + PDPTE_LARGE pdpt_large_entry; + PDE pd_base; + PDE pd_entry; + PDE_LARGE pd_large_entry; + PTE pt_base; + PTE pt_entry; + UINT64 base_physical_page; + PHYSICAL_ADDRESS physical; + + cr3.BitAddress = __readcr3(); + + DEBUG_LOG( "cr3: %llx", cr3.BitAddress ); + + physical.QuadPart = cr3.Bits.PhysicalAddress << 12; + + /* Get our PML4 base address */ + pml4_base.BitAddress = MmGetVirtualForPhysical( physical ); + + if ( !MmIsAddressValid(pml4_base.BitAddress) || !pml4_base.BitAddress ) + { + DEBUG_ERROR( "Pml4 base is null or invalid" ); + return; + } + + for ( INT pml4_index = 0; pml4_index < 512; pml4_index++ ) + { + /* get our PML4 entry*/ + pml4_entry.BitAddress = *(UINT64*)( pml4_base.BitAddress + pml4_index * sizeof( UINT64 ) ); + + /* check the present bit */ + if ( pml4_entry.Bits.Present == NULL ) + continue; + + /* read our pml4 entry */ + physical.QuadPart = pml4_entry.Bits.PhysicalAddress << 12; + + pdpt_base.BitAddress = MmGetVirtualForPhysical( physical ); + + if ( !pdpt_base.BitAddress || !MmIsAddressValid( pdpt_base.BitAddress ) ) + continue; + + for ( INT pdpt_index = 0; pdpt_index < 512; pdpt_index++ ) + { + pdpt_entry.BitAddress = *( UINT64* )( pdpt_base.BitAddress + pdpt_index * sizeof( UINT64 ) ); + + if ( pdpt_entry.Bits.Present == NULL ) + continue; + + if ( IS_LARGE_PAGE( pdpt_entry.BitAddress ) ) + { + pdpt_large_entry.BitAddress = pdpt_entry.BitAddress; + + //scan large page bla bla + + continue; + } + + physical.QuadPart = pdpt_entry.Bits.PhysicalAddress << 12; + + pd_base.BitAddress = MmGetVirtualForPhysical( physical ); + + if ( !pd_base.BitAddress || !MmIsAddressValid( pd_base.BitAddress ) ) + continue; + + for ( INT pd_index = 0; pd_index < 512; pd_index++ ) + { + pd_entry.BitAddress = *( UINT64* )( pd_base.BitAddress + pd_index * sizeof( UINT64 ) ); + + if ( pd_entry.Bits.Present == NULL ) + continue; + + if ( IS_LARGE_PAGE( pd_entry.BitAddress ) ) + { + /* 2MB size page */ + pd_large_entry.BitAddress = pd_entry.BitAddress; + + //scan etc. + + continue; + } + + physical.QuadPart = pd_entry.Bits.PhysicalAddress << 12; + + pt_base.BitAddress = MmGetVirtualForPhysical( physical ); + + if ( !pt_base.BitAddress || !MmIsAddressValid( pt_base.BitAddress ) ) + continue; + + for ( INT pt_index = 0; pt_index < 512; pt_index++ ) + { + pt_entry.BitAddress = *( UINT64* )( pt_base.BitAddress + pt_index * sizeof( UINT64 ) ); + + if ( pt_entry.Bits.Present == NULL ) + continue; + + base_physical_page = pt_entry.Bits.PhysicalAddress << 12; + + + } + } + } + } + +} + +VOID ScanNonPagedPoolForProcessTags() +{ + NTSTATUS status; + PKDDEBUGGER_DATA64 debugger_data = NULL; + UINT64 non_paged_pool_start = NULL; + UINT64 non_paged_pool_end = NULL; + + /* must free this */ + debugger_data = GetGlobalDebuggerData(); + + if ( debugger_data == NULL ) + { + DEBUG_ERROR( "Debugger data is null" ); + return STATUS_ABANDONED; + } + + non_paged_pool_start = debugger_data->MmNonPagedPoolStart; + non_paged_pool_end = debugger_data->MmNonPagedPoolEnd; + + DEBUG_LOG( "NonPagedPool start: %llx, end %llx", non_paged_pool_start, non_paged_pool_end ); + + WalkKernelPageTables(); + +/* for ( ; non_paged_pool_start <= non_paged_pool_end; non_paged_pool_start++ ) + { + CHAR current_byte = *( CHAR* )non_paged_pool_start; + DEBUG_LOG( "Current byte: %c", current_byte ); + */ + + ExFreePoolWithTag( debugger_data, POOL_DEBUGGER_DATA_TAG ); +} \ No newline at end of file diff --git a/driver/pool.h b/driver/pool.h new file mode 100644 index 0000000..ff67055 --- /dev/null +++ b/driver/pool.h @@ -0,0 +1,432 @@ +#ifndef POOL_H +#define POOL_H + +#include + +#define POOL_DUMP_BLOCK_TAG 'dump' +#define POOL_DEBUGGER_DATA_TAG 'data' + +/* creds: https://www.unknowncheats.me/forum/2602838-post2.html */ + +typedef struct _DBGKD_DEBUG_DATA_HEADER64 +{ + LIST_ENTRY64 List; + ULONG OwnerTag; + ULONG Size; +} DBGKD_DEBUG_DATA_HEADER64, * PDBGKD_DEBUG_DATA_HEADER64; + +typedef struct _KDDEBUGGER_DATA64 +{ + DBGKD_DEBUG_DATA_HEADER64 Header; + ULONG64 KernBase; + ULONG64 BreakpointWithStatus; + ULONG64 SavedContext; + USHORT ThCallbackStack; + USHORT NextCallback; + USHORT FramePointer; + USHORT PaeEnabled; + ULONG64 KiCallUserMode; + ULONG64 KeUserCallbackDispatcher; + ULONG64 PsLoadedModuleList; + ULONG64 PsActiveProcessHead; + ULONG64 PspCidTable; + ULONG64 ExpSystemResourcesList; + ULONG64 ExpPagedPoolDescriptor; + ULONG64 ExpNumberOfPagedPools; + ULONG64 KeTimeIncrement; + ULONG64 KeBugCheckCallbackListHead; + ULONG64 KiBugcheckData; + ULONG64 IopErrorLogListHead; + ULONG64 ObpRootDirectoryObject; + ULONG64 ObpTypeObjectType; + ULONG64 MmSystemCacheStart; + ULONG64 MmSystemCacheEnd; + ULONG64 MmSystemCacheWs; + ULONG64 MmPfnDatabase; + ULONG64 MmSystemPtesStart; + ULONG64 MmSystemPtesEnd; + ULONG64 MmSubsectionBase; + ULONG64 MmNumberOfPagingFiles; + ULONG64 MmLowestPhysicalPage; + ULONG64 MmHighestPhysicalPage; + ULONG64 MmNumberOfPhysicalPages; + ULONG64 MmMaximumNonPagedPoolInBytes; + ULONG64 MmNonPagedSystemStart; + ULONG64 MmNonPagedPoolStart; + ULONG64 MmNonPagedPoolEnd; + ULONG64 MmPagedPoolStart; + ULONG64 MmPagedPoolEnd; + ULONG64 MmPagedPoolInformation; + ULONG64 MmPageSize; + ULONG64 MmSizeOfPagedPoolInBytes; + ULONG64 MmTotalCommitLimit; + ULONG64 MmTotalCommittedPages; + ULONG64 MmSharedCommit; + ULONG64 MmDriverCommit; + ULONG64 MmProcessCommit; + ULONG64 MmPagedPoolCommit; + ULONG64 MmExtendedCommit; + ULONG64 MmZeroedPageListHead; + ULONG64 MmFreePageListHead; + ULONG64 MmStandbyPageListHead; + ULONG64 MmModifiedPageListHead; + ULONG64 MmModifiedNoWritePageListHead; + ULONG64 MmAvailablePages; + ULONG64 MmResidentAvailablePages; + ULONG64 PoolTrackTable; + ULONG64 NonPagedPoolDescriptor; + ULONG64 MmHighestUserAddress; + ULONG64 MmSystemRangeStart; + ULONG64 MmUserProbeAddress; + ULONG64 KdPrintCircularBuffer; + ULONG64 KdPrintCircularBufferEnd; + ULONG64 KdPrintWritePointer; + ULONG64 KdPrintRolloverCount; + ULONG64 MmLoadedUserImageList; + ULONG64 NtBuildLab; + ULONG64 KiNormalSystemCall; + ULONG64 KiProcessorBlock; + ULONG64 MmUnloadedDrivers; + ULONG64 MmLastUnloadedDriver; + ULONG64 MmTriageActionTaken; + ULONG64 MmSpecialPoolTag; + ULONG64 KernelVerifier; + ULONG64 MmVerifierData; + ULONG64 MmAllocatedNonPagedPool; + ULONG64 MmPeakCommitment; + ULONG64 MmTotalCommitLimitMaximum; + ULONG64 CmNtCSDVersion; + ULONG64 MmPhysicalMemoryBlock; + ULONG64 MmSessionBase; + ULONG64 MmSessionSize; + ULONG64 MmSystemParentTablePage; + ULONG64 MmVirtualTranslationBase; + USHORT OffsetKThreadNextProcessor; + USHORT OffsetKThreadTeb; + USHORT OffsetKThreadKernelStack; + USHORT OffsetKThreadInitialStack; + USHORT OffsetKThreadApcProcess; + USHORT OffsetKThreadState; + USHORT OffsetKThreadBStore; + USHORT OffsetKThreadBStoreLimit; + USHORT SizeEProcess; + USHORT OffsetEprocessPeb; + USHORT OffsetEprocessParentCID; + USHORT OffsetEprocessDirectoryTableBase; + USHORT SizePrcb; + USHORT OffsetPrcbDpcRoutine; + USHORT OffsetPrcbCurrentThread; + USHORT OffsetPrcbMhz; + USHORT OffsetPrcbCpuType; + USHORT OffsetPrcbVendorString; + USHORT OffsetPrcbProcStateContext; + USHORT OffsetPrcbNumber; + USHORT SizeEThread; + ULONG64 KdPrintCircularBufferPtr; + ULONG64 KdPrintBufferSize; + ULONG64 KeLoaderBlock; + USHORT SizePcr; + USHORT OffsetPcrSelfPcr; + USHORT OffsetPcrCurrentPrcb; + USHORT OffsetPcrContainedPrcb; + USHORT OffsetPcrInitialBStore; + USHORT OffsetPcrBStoreLimit; + USHORT OffsetPcrInitialStack; + USHORT OffsetPcrStackLimit; + USHORT OffsetPrcbPcrPage; + USHORT OffsetPrcbProcStateSpecialReg; + USHORT GdtR0Code; + USHORT GdtR0Data; + USHORT GdtR0Pcr; + USHORT GdtR3Code; + USHORT GdtR3Data; + USHORT GdtR3Teb; + USHORT GdtLdt; + USHORT GdtTss; + USHORT Gdt64R3CmCode; + USHORT Gdt64R3CmTeb; + ULONG64 IopNumTriageDumpDataBlocks; + ULONG64 IopTriageDumpDataBlocks; +} KDDEBUGGER_DATA64, * PKDDEBUGGER_DATA64; + +typedef struct _KDDEBUGGER_DATA_ADDITION64 +{ + ULONG64 VfCrashDataBlock; + ULONG64 MmBadPagesDetected; + ULONG64 MmZeroedPageSingleBitErrorsDetected; + ULONG64 EtwpDebuggerData; + USHORT OffsetPrcbContext; + USHORT OffsetPrcbMaxBreakpoints; + USHORT OffsetPrcbMaxWatchpoints; + ULONG OffsetKThreadStackLimit; + ULONG OffsetKThreadStackBase; + ULONG OffsetKThreadQueueListEntry; + ULONG OffsetEThreadIrpList; + USHORT OffsetPrcbIdleThread; + USHORT OffsetPrcbNormalDpcState; + USHORT OffsetPrcbDpcStack; + USHORT OffsetPrcbIsrStack; + USHORT SizeKDPC_STACK_FRAME; + USHORT OffsetKPriQueueThreadListHead; + USHORT OffsetKThreadWaitReason; + USHORT Padding; + ULONG64 PteBase; + ULONG64 RetpolineStubFunctionTable; + ULONG RetpolineStubFunctionTableSize; + ULONG RetpolineStubOffset; + ULONG RetpolineStubSize; +}KDDEBUGGER_DATA_ADDITION64, * PKDDEBUGGER_DATA_ADDITION64; + + +typedef struct _DUMP_HEADER +{ + ULONG Signature; + ULONG ValidDump; + ULONG MajorVersion; + ULONG MinorVersion; + ULONG_PTR DirectoryTableBase; + ULONG_PTR PfnDataBase; + PLIST_ENTRY PsLoadedModuleList; + PLIST_ENTRY PsActiveProcessHead; + ULONG MachineImageType; + ULONG NumberProcessors; + ULONG BugCheckCode; + ULONG_PTR BugCheckParameter1; + ULONG_PTR BugCheckParameter2; + ULONG_PTR BugCheckParameter3; + ULONG_PTR BugCheckParameter4; + CHAR VersionUser[ 32 ]; + struct _KDDEBUGGER_DATA64* KdDebuggerDataBlock; +} DUMP_HEADER, * PDUMP_HEADER; + +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, Signature ) == 0 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, ValidDump ) == 4 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MajorVersion ) == 8 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MinorVersion ) == 0xc ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, DirectoryTableBase ) == 0x10 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PfnDataBase ) == 0x18 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PsLoadedModuleList ) == 0x20 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PsActiveProcessHead ) == 0x28 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MachineImageType ) == 0x30 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, NumberProcessors ) == 0x34 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckCode ) == 0x38 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter1 ) == 0x40 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter2 ) == 0x48 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter3 ) == 0x50 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter4 ) == 0x58 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, KdDebuggerDataBlock ) == 0x80 ); + +#ifndef _WIN64 +#define KDDEBUGGER_DATA_OFFSET 0x1068 +#else +#define KDDEBUGGER_DATA_OFFSET 0x2080 +#endif + +#ifndef _WIN64 +#define DUMP_BLOCK_SIZE 0x20000 +#else +#define DUMP_BLOCK_SIZE 0x40000 +#endif + +NTSYSAPI +ULONG +NTAPI +KeCapturePersistentThreadState( + __in PCONTEXT Context, + __in_opt PKTHREAD Thread, + __in ULONG BugCheckCode, + __in ULONG_PTR BugCheckParameter1, + __in ULONG_PTR BugCheckParameter2, + __in ULONG_PTR BugCheckParameter3, + __in ULONG_PTR BugCheckParameter4, + __in PDUMP_HEADER DumpHeader +); + +VOID ScanNonPagedPoolForProcessTags(); + +typedef union _DIRECTORY_TABLE_BASE +{ + struct + { + UINT64 Ignored0 : 3; /* 2:0 */ + UINT64 PageWriteThrough : 1; /* 3 */ + UINT64 PageCacheDisable : 1; /* 4 */ + UINT64 _Ignored1 : 7; /* 11:5 */ + UINT64 PhysicalAddress : 36; /* 47:12 */ + UINT64 _Reserved0 : 16; /* 63:48 */ + + } Bits; + + UINT64 BitAddress; + +} CR3, DIR_TABLE_BASE; + +typedef union _VIRTUAL_MEMORY_ADDRESS +{ + struct + { + UINT64 PageIndex : 12; /* 0:11 */ + UINT64 PtIndex : 9; /* 12:20 */ + UINT64 PdIndex : 9; /* 21:29 */ + UINT64 PdptIndex : 9; /* 30:38 */ + UINT64 Pml4Index : 9; /* 39:47 */ + UINT64 Unused : 16; /* 48:63 */ + + } Bits; + + UINT64 BitAddress; + +} VIRTUAL_ADDRESS, * PVIRTUAL_ADDRESS; + +typedef union _PML4_ENTRY +{ + struct + { + UINT64 Present : 1; /* 0 */ + UINT64 ReadWrite : 1; /* 1 */ + UINT64 UserSupervisor : 1; /* 2 */ + UINT64 PageWriteThrough : 1; /* 3 */ + UINT64 PageCacheDisable : 1; /* 4 */ + UINT64 Accessed : 1; /* 5 */ + UINT64 _Ignored0 : 1; /* 6 */ + UINT64 _Reserved0 : 1; /* 7 */ + UINT64 _Ignored1 : 4; /* 11:8 */ + UINT64 PhysicalAddress : 40; /* 51:12 */ + UINT64 _Ignored2 : 11; /* 62:52 */ + UINT64 ExecuteDisable : 1; /* 63 */ + } Bits; + UINT64 BitAddress; +} PML4E; + +typedef union _PDPT_ENTRY +{ + struct + { + UINT64 Present : 1; /* 0 */ + UINT64 ReadWrite : 1; /* 1 */ + UINT64 UserSupervisor : 1; /* 2 */ + UINT64 PageWriteThrough : 1; /* 3 */ + UINT64 PageCacheDisable : 1; /* 4 */ + UINT64 Accessed : 1; /* 5 */ + UINT64 _Ignored0 : 1; /* 6 */ + UINT64 PageSize : 1; /* 7 */ + UINT64 _Ignored1 : 4; /* 11:8 */ + UINT64 PhysicalAddress : 40; /* 51:12 */ + UINT64 _Ignored2 : 11; /* 62:52 */ + UINT64 ExecuteDisable : 1; /* 63 */ + } Bits; + UINT64 BitAddress; +} PDPTE; + +typedef union _PD_ENTRY +{ + struct + { + UINT64 Present : 1; /* 0 */ + UINT64 ReadWrite : 1; /* 1 */ + UINT64 UserSupervisor : 1; /* 2 */ + UINT64 PageWriteThrough : 1; /* 3 */ + UINT64 PageCacheDisable : 1; /* 4 */ + UINT64 Accessed : 1; /* 5 */ + UINT64 _Ignored0 : 1; /* 6 */ + UINT64 PageSize : 1; /* 7 */ + UINT64 _Ignored1 : 4; /* 11:8 */ + UINT64 PhysicalAddress : 38; /* 49:12 */ + UINT64 _Reserved0 : 2; /* 51:50 */ + UINT64 _Ignored2 : 11; /* 62:52 */ + UINT64 ExecuteDisable : 1; /* 63 */ + } Bits; + UINT64 BitAddress; +} PDE; + +typedef union _PT_ENTRY +{ + struct + { + UINT64 Present : 1; /* 0 */ + UINT64 ReadWrite : 1; /* 1 */ + UINT64 UserSupervisor : 1; /* 2 */ + UINT64 PageWriteThrough : 1; /* 3 */ + UINT64 PageCacheDisable : 1; /* 4 */ + UINT64 Accessed : 1; /* 5 */ + UINT64 Dirty : 1; /* 6 */ + UINT64 PageAttributeTable : 1; /* 7 */ + UINT64 Global : 1; /* 8 */ + UINT64 _Ignored0 : 3; /* 11:9 */ + UINT64 PhysicalAddress : 38; /* 49:12 */ + UINT64 _Reserved0 : 2; /* 51:50 */ + UINT64 _Ignored1 : 7; /* 58:52 */ + UINT64 ProtectionKey : 4; /* 62:59 */ + UINT64 ExecuteDisable : 1; /* 63 */ + } Bits; + UINT64 BitAddress; +} PTE; + +typedef union _PDPT_ENTRY_LARGE +{ + struct + { + UINT64 Present : 1; /* 0 */ + UINT64 ReadWrite : 1; /* 1 */ + UINT64 UserSupervisor : 1; /* 2 */ + UINT64 PageWriteThrough : 1; /* 3 */ + UINT64 PageCacheDisable : 1; /* 4 */ + UINT64 Accessed : 1; /* 5 */ + UINT64 Dirty : 1; /* 6 */ + UINT64 PageSize : 1; /* 7 */ + UINT64 Global : 1; /* 8 */ + UINT64 _Ignored0 : 3; /* 11:9 */ + UINT64 PageAttributeTable : 1; /* 12 */ + UINT64 _Reserved0 : 17; /* 29:13 */ + UINT64 PhysicalAddress : 22; /* 51:30 */ + UINT64 _Ignored1 : 7; /* 58:52 */ + UINT64 ProtectionKey : 4; /* 62:59 */ + UINT64 ExecuteDisable : 1; /* 63 */ + } Bits; + UINT64 BitAddress; +} PDPTE_LARGE; + +typedef union _PD_ENTRY_LARGE +{ + struct + { + UINT64 Present : 1; /* 0 */ + UINT64 ReadWrite : 1; /* 1 */ + UINT64 UserSupervisor : 1; /* 2 */ + UINT64 PageWriteThrough : 1; /* 3 */ + UINT64 PageCacheDisable : 1; /* 4 */ + UINT64 Accessed : 1; /* 5 */ + UINT64 Dirty : 1; /* 6 */ + UINT64 PageSize : 1; /* 7 */ + UINT64 Global : 1; /* 8 */ + UINT64 _Ignored0 : 3; /* 11:9 */ + UINT64 PageAttributeTalbe : 1; /* 12 */ + UINT64 _Reserved0 : 8; /* 20:13 */ + UINT64 PhysicalAddress : 29; /* 49:21 */ + UINT64 _Reserved1 : 2; /* 51:50 */ + UINT64 _Ignored1 : 7; /* 58:52 */ + UINT64 ProtectionKey : 4; /* 62:59 */ + UINT64 ExecuteDisable : 1; /* 63 */ + } Bits; + UINT64 BitAddress; +} PDE_LARGE; + +/* + * Generic macros that allow you to quickly determine whether + * or not a page table entry is present or may forward to a + * large page of data, rather than another page table (applies + * only to PDPTEs and PDEs) + */ +#define IS_LARGE_PAGE(x) ( (BOOLEAN)((x >> 7) & 1) ) +#define IS_PAGE_PRESENT(x) ( (BOOLEAN)(x & 1) ) + +#define PAGE_1GB_SHIFT 30 +#define PAGE_1GB_OFFSET(x) ( x & (~(MAXUINT64 << PAGE_1GB_SHIFT)) ) + +#define PAGE_2MB_SHIFT 21 +#define PAGE_2MB_OFFSET(x) ( x & (~(MAXUINT64 << PAGE_2MB_SHIFT)) ) + +#define PAGE_4KB_SHIFT 12 +#define PAGE_4KB_OFFSET(x) ( x & (~(MAXUINT64 << PAGE_4KB_SHIFT)) ) + +#endif \ No newline at end of file