转自:http://blog.nandaka.io/paging-virtual-to-physical-address-translation-via-windbg/
PAE/Non-PAE参考:
Paging – Virtual to Physical address translation
Paging in PAE-mode – Virtual to Physical Address Translation
We have covered the address translation for PAE and non-PAE mode in x86 in previous articles. In this article we will see the address translation in action. We will first do it manually and then learn ‘!pte’ command in WinDbg which will dump the PDE and PTE for us without much of effort.
I am using Win7 x86 VM and PAE mode is by default enabled so we will go through the 3 levels of translations.
It is strongly recommended that you go through the previous articles on address translation before continuing further.
Figure below will help you recall how the virtual address is divided in PAE mode.
Here is the memory address translation process in PAE mode:
Image taken from the book, Windows Internals by M Russinovich, D A Solomon, A Ionescu.
Each PTE\PDE entry is 64 bit wide and PFN bits that are used to locate the base of physical page are 24 bits as compared to 20 bits in 32 bit PTE\PDE.
Let’s start with the translation. We know that in PAE mode, CR3 CPU register holds the base address of Page Directory Pointer Table(PDPT). Each process running on Windows has its own Directory Base(DirBase) which stores the physical address of PDPT. CR3 CPU register is loaded with this DirBase whenever a context switch happens for the thread which belong to a process different than the current running thread. You can dump the DirectoryTableBase with the following WinDbg command:
1: kd> !process 0 0 explorer.exe PROCESS 84d59030 SessionId: 1 Cid: 045c Peb: 7ffd5000 ParentCid: 00f0 DirBase: 3ec331a0 ObjectTable: 8ce0eb20 HandleCount: 641. Image: explorer.exe
0: kd> dt nt!_KPROCESS 84d59030 -y dir +0x018 DirectoryTableBase : 0x3ec331a0 |
Let’s dump CR3 register.
0: kd> r cr3 cr3=00185000 |
I just mentioned that DirBase would be same as CR3 register however it is showing different value. The problem is that you are not in context of the process. This is a very common mistake so please make sure you are in the context of the process in WinDbg before you check CR3.
1: kd> .process /i 84d59030 You need to continue execution (press ‘g’ <enter>) for the context to be switched. When the debugger breaks in again, you will be in the new process context.
1: kd> g Break instruction exception – code 80000003 (first chance) nt!RtlpBreakWithStatusInstruction: 8266b394 cc int 3 |
Now we are in the context of the process ‘explorer.exe’. If you dump CR3 CPU register now you will see the DirBase in CR3.
0: kd> r cr3 cr3=3ec331a0 |
Let’s pick a virtual address to do the translation, say process address itself i.e. 84d59030
84d59030 ——> 10 000100110 101011001 000000110000
PDPT Index 10 = 2
PDT Index 000100110 = 38 or 0x26
PT Index 101011001 = 345 or 0x159
Byte Index 000000110000 = 48 or 0x30
CR3 CPU register or DirBase contains the physical address of base of PDPT. There are 4 possible entries in PDPT and virtual address PDPT index is 2. You can dump the physical memory via ‘!d’ WinDbg command as shown below.
Let’s dump the PDPT:
0: kd> !dq 3ec331a0 l4 #3ec331a0 00000000`10df0801 00000000`11271801 #3ec331b0 00000000`10e32801 00000000`11173801
|
Or you can directly dump the index 2 of PDPT as follow:
0: kd> !dq 3ec331a0 + (2*8) l1 #3ec331b0 00000000`10e32801 |
PDPT Entry contains 00000000`10e32801 |
Revisit the format of the PDE\PTE in PAE mode. First 12 bits are for various flags and next 24 bits are for PFN. Highlighted in Green is the PFN part of the PDPT Entry in PAE mode.
PFN of PDT base is 0`10e32 (24 bits in PAE mode). |
Physical address of PDT base is 10e32000 (appended by 12 bits)
First level of table (PDPT) is translated and we have the base of PDT. Let’s move to the PDE of the virtual address 84d59030.
PDT Index from virtual address is decimal 38 or hex 26.
0: kd> ?10e32000+(26*8) Evaluate expression: 283320624 = 10e32130
0: kd> !dq 10e32130 l1 #10e32130 00000000`3fec7863 |
PDE contains 00000000`3fec7863 |
Extract the PFN part:
PFN of base of Page Table(PT) is 3fec7 (24 bit in PAE Mode) |
Physical address of PT base is 03fec7000 (appended by 12 bits)
0: kd> ?03fec7000+(0x159*8) Evaluate expression: 1072462536 = 3fec7ac8
0: kd> !dq 3fec7ac8 l1 #3fec7ac8 00000000`3ef59963 |
PTE contains 00000000`3ef59963 |
PFN of the page where the virtual address resides is 03ef59 |
Base of the page is 03ef59000 (appended by 12 bits)
DWORD referred by the virtual address resides at the hex 30 byte offset:
0: kd> ?03ef59000+30 Evaluate expression: 1056280624 = 3ef59030
0: kd> !dd 3ef59030 l1 #3ef59030 00260003 |
Dump the content of the virtual memory by ‘dd’ command.
0: kd> dd 84d59030 l1 84d59030 00260003 |
Above translation can be easily done via ‘!pte’ WinDbg command as shown below.
0: kd> !pte 84d59030 VA 84d59030 PDE at C0602130 PTE at C0426AC8 contains 000000003FEC7863 contains 000000003EF59963 pfn 3fec7 —DA–KWEV pfn 3ef59 -G-DA–KWEV |
Or
Debugger does not show the PDPT in the output of ‘!pte’ Command but I have dumped it manually during the translation. Flags corresponds to the PDE\PTE flags mentioned above. Physical page where the virtual address points to is given by the PFN of PTE as shown above
In x64, it is no different except, additional levels of translation. Here is 64 bit PDE\PTE entry and translation process:
Image taken from the book, Windows Internals by M Russinovich, D A Solomon, A Ionescu.
PROCESS ffffe000ac169080 SessionId: 1 Cid: 0228 Peb: f7a9cd5000 ParentCid: 01d4 DirBase: 2ecbd000 ObjectTable: ffffc00134a5b7c0 HandleCount: <Data Not Accessible> Image: winlogon.exe
0: kd> r cr3 cr3=000000002ecbd000
Note: Make sure you are in the context of the process |
Here is the output of ‘!pte’ command for 64 bit OS. I have taken the process address for translation. The offset in page is 80 highlighted in green.
0: kd> !pte ffffe000ac169080 VA ffffe000ac169080 PXE at FFFFF6FB7DBEDE00 PPE at FFFFF6FB7DBC0010 PDE at FFFFF6FB78002B00 PTE at FFFFF6F000560B48 contains 0000000000532863 contains 0000000000331863 contains 0000000034BD9863 contains 8000000030342963 pfn 532 —DA–KWEV pfn 331 —DA–KWEV pfn 34bd9 —DA–KWEV pfn 30342 -G-DA–KW-V
|
Or
The base address of the physical page is 30342000 and offset in 4K page is 080. Let’s first get the content via virtual address ffffe000ac169080.
0: kd> dq ffffe000ac169080 l1 ffffe000`ac169080 00000000`00b60003 |
Let’s do it via physical address obtained from PTE above and add offset hex 80 to it.
0: kd> !dq 30342000+80 l1 #30342080 00000000`00b60003 |
Alright, so we have covered the address translation successfully. You can follow the manual process on x64 as well but just make sure that you are in the context of the process for which you are translating the virtual address and take caution while using hex and decimal number conversion.