當今作業系統普遍采用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++
上一篇:計算機網路面試八股文
下一篇:返回列表