首页
社区
课程
招聘
[求助]MmIsAddressValid 和 ProbeForRead
发表于: 2014-1-31 05:40 13024

[求助]MmIsAddressValid 和 ProbeForRead

2014-1-31 05:40
13024
请看一段在驱动中判断PE文件格式的代码(代码很乱,勿喷):

pBaseADDR 是文件映射到内存之后的地址.

		__try
		{
[COLOR="Red"]			ProbeForRead((PVOID)(dosheader->e_lfanew+(LONG)pBaseADDR),sizeof(IMAGE_NT_SIGNATURE),1);

			if(MmIsAddressValid((PVOID)(dosheader->e_lfanew+(LONG)pBaseADDR)))[/COLOR]
			{
				if( *(DWORD*)(dosheader->e_lfanew+(LONG)pBaseADDR) != IMAGE_NT_SIGNATURE )
				{
					KdPrint(("不是PE文件(NT_SIGNATURE) %wZ\n",&nameInfo->Name));
				
				}
			}else{
				KdPrint(("MmIsAddressValid error(IMAGE_NT_SIGNATURE):%wZ\n",&nameInfo->Name));

			}

		}__except(EXCEPTION_EXECUTE_HANDLER)
		{
			KdPrint(("ProbeForRead error(IMAGE_NT_SIGNATURE)\n"));

		}



这段代码是为了检测PE文件NT头开始的4字节是不是"PE00", 如果是正常的32位PE文件,没有什么问题.但是如果是16位的PE文件,DOS头的e_lfanew字段,很可能是一个极大的数值(比文件尺寸还大),这个时候如果不加判断,直接读取这个位置的数据,直接蓝屏.

所以我加了一句ProbeForRead, 但是,加了这一句并不能避免因为e_lfanew过大而导致的蓝屏,即使e_lfanew比整个文件尺寸还大,他都没有抛出异常.但是如果访问的话,会蓝屏.

所以又加了一句MmIsAddressValid,加了这句之后,可以避免蓝屏.
但是有时候,虽然e_lfanew的数值很大,但是pBaseADDR加上e_lfanew,还处于我们映射的文件范围之内,实际上是可以读取的,但是MmIsAddressValid返回了"假".  

XPSP3系统中windows目录下winhelp.exe,这是个16位的程序,如果按照32位PE文件的结构来看,它的e_lfanew值为1E00, 而这个文件的大小是0x3FDF0, 1E00是在文件映射内存的范围之内的,是可以读取的,但是mmisvalidaddress返回假.

从MSDN上看到的说明是:

mmisvalidaddress 仅检测内核地址是否会发生缺页,同时不推荐使用这个函数.
ProbeForRead 会确保内存地址是有效的且在用户空间中.

这样看的话, mmisvalidaddress  返回假 可以理解,可能是因为会发生缺页.

system32文件夹下,有一个dosx.exe,也是个16位的程序,按照32位PE格式来解析,e_lfanew为0x1A688F07,但是实际上这个文件的大小才0XD260, 这样读取会出错,但是ProbeForRead却没有抛出异常.

这种情况下,有什么办法能准确检测指定内存是否可读呢?

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

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
好像没有标准的方法....
我觉得你的路有问题.....

判断pe文件的方法可以采用标准方法...16.32.64位pe文件都可以区分的.....
这种情况我一般用__try来处理.........

自己的理解不知道对不对...
2014-1-31 10:55
0
雪    币: 11
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
__try在内核里是个坑……不解释了……
顺便说句,过年还在研究技术,真苦逼呵……
2014-1-31 17:38
0
雪    币: 478
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
[QUOTE='[轻云];1258357']好像没有标准的方法....
我觉得你的路有问题.....

判断pe文件的方法可以采用标准方法...16.32.64位pe文件都可以区分的.....
这种情况我一般用__try来处理.........

自己的理解不知道对不对...[/QUOTE]

不是这样的,你找一个16位的PE文件,看他的elfanew字段,你就能看出问题了.16位文件,只有dos头,没有NT头
2014-1-31 21:32
0
雪    币: 478
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
少壮不努力,老大徒伤悲啊.我起步本来就晚,趁现在有点精力得抓紧时间学习啊
2014-1-31 21:33
0
雪    币: 11
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
你到底要拦截什么额……
拦截进程用PsSetCreateProcessNotifyRoutineEx
拦截dll和驱动用PsSetLoadImageNotifyRoutine
如果调用进程为4则是驱动
否则是dll或进程映像
排除掉进程映像
判断出dll的加载
2014-1-31 22:14
0
雪    币: 478
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
在PsSetLoadImageNotifyRoutine里面拦截驱动,是往imagebase里面写数据来达到拦截的目的是吧,但是我发现改了之后,这个驱动第二次加载的时候,直接返回错误,而且也没有进入到我的回调里面.就是改一次,永久生效
2014-1-31 22:27
0
雪    币: 11
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
qq上说吧……
2014-1-31 22:36
0
游客
登录 | 注册 方可回帖
返回
//