windows在内存设计之初,设计了一个内核Mark标记,从0xFFFF8000 0000 0000起一直标记了0x100个的标记,这里被微软根据特定的位算法进行了特别的划分(代码演示)。
他的内核内存标记如下:
那这些数字代表什么意义了?微软其实已经定了一个枚举类型来详细记录:
那通过这两个我们就可以反推出我们需要的内存布局(有些内存布局在这里无法得到,是因为有额外的处理流程,可以通过别的方法得到)
#include <ntddk.h> #define NameSize 0x10 #define MiVaUnused 0 #define MiVaSessionSpace 1 #define MiVaProcessSpace 2 #define MiVaBootLoaded 3 #define MiVaPfnDatabase 4 #define MiVaNonPagedPool 5 #define MiVaPagedPool 6 #define MiVaSpecialPoolPaged 7 #define MiVaSystemCache 8 #define MiVaSystemPtes 9 #define MiVaHal 10 #define MiVaSessionGlobalSpace 11 #define MiVaDriverImages 12 #define MiVaSystemPtesLarge 13 #define MiVaKernelStacks 14 #define MiVaMaximumType 15 PCHAR TypeName[NameSize] = { "MiVaUnused", "MiVaSessionSpace", "MiVaProcessSpace", "MiVaBootLoaded", "MiVaPfnDatabase", "MiVaNonPagedPool", "MiVaPagedPool", "MiVaSpecialPoolPaged", "MiVaSystemCache", "MiVaSystemPtes", "MiVaHal", "MiVaSessionGlobalSpace", "MiVaDriverImages", "MiVaSystemPtesLarge", "MiVaKernelStacks", "MiVaMaximumType" }; PVOID FindBase(); PVOID FindSystemKernenlRegion(PVOID pMark); PVOID FindBaseRegion(PVOID pMark, UCHAR Type); VOID Unload(PDRIVER_OBJECT pDriverObject) { KdPrint(("end\n")); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath) { KdPrint(("start\n")); pDriverObject->DriverUnload = Unload; //第一步找到Mark地址 PVOID pMarkAddr = FindBase(); //第二步开始解析 FindSystemKernenlRegion(pMarkAddr); PVOID NonPool = ExAllocatePoolWithTag(NonPagedPool, 0x1000, 'NonP'); PVOID Pool = ExAllocatePoolWithTag(PagedPool, 0x1000, 'ionP'); KdPrint(("NonPagePool=%llx", NonPool)); KdPrint(("PagePool=%llx", Pool)); ExFreePool(NonPool); ExFreePool(Pool); return STATUS_SUCCESS; } PVOID FindBase() { UNICODE_STRING FuncName; RtlInitUnicodeString(&FuncName, L"ExAcquirePushLockExclusiveEx"); PVOID FuncAddr=MmGetSystemRoutineAddress(&FuncName); PUCHAR var = (PUCHAR)FuncAddr; for (int i = 0; i < 0x100; i++) { if (*var == 0x48 && *(var+3)==0x27) { return var+(*(PUINT32)(var - 4)); } var++; } return 0; } PVOID FindSystemKernenlRegion(PVOID pMark) { PVOID Region = 0; for (int i = 0; i < 0x10; i++) { KdPrint(("%s=%llx\n", TypeName[i], FindBaseRegion(pMark, i))); } } PVOID FindBaseRegion(PVOID pMark,UCHAR Type) { PUCHAR var = pMark; UINT64 pBaseAddr = 0x100; // for (int i = 0; i < 0x100; i++) { if (*(var) == Type) { pBaseAddr =((pBaseAddr | i) << 0x27 | 0xFFFF000000000000); return pBaseAddr; } var++; } return 0; }
完