page table walking stuff started

This commit is contained in:
lhodges1 2023-08-26 22:07:06 +10:00
parent dd38277278
commit cfb3640a88
7 changed files with 636 additions and 0 deletions

View file

@ -108,6 +108,8 @@ NTSTATUS DriverEntry(
config.protected_process_eprocess = NULL;
config.protected_process_id = NULL;
WalkKernelPageTables();
status = IoCreateDevice(
DriverObject,
NULL,

View file

@ -133,6 +133,7 @@
<ClCompile Include="ioctl.c" />
<ClCompile Include="modules.c" />
<ClCompile Include="nmi.c" />
<ClCompile Include="pool.c" />
<ClCompile Include="queue.c" />
</ItemGroup>
<ItemGroup>
@ -144,6 +145,7 @@
<ClInclude Include="ioctl.h" />
<ClInclude Include="modules.h" />
<ClInclude Include="nmi.h" />
<ClInclude Include="pool.h" />
<ClInclude Include="queue.h" />
</ItemGroup>
<ItemGroup>

View file

@ -48,6 +48,9 @@
<ClCompile Include="integrity.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pool.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="driver.h">
@ -77,6 +80,9 @@
<ClInclude Include="integrity.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pool.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<MASM Include="asm.asm">

View file

@ -5,6 +5,8 @@
#define POOL_TAG_INTEGRITY 'intg'
VOID WalkKernelPageTables();
NTSTATUS CopyDriverExecutableRegions(
_In_ PIRP Irp
);

View file

@ -6,6 +6,7 @@
#include "modules.h"
#include "driver.h"
#include "callbacks.h"
#include "pool.h"
#include "integrity.h"
#include "hv.h"

191
driver/pool.c Normal file
View file

@ -0,0 +1,191 @@
#include "pool.h"
#include "common.h"
#include <intrin.h>
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 );
}

432
driver/pool.h Normal file
View file

@ -0,0 +1,432 @@
#ifndef POOL_H
#define POOL_H
#include <ntifs.h>
#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