added new extension command to PagingDbgExt

This commit is contained in:
winterknife
2025-06-15 18:03:13 -04:00
parent c084a42b38
commit bc16f431ab
7 changed files with 625 additions and 149 deletions
+130 -1
View File
@@ -7,7 +7,7 @@
//
// Modifications:
// 2025-05-20 Created
// 2025-06-02 Updated
// 2025-06-08 Updated
// ========================================================================
// ========================================================================
@@ -108,6 +108,120 @@ typedef union _PML4E {
} PML4E, *PPML4E;
#pragma warning(pop)
// PDPT Entry (PDPTE)
#pragma warning(push)
#pragma warning(disable: 4201)
typedef union _PDPTE {
struct {
QWORD P : 1; // Present
QWORD RW : 1; // Read/Write
QWORD US : 1; // User/Supervisor
QWORD PWT : 1; // Page-level Write Through
QWORD PCD : 1; // Page-level Cache Disable
QWORD A : 1; // Accessed
QWORD D : 1; // Dirty
QWORD PS : 1; // Page Size (must be set if entry maps a 1 GB page), reserved (must be 0) if processor doesn't support huge pages
QWORD G : 1; // Global (if CR4.PGE = 1, determines whether the translation is global, ignored otherwise)
QWORD Ignored1 : 2; // Ignored
QWORD R : 1; // Restart (HLAT paging)
QWORD PAT : 1; // Page Attribute Table (PAT)
QWORD Reserved1 : 17; // Reserved (must be 0)
QWORD PFN1 : 18; // Physical address of the 1-GByte page referenced by this entry
QWORD Reserved2 : 4; // Reserved (must be 0)
QWORD Ignored2 : 7; // Ignored
QWORD PK : 4; // Protection Key (if CR4.PKE = 1 or CR4.PKS = 1, this may control the pages access rights, ignored otherwise)
QWORD XD : 1; // Execute Disable, reserved (must be 0) if IA32_EFER.NXE = 0
};
struct {
QWORD : 12;
QWORD PFN2 : 36; // Physical address of 4-KByte aligned page directory referenced by this entry
QWORD : 16;
};
QWORD Value;
} PDPTE, *PPDPTE;
#pragma warning(pop)
// PD Entry (PDE)
#pragma warning(push)
#pragma warning(disable: 4201)
typedef union _PDE {
struct {
QWORD P : 1; // Present
QWORD RW : 1; // Read/Write
QWORD US : 1; // User/Supervisor
QWORD PWT : 1; // Page-level Write Through
QWORD PCD : 1; // Page-level Cache Disable
QWORD A : 1; // Accessed
QWORD D : 1; // Dirty
QWORD PS : 1; // Page Size (must be set if entry maps a 2 MB page)
QWORD G : 1; // Global (if CR4.PGE = 1, determines whether the translation is global, ignored otherwise)
QWORD Ignored1 : 2; // Ignored
QWORD R : 1; // Restart (HLAT paging)
QWORD PAT : 1; // Page Attribute Table (PAT)
QWORD Reserved1 : 8; // Reserved (must be 0)
QWORD PFN1 : 27; // Physical address of the 2-MByte page referenced by this entry
QWORD Reserved2 : 4; // Reserved (must be 0)
QWORD Ignored2 : 7; // Ignored
QWORD PK : 4; // Protection Key (if CR4.PKE = 1 or CR4.PKS = 1, this may control the pages access rights, ignored otherwise)
QWORD XD : 1; // Execute Disable, reserved (must be 0) if IA32_EFER.NXE = 0
};
struct {
QWORD : 12;
QWORD PFN2 : 36; // Physical address of 4-KByte aligned page table referenced by this entry
QWORD : 16;
};
QWORD Value;
} PDE, *PPDE;
#pragma warning(pop)
// PT Entry (PTE)
#pragma warning(push)
#pragma warning(disable: 4201)
typedef union _PTE {
struct {
QWORD P : 1; // Present
QWORD RW : 1; // Read/Write
QWORD US : 1; // User/Supervisor
QWORD PWT : 1; // Page-level Write Through
QWORD PCD : 1; // Page-level Cache Disable
QWORD A : 1; // Accessed
QWORD D : 1; // Dirty
QWORD PAT : 1; // Page Attribute Table (PAT)
QWORD G : 1; // Global (if CR4.PGE = 1, determines whether the translation is global, ignored otherwise)
QWORD Ignored1 : 2; // Ignored
QWORD R : 1; // Restart (HLAT paging)
QWORD PFN : 36; // Physical address of the 4-KByte page referenced by this entry
QWORD Reserved1 : 4; // Reserved (must be 0)
QWORD Ignored2 : 7; // Ignored
QWORD PK : 4; // Protection Key (if CR4.PKE = 1 or CR4.PKS = 1, this may control the pages access rights, ignored otherwise)
QWORD XD : 1; // Execute Disable, reserved (must be 0) if IA32_EFER.NXE = 0
};
QWORD Value;
} PTE, *PPTE;
#pragma warning(pop)
// Windows x64 hardware PxE (MMU's interpretation)
typedef struct _MMPTE_HARDWARE {
QWORD Valid : 1; // Present
QWORD Dirty1 : 1; // Read/Write (cleared together with Dirty bit)
QWORD Owner : 1; // User/Supervisor
QWORD WriteThrough : 1; // Page-level Write Through
QWORD CacheDisable : 1; // Page-level Cache Disable
QWORD Accessed : 1; // Accessed
QWORD Dirty : 1; // Dirty
QWORD LargePage : 1; // Page Attribute Table (PAT) or Page Size (PS)
QWORD Global : 1; // Global
QWORD CopyOnWrite : 1; // Copy On Write (CoW)
QWORD Unused : 1; // Ignored
QWORD Write : 1; // Used by the Memory Manager to recognize the page as writable
QWORD PageFrameNumber : 36; // Page Frame Number (PFN)
QWORD ReservedForHardware : 4; // Reserved (must be 0)
QWORD ReservedForSoftware : 4; // Reserved (must be 0)
QWORD WsleAge : 4; // Working Set List Entry (WSLE)
QWORD WsleProtection : 3; // Working Set List Entry (WSLE)
QWORD NoExecute : 1; // Execute Disable (XD/NX)
} MMPTE_HARDWARE, *PMMPTE_HARDWARE;
#pragma endregion
// ========================================================================
@@ -177,6 +291,21 @@ extern "C" __declspec(dllexport) VOID __stdcall get_pxe_address(
_In_z_ PCSTR strArgs
);
/// @brief Built-in command to translate the specified linear address (VA) to its mapped physical address (PA) and determine the VA's access rights from the CR3
/// @param hCurrentProcess Handle for the current process
/// @param hCurrentThread Handle for the current thread
/// @param qwCurrentPc Program counter
/// @param dwProcessor Current processor
/// @param strArgs Command line arguments (VA and CR3 value)
/// @return None
extern "C" __declspec(dllexport) VOID __stdcall get_physical_address(
_In_ HANDLE hCurrentProcess,
_In_ HANDLE hCurrentThread,
_In_ QWORD qwCurrentPc,
_In_ DWORD dwProcessor,
_In_z_ PCSTR strArgs
);
#pragma endregion
// ========================================================================
Binary file not shown.
+1 -1
View File
@@ -58,7 +58,7 @@
<AdditionalOptions>%(AdditionalOptions) /homeparams</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Native</SubSystem>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
+165 -143
View File
@@ -1,7 +1,7 @@
# EVENSTAR - PagingDbgExt
## Version
- `v10.5.6`
- `v10.6.6`
## Brief
- `ISA: x86`
@@ -15,33 +15,34 @@
## Usage
- Set up kernel-mode debugging of the target
```
0: kd> vertarget
1: kd> vertarget
Windows 10 Kernel Version 22000 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Edition build lab: 22000.1.amd64fre.co_release.210604-1628
Kernel base = 0xfffff804`6580f000 PsLoadedModuleList = 0xfffff804`66438b90
Debug session time: Tue Jun 3 17:15:28.502 2025 (UTC - 4:00)
System Uptime: 0 days 0:12:56.092
Kernel base = 0xfffff804`4fe00000 PsLoadedModuleList = 0xfffff804`50a29b90
Debug session time: Sun Jun 15 14:17:31.297 2025 (UTC - 4:00)
System Uptime: 0 days 3:37:31.814
0: kd> .load PagingDbgExt.dll
1: kd> .load PagingDbgExt.dll
0: kd> .chain
1: kd> .chain
--snip--
Extension DLL chain:
PagingDbgExt: API 10.5.6,
PagingDbgExt: API 10.6.6,
[path: C:\Users\winterknife\Desktop\Tools\WinDbgExtensions\PagingDbgExt.dll]
--snip--
0: kd> .extmatch /D /e PagingDbgExt *
1: kd> .extmatch /D /e PagingDbgExt *
!PagingDbgExt.check_4_level_paging_mode
!PagingDbgExt.get_kernel_dtb
!PagingDbgExt.get_physical_address
!PagingDbgExt.get_pml4_autoentry_index
!PagingDbgExt.get_process_dtb
!PagingDbgExt.get_pxe_address
!PagingDbgExt.get_pxe_base
!PagingDbgExt.help
0: kd> !PagingDbgExt.help
1: kd> !PagingDbgExt.help
Help for debugger extension DLL PagingDbgExt.dll
help - Show help menu
get_kernel_dtb - Find the kernel's DTB (DirectoryTableBase) which is the physical address of the base of the paging-structure hierarchy for KVAS contained in CR3 from the Low Stub
@@ -50,172 +51,169 @@ Help for debugger extension DLL PagingDbgExt.dll
get_pml4_autoentry_index - Find the self-reference entry/auto-entry index of the Page Map Level 4 (PML4) table from the CR3
get_pxe_base - Compute the starting KVA of the paging structure entry (PxE) range from the PML4 table auto-entry index
get_pxe_address - Compute the KVA of the paging structure entry (PxE) that maps the specified VA from the PML4 table auto-entry index
get_physical_address - Translate the specified linear address (VA) to its mapped physical address (PA) and determine the VA's access rights from the CR3
0: kd> !PagingDbgExt.get_kernel_dtb
1: kd> !PagingDbgExt.get_kernel_dtb
[+] nt!_PROCESSOR_START_BLOCK structure found at PA=0x13000
[+] HAL Heap base KVA=0xFFFFF7C440000000
[+] HAL Heap base KVA=0xFFFFF7D980000000
[+] nt!_PROCESSOR_START_BLOCK.ProcessorState.SpecialRegisters.Cr3=0x1AE000
0: kd> ? poi(nt!HalpLowStubPhysicalAddress)
1: kd> ? poi(nt!HalpLowStubPhysicalAddress)
Evaluate expression: 77824 = 00000000`00013000
0: kd> ? poi(nt!HalpOriginalHeapStart)
Evaluate expression: -9052717318144 = fffff7c4`40000000
1: kd> ? poi(nt!HalpOriginalHeapStart)
Evaluate expression: -8961449263104 = fffff7d9`80000000
0: kd> r @cr3
cr3=00000000001ae000
0: kd> !process 4 0
Searching for Process with Cid == 4
PROCESS ffffc4866e2ab040
SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 001ae000 ObjectTable: ffffe7876f403dc0 HandleCount: 1970.
Image: System
0: kd> dt nt!_KPROCESS ffffc4866e2ab040 DirectoryTableBase
+0x028 DirectoryTableBase : 0x1ae000
0: kd> dt /p nt!_KPROCESSOR_STATE 0x13090 SpecialRegisters.Cr3
1: kd> dt /p nt!_KPROCESSOR_STATE 0x13090 SpecialRegisters.Cr3
+0x000 SpecialRegisters :
+0x010 Cr3 : 0x1ae000
0: kd> !db 0x13000
# 13000 e9 4d 06 00 01 00 00 00-01 00 00 00 3f 00 18 30 .M..........?..0
# 13010 01 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
# 13020 00 00 00 00 00 00 00 00-00 00 00 00 00 9b 20 00 .............. .
# 13030 00 00 00 00 00 00 00 00-ff ff 00 00 00 93 cf 00 ................
# 13040 00 00 00 00 00 00 00 00-ff ff 00 00 00 9b cf 00 ................
# 13050 00 00 00 00 00 00 00 00-00 90 4f 79 00 00 00 00 ..........Oy....
# 13060 79 36 01 00 30 00 d7 36-01 00 10 00 00 00 00 00 y6..0..6........
# 13070 70 18 c2 65 04 f8 ff ff-00 c0 00 40 c4 f7 ff ff p..e.......@....
1: kd> r @cr3
cr3=00000000001ae000
0: kd> db poi(nt!HalpLowStub)
fffff7c4`4000c000 e9 4d 06 00 01 00 00 00-01 00 00 00 3f 00 18 30 .M..........?..0
fffff7c4`4000c010 01 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
fffff7c4`4000c020 00 00 00 00 00 00 00 00-00 00 00 00 00 9b 20 00 .............. .
fffff7c4`4000c030 00 00 00 00 00 00 00 00-ff ff 00 00 00 93 cf 00 ................
fffff7c4`4000c040 00 00 00 00 00 00 00 00-ff ff 00 00 00 9b cf 00 ................
fffff7c4`4000c050 00 00 00 00 00 00 00 00-00 90 4f 79 00 00 00 00 ..........Oy....
fffff7c4`4000c060 79 36 01 00 30 00 d7 36-01 00 10 00 00 00 00 00 y6..0..6........
fffff7c4`4000c070 70 18 c2 65 04 f8 ff ff-00 c0 00 40 c4 f7 ff ff p..e.......@....
1: kd> !process 4 0
Searching for Process with Cid == 4
PROCESS ffff8088a80af040
SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 001ae000 ObjectTable: ffffcf03a6203dc0 HandleCount: 2209.
Image: System
0: kd> dps poi(nt!HalpLowStub) L10
fffff7c4`4000c000 00000001`00064de9
fffff7c4`4000c008 3018003f`00000001
fffff7c4`4000c010 00000000`00000001
fffff7c4`4000c018 00000000`00000000
fffff7c4`4000c020 00000000`00000000
fffff7c4`4000c028 00209b00`00000000
fffff7c4`4000c030 00000000`00000000
fffff7c4`4000c038 00cf9300`0000ffff
fffff7c4`4000c040 00000000`00000000
fffff7c4`4000c048 00cf9b00`0000ffff
fffff7c4`4000c050 00000000`00000000
fffff7c4`4000c058 00000000`794f9000
fffff7c4`4000c060 36d70030`00013679
fffff7c4`4000c068 00000000`00100001
fffff7c4`4000c070 fffff804`65c21870 nt!HalpLMStub
fffff7c4`4000c078 fffff7c4`4000c000
1: kd> dps poi(nt!HalpLowStub) L10
fffff7d9`8000c000 00000001`00064de9
fffff7d9`8000c008 3018003f`00000001
fffff7d9`8000c010 00000000`00000001
fffff7d9`8000c018 00000000`00000000
fffff7d9`8000c020 00000000`00000000
fffff7d9`8000c028 00209b00`00000000
fffff7d9`8000c030 00000000`00000000
fffff7d9`8000c038 00cf9300`0000ffff
fffff7d9`8000c040 00000000`00000000
fffff7d9`8000c048 00cf9b00`0000ffff
fffff7d9`8000c050 00000000`00000000
fffff7d9`8000c058 00000000`bffff000
fffff7d9`8000c060 36d70030`00013679
fffff7d9`8000c068 00000000`00100001
fffff7d9`8000c070 fffff804`50212870 nt!HalpLMStub
fffff7d9`8000c078 fffff7d9`8000c000
0: kd> !pte poi(nt!HalpLowStub)
VA fffff7c44000c000
PXE at FFFFF97CBE5F2F78 PPE at FFFFF97CBE5EF888 PDE at FFFFF97CBDF11000 PTE at FFFFF97BE2200060
contains 0000000002182063 contains 8000000002185063 contains 8000000002186063 contains 8000000000013963
pfn 2182 ---DA--KWEV pfn 2185 ---DA--KW-V pfn 2186 ---DA--KW-V pfn 13 -G-DA--KW-V
0: kd> !vtop 0x1ae000 0xfffff7c44000c000
Amd64VtoP: Virt fffff7c44000c000, pagedir 00000000001ae000
Amd64VtoP: PML4E 00000000001aef78
Amd64VtoP: PDPE 0000000002182888
Amd64VtoP: PDE 0000000002185000
Amd64VtoP: PTE 0000000002186060
Amd64VtoP: Mapped phys 0000000000013000
Virtual address fffff7c44000c000 translates to physical address 13000.
0: kd> !process 0 0 lsass.exe
PROCESS ffffc4866ede80c0
SessionId: 0 Cid: 02e8 Peb: 414677f000 ParentCid: 0208
DirBase: 7dec0000 ObjectTable: ffffe78771c7b2c0 HandleCount: 926.
1: kd> !process 0 0 lsass.exe
PROCESS ffff8088a8b26080
SessionId: 0 Cid: 02e4 Peb: 9c876d1000 ParentCid: 0210
DirBase: 10f8f1000 ObjectTable: ffffcf03a8a81280 HandleCount: 999.
Image: lsass.exe
0: kd> !PagingDbgExt.get_process_dtb 0xffffc4866ede80c0
[*] nt!_EPROCESS KVA=0xFFFFC4866EDE80C0
[+] nt!_EPROCESS.Pcb.DirectoryTableBase=0x7DEC0000
1: kd> !PagingDbgExt.get_process_dtb 0xffff8088a8b26080
[*] nt!_EPROCESS KVA=0xFFFF8088A8B26080
[+] nt!_EPROCESS.Pcb.DirectoryTableBase=0x10F8F1000
0: kd> !PagingDbgExt.check_4_level_paging_mode
[!] Current processor number = 0
1: kd> !PagingDbgExt.check_4_level_paging_mode
[!] Current processor number = 1
[+] 4-level IA-32e paging mode is enabled!
0: kd> !PagingDbgExt.get_pml4_autoentry_index 0x1AE000
[!] Current processor number = 0
1: kd> !PagingDbgExt.get_pml4_autoentry_index 0x1AE000
[!] Current processor number = 1
[+] 4-level IA-32e paging mode is enabled!
[*] CR3=0x1AE000
[+] Page Map Level 4 (PML4) table base PA=0x1AE000
[+] PML4 auto-entry found at index: 0x1F2 (0n498)
[+] PML4 auto-entry found at index: 0x151 (0n337)
0: kd> ? (poi(nt!MmPteBase) >> 0n39) & 0x1ff
Evaluate expression: 498 = 00000000`000001f2
1: kd> ? (poi(nt!MmPteBase) >> 0n39) & 0x1ff
Evaluate expression: 337 = 00000000`00000151
0: kd> !PagingDbgExt.get_pxe_base 0x1F2
[!] Current processor number = 0
1: kd> !PagingDbgExt.get_pxe_base 0x151
[!] Current processor number = 1
[+] 4-level IA-32e paging mode is enabled!
[*] PML4 table auto-entry index: 0x1F2 (0n498)
[+] PTE_BASE=0xFFFFF90000000000
[+] PDE_BASE=0xFFFFF97C80000000
[+] PPE_BASE=0xFFFFF97CBE400000
[+] PXE_BASE=0xFFFFF97CBE5F2000
[+] PXE_SELFMAP=0xFFFFF97CBE5F2F90
[+] PXE_TOP=0xFFFFF97CBE5F2FFF
[+] PPE_TOP=0xFFFFF97CBE5FFFFF
[+] PDE_TOP=0xFFFFF97CBFFFFFFF
[+] PTE_TOP=0xFFFFF97FFFFFFFFF
[*] PML4 table auto-entry index: 0x151 (0n337)
[+] PTE_BASE=0xFFFFA88000000000
[+] PDE_BASE=0xFFFFA8D440000000
[+] PPE_BASE=0xFFFFA8D46A200000
[+] PXE_BASE=0xFFFFA8D46A351000
[+] PXE_SELFMAP=0xFFFFA8D46A351A88
[+] PXE_TOP=0xFFFFA8D46A351FFF
[+] PPE_TOP=0xFFFFA8D46A3FFFFF
[+] PDE_TOP=0xFFFFA8D47FFFFFFF
[+] PTE_TOP=0xFFFFA8FFFFFFFFFF
0: kd> ? poi(nt!MmPteBase)
Evaluate expression: -7696581394432 = fffff900`00000000
1: kd> ? poi(nt!MmPteBase)
Evaluate expression: -96207267430400 = ffffa880`00000000
0: kd> uf nt!MiGetPteAddress
1: kd> uf nt!MiGetPteAddress
nt!MiGetPteAddress:
fffff804`65b20f90 48c1e909 shr rcx,9
fffff804`65b20f94 48b8f8ffffff7f000000 mov rax,7FFFFFFFF8h
fffff804`65b20f9e 4823c8 and rcx,rax
fffff804`65b20fa1 48b80000000000f9ffff mov rax,0FFFFF90000000000h
fffff804`65b20fab 4803c1 add rax,rcx
fffff804`65b20fae c3 ret
fffff804`50111f90 48c1e909 shr rcx,9
fffff804`50111f94 48b8f8ffffff7f000000 mov rax,7FFFFFFFF8h
fffff804`50111f9e 4823c8 and rcx,rax
fffff804`50111fa1 48b80000000080a8ffff mov rax,0FFFFA88000000000h
fffff804`50111fab 4803c1 add rax,rcx
fffff804`50111fae c3 ret
0: kd> uf nt!MiGetPdeAddress
1: kd> uf nt!MiGetPdeAddress
nt!MiGetPdeAddress:
fffff804`65ae0420 48c1e912 shr rcx,12h
fffff804`65ae0424 81e1f8ffff3f and ecx,3FFFFFF8h
fffff804`65ae042a 48b8000000807cf9ffff mov rax,0FFFFF97C80000000h
fffff804`65ae0434 4803c1 add rax,rcx
fffff804`65ae0437 c3 ret
fffff804`500d1420 48c1e912 shr rcx,12h
fffff804`500d1424 81e1f8ffff3f and ecx,3FFFFFF8h
fffff804`500d142a 48b800000040d4a8ffff mov rax,0FFFFA8D440000000h
fffff804`500d1434 4803c1 add rax,rcx
fffff804`500d1437 c3 ret
0: kd> rdmsr 0xC0000082
msr[c0000082] = fffff804`65c37bc0
0: kd> !PagingDbgExt.get_pxe_address 0xfffff80465c37bc0 0x1f2
[!] Current processor number = 0
1: kd> !PagingDbgExt.get_pxe_address 0xFFFFF78000000000 0x151
[!] Current processor number = 1
[+] 4-level IA-32e paging mode is enabled!
[*] VA=0xFFFFF80465C37BC0
[*] PML4 table auto-entry index: 0x1F2 (0n498)
[+] PTE KVA=0xFFFFF97C0232E1B8
[+] PDE KVA=0xFFFFF97CBE011970
[+] PPE KVA=0xFFFFF97CBE5F0088
[+] PXE KVA=0xFFFFF97CBE5F2F80
[*] VA=0xFFFFF78000000000
[*] PML4 table auto-entry index: 0x151 (0n337)
[+] PTE KVA=0xFFFFA8FBC0000000
[+] PDE KVA=0xFFFFA8D47DE00000
[+] PPE KVA=0xFFFFA8D46A3EF000
[+] PXE KVA=0xFFFFA8D46A351F78
0: kd> !pte 0xfffff80465c37bc0
VA fffff80465c37bc0
PXE at FFFFF97CBE5F2F80 PPE at FFFFF97CBE5F0088 PDE at FFFFF97CBE011970 PTE at FFFFF97C0232E1B8
contains 000000000218B063 contains 000000000218C063 contains 000000000219C063 contains 090000007F05C121
pfn 218b ---DA--KWEV pfn 218c ---DA--KWEV pfn 219c ---DA--KWEV pfn 7f05c -G--A--KREV
1: kd> !pte 0xFFFFF78000000000
VA fffff78000000000
PXE at FFFFA8D46A351F78 PPE at FFFFA8D46A3EF000 PDE at FFFFA8D47DE00000 PTE at FFFFA8FBC0000000
contains 000000000F202063 contains 000000000F203063 contains 000000000F204063 contains 800000000F22C963
pfn f202 ---DA--KWEV pfn f203 ---DA--KWEV pfn f204 ---DA--KWEV pfn f22c -G-DA--KW-V
0: kd> !pte 0xFFFFF97CBE011970
VA fffff97c0232e000
PXE at FFFFF97CBE5F2F90 PPE at FFFFF97CBE5F2F80 PDE at FFFFF97CBE5F0088 PTE at FFFFF97CBE011970
contains 80000000001AE063 contains 000000000218B063 contains 000000000218C063 contains 000000000219C063
pfn 1ae ---DA--KW-V pfn 218b ---DA--KWEV pfn 218c ---DA--KWEV pfn 219c ---DA--KWEV
1: kd> rdmsr 0xC0000082
msr[c0000082] = fffff804`50228bc0
0: kd> .unload PagingDbgExt.dll
1: kd> !PagingDbgExt.get_physical_address 0xfffff80450228bc0 0x1ae000
[!] Current processor number = 1
[+] 4-level IA-32e paging mode is enabled!
[*] VA=0xFFFFF80450228BC0
[*] CR3=0x1AE000
[+] PML4 table base PA=0x1AE000
[+] PML4 index: 0x1F0 (0n496)
[+] PML4E PA=0x1AEF80
[+] PML4E contents=0xF20B063
[+] PDPT base PA=0xF20B000
[+] PDPT index: 0x11 (0n17)
[+] PDPTE PA=0xF20B088
[+] PDPTE contents=0xF20C063
[+] PD table base PA=0xF20C000
[+] PD index: 0x81 (0n129)
[+] PDE PA=0xF20C408
[+] PDE contents=0xA000001008001A1
[+] 2 MB physical page base PA=0x100800000
[+] 2 MB physical page offset: 0x28BC0 (0n166848)
[+] PA=0x100828BC0
[+] Read-only address.
[+] Supervisor-mode address.
[+] Executable address.
[+] Dirty: 0
[+] Global: 1
1: kd> !vtop 0x1ae000 0xfffff80450228bc0
Amd64VtoP: Virt fffff80450228bc0, pagedir 00000000001ae000
Amd64VtoP: PML4E 00000000001aef80
Amd64VtoP: PDPE 000000000f20b088
Amd64VtoP: PDE 000000000f20c408
Amd64VtoP: Large page mapped phys 0000000100828bc0
Virtual address fffff80450228bc0 translates to physical address 100828bc0.
1: kd> !pte fffff804`50228bc0
VA fffff80450228bc0
PXE at FFFFA8D46A351F80 PPE at FFFFA8D46A3F0088 PDE at FFFFA8D47E011408 PTE at FFFFA8FC02281140
contains 000000000F20B063 contains 000000000F20C063 contains 0A000001008001A1 contains 0000000000000000
pfn f20b ---DA--KWEV pfn f20c ---DA--KWEV pfn 100800 -GL-A--KREV LARGE PAGE pfn 100828
1: kd> .unload PagingDbgExt.dll
Unloading PagingDbgExt extension DLL
```
@@ -243,4 +241,28 @@ I don't plan on improving the heuristics at the moment but you reading this shou
9. [Getting Physical: Extreme abuse of Intel based Paging Systems - Part 3 - Windows HAL's Heap](https://www.coresecurity.com/core-labs/articles/getting-physical-extreme-abuse-of-intel-based-paging-systems)
10. [Windows 8 Kernel Memory Protections Bypass](https://labs.withsecure.com/publications/windows-8-kernel-memory-protections-bypass)
11. [Virtual Memory - Intro to Paging Tables](https://blog.back.engineering/23/08/2020/)
12. [What Makes It Page?: The Windows 7 (x64) Virtual Memory Manager](https://www.amazon.ca/What-Makes-Page-Windows-Virtual/dp/1479114294)
12. [What Makes It Page?: The Windows 7 (x64) Virtual Memory Manager](https://www.amazon.ca/What-Makes-Page-Windows-Virtual/dp/1479114294)
13. [Circumventing Leak Restrictions and Breaking KASLR on Windows 11 24H2 using an HVCI-compatible Driver with Physical Memory Access](https://xacone.github.io/kaslr_leak_24h2.html)
14. [Windows Address Translation Deep Dive Part 1](https://bsodtutorials.wordpress.com/2021/06/14/windows-address-translation-deep-dive-part-1/)
15. [Windows Address Translation Deep Dive Part 2](https://bsodtutorials.wordpress.com/2024/04/05/windows-address-translation-deep-dive-part-2/)
16. [Windows Address Translation Deep Dive Part 3](https://bsodtutorials.wordpress.com/2024/05/14/windows-address-translation-deep-dive-part-3/)
17. [Windows Memory Introspection with IceBox](https://blog.thalium.re/posts/windows-full-memory-introspection-with-icebox/)
18. [Windows Virtual Address Translation and the Pagefile.](https://web.archive.org/web/20200120124724/http://blog.rekall-forensic.com/2014/10/windows-virtual-address-translation-and.html)
19. [Windows 10 KVAS and Software SMEP](https://wumb0.in/windows-10-kvas-and-software-smep.html)
20. [MMPTE_HARDWARE](https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/mi/mmpte/hardware.htm)
21. [Virtual Memory, Page Tables, and One Bit - CVE-2016-7255](https://ricklarabee.blogspot.com/2017/01/virtual-memory-page-tables-and-one-bit.html)
22. [Windows 10 HALs Heap Extinction of the "HalpInterruptController" Table Exploitation Technique](https://labs.bluefrostsecurity.de/blog/2017/05/11/windows-10-hals-heap-extinction-of-the-halpinterruptcontroller-table-exploitation-technique/)
23. [Meltdown Reloaded: Breaking Windows KASLR by Leaking KVA Shadow Mappings](https://labs.bluefrostsecurity.de/blog/2020/06/30/meltdown-reloaded-breaking-windows-kaslr/)
24. [Turning the Pages: Introduction to Memory Paging on Windows 10 x64](https://connormcgarr.github.io/paging/)
25. [Exploit Development: Leveraging Page Table Entries for Windows Kernel Exploitation](https://connormcgarr.github.io/pte-overwrites/)
26. [Page Table: From Virtual to Physical](https://dx9.uk/posts/physical-memory/)
27. [Direct Page Manipulation (DPM)](https://github.com/SamuelTulach/DirectPageManipulation)
28. [anyvtop](https://github.com/kkent030315/anyvtop)
29. [PageTableInjection](https://github.com/kkent030315/PageTableInjection)
30. [PTView](https://github.com/VollRagm/PTView)
31. [PTM - Page Table Manipulation From Usermode](https://blog.back.engineering/01/12/2020/)
32. [Making something out of Zeros: Alternative primitive for Windows Kernel Exploitation](https://www.coresecurity.com/core-labs/articles/making-something-out-zeros-alternative-primitive-windows-kernel-exploitation)
33. [pagewalkr](https://github.com/Deputation/pagewalkr)
34. [Paging](https://shhoya.github.io/hv_paging.html)
35. [Demystifying Physical Memory Primitive Exploitation on Windows](https://0dr3f.github.io/Demystifying_Physical_Memory_Primitive_Exploitation_on_Windows)
36. [Intel® 64 and IA-32 Architectures Software Developer Manuals](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html)
+2 -2
View File
@@ -8,7 +8,7 @@
//
// Modifications:
// 2024-10-08 Created
// 2025-06-03 Updated
// 2025-06-15 Updated
// ========================================================================
// ========================================================================
@@ -23,7 +23,7 @@
#pragma region GLOBALS
EXT_API_VERSION ApiVersion = { 10, 5, EXT_API_VERSION_NUMBER64, 0 };
EXT_API_VERSION ApiVersion = { 10, 6, EXT_API_VERSION_NUMBER64, 0 };
WINDBG_EXTENSION_APIS ExtensionApis;
DWORD SavedMajorVersion;
DWORD SavedMinorVersion;
+2 -1
View File
@@ -8,7 +8,7 @@
//
// Modifications:
// 2025-05-14 Created
// 2025-06-03 Updated
// 2025-06-15 Updated
// ========================================================================
// ========================================================================
@@ -47,6 +47,7 @@ VOID __stdcall help(
" get_pml4_autoentry_index - Find the self-reference entry/auto-entry index of the Page Map Level 4 (PML4) table from the CR3\n"
" get_pxe_base - Compute the starting KVA of the paging structure entry (PxE) range from the PML4 table auto-entry index\n"
" get_pxe_address - Compute the KVA of the paging structure entry (PxE) that maps the specified VA from the PML4 table auto-entry index\n"
" get_physical_address - Translate the specified linear address (VA) to its mapped physical address (PA) and determine the VA's access rights from the CR3\n"
);
}
+325 -1
View File
@@ -10,7 +10,7 @@
//
// Modifications:
// 2025-05-20 Created
// 2025-06-03 Updated
// 2025-06-14 Updated
// ========================================================================
// ========================================================================
@@ -361,4 +361,328 @@ cleanup:
return;
}
_Use_decl_annotations_
VOID __stdcall get_physical_address(
HANDLE hCurrentProcess,
HANDLE hCurrentThread,
QWORD qwCurrentPc,
DWORD dwProcessor,
PCSTR strArgs
) {
// Init local variables
BOOLEAN bTranslation = FALSE;
VIRTUAL_ADDRESS virtualAddress; ZERO_MEMORY(&virtualAddress, sizeof(VIRTUAL_ADDRESS));
QWORD qwCR3 = 0;
QWORD qwPML4BasePa = 0;
QWORD qwPML4Index = 0;
QWORD qwPML4EPa = 0;
PML4E pml4e; ZERO_MEMORY(&pml4e, sizeof(PML4E));
DWORD dwBytesRead = 0;
QWORD qwPDPTBasePa = 0;
QWORD qwPDPTIndex = 0;
QWORD qwPDPTEPa = 0;
PDPTE pdpte; ZERO_MEMORY(&pdpte, sizeof(PDPTE));
QWORD qwPhysicalPageBasePa = 0;
QWORD qwPhysicalPageOffset = 0;
QWORD qwPhysicalAddress = 0;
BOOLEAN bReadableWritablePage = FALSE;
BOOLEAN bUserModePage = FALSE;
BOOLEAN bNonExecutablePage = FALSE;
BOOLEAN bDirtyPage = FALSE;
BOOLEAN bGlobalPage = FALSE;
QWORD qwPDBasePa = 0;
QWORD qwPDIndex = 0;
QWORD qwPDEPa = 0;
PDE pde; ZERO_MEMORY(&pde, sizeof(PDE));
QWORD qwPTBasePa = 0;
QWORD qwPTIndex = 0;
QWORD qwPTEPa = 0;
PTE pte; ZERO_MEMORY(&pte, sizeof(PTE));
// Determine if the target uses 64-bit pointers
if (!IsPtr64()) {
dprintf("[-] IA-32 target is not supported by this extension!\n");
goto cleanup;
}
// Check if paging mode == 4-level IA-32e
// Add a check for HLAT paging (IA32_VMX_PROCBASED_CTLS3[1] - Enable HLAT)
if (!check_4_level_paging_mode(hCurrentProcess, hCurrentThread, qwCurrentPc, dwProcessor, strArgs)) {
goto cleanup;
}
// Convert string representation of the VA to an integer
// In 4-level IA-32e paging mode, linear address width == 48
if (!StrToInt64ExA(strArgs, STIF_SUPPORT_HEX, (LONGLONG*)&virtualAddress.Value)) {
dprintf("[-] Invalid args!\n");
goto cleanup;
}
dprintf("[*] VA=0x%I64X\n", virtualAddress.Value);
// Convert string representation of the CR3 value to an integer
if (!StrToInt64ExA(StrStrA(strArgs, " "), STIF_SUPPORT_HEX, (LONGLONG*)&qwCR3)) {
dprintf("[-] Invalid args!\n");
goto cleanup;
}
dprintf("[*] CR3=0x%I64X\n", qwCR3);
// Every paging structure is 4096 bytes in size and comprises a number of individual entries
// In 4-level IA-32e paging mode, sizeof(paging structure entry) == 64 bits (8 bytes)
// In 4-level IA-32e paging mode, number of paging structure entries in each table == 512 (4096 / 8)
// Every valid paging structure entry contains a PFN (PA >> PAGE_SHIFT) which can be used to either reference another paging structure entry or to map a page
// CR3 contains the physical address of the first paging structure that the processor will use for linear address translation
// In 4-level IA-32e paging mode, the first paging structure is the Page Map Level 4 (PML4) table
// In 4-level IA-32e paging mode, physical address width == MAXPHYADDR (given by CPUID.80000008H:EAX[7:0], MAXPHYADDR is at most 52)
// In Windows x64, MAXPHYADDR == 48
// CR3[MAXPHYADDR1:12] == Physical address of the 4-KByte aligned PML4 table used for linear-address translation
qwPML4BasePa = PFN_TO_PAGE(extract_bits(qwCR3, 12, 36), PAGE_SIZE_4KB);
dprintf("[+] PML4 table base PA=0x%I64X\n", qwPML4BasePa);
// Get the PML4 index from the VA
// A PML4E is identified using a PML4 index == VA[47:39] (9 bits)
qwPML4Index = virtualAddress.PML4Index;
dprintf("[+] PML4 index: 0x%X (0n%d)\n", qwPML4Index, qwPML4Index);
// Compute PML4E PA for the given VA
qwPML4EPa = qwPML4BasePa + (qwPML4Index * sizeof(PML4E));
dprintf("[+] PML4E PA=0x%I64X\n", qwPML4EPa);
// Read the selected PML4E for the given VA
// Each PML4E controls access to a 512 GB region of the linear-address space
ReadPhysical(qwPML4EPa, &pml4e.Value, sizeof(PML4E), &dwBytesRead);
if (dwBytesRead != sizeof(PML4E)) {
dprintf("[-] Error reading physical memory!\n");
goto cleanup;
}
dprintf("[+] PML4E contents=0x%I64X\n", pml4e.Value);
// Check for invalid PML4E (an entry that is used neither to reference another paging structure nor to map a page)
// There is no translation for a linear address whose translation would use such a paging structure entry
// Any access to such a VA would cause a Page Fault exception (#PF)
// In Windows x64, such a PxE is then interpreted by the Memory Manager as a software PTE of which there are various types
if (pml4e.P == 0 || pml4e.PS == 1 || pml4e.Reserved1 != 0) {
dprintf("[-] Invalid PML4E!\n");
goto cleanup;
}
// In 4-level IA-32e paging mode, the second paging structure is the Page Directory Pointer Table (PDPT)
// PML4E[MAXPHYADDR1:12] == Physical address of 4-KByte aligned PDPT referenced by this entry
qwPDPTBasePa = PFN_TO_PAGE(pml4e.PFN, PAGE_SIZE_4KB);
dprintf("[+] PDPT base PA=0x%I64X\n", qwPDPTBasePa);
// Get the PDPT index from the VA
// A PDPTE is identified using a PDPT index == VA[38:30] (9 bits)
qwPDPTIndex = virtualAddress.PDPTIndex;
dprintf("[+] PDPT index: 0x%X (0n%d)\n", qwPDPTIndex, qwPDPTIndex);
// Compute PDPTE PA for the given VA
qwPDPTEPa = qwPDPTBasePa + (qwPDPTIndex * sizeof(PDPTE));
dprintf("[+] PDPTE PA=0x%I64X\n", qwPDPTEPa);
// Read the selected PDPTE for the given VA
// Each PDPTE controls access to a 1 GB region of the linear-address space
ReadPhysical(qwPDPTEPa, &pdpte.Value, sizeof(PDPTE), &dwBytesRead);
if (dwBytesRead != sizeof(PDPTE)) {
dprintf("[-] Error reading physical memory!\n");
goto cleanup;
}
dprintf("[+] PDPTE contents=0x%I64X\n", pdpte.Value);
// Check for invalid PDPTE (an entry that is used neither to reference another paging structure nor to map a page)
if (pdpte.P == 0 || pdpte.Reserved2 != 0) {
dprintf("[-] Invalid PDPTE!\n");
goto cleanup;
}
// Check Page Size (PS) bit of PDPTE
if (pdpte.PS == 1 && pdpte.Reserved1 == 0) {
// PDPTE maps a 1 GB page
// PDPTE[MAXPHYADDR1:30] == Physical address of the 1-GByte page referenced by this entry
qwPhysicalPageBasePa = PFN_TO_PAGE(pdpte.PFN1, PAGE_SIZE_1GB);
dprintf("[+] 1 GB physical page base PA=0x%I64X\n", qwPhysicalPageBasePa);
// Get the physical page offset from the VA
// 1 GB physical page offset == VA[29:0] (30 bits)
qwPhysicalPageOffset = virtualAddress.Offset1GB;
dprintf("[+] 1 GB physical page offset: 0x%X (0n%d)\n", qwPhysicalPageOffset, qwPhysicalPageOffset);
// Data may be written to any linear address (subject to CPL, WP, and SMAP) with a translation for which the R/W flag (bit 1) is 1 in every paging structure entry controlling the translation
bReadableWritablePage = ((pml4e.RW) && (pdpte.RW));
// If the U/S flag (bit 2) is 0 in at least one of the paging structure entries controlling the translation of the linear address, the address is a supervisor-mode address
// Otherwise, the address is a user-mode address
bUserModePage = ((pml4e.US) && (pdpte.US));
// Instructions may be fetched from any linear address (subject to CPL, NXE, and SMEP) with a translation for which the XD flag (bit 63) is 0 in every paging structure entry controlling the translation
bNonExecutablePage = ((pml4e.XD) || (pdpte.XD));
// Whenever there is a write to a linear address, the processor sets the Dirty flag (bit 6) if it is not already set in the paging structure entry that maps the page
bDirtyPage = pdpte.D;
// If the Global flag (bit 8) is 1 in the paging structure entry that maps the page, any TLB entry cached for the linear address using that paging structure entry is considered to be global (subject to PGE)
bGlobalPage = pdpte.G;
bTranslation = TRUE;
goto cleanup;
}
// In 4-level IA-32e paging mode, the third paging structure is the Page Directory (PD) table
// PDPTE[MAXPHYADDR1:12] == Physical address of 4-KByte aligned PD table referenced by this entry
qwPDBasePa = PFN_TO_PAGE(pdpte.PFN2, PAGE_SIZE_4KB);
dprintf("[+] PD table base PA=0x%I64X\n", qwPDBasePa);
// Get the PD index from the VA
// A PDE is identified using a PD index == VA[29:21] (9 bits)
qwPDIndex = virtualAddress.PDIndex;
dprintf("[+] PD index: 0x%X (0n%d)\n", qwPDIndex, qwPDIndex);
// Compute PDE PA for the given VA
qwPDEPa = qwPDBasePa + (qwPDIndex * sizeof(PDE));
dprintf("[+] PDE PA=0x%I64X\n", qwPDEPa);
// Read the selected PDE for the given VA
// Each PDE controls access to a 2 MB region of the linear-address space
ReadPhysical(qwPDEPa, &pde.Value, sizeof(PDE), &dwBytesRead);
if (dwBytesRead != sizeof(PDE)) {
dprintf("[-] Error reading physical memory!\n");
goto cleanup;
}
dprintf("[+] PDE contents=0x%I64X\n", pde.Value);
// Check for invalid PDE (an entry that is used neither to reference another paging structure nor to map a page)
if (pde.P == 0 || pde.Reserved2 != 0) {
dprintf("[-] Invalid PDE!\n");
goto cleanup;
}
// Check Page Size (PS) bit of PDE
if (pde.PS == 1 && pde.Reserved1 == 0) {
// PDE maps a 2 MB page
// PDE[MAXPHYADDR1:21] == Physical address of the 2-MByte page referenced by this entry
qwPhysicalPageBasePa = PFN_TO_PAGE(pde.PFN1, PAGE_SIZE_2MB);
dprintf("[+] 2 MB physical page base PA=0x%I64X\n", qwPhysicalPageBasePa);
// Get the physical page offset from the VA
// 2 MB physical page offset == VA[20:0] (21 bits)
qwPhysicalPageOffset = virtualAddress.Offset2MB;
dprintf("[+] 2 MB physical page offset: 0x%X (0n%d)\n", qwPhysicalPageOffset, qwPhysicalPageOffset);
// Data may be written to any linear address (subject to CPL, WP, and SMAP) with a translation for which the R/W flag (bit 1) is 1 in every paging structure entry controlling the translation
bReadableWritablePage = ((pml4e.RW) && (pdpte.RW) && (pde.RW));
// If the U/S flag (bit 2) is 0 in at least one of the paging structure entries controlling the translation of the linear address, the address is a supervisor-mode address
// Otherwise, the address is a user-mode address
bUserModePage = ((pml4e.US) && (pdpte.US) && (pde.US));
// Instructions may be fetched from any linear address (subject to CPL, NXE, and SMEP) with a translation for which the XD flag (bit 63) is 0 in every paging structure entry controlling the translation
bNonExecutablePage = ((pml4e.XD) || (pdpte.XD) || (pde.XD));
// Whenever there is a write to a linear address, the processor sets the Dirty flag (bit 6) if it is not already set in the paging structure entry that maps the page
bDirtyPage = pde.D;
// If the Global flag (bit 8) is 1 in the paging structure entry that maps the page, any TLB entry cached for the linear address using that paging structure entry is considered to be global (subject to PGE)
bGlobalPage = pde.G;
bTranslation = TRUE;
goto cleanup;
}
// In 4-level IA-32e paging mode, the fourth paging structure is the Page Table (PT)
// PDE[MAXPHYADDR1:12] == Physical address of 4-KByte aligned PT referenced by this entry
qwPTBasePa = PFN_TO_PAGE(pde.PFN2, PAGE_SIZE_4KB);
dprintf("[+] PT base PA=0x%I64X\n", qwPTBasePa);
// Get the PT index from the VA
// A PTE is identified using a PT index == VA[20:12] (9 bits)
qwPTIndex = virtualAddress.PTIndex;
dprintf("[+] PT index: 0x%X (0n%d)\n", qwPTIndex, qwPTIndex);
// Compute PTE PA for the given VA
qwPTEPa = qwPTBasePa + (qwPTIndex * sizeof(PTE));
dprintf("[+] PTE PA=0x%I64X\n", qwPTEPa);
// Read the selected PTE for the given VA
// Each PTE controls access to a 4 KB region of the linear-address space
ReadPhysical(qwPTEPa, &pte.Value, sizeof(PTE), &dwBytesRead);
if (dwBytesRead != sizeof(PTE)) {
dprintf("[-] Error reading physical memory!\n");
goto cleanup;
}
dprintf("[+] PTE contents=0x%I64X\n", pte.Value);
// Check for invalid PTE (an entry that is used neither to reference another paging structure nor to map a page)
if (pte.P == 0 || pte.Reserved1 != 0) {
dprintf("[-] Invalid PTE!\n");
goto cleanup;
}
// PTE maps a 4 KB page
// PTE[MAXPHYADDR1:12] == Physical address of the 4-KByte page referenced by this entry
qwPhysicalPageBasePa = PFN_TO_PAGE(pte.PFN, PAGE_SIZE_4KB);
dprintf("[+] 4 KB physical page base PA=0x%I64X\n", qwPhysicalPageBasePa);
// Get the physical page offset from the VA
// 4 KB physical page offset == VA[11:0] (12 bits)
qwPhysicalPageOffset = virtualAddress.Offset4KB;
dprintf("[+] 4 KB physical page offset: 0x%X (0n%d)\n", qwPhysicalPageOffset, qwPhysicalPageOffset);
// Data may be written to any linear address (subject to CPL, WP, and SMAP) with a translation for which the R/W flag (bit 1) is 1 in every paging structure entry controlling the translation
bReadableWritablePage = ((pml4e.RW) && (pdpte.RW) && (pde.RW) && (pte.RW));
// If the U/S flag (bit 2) is 0 in at least one of the paging structure entries controlling the translation of the linear address, the address is a supervisor-mode address
// Otherwise, the address is a user-mode address
bUserModePage = ((pml4e.US) && (pdpte.US) && (pde.US) && (pte.US));
// Instructions may be fetched from any linear address (subject to CPL, NXE, and SMEP) with a translation for which the XD flag (bit 63) is 0 in every paging structure entry controlling the translation
bNonExecutablePage = ((pml4e.XD) || (pdpte.XD) || (pde.XD) || (pte.XD));
// Whenever there is a write to a linear address, the processor sets the Dirty flag (bit 6) if it is not already set in the paging structure entry that maps the page
bDirtyPage = pte.D;
// If the Global flag (bit 8) is 1 in the paging structure entry that maps the page, any TLB entry cached for the linear address using that paging structure entry is considered to be global (subject to PGE)
bGlobalPage = pte.G;
bTranslation = TRUE;
// Cleanup
cleanup:
if (bTranslation) {
// Get mapped physical address (PA)
qwPhysicalAddress = qwPhysicalPageBasePa + qwPhysicalPageOffset;
dprintf("[+] PA=0x%I64X\n", qwPhysicalAddress);
// Display the access rights for the linear address
// Data reads, data writes, and instruction fetches to/from the linear address depend on the access rights specified by the paging structure entries controlling the translation
if (bReadableWritablePage) {
dprintf("[+] Writable address.\n");
}
else {
dprintf("[+] Read-only address.\n");
}
if (bUserModePage) {
dprintf("[+] User-mode address.\n");
}
else {
dprintf("[+] Supervisor-mode address.\n");
}
if (bNonExecutablePage) {
dprintf("[+] Non-executable address.\n");
}
else {
dprintf("[+] Executable address.\n");
}
dprintf("[+] Dirty: %d\n", bDirtyPage);
dprintf("[+] Global: %d\n", bGlobalPage);
}
return;
}
#pragma endregion