百度一下0x000000c5,可得到的结果有 26600 条。但是在绝大多数的结果内,没有人给出了对症下药的合理方案。在我看来,蓝屏发生后,如若想要彻底解决,就不应该去"尝试"各种解决方案,而是使用 WinDbg 一类的利器,直接找到罪魁祸首。
首先,我们来认识一下,什么是常见的 0x000000c5 崩溃。
值为 0x000000c5的 bug check 其实是 DRIVER_CORRUPTED_EXPOOL。什么意思呢?说明系统尝试以过高的进程 IRQL 级别去访问无效内存。在蓝屏信息中,0x000000c5 后面的括号内还应跟有四个参数,其中第一个表明引用的内存地址,第二个参数表示引用时的 IRQL 级别,第三个参数要么是0要么是1,0表示读取,1表示写入,最后一个参数表示引用该内存的一个地址。
那么,一般有哪些原因引起了该错误呢?
引起该问题的一般原因为,一定有一个驱动程序损坏了系统的内存池。如果驱动损坏的是小于一个页面大小的分配单元,那么就会引发 0x000000c5 错误;倘若驱动损坏的是很大的区域,那么就会引发 DRIVER_CORRUPTED_MMPOOL 错误,值为 0x000000D0。
我该如何解决?
我的建议是,一定要启用特殊池!如果不启用特殊池,我们是无法得到真正的罪魁祸首的。而且,对于这个错误的直系、嫡系错误,我都推荐使用特殊池。我手头上暂时没有保存下来的 0x000000c5 内存转储,但是有一个 0x100000C5 DRIVER_CORRUPTED_EXPOOL。下面我展示一下堆栈结果:
从图中我们可以看见,0x7c90e514 并没有得到正确的解析,而且我可以告诉大家,它的地址也不是真实值,而是 WinDbg 根据内存上下文猜解的。此例中,我们就算使用 dds adb6ad48 命令,再配合 dds 命令,也只能找到一个微软公司的 win32k.sys 文件,这显然不是罪魁祸首。为了让我们能够定位出这个杀手驱动,我们不得不使用特殊池。
什么是特殊池?原理是什么?
特殊池就是特殊内存池,一旦启用,就好像系统部署了7x24小时监控,盯着可能是罪魁祸首的驱动。关于原理,我简单解释一下,就是通过启用特殊内存池,被检验的所有驱动程序对于略小于一个页面大小的缓冲区申请都将使用特殊内存池,不而是使用一般情形下的换页或非换页内存池。从特殊内存池中分配的缓冲区被夹在两个无效页面之间。因此,对于小于一个页面大小的缓冲区的溢出,系统在溢出发生时就会检测到,因为它导致了在缓冲区之后的无效页面发生了页面错误,也就是pagefault。那么,再次崩溃时,得到的错误应该是 DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION(0x000000d6),这样就将不可调试的转为可调试的转储文件了,而且运气好的话能够看见Windbg直接指出引起崩溃的驱动。
怎样启用特殊池?
1、运行"verifier.exe",您会看见"驱动程序验证程序管理器"向导;
2、选择第二项——"创建自定义设置(供程序开发人员使用)",然后点击"下一步";
3、选择第二项——"从一个完整的列表选择单个设置",并点击"下一步";
4、仅选中第一项——"特殊池"前面的复选框,进入下一步;
5、选择第三项——"自动选择这台计算机上安装的所有驱动程序",点击"完成";
6、重新启动系统。
在重启系统之后,特殊池就生效了,接下来您要做的就是等待系统再次崩溃出现蓝屏。通过蓝屏之后重新生成的内存转储文件就因该可以查到真凶了。
以上用到的 verifier.exe 在系统中有,在 Windows Driver Kit 里面也带有。如果通过它启用特殊池也未能查明真凶,请使用Debugging Tools for Windows 中的 gFlags 工具通过 pool tag 启用特殊池再试。
参考资料:
1. 《Debugging Help》 in Debugging Tools for Windows
2. MSDN - 《Windows Driver Kit》