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