日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

Windows x64内核学习笔记(四)—— 9-9-9-9-12分页

發(fā)布時(shí)間:2025/3/21 windows 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows x64内核学习笔记(四)—— 9-9-9-9-12分页 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Windows x64內(nèi)核學(xué)習(xí)筆記(四)—— 9-9-9-9-12分頁(yè)

  • 前言
  • 9-9-9-9-12分頁(yè)
    • 實(shí)驗(yàn)一:線性地址轉(zhuǎn)物理地址
  • 頁(yè)表基址
    • 定位基址
    • PTE to PXE
    • 實(shí)驗(yàn)二:通過(guò)頁(yè)表基址定位各級(jí)頁(yè)表的物理頁(yè)
    • 代碼實(shí)現(xiàn)
  • 參考資料

前言

在學(xué)習(xí)VT虛擬化技術(shù)的EPT物理地址轉(zhuǎn)換時(shí),我們簡(jiǎn)單提到過(guò)9-9-9-9-12分頁(yè)的概念,即支持48位物理地址轉(zhuǎn)換。

9-9-9-9-12分頁(yè)

描述:隨著計(jì)算機(jī)技術(shù)的發(fā)展,64位系統(tǒng)逐漸占據(jù)主流地位,那么也就表示CPU的最大尋址范圍為64位。但實(shí)際上,CPU只使用了其中的48位用于尋址,并使用9-9-9-9-12分頁(yè)模式。即便如此,在未來(lái)較長(zhǎng)一段時(shí)間里,48位尋址范圍也足夠大部分人的日常使用了。

9-9-9-9-12分頁(yè)表示物理地址擁有四級(jí)頁(yè)表,在Intel開(kāi)發(fā)手冊(cè)中,將這四級(jí)頁(yè)表分別稱(chēng)為PML4E、PDPTE、PDE、PTE;但微軟的命名方式略有不同,將這四級(jí)頁(yè)表分別稱(chēng)為PXE、PPE、PDE、PTE,WinDbg中也是如此。

由于之后的大部分操作都是使用WinDbg完成的,因此我們?cè)谥蟮墓P記中都使用微軟對(duì)四級(jí)頁(yè)表的命名方式。

實(shí)驗(yàn)一:線性地址轉(zhuǎn)物理地址

第一步:打開(kāi)記事本
啟動(dòng)一個(gè)64位的notepad.exe,寫(xiě)入字符串“Hello World”。

第二步:定位線性地址
使用CE定位字符串“Hello World”的線性地址。

可以看到這里搜出了很多線性地址,怎么確定是哪一個(gè)呢?

可以在字符串后面再寫(xiě)入一些其他的字符,看看哪些線性地址的值會(huì)發(fā)生變化。

只剩下兩個(gè)了,MSCTF.dll是微軟用于提供文本服務(wù)的dll,那么真正的線性地址能確定是21BABF52920了。
第三步:拆分線性地址
將線性地址的二進(jìn)制位拆分成9-9-9-9-12五組,可以借助WinDbg或計(jì)算器得到二進(jìn)制。

拆分結(jié)果如下:

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

第四步:定位頁(yè)表基址
首先我們需要通過(guò)notepad.exe進(jìn)程的Cr3得到物理頁(yè)的基址,即第一個(gè)PXE的地址。


第五步:定位PXE

注意:高位的0a00和低位的867是屬性位,不包含在物理地址中。
第六步:定位PPE

第七步:定位PDE

第八步:定位PTE

第九步:定位物理頁(yè)

成功定位到了記事本中的字符串文本,后面的"123"是之前殘留的數(shù)據(jù)。

頁(yè)表基址

思考:一個(gè)進(jìn)程該如何訪問(wèn)自己的物理頁(yè)呢?可以通過(guò)讀取Cr3的值進(jìn)行訪問(wèn)嗎?
答案:不行,Cr3中保存的頁(yè)表基址是物理地址,程序如果直接訪問(wèn)這個(gè)地址,雖然看上去值是一樣的,但實(shí)際上訪問(wèn)的是一個(gè)線性地址,會(huì)被虛擬內(nèi)存管理器解析成另一個(gè)地址。

實(shí)際上,操作系統(tǒng)會(huì)將當(dāng)前進(jìn)程的物理頁(yè)映射在某個(gè)線性地址中,以供程序讀取自己的頁(yè)表內(nèi)容。
在x86系統(tǒng)中,頁(yè)表基址是固定的,位于0xC0000000,將這個(gè)線性地址進(jìn)行解析,訪問(wèn)其物理頁(yè)的內(nèi)容,會(huì)發(fā)現(xiàn)從這個(gè)地址開(kāi)始,里面保存的數(shù)據(jù)為當(dāng)前程序的所有物理頁(yè)地址。

