《格蠹汇编软件调试案例集锦》之拯救发疯的Windows7
首先打开WinDbg,然后在File菜单下选择Open Crash Dump,打开WERA7FB.tmp.mdmp文件。此时WinDbg就已经帮我们断下来了:
我们发现在280号进程中的2a4号线程中出现了缓存区溢出的问题。
用kn查看栈上的情况。kn 中的k用来显示所给定的线程中的栈帧的情况,并且能够显示相应的信息;n能够显示栈的数字或栈的编号。
我们可以看到出现了几个Wer开头的函数,
wer的意思是Windows Error Report,说明这个进程在终止前调用了WER设施,8号栈帧中的函数是UnhandledExceptionFilter,这是位于kernel32.dll中的用于处置未处理异常的核心函数,它也是系统在终止掉一个进程前做最后处理的地方,应用程序错误对话框和JIT调试都是从这个函数发起的。一般来说这个函数下面就是导致异常的函数。
这个异常函数的名称叫做_report_gsfailure,其所在的模块为umpo.dll。
我们用lmvm umpo看一下这个模块,lmvm +模块名称,就是查看模块。lm就是能够列出所读取的模块的信息。v它能够显示出符号文件名称,以及文件的映像名称等等的详细信息,m进行模块名称的匹配。
上面已经列出了关于umpo这个模块的比较详细的信息,这个umpo模块是没有问题的。
我们继续分析栈帧
发现umpo这个模块中的UmpoAlpcSendPowerMessage函数出现了缓冲区溢出的情况。当这个函数要返回的时候,编译在函数中的溢出检查代码检测出了溢出,于是调用_report_gsfailure函数来报告错误。这种检测溢出的方式通常称为基于Cookie的溢出检查,简称为GS机制。GS机制就是在可能发生溢出的函数所使用的栈帧起始处(EBP-4的位置)存放一个称为Cookie的整数,在函数返回时检查这个Cookie是否完好,如果被破坏了,就说明函数中发生了溢出。部署和检查Cookie的代码都是编译器在编译时加入到函数中的。
所以我们看一下Cookie以及EBP的值等于多少
dd 中的d用于显示我们内存中的一些值,第二个d表示以double-word双字的形式进行显示。
可以看到第一个00640064就是Cookie值,父函数的EBP也是00640064,而返回地址则是006a002e。可以发现,这些值都不像是正规的内存地址,反而像是ASCII码值。看来由于出现了缓冲区溢出的问题,使得一些重要的数据都被冲掉了,变成了其它的数值。下面我们可以看一下出问题的函数的变量空间的情况。那么该如何确定这个范围呢?首先用两个函数的保存有EBP的位置的地址相减,也就是0x009AFB30减去0x009AF924,得出的结果为0x20C。但是对于_report_gsfailure这个函数而言,它的下方还包含有Cookie值以及EBP的地址,一共占据了8个字节的空间,所以还应当用0x20C减去8,也就是0x204,就是问题函数UmpoAlpcSendPowerMessage的变量空间了。那么下面就来看一下这个空间中发生了什么
上述命令的意思是以字节的形式显示内存地址为0x009AFB30减去0x204位置的内容。
可以看到这里出现了一个超长的文件名,那么我们就可以知道,这就是出现缓冲区溢出问题的源头了。可见上图中第一个红框就是EBP,而第二个红框则是返回地址的位置。现在可以知道,因为Umpo模块中的函数UmpoAlpcSendPowerMessage接收到了一个比预想长度还要长的参数,于是就发生了缓冲区的溢出情况,从而触发了GS机制。既然知道了原因,那么我们现在只要把文件的名称改短,问题也就能够解决了。
通过本次调试学习了GS机制,以及winDbg的几个命令,感谢ichunqiu提供学习实验环境!