总结一下得到内核模块地址的方法
网上说的比较常见的4种方法:1、通过DriverEntry传入的DriverObject参数的DriverSection成员指向LDR_DATA_TABLE_ENTRY结构,通过遍历这张表得到ntoskrnl的基址和大小
2、ZwQuerySystemInformation大法
3、搜索内存
4、利用KPCR结构
存在的问题:
1、第3种方法还没搞定,combojiangn牛的汇编看不太懂,基础不行啊,之后补上C的
2、第1种方法和第4种方法得到的结果比ZwQuerySystemInformation少一个
3、第1种方法如果输出BaseDllName是ntoskrnl.exe,如果输出FullDllName则是:\WINDOWS\system32\ntkrnlpa.exe,地址都是:804d8000,不明白为何
环境:虚拟机VMWare:WIN XP SP3+ WDK ---- WINXP Check方式编译
**** Hidden Message ***** 搜内存原理是这样的。
在DriverEntry内取得返回地址。
(为什么可以取返回地址,想一想驱动的加载过程具体说就nt!IopLoadDriver内那句Call dword ptr )而这个返回地址就在内核文件内部。然后以返回地址为起点,按页对齐(对齐只是为了加快搜索速度,不对齐也行)向前搜。直到匹配了PE特征。而第一个匹配PE特征的地址就是内核文件基地址。
明白了原理相信C代码就很容易了。我顺带贴一个。
BOOLEAN
FindBaseAndSize(
IN PVOID SomePtr,
OUT PVOID *BaseAddress OPTIONAL,
OUT ULONG *ImageSize OPTIONAL
)
{
ULONG SomeAddress = (ULONG) SomePtr;
for ( SomeAddress &= 0xFFFFF000 ; ; SomeAddress -= PAGE_SIZE )
{
if(MmIsAddressValid ((PVOID)SomeAddress) && *(USHORT*)SomeAddress == IMAGE_DOS_SIGNATURE ) // MZ signature?
{
PVOID NtHeader = RtlImageNtHeader ((PVOID)SomeAddress);// + ((IMAGE_DOS_HEADER*)SomeAddress)->e_lfanew;
if (MmIsAddressValid ((PVOID)NtHeader) && *(ULONG*)NtHeader == IMAGE_NT_SIGNATURE) // PE signature?
{
if (ARGUMENT_PRESENT (BaseAddress))
*BaseAddress = (PVOID)SomeAddress;
if (ARGUMENT_PRESENT (ImageSize))
*ImageSize = ((IMAGE_NT_HEADERS*)NtHeader)->OptionalHeader.SizeOfImage;
return TRUE;
}
}
}
return FALSE;
}
在DriverEntry内调用的时候FindBaseAndSize(DriverEntry返回地址,XXX,XXX)。
备注:
一、实际上也不一定非取得返回地址,内核内任意一个函数的地址都可以作为起点。
二、我顺手贴的这个代码不支持X64. 真是汗啊我的帖子好少啊加油! 帖子不错,顶一个 灌水喽,哇哈哈, 看流星社区总规则 Ver 2.0 支持楼主,支持看流星社区,以后我会经常来! 支持楼主,支持看流星社区,以后我会经常来!
页:
[1]