!pte (display page-level address and entries)
Description of '!pte' command in HyperDbg.

Command

!pte

Syntax

!pte [Virtual Address]

Description

Displays the PML4E, PDPTE, PDE, PTE for the specified address.

Parameters

[Virtual Address]
The virtual address of where we want to read its page-level entries.

Examples

The following command shows the page-level entries nt!ExAllocatePoolWithTag.
1
HyperDbg> !pte nt!ExAllocatePoolWithTag
2
VA fffff801639b1030
3
PML4E (PXE) at ffffeaf57abd5f80 contains 0000000005109063
4
PDPT (PPE) at ffffeaf57abf0028 contains 000000000510a063
5
PDE at ffffeaf57e0058e0 contains 0a000000034000a1
6
PDE is a large page, so it doesn't have a PTE
Copied!
The following command shows the page-level entries nt!ExAllocatePoolWithTag+5.
1
HyperDbg> !pte nt!ExAllocatePoolWithTag+5
2
VA fffff801639b1035
3
PML4E (PXE) at ffffeaf57abd5f80 contains 0000000005109063
4
PDPT (PPE) at ffffeaf57abf0028 contains 000000000510a063
5
PDE at ffffeaf57e0058e0 contains 0a000000034000a1
6
PDE is a large page, so it doesn't have a PTE
Copied!
The following command shows the page-level entries fffff80040f00c28.
1
HyperDbg> !pte fffff80040f00c28
2
VA fffff80040f00c28
3
PML4E (PXE) at ffff83c1e0f07f80 contains 0000000004108063
4
PDPT (PPE) at ffff83c1e0ff0008 contains 000000000411c063
5
PDE at ffff83c1fe001038 contains 0000000004124063
6
PTE at ffff83fc00207800 contains 8900000006470863
Copied!
The following command shows the page-level entries fffff8003ad6f010. Note that some entries might have a large PDE and no PTE.
1
HyperDbg> !pte fffff8003ad6f010
2
VA fffff8003ad6f010
3
PML4E (PXE) at ffff83c1e0f07f80 contains 0000000004108063
4
PDPT (PPE) at ffff83c1e0ff0000 contains 0000000004109063
5
PDE at ffff83c1fe000eb0 contains 00000000028008e3
6
PDE is a large page, so it doesn't have a PTE
Copied!

IOCTL

This function works by calling DeviceIoControl with IOCTL = IOCTL_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS, you have to send it in the following structure.
1
typedef struct _DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS {
2
3
UINT64 VirtualAddress;
4
5
UINT64 Pml4eVirtualAddress;
6
UINT64 Pml4eValue;
7
8
UINT64 PdpteVirtualAddress;
9
UINT64 PdpteValue;
10
11
UINT64 PdeVirtualAddress;
12
UINT64 PdeValue;
13
14
UINT64 PteVirtualAddress;
15
UINT64 PteValue;
16
17
} DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS,
18
*PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS;
Copied!
You should only fill the VirtualAddress of the above structure when the IOCTL returns from the kernel. Other parts of this structure are filled with valid entry virtual addresses and the entry value itself.
You can map the value to each entry's structure (Look at Intel SDM for more information).
Also, the structures are available in MemoryMapper.h but they might be outdated.

Remarks

If the VirtualAddress and Value of entry for PDE and PTE from the kernel IOCTL are the same, the entry has a LARGE PDE and doesn't have PTE.
This command will continue the debuggee for some time (in Debugger Mode). This means that you lose the current context (registers & memory) after executing this command.

Requirements

None
None
Last modified 1d ago