Probably you may try an approach like this. You want to walk through paging tables. OS maps all necessary physical addresses of paging tables at these virtual addresses (to easily access/modify paging tables).
#define PXE_BASE 0xFFFFF6FB7DBED000UI64
#define PXE_SELFMAP 0xFFFFF6FB7DBEDF68UI64
#define PPE_BASE 0xFFFFF6FB7DA00000UI64
#define PDE_BASE 0xFFFFF6FB40000000UI64
#define PTE_BASE 0xFFFFF68000000000UI64
You have virtual address VA stored somewhere in the buffer.
Code: Select allmov rdx,[your_stored_VA]
; canonical address ?
mov rax,rdx
sar rax,47
inc rax
cmp rax,1
jnbe error ; noncanonical address
; process first level of paging tables
mov rcx,0xFFFFF6FB7DBED000 ; PML4 is mapped here
mov rax,rdx
shr rax,39
and eax,0x1FF
mov rax,[rcx+rax*8] ; get PML4E
test al,1
jz error ; page not present (P bit = 0), CPU will generate #PF at any attempt to touch the VA
; now if you want PA of next level of paging tables it is in bits 47-12 of RAX, but you can't access directly that PA, luckily the next level of paging tables is mapped at certain VA
; process second level of paging tables
mov rcx,0xFFFFF6FB7DA00000
mov rax,rdx
shr rax,30
and eax,0x3FFFF
mov rax,[rcx+rax*8] ; get PDPE
test al,1
jz error ; CPU will generate #PF
test al,0x80 ; 1 GB paging, probably not used by ms win yet, also CPUID must report that CPU is 1GB paging capable...
jnz OK ; VA translation is valid, paging tables walk completed successfully
; process third level of paging tables
mov rcx, 0xFFFFF6FB40000000
mov rax,rdx
shr rax,21
and eax,7FFFFFFh
mov rax,[rcx+rax*8] ; get PDE
test al,1
jz error
test al,0x80 ; 2 MB paging, PDE.PS bit
jnz OK ; VA translation is valid, paging tables walk completed successfully
; process fourth level of paging tables, the last one
mov rcx,0xFFFFF68000000000
mov rax,rdx
shr rax,12
mov r8,0xFFFFFFFFF
and r8,rax
mov rax,[rcx+r8*8] ; get PTE
test al,1
jz error
OK:
; if you go here page tables walk was finished successfully
; now if you want PA of page where last level of paging tables is pointing it is in bits 47-12 of RAX, but remeber you can't access it directly
mov r8,0x000FFFFFFFFFF000
and rax,r8
; rax = final PA
; the offset in the PA to construct the final address is in bits 11-0 of rdx for 4kB 4-level paging, in bits 20-0 of rdx for 2MB 3-level paging, 29-0 of rdx for 1GB 2-level paging
remember that the above code works only for current process
for an alien process you have to extract PA from every level of paging tables and map every PA (MmMapIoSpace) to be able to access it