主頁 > 後端開發 > 驅動開發:內核決議記憶體四級頁表

驅動開發:內核決議記憶體四級頁表

2023-05-29 10:57:11 後端開發

當今作業系統普遍采用64位架構,CPU最大尋址能力雖然達到了64位,但其實僅僅只是用到了48位進行尋址,其記憶體管理采用了9-9-9-9-12的分頁模式,9-9-9-9-12分頁表示物理地址擁有四級頁表,微軟將這四級依次命名為PXE、PPE、PDE、PTE這四項,

關于記憶體管理和分頁模式,不同的作業系統和體系結構可能會有略微不同的實作方式,9-9-9-9-12的分頁模式是一種常見的分頁方案,其中物理地址被分成四級頁表:PXE(Page Directory Pointer Table Entry)、PPE(Page Directory Entry)、PDE(Page Table Entry)和PTE(Page Table Entry),這種分頁模式可以支持大量的物理記憶體地址映射到虛擬記憶體地址空間中,每個級別的頁表都負責將虛擬地址映射到更具體的物理地址,通過這種層次化的頁表結構,作業系統可以更有效地管理和分配記憶體,

首先一個PTE管理1個分頁大小的記憶體也就是0x1000位元組,PTE結構的決議非常容易,打開WinDBG輸入!PTE 0即可決議,如下所示,當前地址0位置處的PTE基址是FFFF898000000000,由于PTE的一個頁大小是0x1000所以當記憶體地址高于0x1000時將會切換到另一個頁中,如下FFFF898000000008則是另一個頁中的地址,

0: kd> !PTE 0
                                           VA 0000000000000000
PXE at FFFF89C4E2713000    PPE at FFFF89C4E2600000    PDE at FFFF89C4C0000000    PTE at FFFF898000000000
contains 8A0000000405F867  contains 0000000000000000
pfn 405f      ---DA--UW-V  not valid

0: kd> !PTE 0x1000
                                           VA 0000000000001000
PXE at FFFF89C4E2713000    PPE at FFFF89C4E2600000    PDE at FFFF89C4C0000000    PTE at FFFF898000000008
contains 8A0000000405F867  contains 0000000000000000
pfn 405f      ---DA--UW-V  not valid

由于PTE是動態變化的,找到該地址的關鍵就在于通過MmGetSystemRoutineAddress函式動態得到MmGetVirtualForPhysical的記憶體地址,然后向下掃描特征尋找mov rdx,0FFFF8B0000000000h并將內部的地址提取出來,

這段代碼完整版如下所示,代碼可動態定位到PTE的記憶體地址,然后將其取出;

// 署名權
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: [email protected]

#include <ntifs.h>
#include <ntstrsafe.h>

// 指定記憶體區域的特征碼掃描
PVOID SearchMemory(PVOID pStartAddress, PVOID pEndAddress, PUCHAR pMemoryData, ULONG ulMemoryDataSize)
{
	PVOID pAddress = NULL;
	PUCHAR i = NULL;
	ULONG m = 0;

	// 掃描記憶體
	for (i = (PUCHAR)pStartAddress; i < (PUCHAR)pEndAddress; i++)
	{
		// 判斷特征碼
		for (m = 0; m < ulMemoryDataSize; m++)
		{
			if (*(PUCHAR)(i + m) != pMemoryData[m])
			{
				break;
			}
		}
		// 判斷是否找到符合特征碼的地址
		if (m >= ulMemoryDataSize)
		{
			// 找到特征碼位置, 獲取緊接著特征碼的下一地址
			pAddress = (PVOID)(i + ulMemoryDataSize);
			break;
		}
	}

	return pAddress;
}

// 獲取到函式地址
PVOID GetMmGetVirtualForPhysical()
{
	PVOID VariableAddress = 0;
	UNICODE_STRING uioiTime = { 0 };

	RtlInitUnicodeString(&uioiTime, L"MmGetVirtualForPhysical");
	VariableAddress = (PVOID)MmGetSystemRoutineAddress(&uioiTime);
	if (VariableAddress != 0)
	{
		return VariableAddress;
	}
	return 0;
}

// 驅動卸載例程
VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("Uninstall Driver \n");
}

