Conversion to the virtual spatial address to the physical space address in the user state

zhaozj2021-02-17  47

http://flier_lu.blogone.net/?id=1428057

In the article "Automatic NT System Service Description Table and Function Map Watch", I give a functional function from the virtual address to the physical address translation.

The following is quoted:

Physical_address TphysicalMemorymapping :: LineradDresstophysicalAddress (LPCVOID LPVIRTUALADDRESS)

{

Physical_address addr = {0, 0};

IF ((DWORD) LPVIRTUALADDRESS <0x80000000L || (DWORD) LPVIRTUALADDRESS> = 0xa0000000L)

Addr.quadpart = (dword) LPVIRTUALADDRESS & 0X0FFFF000;

Else

Addr.quadpart = (dword) LPVIRTUALADDRESS & 0X1FFFF000;

Return addr;

}

This function actually processes the conversion of the memory address of 0x8000000 - 0xA0000000, and the 0xA0000000 or more, just use PA = VA & 0x0FFFFFF000 to ensure that the access will not be wrong, this actually does not acquire the actual content of this memory. Understanding the Winnt / 2K memory layout should know that in order to make the system easily and ensure address conversion efficiency, WinNT maps 0x80000000 - 0xa0000000 memory to physical memory, the conversion algorithm is a simple PA = Va & 0x1FFFF000; and more than 0xa0000000 or more The virtual address is to use the two-level page table index to realize the mapping of the virtual address page to the physical address page (if AWE is enabled, it is not discussed here, the principle is similar). Therefore, to truly access 0xA0000000 or more virtual address memory, you must read the PDE / PTE table of the process. But the problem is that the PDE page table is typically stored in the virtual address 0xc0300000, and the PTE page table begins from the virtual address 0xC0000000. That is to say, these page tables themselves are stored on the virtual address that can be accessed in the page table. Introduce the PDE / PTE table for virtual addresses to physical address translation, first you want to know which physical page of 0xc0300000 and 0xC0000000 maps. In this way, there is a problem with eggs, huh, huh. The NT core itself can be directly accessed directly by the PDE page table starting in the process CR3 register, but ingenious is that the access CR3 needs to have RING 0. Therefore, most of the paper introduces the virtual address to the physical address translation, after describing the two-stage mapping, it is a code demo implementation for Ring 0 layers, such as WebCrazy, "Small WINDOWS NT / 2000 Paging Mechanism". Because this type of article is more, I will not be in Luo Tao memory structure and conversion algorithm, and friends who are interested in research can refer to INSIDE WIN2K 3nd and WebCrazy related articles. Since the physical address of PDE / PTE cannot be known, I can't access CR3 directly, I started to ponder all kinds of routes. Yesterday, I tose for a long time, overridden the source code in NTOS / KE and NTOS / MM directory. After a big experience, after the advantage of Open Source Windows NT, I finally found a perfect solution: P We know PDE / PTE is related to the process. Because each process has its own virtual space, there must be a complete set of separate page tables. At the time of thread switching, if the two threads are in one process, there is no need to do the page table; if the two threads span the process, the context of the process of the target thread must be loaded, which includes what we need. CR3 content. After crossing the code, I found that the contents of the CR3 were saved to EPROCESS :: KProcess :: DirectoryTableBase [0]. This variable saves the PDE page table physical address and the Hyber Space PTE page table physical address (later in detail later). So the implementation of the idea is clear: 1. Take the eProcess 2. of the current process 2. Read the PDE page table Physical address 3. Decompose the virtual address to obtain the index of the PDE / PTE table 4. Check the table to get the target physical page address, read the physical page content. 1. Take the eProcess address of the eProcess current process of the current process in Ntoskrnl.exe's space, so you can map memory access by direct mapping.

Use OpenProcess to open the current process, get the handle; use the NTDLL :: ZWQuerySystemInformation function to get all the core handles, linearly search the process handle, the kernel object whose point points is EPRocess. 2. Read the PDE page table Physical Address PDE Page Table Physical Address At the EPRocess Structure Offset 0x18 3. Decompose the virtual address to obtain the index of the PDE / PTE table to decompose the target virtual address such as 0xA01A8148: DDDDDDDDDTTTTTTTTTTTBBBBBBBBBBB 01234567890123456789012345678901 High 10 The bit is a PDE index; the middle 10 bits are the PTE index; the end 12 bits is the page-byte index. 4. Check the list to get the target physical page address and read the physical page content. The PDE / PTE entry is a DWORD that defines the index of the next level. The following is quoted:

Typedef struct _mmpte_hardware {

Ulong Valid: 1;

Ulong Write: 1; // Up Version

Ulong Owner: 1;

Ulong Writethrough: 1;

Ulong cachedisable: 1;

Ulong Accessed: 1;

Ulong dirty: 1;

Ulong largepage: 1;

Ulong global: 1;

Ulong CopyonWrite: 1; // Software Field

Ulong prototype: 1; // Software Field

Ulong reserved: 1; // Software Field

Ulong Pageframenumber: 20;

} MMPTE_HARDWARE, * PMMPTE_HARDWARE;

The specific checklist conversion algorithm is as follows

The following is quoted:

#define getpdeaddress (Base, VA) ((BASE) ((Ulong) >> 22) << 2))

#define getPteaddress (Base, VA) ((BASE) (((Ulong) >> 12) & 0x3FF) << 2))

Const Physical_Address TphysicalMemoryMapping :: LineradDressTophysicalAddRESS (LPCVOID LPVIRTUALADDRESS)

{

Physical_address addr = {0, 0};

IF ((DWORD) LPVIRTUALADDRESS> = 0x80000000L && (DWORD) LPVIRTUALADDRESS <0XA0000000L)

{

Addr.quadpart = (dword) LPVIRTUALADDRESS & 0X1FFFF000;

}

Else

{

MMPTE_HARDWARE PDE, PTE;

M_PManager-> ReadphysicalMemoryPage (GetPdeaddress (M_PManager-> PTE.LOWPART, LPVIRTUALADDRESS, & PDE, SIZEOF (PDE);

M_PManager-> ReadphysicalMemoryPage (pde.pageframenumber << Page_shift, lpvirtualaddress, & PTE, SIZEOF (PTE);

Addr.lowpart = (PTE.PageFramenumber << Page_shift) Byte_offset (LPVIRTUALADDRESS);

Return addr;

}

If you know the physical address of the target page, you can get directly obtained by reading / device / physicalmemory.

转载请注明原文地址:https://www.9cbs.com/read-29258.html

New Post(0)