Windows x64 kernel learning notes - 9-9-9-9-12 Pagination

preface

Learning VT virtualization technology EPT physical address translation We briefly mentioned the concept of 9-9-9-9-12 paging, which supports 48 bit physical address translation.

9-9-9-9-12 Pagination

Description: with the development of computer technology, 64 bit system gradually occupies the mainstream position, which means that the maximum addressing range of CPU is 64 bits. But in fact, the CPU actually uses only 48 bits for addressing, and the addressing mode uses 9-9-9-9-12 paging mode. Even so, the 48 bit addressing range will be enough for most people's daily use for a long time in the future.

9-9-9-9-12 paging indicates that the physical address has a four level page table. In Intel development manual, these four level page tables are called PML4E, PDPTE, PDE and PTE respectively; However, Microsoft's naming method is slightly different. These four level page tables are called PXE, PPE, PDE and PTE respectively, and the same is true in WinDbg.

Since most of the subsequent operations are completed using WinDbg, we use Microsoft's naming method for the four level page table in our subsequent notes.

Experiment 1: linear address to physical address

Step 1: open Notepad
Start a 64 bit Notepad Exe, write the string "Hello World".

Step 2: locate the linear address
Use CE to locate the linear address of the string "Hello World".

You can see that many linear addresses have been found here. How to determine which one?

You can write some other characters after the string to see which linear address values will change.

There are only two left, msctf dll is a dll used by Microsoft to provide text services, so the real linear address can be determined to be 21BABF52920.
Step 3: split the linear address
The binary bits of the linear address are divided into five groups of 9-9-9-9-12, which can be obtained with the help of WinDbg or calculator.

The splitting results are as follows:

0 0000 0100			//004
0 0110 1110			//06e
1 0101 1111			//15f
1 0101 0010			//152
1001 0010 0000		//920

Step 4: location table
First, we need to pass Notepad Cr3 of exe process gets the base address of the physical page, that is, the address of the first PXE.


Step 5: locate PXE

Note: 0a00 and 867 are attribute bits and are not included in the physical address.
Step 6: locate PPE

Step 7: locate PDE

Step 8: locate PTE

Step 9: locate the physical page

Successfully locate the string text in Notepad, followed by "123" is the previous residual data.

Page table base address

Thinking: how should a process access its own physical page? Can it be accessed by reading the value of Cr3?
Answer: No, the base address of the page table saved in Cr3 is a physical address. If the program directly accesses this address, although it looks like the same value, it actually accesses a linear address, which will be resolved into another address by the virtual memory manager.

In fact, the operating system will map the physical page of the current process to a linear address for the program to read its own page table content.
In the x86 system, the base address of the page table is fixed at 0xC0000000. Analyze this linear address and access the content of its physical page. You will find that the data stored in it starts from this address and is all the physical page addresses of the current program.

In x64 system, the base address of page table is no longer a fixed value, but randomly generated every time the system starts.

You can view the linear address corresponding to the 0 address in WinDbg to determine the current page table base address.

It can be seen that the linear address of the page table base address of the current system is 0xffff8000000000. Note that only the last 48 bits are valid addresses.

Among them, each physical page occupies 8 bytes. For example, the first physical page address is located at the linear address 0xffff80000000000, and the second physical page address is located at the linear address 0xffff80000000000. Each physical page contains 1024 bytes of data.

Location base address

Description: if the base address is randomly assigned every time the system starts, how to locate the base address? In fact, there are many methods, most of which are by extracting feature codes.

Taking the method provided by teacher Zhou He as an example, first locate the address of the kernel module in WinDbg.

Then search the kernel module for the location where the same value as the current page table base address appears. The current page table base address is 0xffff8000000000.

Then, locate the location of the data in IDA, and you can see that a line of code refers to the hard coding of this value.

Viewing this code in WinDbg, you can recognize the function located in CcUnpinFileDataEx.

Then, since the base address is not fixed every time the system starts, these values cannot be fixed hard coded. Someone must have modified these values. When it needs to be used, the hard coding can be extracted through a fixed offset to obtain the page table base address, but it should be noted that the offset of different versions of kernel files may be different.