而在x64系統(tǒng)中,頁(yè)表基址不再是固定的值,而是每次系統(tǒng)啟動(dòng)后隨機(jī)生成的。

可以在WinDbg中查看0地址對(duì)應(yīng)的線性地址來(lái)確定當(dāng)前的頁(yè)表基址。

可以看到,當(dāng)前系統(tǒng)的頁(yè)表基址的線性地址為0xFFFF800000000000,注意,只有后48位才是有效地址。

其中,每個(gè)物理頁(yè)占8個(gè)字節(jié),例如,第一個(gè)物理頁(yè)地址位于線性地址0xFFFF800000000000,第二個(gè)物理頁(yè)地址位于線性地址0xFFFF800000000008,每個(gè)物理頁(yè)中包含1024個(gè)字節(jié)的數(shù)據(jù)。

定位基址

描述:如果系統(tǒng)每次啟動(dòng)時(shí),基址是隨機(jī)分配的,那么該如何定位基址呢?其實(shí)方法有挺多的,大部分方式是通過(guò)提取特征碼。

以周壑老師提供的方法為例,首先在WinDbg中定位內(nèi)核模塊的地址。

然后在內(nèi)核模塊中搜索與當(dāng)前頁(yè)表基址相同的值出現(xiàn)的位置,當(dāng)前頁(yè)表基址為0xFFFF800000000000。

接著,在IDA中定位到數(shù)據(jù)所在的位置,可以看到是某行代碼引用了這個(gè)值的硬編碼。

在WinDbg中查看這段代碼,能夠識(shí)別到位于CcUnpinFileDataEx函數(shù)。

那么,由于系統(tǒng)每次啟動(dòng)時(shí)基址是不固定的,因此這些值也不可能是固定的硬編碼,肯定是有“人”對(duì)這些值進(jìn)行了修改,在需要使用時(shí),可以通過(guò)固定的偏移量提取硬編碼,從而得到頁(yè)表基址,但要注意不同版本的內(nèi)核文件的偏移量可能是不同的。

PTE to PXE

思考:如果已經(jīng)得到了頁(yè)表基址,即PTE的地址,那么,能否再得到PDE、PPE以及PXE的線性地址呢?
答案:可以,因?yàn)轫?yè)表基址本身也是一個(gè)線性地址,也需要有人來(lái)管理,因此將頁(yè)表基址本身當(dāng)做一個(gè)線性地址,向右移動(dòng)12位能夠得到PDE基址對(duì)應(yīng)的PTI,再乘以8(每個(gè)物理頁(yè)地址占8個(gè)字節(jié))就能夠得到PDE基址在頁(yè)表基址中的偏移量,然后將這個(gè)偏移量再加上頁(yè)表基址就能得到PDE基址所在的線性地址。同理,也能夠通過(guò)PDE基址得到PPE基址和PXE基址的線性地址。

計(jì)算公式:PAE = PTE_BASE + (Address >> 12) << 3;

實(shí)驗(yàn)二:通過(guò)頁(yè)表基址定位各級(jí)頁(yè)表的物理頁(yè)

描述:以gdt基址為例,通過(guò)頁(yè)表基址尋找保存其線性地址的各項(xiàng)頁(yè)表的物理地址,此時(shí)頁(yè)表基址為0xFFFF800000000000。

第一步:定位PTE的線性地址,并查看物理頁(yè)的物理地址

第二步:定位PDE的線性地址,并查看PTE的物理地址

第三步:定位PPE的線性地址,并查看PDE的物理地址

第四步:定位PXE所在的線性地址,并查看PPE的物理地址

第五步:使用!pte指令進(jìn)行驗(yàn)證

代碼實(shí)現(xiàn)

#include "ntddk.h"ULONG64 g_NT_BASE = 0xfffff80348aa4000; // lm命令得到 ULONG64 g_PTE_BASE; ULONG64 g_PDE_BASE; ULONG64 g_PPE_BASE; ULONG64 g_PXE_BASE;//卸載函數(shù) 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; // 頁(yè)表基址硬編碼相對(duì)于內(nèi)核文件基址的偏移量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; }

運(yùn)行結(jié)果

使用WinDbg進(jìn)行驗(yàn)證

kd> r gdtr
gdtr=fffff8034b290fb0

參考資料

  • bilibili周壑:x64內(nèi)核研究系列教程

總結(jié)

以上是生活随笔為你收集整理的Windows x64内核学习笔记(四)—— 9-9-9-9-12分页的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。