// 驅動入口地址
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("Hello LyShark \n");

	// 獲取函式地址
	PVOID address = GetMmGetVirtualForPhysical();

	DbgPrint("GetMmGetVirtualForPhysical = %p \n", address);

	UCHAR pSecondSpecialData[50] = { 0 };
	ULONG ulFirstSpecialDataSize = 0;

	pSecondSpecialData[0] = 0x48;
	pSecondSpecialData[1] = 0xc1;
	pSecondSpecialData[2] = 0xe0;
	ulFirstSpecialDataSize = 3;

	// 定位特征碼
	PVOID PTE = SearchMemory(address, (PVOID)((PUCHAR)address + 0xFF), pSecondSpecialData, ulFirstSpecialDataSize);
	__try
	{
		PVOID lOffset = (ULONG)PTE + 1;
		DbgPrint("PTE Address = %p \n", lOffset);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		DbgPrint("error");
	}

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

運行如上代碼可動態獲取到當前系統的PTE地址,然后將PTE填入到g_PTEBASE中,即可實作決議系統內的四個標志位,完整決議代碼如下所示;

// 署名權
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: [email protected]

#include <ntifs.h>
#include <ntstrsafe.h>

INT64 g_PTEBASE = 0;
INT64 g_PDEBASE = 0;
INT64 g_PPEBASE = 0;
INT64 g_PXEBASE = 0;

PULONG64 GetPteBase(PVOID va)
{
	return (PULONG64)((((ULONG64)va & 0xFFFFFFFFFFFF) >> 12) * 8) + g_PTEBASE;
}

PULONG64 GetPdeBase(PVOID va)
{
	return (PULONG64)((((ULONG64)va & 0xFFFFFFFFFFFF) >> 12) * 8) + g_PDEBASE;
}

PULONG64 GetPpeBase(PVOID va)
{
	return (PULONG64)((((ULONG64)va & 0xFFFFFFFFFFFF) >> 12) * 8) + g_PPEBASE;
}

PULONG64 GetPxeBase(PVOID va)
{
	return (PULONG64)((((ULONG64)va & 0xFFFFFFFFFFFF) >> 12) * 8) + g_PXEBASE;
}

// 驅動卸載例程
VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("Uninstall Driver \n");
}

// 驅動入口地址
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("Hello LyShark \n");

	g_PTEBASE = 0XFFFFF20000000000;

	g_PDEBASE = (ULONG64)GetPteBase((PVOID)g_PTEBASE);
	g_PPEBASE = (ULONG64)GetPteBase((PVOID)g_PDEBASE);
	g_PXEBASE = (ULONG64)GetPteBase((PVOID)g_PPEBASE);

	DbgPrint("PXE = %p \n", g_PXEBASE);
	DbgPrint("PPE  = %p \n", g_PPEBASE);
	DbgPrint("PDE  = %p \n", g_PDEBASE);
	DbgPrint("PTE  = %p \n", g_PTEBASE);

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

我的系統內PTE地址為0XFFFFF20000000000,填入變數內決議效果如下圖所示;

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/553684.html

標籤:C++

上一篇:計算機網路面試八股文

下一篇:返回列表

