一、查看pte 0 可以看到當前 PTE為:FFFFF68000000000
得到PTE 之后可以根據公式 可以計算 PDE PPE PXE 的位置
g_PTE_BASE =(((虛擬地址 & 0xffffffffffff) >> 12)) << 3) + g_PTE_BASE)//這里的g_PTE_BASE 下面會用說明怎么找到
g_PDE_BASE=(((虛擬地址 & 0xffffffffffff) >> 21)) << 3) + g_PDE_BASE)
g_PPE_BASE=(((虛擬地址 & 0xffffffffffff) >> 30)) << 3) + g_PPE_BASE)
g_PXE_BASE=(((虛擬地址 & 0xffffffffffff) >> 39)) << 3) + g_PXE_BASE)
下面看看我們怎么獲取 g_PTE_BASE 找到nt 這個模塊 它的地址為:fffff802`4960b000
nt模塊地址 掃描的大小 PTE基地址
查看一下內核當中有什么函數引用了PTE 這里windbg 命令S 掃描一下 s fffff802`4960b000 l10000 00 00 00 00 80 f6 ff ff
隨便找一個函數查看 其實這里是什么函數無所謂,但這里就能得出一個公式 函數的基地址 - nt模塊基地址 = PET基地址偏移
我的系統是win10 1803 這個150F就是1803系統PET基地址偏移 nt模塊基地址+PET基地址偏移 = g_PTE_BASE 這里就獲取到了隨機化PTE_BASE基地址
用代碼驗證一下 隨便找一個 虛擬地址
代碼運行結果 得到的基地址是一樣的

#include"標頭.h" ULONG64 Ntoskrnl_Base; ULONG64 g_PTE_BASE; ULONG64 g_PDE_BASE; ULONG64 g_PPE_BASE; ULONG64 g_PXE_BASE; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { struct { ULONG TimeDateStamp; }; struct { PVOID LoadedImports; }; }; }LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; VOID DriverUnload(PDRIVER_OBJECT pDriverObject) { DbgPrint("已卸載!\n"); } PULONG64 GetPxeAddress(PVOID addr) { return (PULONG64)((((((ULONG64)addr & 0xffffffffffff) >> 39)) << 3) + g_PXE_BASE); } PULONG64 GetPpeAddress(PVOID addr) { return (PULONG64)((((((ULONG64)addr & 0xffffffffffff) >> 30)) << 3) + g_PPE_BASE); } PULONG64 GetPdeAddress(PVOID addr) { return (PULONG64)((((((ULONG64)addr & 0xffffffffffff) >> 21)) << 3) + g_PDE_BASE); } PULONG64 GetPteAddress(PVOID addr) { return (PULONG64)((((((ULONG64)addr & 0xffffffffffff) >> 12)) << 3) + g_PTE_BASE); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) { ULONG iCount = 0; DbgPrint("啟動!\n"); pDriverObject->DriverUnload = DriverUnload; //KdBreakPoint(); UNICODE_STRING UnicodeString2; RtlInitUnicodeString(&UnicodeString2, L"ntoskrnl.exe"); PLDR_DATA_TABLE_ENTRY pLdr = NULL; PLIST_ENTRY pListEntry = NULL; PLIST_ENTRY pCurrentListEntry = NULL; PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL; pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection; pListEntry = pLdr->InLoadOrderLinks.Flink; pCurrentListEntry = pListEntry->Flink; while (pCurrentListEntry != pListEntry) { pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (pCurrentModule->BaseDllName.Buffer!=0) { if (RtlEqualUnicodeString(&pCurrentModule->BaseDllName, &UnicodeString2, FALSE)) { DbgPrint("ModuleName = %wZ ModuleBase = %p \r\n", pCurrentModule->BaseDllName, pCurrentModule->DllBase); Ntoskrnl_Base = pCurrentModule->DllBase; break; } } pCurrentListEntry = pCurrentListEntry->Flink; } g_PTE_BASE = *(PULONG64)(Ntoskrnl_Base + 0x150F);//這里的150F 我寫死了我測試過很多便不會變動相對還是穩定的, 但保險起見 可以獲取函數地址 根據公式動態計算得出偏移; g_PDE_BASE=(PULONG64)GetPteAddress((PVOID)g_PTE_BASE); g_PPE_BASE = (PULONG64)GetPteAddress((PVOID)g_PDE_BASE); g_PXE_BASE = (PULONG64)GetPteAddress((PVOID)g_PPE_BASE); DbgPrint("PXE------%p\n", GetPxeAddress((PVOID)0xfffff8024ba69fb0)); DbgPrint("PpE------%p\n", GetPpeAddress((PVOID)0xfffff8024ba69fb0)); DbgPrint("PdE------%p\n", GetPdeAddress((PVOID)0xfffff8024ba69fb0)); DbgPrint("PtE------%p\n", GetPteAddress((PVOID)0xfffff8024ba69fb0)); return STATUS_SUCCESS; }
參考嗶哩嗶哩 周壑:https://space.bilibili.com/37877654/video