A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #19761  by myid
 Mon Jun 24, 2013 11:37 am
Hi, everyone.

I know the virtual address of a process and I know the DirBase(EPROCESS.DirectoryTableBase) of process.

How to calculate PML4E/PDPE/PDE/PTE/Physical Address (like the !vtop command in WINDBG)?

Thanks.
 #19771  by Vrtule
 Mon Jun 24, 2013 5:37 pm
Hello,

you can try to parse process page tables. Look into the Intel manuals in order to determine the structure of the page table entries (page directory entries, page directory pointer table entries or page map level 4 entries). However, you still require either to perform physical to virtual address translation (AFAIK the entries contain physical addresses not virtual) or to read physical memory "directly".

The structure and number of levels of process page tables also depends on processor settings, os the thing might be a little bit more complicated when your code is required to work on various platforms supported by Windows.
 #19775  by myid
 Mon Jun 24, 2013 6:55 pm
Vrtule wrote:Hello,

you can try to parse process page tables. Look into the Intel manuals in order to determine the structure of the page table entries (page directory entries, page directory pointer table entries or page map level 4 entries). However, you still require either to perform physical to virtual address translation (AFAIK the entries contain physical addresses not virtual) or to read physical memory "directly".

The structure and number of levels of process page tables also depends on processor settings, os the thing might be a little bit more complicated when your code is required to work on various platforms supported by Windows.
I see, I will try to do it. :D
 #19796  by feryno
 Tue Jun 25, 2013 9:05 am
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 all
mov 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
 #19806  by myid
 Tue Jun 25, 2013 6:18 pm
feryno wrote: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 all
mov 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
Thank for your reply.