一、查看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