Search This Blog

Thursday, February 23, 2012

Address Translation Walk-through (Virtual to Physical)

Just recently I had a chance to read part of Windows Internals again and chat with my co-worker on the topic of Memory Management and then he showed me how to walk page tables to translate virtual address to physical address so let me share that experience here.

For this exercise, we will use the virtual address of Nt!NtCreateFile as an example and we will convert that address to physical address and compare what's there.
In this example, we use 32-bit windows PAE mode and we can check if windows is in PAE mode in several ways and one easy way to find out if we are running on PAE kernel is to look up where PDE is loaded. If you see that PDE is loaded at 0xC0600000, it is PAE kernel. Please refer to Free System Page Table Entries blog post for more info on it.

PAE mode has the following three level page tables so we need to keep this in mind as we translate.
  • Page Directory Pointer Table 
  • Page Directory 
  • Page Table
In addition, in PAE mode each entry is 8 byte size so we need to multiply the index value by eight. If it were non-PAE 32bit mode, we had only two levels and each entry is 4 byte long. With PAE mode on, we can address more memory because each PDE and PTE is 64-bit wide. Internally 32-bit system represents physical addresses with 24 bits so with PAE mode on we can fully maximize PFNs upto 2^24 and thus, it can support upto 64GB(2^24+12)


0. Locate virtual address of NtCreateFile
kd> x nt!ntcreatefile

8286f2a2          nt!NtCreateFile = no type information
kd> !pte nt!ntcreatefile
                    VA 8286f2a2
PDE at C06020A0            PTE at C0414378
contains 00000000001D0063  contains 000000000286F121
pfn 1d0       ---DA--KWEV  pfn 286f      -G--A--KREV


1. Find the current process
kd> !process -1 0
PROCESS 85b9fbb0  SessionId: 0  Cid: 03d0    Peb: 7ffd5000  ParentCid: 0238
    DirBase: 7ef5b1a0  ObjectTable: 8a585968  HandleCount: 594.
    Image: svchost.exe


 2. Check cr3 value for the location of PDPT. This should be same as DirBase from #1 result.
kd> r cr3
cr3=7ef5b080


3. Get binary representation of NtCreateFile virtual address
kd> .formats 0x8286f2a2
Evaluate expression:
  Hex:     8286f2a2
  Decimal: -2105085278
  Octal:   20241571242
  Binary:  10000010 10000110 11110010 10100010
  .. skip ...


 Let us split binary values as follows so that we can use them as an index to tables.
10(index to PDPT) 000010100(index to PDE) 001101111(index to PTE) 001010100010(offset)


4. Get to PDPT entry - 0y means it is binary number representation and l1 means only one entry (it is english alphabet 'l' not pipe '|')
kd> dd /p @cr3+0y10*8 l1
7ef5b090  1ad8b801


5. Check what's in the entry - only the first 20 bits are used and the rest are for flags
kd> .formats 1ad8b801
Evaluate expression:
  Hex:     1ad8b801
  Decimal: 450410497
  Octal:   03266134001
  Binary:  00011010 11011000 10111000 00000001
  ... skip ...


6. Get the address of PDE (Not necessary but this is one way to do hex value converting)
kd> ? 0y00011010110110001011
Evaluate expression: 109963 = 0001ad8b


7. Get to PDE for this particular address
kd> dd /p 0x0001ad8b * 0x1000 + 0y10100 * 8 |1
1ad8b0a0  001d0063


8. Get to PTE
kd> dd /p 0x1d0 * 0x1000 + 0y1101111 * 8 |1
001d0378  0286f121


9. Finally get the actual physical address and this time we do not need to multiply by 8
kd> up 0x286f000+0y1010100010
0286f2a2 8bff            mov     edi,edi
0286f2a4 55              push    ebp
0286f2a5 8bec            mov     ebp,esp
0286f2a7 51              push    ecx
0286f2a8 33c0            xor     eax,eax
0286f2aa 50              push    eax
0286f2ab 6a20            push    20h
0286f2ad 50              push    eax


10. Let us compare disassembly from virtual address

kd> uf nt!ntcreatefile
nt!NtCreateFile:
8286f2a2 8bff            mov     edi,edi
8286f2a4 55              push    ebp
8286f2a5 8bec            mov     ebp,esp
8286f2a7 51              push    ecx
8286f2a8 33c0            xor     eax,eax
8286f2aa 50              push    eax
8286f2ab 6a20            push    20h
8286f2ad 50              push    eax
8286f2ae 50              push    eax


They have the same content so we were able to translate the address. Cool!