標籤雲
其他(159902) Python(38178) JavaScript(25460) Java(18141) C(15232) 區塊鏈(8268) C#(7972) AI(7469) 爪哇(7425) MySQL(7214) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5344) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4578) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2434) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1977) 功能(1967) Web開發(1951) HtmlCss(1949) C++(1925) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1878) .NETCore(1862) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • 驅動開發:內核決議記憶體四級頁表

    當今作業系統普遍采用64位架構,CPU最大尋址能力雖然達到了64位,但其實僅僅只是用到了48位進行尋址,其記憶體管理采用了`9-9-9-9-12`的分頁模式,`9-9-9-9-12`分頁表示物理地址擁有四級頁表,微軟將這四級依次命名為PXE、PPE、PDE、PTE這四項。關于記憶體管理和分頁模式,不同的... ......

    uj5u.com 2023-05-29 10:57:11 more
  • 計算機網路面試八股文

    ## 網路分層結構 計算機網路體系大致分為三種,OSI七層模型、TCP/IP四層模型和五層模型。一般面試的時候考察比較多的是五層模型。最全面的Java面試網站:[最全面的Java面試網站](https://topjavaer.cn) ![](http://img.topjavaer.cn/img/t ......

    uj5u.com 2023-05-29 07:47:54 more
  • Java的Object類的方法

    Java的Object類是所有類的根類,它提供了一些通用的方法。下面是一些常用的Object類方法: 1. equals(Object obj):判斷當前物件是否與給定物件相等。默認情況下,equals方法比較的是物件的參考,但可以通過在具體類中重寫equals方法來改變其比較行為。 2. hash ......

    uj5u.com 2023-05-29 07:47:29 more
  • Python 使用ConfigParser操作ini組態檔

    ini 組態檔格式如下 要求:ini 檔案必須是GBK編碼,如果是UTF-8編碼,python讀取組態檔會報錯。 # 這里是注釋內容 # [FY12361] #婦幼保健介面服務埠 serverIP=192.168.1.11 serverPort=8400 [SM] #國產SM加密服務埠 se ......

    uj5u.com 2023-05-29 07:47:23 more
  • Rust Web 全堆疊開發之 Actix 嘗鮮并構建REST API

    # Rust Web 全堆疊開發之 Actix 嘗鮮并構建REST API ## 一、Actix 嘗鮮 ### 需要使用的crate - actix-web v4.3.1 - actix-rt v2.8.0 ```bash ~ via 🅒 base ? cd rust ~/rust via 🅒 b ......

    uj5u.com 2023-05-29 07:47:16 more
  • QT 繪制波形圖、頻譜圖、瀑布圖、星座圖、眼圖、語圖

    最近在學中頻信號處理的一些東西,順便用 QT 寫了一個小工具,可以顯示信號的時域波形圖、幅度譜、功率譜、二次方譜、四次方譜、八次方譜、瞬時包絡、瞬時頻率、瞬時相位、非線性瞬時相位、瞬時幅度直方圖、瞬時頻率直方圖、瞬時相位直方圖、眼圖、星座圖、語譜圖、瀑布圖。 ......

    uj5u.com 2023-05-29 07:46:15 more
  • 【VS Code+Qt6】拖放操作

    由于老周的示例代碼都是用 VS Code + CMake + Qt 寫的,為了不誤匯入,在標題中還是加上“VS Code”好一些。 上次咱們研究了剪貼板的基本用法,也了解了叫 QMimeData 的重要類。為啥要強調這個類?因為接下來扯到的拖放操作也是和它有關系。哦,對了,咱們先避開一下主題,關于剪 ......

    uj5u.com 2023-05-29 07:45:36 more
  • Python asyncio之協程學習總結

    ## 實踐環境 Python 3.6.2 ## 什么是協程 **協程**(Coroutine)一種電腦程式組件,該程式組件通過允許暫停和恢復任務,為非搶占式多任務生成子程式。**協程**也可以簡單理解為協作的程式,通過協同多任務處理實作并發的函式的變種(一種可以支持中斷的函式)。 下面,我們通過日常 ......

    uj5u.com 2023-05-29 07:45:19 more
  • Java 網路編程 —— 創建非阻塞的 HTTP 服務器

    ## HTTP 概述 HTTP 客戶程式必須先發出一個 HTTP 請求,然后才能接收到來自 HTTP 服器的回應,瀏覽器就是最常見的 HTTP 客戶程式。HTTP 客戶程式和 HTTP 服務器分別由不同的軟體開發商提供,它們都可以用任意的編程語言撰寫。HTTP 嚴格規定了 HTTP 請求和 HTTP ......

    uj5u.com 2023-05-29 07:45:07 more
  • 527訓練總結

    訓練內容:2023江西省賽VP 賽后總結: 比賽程序: 做了簽到以后純純開始坐牢...... 策略失誤: I題被定位成簽到題也過了十四個人,但是后續沒有花更多的時間去看,一直在鉆“如何存盤圖上路徑”的牛角尖,沒有往“存在巧妙解法”這個角度思考。另外寫dfs的假解法的程序中發現對vector的基本洗掉 ......

    uj5u.com 2023-05-29 07:45:03 more