一直使用Sysinternals提供的免费工具,尽管在面对一些垃圾软件层出不穷的流氓手段时,这些工具未免显得太过正统/保守,但在一个基本正常的系统中,应该说Mark提供给我们的手段还是最全面和最便捷的.
OK,广告结束,进入正题.最近发现在自己的系统上 pslist.exe 始终不能正确运行,总是只打出credit信息就直接崩溃.如下:
基于对Mark的信任,我初步猜测是正在使用的XP系统存在某种问题导致 pslist.exe 崩溃的出现.当终于不再能忍受这个可恶的对话框,加之想尝试一下OllyDbg的念头在作祟(嗯,是的,我不干这些好多年),今天决定操练一下来看看原因究竟在哪儿.
应该说OllyDbg的界面还是相当友好的,很快就定位了崩溃地址:
显然这里 EAX 寄存器存放的应该是一个指针数组的基地址,其值位于0x0013f654,但不知什么原因却被置为了NULL.此时直接的想法就是在0x13f654下内存写断点进行跟踪,但在几次尝试后我放弃了这项努力:OllyDbg的Memory Breakpoint似乎存在次数限制,在几次(4?)成功的拦截后,它不再能捕获到后续的写入操作.没办法,还是上最原始也最可靠的方式,通过OllyDbg的call stack窗口结合反汇编代码的阅读,确定了问题所在:
这里0x4010B3处是对RegQueryKeyEx的调用,实际上是在尝试获取性能计数器键[HKLM\SOFTWARE\Microsoft\Windows NT\CurrenetVersion\Perflib\009]下值Counter的size,考虑到 pslist.exe 是通过PDH来做进程/线程枚举,这个读操作本身并无奇怪指出,但奇怪的是,在我的XP上这个键下居然没有任何值!
进一步的调试发现,按照正常的流程,pslist.exe 应该在获取到该键下相应值的size后,动态申请一段内存然后再次调用RegQueryValueEx来真正获取该值的内容,如下所示:
0x404a61处是进行内存分配的确切地址,正常的流程应该是走到这里来的.但现在的问题是,由于Counter值的不存在导致了第一次RegQueryValueEx的失败,而 pslist.exe 并没有正确的处理这个失败,却又在接下来的代码中继续使用了0x13f654做为基地址来遍历Counter值的内容(Counter和另外一个期望的值Help都是REG_MULTI_SZ类型),于是出现了崩溃.
问题找到就好办了,手工恢复了系统的性能计数器,再次运行pslist.exe,一切OK!
结论:
1.我的XP系统确实存在问题,那就是性能计数器丢失了.具体原因待查.这次问题说明,性能计数器是不能随便删除的,虽然对你可能不重要,但确实有一些工具依赖它:)
2.Mark的pslist.exe代码没有正确处理RegQueryValueEx的全部错误(注意这里我说全部,因为如果Counter/Help存在但值为空的话,pslist.exe是能正确报告这个状况的).呵呵,看来即使是大牛如Mark,在这些细节上也会犯和我们一样的错误:)不过也许这些代码已不再由Mark本人维护?!
阅读(3140) | 评论(0) | 转发(0) |