【旧文章搬运】PsVoid中IrpCreateFile函数在Win7下蓝屏BUG分析及解决
原文发表于百度空间,2010-04-05
==========================================================================
这也许是我这个假期唯一做的跟Code有关的事了,已经一个多月没写代码了~~
问题是这样的,某同学A,在自己的工程中使用了PsVoid的部分驱动源码(感谢炉子开源~~),提到里面的IrpCreateFile函数在Win7下始终会蓝屏,希望我能帮忙解决一下。于是,拿出调试器开始debug之旅~~
先简单介绍下,IrpCreateFile中PsVoid中Irp文件操作库中的一个函数,主要功能就是直接发IRP实现文件打开操作。该函数在WinXP/2003下均正常工作,但是在Win7下总是会蓝屏。写了个测试驱动扔到Vmware里,挂上调试器跟踪了一下,初步发现问题出在填充完IRP准备向下IoCallDriver时。现场如下:
kd> u IofCallDriver
nt!IofCallDriver:
83a7b458 8bff mov edi,edi
83a7b45a push ebp
83a7b45b 8bec mov ebp,esp
83a7b45d push ecx
83a7b45e a15c7aba83 mov eax,dword ptr [nt!pIofCallDriver (83ba7a5c)]
83a7b463 push esi
83a7b464 8bf1 mov esi,ecx //DeviceObject参数保存至esi
83a7b466 33c9 xor ecx,ecx
....
83a88492 8a08 mov cl,byte ptr [eax] //eax指向IoStackLocation,這里是判断MajorFunction
83a88494 mov dword ptr [eax+14h],esi //取刚才保存的DeviceObject参数,赋给IrpStack->DeviceObject
83a88497 80f916 cmp cl,16h
83a8849a jne nt!IofCallDriver+0x57 (83a884b0)
kd> p
nt!IofCallDriver+0x57:
83a884b0 8b4608 mov eax,dword ptr [esi+] //取DeviceObject->DriverObject,很不幸这里DeviceObject是NULL,于是杯具发生了。。。
大概就是这样的,DeviceObject是IrpCreateFile函数中的一个局部变量,当IoCallDriver时DeviceObject参数竟然是NULL,那取DeviceObject->DriverObject必然会蓝屏了~~
刚开始,我怀疑前面取到的DeviceObject就是NULL,代码如下:
DbgPrint("The Volume FileObject=0x%08X\n",pFile);
DeviceObject = pFile->Vpb->DeviceObject;
DbgPrint("pFile->Vpb->DeviceObject = 0x%08X\n",DeviceObject);
RealDevice = pFile->Vpb->RealDevice;
DbgPrint("pFile->Vpb->RealDevice = 0x%08X\n",RealDevice);
但是再次调试,发现这里是正常的,DeviceObject的值有效,不知怎的在准备IoCallDriver时变成了0,于是,再次调试~~
这次调试时,密切监视DeviceObject值的变化。终于发现,在走过以下代码之后,DeviceObject变成了0
RtlZeroMemory(&AuxData, sizeof(AUX_ACCESS_DATA));
ntStatus = SeCreateAccessState( &AccessState,
&AuxData,
DesiredAccess,
IoGetFileObjectGenericMapping());
在调用完SeCreateAccessState之后,DeviceObject变成了0,很莫名的问题啊。不过,目标已经锁定在SeCreateAccessState,再重启,再次来过。。。
过程如下:
在IrpCreateFile中:
//DeviceObject = pFile->Vpb->DeviceObject;
93f14759 8b4df4 mov ecx,dword ptr [ebp-0Ch]
93f1475c 8b5108 mov edx,dword ptr [ecx+]
93f1475f 8b4208 mov eax,dword ptr [edx+]
93f14762 898550ffffff mov dword ptr [ebp-0B0h],eax //DeviceObject保存在了ebp-b0处,如下:
kd> dd ebp-b0
807e1994 85bcb020 807e19b4 83e16b29 //可以看到,此时DeviceObject=85bcb020,是有效值
807e19a4 83b2ac02 3c8fb9d2 83b2ac02
807e19b4 807e19c0 83e16cca 534fa145 807e19d0
继续往下,一直到调用SeCreateAccessState之前,这个值都没有变化。
到了SeCreateAccessState,跟进去,发现这个函数只是直接调用了SeCreateAccessStateEx函数,WRK中源码如下,Win7中也没什么变化。
NTSTATUS
SeCreateAccessState(
__out PACCESS_STATE AccessState,
__out PAUX_ACCESS_DATA AuxData,
__in ACCESS_MASK DesiredAccess,
__in_opt PGENERIC_MAPPING GenericMapping
)
{
return SeCreateAccessStateEx (PsGetCurrentThread (),
PsGetCurrentProcess (),
AccessState,
AuxData,
DesiredAccess,
GenericMapping);
}
继续跟进至SeCreateAccessStateEx。。。
发现了两个memset调用~~
kd>
nt!SeCreateAccessStateEx+0x23:
83c6f633 e8e0440400 call nt!RtlMapGenericMask (83cb3b18)
83c6f638 8b7d10 mov edi,dword ptr [ebp+10h] //取第三个参数至edi
83c6f63b 6a74 push 74h
83c6f63d 6a00 push
83c6f63f push edi
83c6f640 e8fbe7e0ff call nt!memset (83a7de40) //将第三个参数AccessState指向的内存清零
83c6f645 8b7514 mov esi,dword ptr [ebp+14h] ////取第三个参数至esi
83c6f648 83c40c add esp,0Ch
83c6f64b 68c0000000 push 0C0h
83c6f650 6a00 push
83c6f652 push esi
83c6f653 e8e8e7e0ff call nt!memset (83a7de40) //将第四个参数AuxData指向的内存清零
这两句对应于以下代码:
RtlZeroMemory(AccessState, sizeof(ACCESS_STATE));
RtlZeroMemory(AuxData, sizeof(AUX_ACCESS_DATA));
//在SeCreateAccessStateEx这个函数中:
kd> p
nt!SeCreateAccessStateEx+0x3b:
83c3664b 68c0000000 push 0C0h
83c36650 6a00 push
83c36652 push esi
83c36653 e8e8e7e0ff call nt!memset (83a44e40) //准备清零
kd> dd esp l4
8cc678cc 8cc6793c 000000c0 8cc67958 //memset的参数
kd> dd 8cc67994 //此时局部变量DeviceObject的值,仍然是正确值
8cc67994 85bd4020 8cc679a0
8cc679a4 8cc679a0
kd> ? 8cc6793c+c0
Evaluate expression: - = 8cc679fc
也就是说,要memset清零的区域是从8cc6793c到8cc679fc, 我们的局部变量的地址8cc67994就在这之间,于是被清零了。。。
为什么会出现这样一个结果呢?AuxData是一个结构体,该参数是从IrpCreateFile中传过来的,和DeviceObject都是局部变量。而现在,对AuxData的操作竟然影响到了DeviceObject,能想到的,就是从他们在栈中的布局入手了。
可以看到,AuxData位于ebp-108h处,与它相邻的局部变量是SourceString,位于ebp-ECh处。
也就是说,AuxData的实际大小只有0x108-0xEC=0x1C
而在SeCreateAccessStateEx中,我们明显可以看到系统认为这个结构的大小是0xC0,那么进行memset时,实际影响的范围是
从ebp-108h到ebp-108h+0xC0=ebp-48h,而我们的局部变量DeviceObject位于ebp-B0h处,正位于这个范围之间,于是就被清零了,同样受影响的还有位于该范围内的SourceString,NameBuffer,ntStatus,ObjectAttributes,DeviceObject,Event,Handle,AccessState等局部变量,如果要再使用这些变量的话,同样会出现问题,比如你要使用Handle的时候,发现竟然成无效句柄了。。。
所以,根本原因就是使用了不正确的结构定义,导致SeCreateAccessStateEx函数对局部变量AuxData清零初始化时同时修改了其它局部变量的值。
原因既然找到了,解决起来就容易了。经询问,A同学说这个结构是他根据PsVoid源码中的定义自己修改的,是一个未文档化的结构。恩,未文档化的东西,用起来难免会有不可靠的时候啊~~~
解决方案:修改AUX_ACCESS_DATA的定义就行了。该结构原来的定义为:
typedef struct _AUX_ACCESS_DATA {
PPRIVILEGE_SET PrivilegesUsed;
GENERIC_MAPPING GenericMapping;
ACCESS_MASK AccessesToAudit;
ACCESS_MASK MaximumAuditMask;
} AUX_ACCESS_DATA, *PAUX_ACCESS_DATA;
该结构现在的大小为0x1C,而Win7中该结构实际大小为0xC0。(0xC0-0x1C)/sizeof(ULONG)=0x29=41,那么修改定义如下:
typedef struct _AUX_ACCESS_DATA {
PPRIVILEGE_SET PrivilegesUsed;
GENERIC_MAPPING GenericMapping;
ACCESS_MASK AccessesToAudit;
ACCESS_MASK MaximumAuditMask;
ULONG Unknown[];
} AUX_ACCESS_DATA, *PAUX_ACCESS_DATA;
修改之后,经测试,蓝屏问题解决~~
【旧文章搬运】PsVoid中IrpCreateFile函数在Win7下蓝屏BUG分析及解决的更多相关文章
- 【旧文章搬运】深入分析Win7的对象引用跟踪机制
原文发表于百度空间及看雪论坛,2010-09-12 看雪论坛地址:https://bbs.pediy.com/thread-120296.htm============================ ...
- 【旧文章搬运】分析了一下360安全卫士的HOOK(二)——架构与实现
原文发表于百度空间及看雪论坛,2009-10-14 看雪论坛地址:https://bbs.pediy.com/thread-99460.htm 刚发这篇文章的时候,因为内容涉及360的核心产品,文章被 ...
- 【旧文章搬运】加载PE文件时IAT的填充时机
原文发表于百度空间,2011-06-20========================================================================== 大致过程如 ...
- 【旧文章搬运】Win7 OBJECT_HEADER之TypeIndex解析
原文发表于百度空间,2010-08-09========================================================================== 在Wind ...
- 【旧文章搬运】对抗RKU的StealthCode检测
原文发表于百度空间,2009-07-02========================================================================== 快一个月没 ...
- 【旧文章搬运】Windows句柄分配算法(一)
原文发表于百度空间,2009-04-04========================================================================== 分析了Wi ...
- 【旧文章搬运】PspCidTable攻与防
原文发表于百度空间,2009-03-29========================================================================== PspCi ...
- 【旧文章搬运】PspCidTable概述
原文发表于百度空间,2009-03-28========================================================================== PspCi ...
- 【原创】驱动开发中Memory read error导致的蓝屏问题
最近在看着<windows驱动开发技术详解>这本书,模仿着敲了第七章中的模拟文件读写部分.在Debug过程中,蓝屏了好多次并出现了各种奇葩的问题.在调了快两天之后,问题终于解决了!现在在这 ...
随机推荐
- Food hub
Work center List Tillage 耕作 Hand harvest 手工采收 Planting 种植 Cultivating 培养 Mulching 覆盖 Dig harvest 挖地采 ...
- OS: 读者写者问题(写者优先+LINUX+多线程+互斥量+代码)(转)
一. 引子 最近想自己写个简单的 WEB SERVER ,为了先练练手,熟悉下在LINUX系统使用基本的进程.线程.互斥等,就拿以前学过的 OS 问题开开刀啦.记得当年学读者写者问题,尤其是写者优先的 ...
- svn 命令个
svn 命令行下常用的几个命令 标签: svnpathdelete工作urlfile 2011-11-28 08:16 128627人阅读 评论(1) 收藏 举报 分类: 版本控制(8) 版权声明 ...
- Sublime Text 3相关配置和设置
Sublime Text 3打开txt中文乱码的解决方法 Sublime Text是一个很强大的编辑器,但是对中文的支持并不好,在Sublime Text 2 时,能够通过命令行的方式安装编码包来解决 ...
- 在html文件引入其它html文件的几种方法
1.IFrame引入,看看下面的代码 <IFRAME NAME="content_frame" width=100% height=600 marginwidth=0 mar ...
- RabbitMQ安装和介绍
简单的安装方式 yum安装erlang,下载rpm包安装rabbitmq 一.编译安装erlang 1. 官方下载包并解压 wget http://erlang.org/download/otp_sr ...
- HDU 5336 XYZ and Drops 2015 Multi-University Training Contest 4 1010
这题的题意是给你一幅图,图里面有水滴.每一个水滴都有质量,然后再给你一个起点,他会在一開始的时候向四周发射4个小水滴,假设小水滴撞上水滴,那么他们会融合,假设质量大于4了,那么就会爆炸,向四周射出质量 ...
- 九度OJ 1137:浮点数加法 (大数运算)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2725 解决:736 题目描述: 求2个浮点数相加的和 题目中输入输出中出现浮点数都有如下的形式: P1P2...Pi.Q1Q2...Qj ...
- 简单监控网站访问是否正常的shell脚本,邮件报警。网站恢复后继续运行。
#!/bin/bash # 使用curl检查网页是否可以正常访问,如果无法访问则发邮件. SITE=crm.bjzgjh.com PROT=80 URL="http://$SITE:$PRO ...
- Windows平台,开机自动运行应用
打开注册表编辑器(Win+R后执行regedit) 进入HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 新建字符串值, ...