mirror of
https://github.com/winterknife/EVENSTAR
synced 2026-06-21 14:13:51 +00:00
added new extension command to PagingDbgExt
This commit is contained in:
@@ -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 page’s 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 page’s 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 page’s 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.
@@ -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
@@ -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 HAL’s 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)
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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[MAXPHYADDR–1: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[MAXPHYADDR–1: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[MAXPHYADDR–1: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[MAXPHYADDR–1: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[MAXPHYADDR–1: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[MAXPHYADDR–1: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[MAXPHYADDR–1: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
|
||||
Reference in New Issue
Block a user