我试图通过直接假设kernel32.dll始终是加载的第三个模块来找到kernel32基地址。
ModLoad: 00400000 024077eb image00400000
ModLoad: 77ad0000 77c7f000 ntdll.dll
ModLoad: 75c80000 75d70000 C:\WINDOWS\SysWOW64\KERNEL32.DLL
ModLoad: 77160000 773d3000 C:\WINDOWS\SysWOW64\KERNELBASE.dll
...
我确实有一个 for 循环来运行模块,但注意到 kernel32.dll 始终是第三个条目。
我可以假设这是可靠的吗?
C 程序输出
Kernel32.dll基地址:0x75C80000
#include <stdio.h>
#include <stdint.h>
#include <windows.h>
#include <winternl.h>
int main()
{
PPEB peb = (PPEB)__readfsdword(0x30);
uintptr_t kernel32Base = 0;
/* Skip first two entries as kernel32.dll is always the third entry */
PLIST_ENTRY ptr = peb->Ldr->InMemoryOrderModuleList.Flink->Flink->Flink;
PLDR_DATA_TABLE_ENTRY e = CONTAINING_RECORD(ptr, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
kernel32Base = (uintptr_t)e->DllBase;
printf("Kernel32.dll Base Address: 0x%p\n", (void*)kernel32Base);
return 0;
}
例如windbg正在加载DbgView.exe
您不会得到明确的“是”,因为您正在深入研究 Windows 内部结构,这些内部结构没有明确记录,并且可以在 Windows 版本之间发生变化。因此,走 PEB 比仅仅假设特定顺序更安全。
但是...以下是 Windows 10 的详细信息,根据 Windows Internals 第 7 版(Pavel Yosifovich、Alex Ionescu、Mark E. Russinovich 和 David A. Solomon)。
图像exe将首先被映射。
Ntdll 被提前加载,因为那里存在很多加载器代码:
Ntdll.dll 始终被加载,并且它是第一个运行的代码 在用户模式下作为新进程的一部分。
对于Windows子系统应用程序,它手动加载Kernel32.dll和 Kernelbase.dll,无论进程的实际导入如何。
考虑到 kernel32 无论如何都会提前出现,进行名称比较不会让你放慢速度。
此外,正如评论中提到的,请务必使用
InLoadOrderModuleList
。