Saturday, 26 January 2013

Primer on !vtop, !pte and Virtual Address to Physical Page mapping in x64


Intro

The best reference I could find on the topic was the post from the MSDN NtDebugging blog, Series - Part 3: Understanding !PTE - Non-PAE and X64 article http://blogs.msdn.com/b/ntdebugging/archive/2010/06/22/part-3-understanding-pte-non-pae-and-x64.aspx.

It helped but I needed to really delve into the mapping mechanisms with an example, as well as call out some of the pitfalls in using the relevant WinDbg commands.

Setup

Taking a look at a instance of notepad as example running on a Windows 7 x64 system (this was performed in WinDbg, using sysinterals livekd)

0: kd> !dml_proc 0xfffffa800c0cd890
Address           PID  Image file name
fffffa80`0c0cd890 bbc  notepad.exe       Full details

Switching to process

0: kd> .process /p /r 0xfffffa800c0cd890
Implicit process is now fffffa80`0c0cd890
Loading User Symbols
.........................

Display loaded modules

0: kd> lmuD
start     
<snip>
00000000`ff460000 00000000`ff495000   notepad    (deferred)
<snip>
  
And let's take a look (using the virtual address), MZ header has we'd expect.

0: kd> db 00000000`ff460000 L100
00000000`ff460000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............
00000000`ff460010  b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
00000000`ff460020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
00000000`ff460030  00 00 00 00 00 00 00 00-00 00 00 00 e8 00 00 00  ................
00000000`ff460040  0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68  ........!..L.!Th
00000000`ff460050  69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f  is program canno
00000000`ff460060  74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20  t be run in DOS
00000000`ff460070  6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00  mode....$.......

(I did do a quick compare with the rest of the image to be sure this was notepad and not just some random MZ header)
  
In order to convert this to the physical address, WinDbg provides two commands to help

!pte
!vtop

Both of these commands walk the below diagram (from the Intel 64 and IA-32 Architecture software development manual volume 3)

!vtop

 !vtop performs the conversion between the virtual address to the corresponding physical address, quite seamlessly  however there's a few minor pitfalls. 

There's two principle formats

!vtop PFN VA 
!vtop 0 VA

PFN - Page Frame Number
VA - Virtual Address

Where 0 is current process context as  set by the .process command (above)
 0: kd> !vtop 0 00000000ff460000
Amd64VtoP: Virt 00000000`ff460000, pagedir 1bf52000
Amd64VtoP: PML4E 1bf52000
Amd64VtoP: PDPE 2`21b80018
Amd64VtoP: PDE 3a001fd0
Amd64VtoP: PTE 17402300
Amd64VtoP: Mapped phys 25051000
Virtual address ff460000 translates to physical address 25051000.

Had we not applied the .process command earlier, our !vtop 0 VA would not have worked :( )  You would get a output like
 0: kd> !vtop 0 00000000ff460000
Amd64VtoP: Virt 00000000`ff460000, pagedir ce985000
Amd64VtoP: PML4E ce985000
Amd64VtoP: PDPE 21bf6018
Amd64VtoP: zero PDPE
Virtual address ff460000 translation fails, error 0xD000014

Alternatively we could have specified the PFN (Page Frame Number) directly. Now you might think (well I did at first) that the pfns from the !pte output should be used. Well actually no, you need the pfn from the DirBase and unlike in 32 bit mode, the pfn is the entire address. 

0: kd> !process 0xfffffa800c0cd890 7
PROCESS fffffa800c0cd890
    SessionId: 1  Cid: 0bbc    Peb: 7fffffdd000  ParentCid: 0484
    DirBase: 1bf52000  ObjectTable: fffff8a00d50a560  HandleCount:  58.
    Image: notepad.exe
    VadRoot fffffa800dcd4870 Vads 58 Clone 0 Private 548. Modified 0. Locked 0.
    DeviceMap fffff8a003ffc4e0

Thus the pfn is 1bf52000 

 0: kd> !vtop 1bf52000  00000000ff460000
Amd64VtoP: Virt 00000000`ff460000, pagedir 1bf52000
Amd64VtoP: PML4E 1bf52000
Amd64VtoP: PDPE 2`21b80018
Amd64VtoP: PDE 3a001fd0
Amd64VtoP: PTE 17402300
Amd64VtoP: Mapped phys 25051000
Virtual address ff460000 translates to physical address 25051000.

So let's take a a look at 0x25051000 physical address (notice the # to indicate physical addresses) Here we use !d* to examine a physical address as opposed d* for a virtual address

0: kd> !db 25051000 L100
#25051000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ..............
#25051010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@.......
#25051020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#25051030 00 00 00 00 00 00 00 00-00 00 00 00 e8 00 00 00 ................
#25051040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th
#25051050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno
#25051060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS
#25051070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......
   

!pte


0: kd> !pte 00000000`ff460000
                                           VA 00000000ff460000
PXE at FFFFF6FB7DBED000    PPE at FFFFF6FB7DA00018    PDE at FFFFF6FB40003FD0    PTE at FFFFF680007FA300
contains 02A0000221B80867  contains 1C1000003A001867  contains 03A0000017402867  contains 82D0000025051025
pfn 221b80    ---DA--UWEV  pfn 3a001     ---DA--UWEV  pfn 17402     ---DA--UWEV  pfn 25051     ----A--UR-V

What does this all mean?

Well the pte entry at address FFFFF680007FA300 contains the PAE Page-Table Entry containing 82D0000025051025, of which the physical address is bits 12 to (M–1) or more precisely 0x25051000

And of course this gives the same result

0: kd> !db 25051000 L100
#25051000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ..............
#25051010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@.......
#25051020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#25051030 00 00 00 00 00 00 00 00-00 00 00 00 e8 00 00 00 ................
#25051040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th
#25051050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno
#25051060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS
#25051070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......


Hope this helps your WinDbg en devours. 

No comments:

Post a Comment