首页
社区
课程
招聘
[原创]总结一下得到内核模块地址的方法,参考N多大牛
发表于: 2011-8-14 21:57 18014

[原创]总结一下得到内核模块地址的方法,参考N多大牛

2011-8-14 21:57
18014

//参考:combojiang:   http://hi.baidu.com/combojiang/blog/item/bfa7a6d9f1c913ee38012f28.html
//      combojiang:   http://hi.baidu.com/hu3167343/blog/item/3fb1cc91e9582507d31b7023.html
//      combojiang:   http://bbs.pediy.com/showthread.php?t=58447
//      莫灰灰:       http://hi.baidu.com/hu3167343/blog/item/3fb1cc91e9582507d31b7023.html
//      还有一些,忘了出处了,一并感谢,此次只是做个总结

网上说的比较常见的4种方法:

1、通过DriverEntry传入的DriverObject参数的DriverSection成员指向LDR_DATA_TABLE_ENTRY结构,通过遍历这张表得到ntoskrnl的基址和大小

2、ZwQuerySystemInformation大法

3、搜索内存

4、利用KPCR结构

存在的问题:

1、第1种方法和第4种方法得到的结果比ZwQuerySystemInformation少一个

2、第1种方法如果输出BaseDllName是ntoskrnl.exe,如果输出FullDllName则是:\WINDOWS\system32\ntkrnlpa.exe,地址都是:804d8000,不明白为何

环境:虚拟机VMWare:WIN XP SP3  + WDK ---- WINXP Check方式编译


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (16)
雪    币: 202
活跃值: (69)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
ULONG EnrtyAddr;//拼写错误
EntryAddr=(ULONG*);->EntryAddr=(ULONG*)DriverEntry;
2011-8-15 07:12
0
雪    币: 27
活跃值: (122)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
3
学习一下..
2011-8-15 08:44
0
雪    币: 862
活跃值: (329)
能力值: ( LV9,RANK:165 )
在线值:
发帖
回帖
粉丝
4
谢谢提醒,这里本来是要注释掉的,忘记了,感谢补全!
2011-8-15 16:50
0
雪    币: 1140
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
挺好的知识普及帖,感谢了!
2011-8-15 18:56
0
雪    币: 321
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习一下,总结是非常必要的。
2011-8-16 08:52
0
雪    币: 8080
活跃值: (2661)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
搜内存原理是这样的。
在DriverEntry内取得返回地址。
(为什么可以取返回地址,想一想驱动的加载过程具体说就nt!IopLoadDriver内那句Call dword ptr [edi+2c])而这个返回地址就在内核文件内部。然后以返回地址为起点,按页对齐(对齐只是为了加快搜索速度,不对齐也行)向前搜。直到匹配了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.
2011-8-16 09:07
0
雪    币: 240
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
很好的基础知识,学习了。
2011-8-16 12:28
0
雪    币: 149
活跃值: (131)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
9
学习写驱动。标记慢慢看。。
2011-8-16 16:03
0
雪    币: 862
活跃值: (329)
能力值: ( LV9,RANK:165 )
在线值:
发帖
回帖
粉丝
10
[QUOTE=傷遺忘;991319]搜内存原理是这样的。
在DriverEntry内取得返回地址。
(为什么可以取返回地址,想一想驱动的加载过程具体说就nt!IopLoadDriver内那句Call dword ptr [edi+2c])而这个返回地址就在内核文件内部。然后以返回地址为起点,按页对齐(对齐只是为了加快搜索速度,不对...[/QUOTE]

感谢讲解

我这样试了试,估计有错误,指针什么的
void Method3(ULONG Base)//,OUT PVOID* BaseAddress,OUT PVOID* ImageSize)//搜索内存,从0x80000000-----0xa0000000
{
	for(Base&=0xfffff000;;Base-=PAGE_SIZE)
	{
		if(MmIsAddressValid((PVOID)Base)&&*(USHORT*)Base==IMAGE_DOS_SIGNATURE )  //MZ标识
		{
			PVOID NTHeader=RtlImageNtHeader((PVOID)Base);//获得NT头指针 
            if(MmIsAddressValid((PVOID)NTHeader)&&*(ULONG*)NTHeader==IMAGE_NT_SIGNATURE)     //PE文件标识
			{
				//MSDN:The ARGUMENT_PRESENT macro takes an argument pointer and returns FALSE if the pointer is NULL, TRUE otherwise.
				/*if (ARGUMENT_PRESENT (BaseAddress))
					*BaseAddress = (PVOID)SomeAddress;

                if (ARGUMENT_PRESENT (ImageSize))
                    *ImageSize = ((IMAGE_NT_HEADERS*)NtHeader)->OptionalHeader.SizeOfImage;*/
				DbgPrint("地址:%8X\n",Base);
			}
		}
		DbgPrint("搜索%8X中...\n",Base);
		if(Base<0x80000000)
		{
			DbgPrint("搜索失败!\n");
				break;
		}
			
	}
}


结果WinDbg看输出都一个小时了才到  搜索E88C4000中...
2011-8-16 18:47
0
雪    币: 862
活跃值: (329)
能力值: ( LV9,RANK:165 )
在线值:
发帖
回帖
粉丝
11
能不能说说上面的代码有哪些问题
2011-8-18 23:53
0
雪    币: 58
活跃值: (1090)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
mark!!
2011-8-24 22:54
0
雪    币: 238
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
不错不错,学习~
2011-8-25 10:00
0
雪    币: 862
活跃值: (329)
能力值: ( LV9,RANK:165 )
在线值:
发帖
回帖
粉丝
14
驱动的返回地址是这么得到的吗?好像不是啊,基础太差了
        EntryAddr=(ULONG)DriverEntry;
        DbgPrint("%8X\n",EntryAddr);
得到的是:  驱动返回地址:F8D14990
明显不在内核文件范围内,求指教
2012-2-6 10:40
0
雪    币: 862
活跃值: (329)
能力值: ( LV9,RANK:165 )
在线值:
发帖
回帖
粉丝
15
方法3终于搞定了
2012-2-7 09:01
0
雪    币: 244
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
楼主灰常辛苦
2012-2-29 15:49
0
雪    币: 329
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
学习学习~
2012-9-9 12:14
0
游客
登录 | 注册 方可回帖
返回
//