PTE to PXE

Thinking: if you have got the base address of the page table, that is, the address of PTE, can you get the linear addresses of PDE, PPE and PXE?
Answer: Yes, because the page table base address itself is also a linear address and needs to be managed by someone, so take the page table base address itself as a linear address, move 12 bits to the right to get the PTI corresponding to the PDE base address, and then multiply it by 8 (each physical page address accounts for 8 bytes) to get the offset of the PDE base address in the page table base address, Then add this offset to the page table base address to get the linear address where the PDE base address is located. Similarly, the linear addresses of PPE base address and PXE base address can also be obtained through PDE base address.

Calculation formula: PAE = PTE_ BASE + (Address >> 12) << 3;

Experiment 2: locate the physical pages of page tables at all levels through the page table base address

Description: Taking the gdt base address as an example, find the physical address of each page table that saves its linear address through the page table base address. At this time, the page table base address is 0xffff8000000000.

Step 1: locate the linear address of the PTE and view the physical address of the physical page

Step 2: locate the linear address of PDE and check the physical address of PTE

Step 3: locate the linear address of PPE and view the physical address of PDE

Step 4: locate the linear address of PXE and check the physical address of PPE

Step 5: use! pte instruction for verification

code implementation

#include "ntddk.h"

ULONG64 g_NT_BASE = 0xfffff80348aa4000;	// lm command obtained
ULONG64 g_PTE_BASE;
ULONG64 g_PDE_BASE;
ULONG64 g_PPE_BASE;
ULONG64 g_PXE_BASE;

//Unload function
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	DbgPrint("Driver Unload .\r\n");
}

ULONG64 GetPTEAddress(PVOID address)
{
	return (PULONG64)(g_PTE_BASE + ((((ULONG64)address & 0xffffffffffff) >> 12) << 3));
}

ULONG64 GetPDEAddress(PVOID address)
{
	return (PULONG64)(g_PDE_BASE + ((((ULONG64)address & 0xffffffffffff) >> 21) << 3));
}

ULONG64 GetPPEAddress(PVOID address)
{
	return (PULONG64)(g_PPE_BASE + ((((ULONG64)address & 0xffffffffffff) >> 30) << 3));
}

ULONG64 GetPXEAddress(PVOID address)
{
	return (PULONG64)(g_PXE_BASE + ((((ULONG64)address & 0xffffffffffff) >> 39) << 3));
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
	DbgPrint("Driver Load .\r\n");
	DriverObject->DriverUnload = DriverUnload;

	ULONG64 offset = 0xa4ad;		// The hard coded offset of the base address of the page table relative to the base address of the kernel file
	g_PTE_BASE = *(PULONG64)(g_NT_BASE + offset);
	g_PDE_BASE = GetPTEAddress(g_PTE_BASE);
	g_PPE_BASE = GetPTEAddress(g_PDE_BASE);
	g_PXE_BASE = GetPTEAddress(g_PPE_BASE);

	DbgPrint("g_PTE_BASE: %p \r\n", g_PTE_BASE);
	DbgPrint("g_PDE_BASE: %p \r\n", g_PDE_BASE);
	DbgPrint("g_PPE_BASE: %p \r\n", g_PPE_BASE);
	DbgPrint("g_PXE_BASE: %p \r\n", g_PXE_BASE);

	ULONG64 gdtr = 0xfffff8034b290fb0;

	DbgPrint("gdtr - PXE: %p \r\n", GetPXEAddress(gdtr));
	DbgPrint("gdtr - PPE: %p \r\n", GetPPEAddress(gdtr));
	DbgPrint("gdtr - PDE: %p \r\n", GetPDEAddress(gdtr));
	DbgPrint("gdtr - PTE: %p \r\n", GetPTEAddress(gdtr));

	return STATUS_SUCCESS;
}

Operation results:

Verify with WinDbg:

kd> r gdtr
gdtr=fffff8034b290fb0

reference material

Keywords: Windows

Added by seansd on Wed, 02 Mar 2022 06:54:43 +0200