【调试】Windows夯机Memory Dump案例分析

简介: 我们已经看了不少Linux的core dump分析案例了,这次我们来看一个案例,其中利用到了Windows memory dump的分析技巧。Windows的memory dump基本原理几乎和Linux并无太大区别,如果是Crash - 内核崩溃类型的dump,分析思路几乎是完全一致的,当然难度主要在于Windows系统封闭性,即无法提供私有符号和源码,所以多需要一些汇编层面的理解。

我们已经看了不少Linux的core dump分析案例了,这次我们来看一个案例,其中利用到了Windows memory dump的分析技巧。Windows的memory dump基本原理几乎和Linux并无太大区别,如果是Crash - 内核崩溃类型的dump,分析思路几乎是完全一致的,当然难度主要在于Windows系统封闭性,即无法提供私有符号和源码,所以多需要一些汇编层面的理解。但是对于夯机的dump分析就需要一些对系统的理解了,这一点Windows和Linux系统的区别就体现出来了。与之前一样,我们还是先来看一下具体的现象:

 

问题现象:

问题现象相对之前要复杂一些,用户反应业务应用经常会有响应慢的现象。此外看到的一个现象是RDP登录会比较慢,有时会停滞在如下界面5分钟以上:

前期分析

第一步我们还是做一些前期的分析,因为我们必须要找到分析的切入点,这决定了我们之后排查的方向是否正确。这里需要多提一句,在分析一些疑难问题时,做一些前期分析,确保排查方向正确是非常必要的,否则一旦方向错误,会耗费大量的时间和精力。

这里我们前期分析的一个目标就是确认问题原因确实是在这台机器上,而不是因为网络或者RDP客户端的问题。那么一个简单的区分方法就是做一些本地RDP,即在这台机器对127.0.0.1发起RDP连接,确认确实也有以上类似现象,那么我们基本就可以放心继续我们在这台机器上的排查了。

信息抓取

夯机Memory Dump的抓取步骤其实相对比较简单,直接在NC上运行virsh dump即可。但是注意一点,我们经常会犯的一个错误是,用户报告机器响应慢,于是我们就直接抓取dump了。这里的一个问题在于,当我们分析memory dump时,我们需要一个切入点,比如需要知道大概是哪个进程出现了夯住的问题,那么我们就可以从这个进程的线程堆栈出发进行分析。如果没有这个切入点,我们会陷入一种不知从何处开始的窘境,当然如果你对系统足够了解,可以做一些猜测,甚至整个系统的所有关键进程进行逐一扫描。但是这将耗费大量的时间,排查效率也大大下降了。

所以在这个实际案例中,我们要求用户在本机上进行RDP,并确保停滞在以上画面5分钟以上,开始抓取dump。这样的好处在于,当分析dump时,我们便可以直接从登录的相关进程开始分析了。

Memory Dump分析

下面就到了真正的分析环节了,面对夯机的memory dump分析个人会有自己思路,对Windows系统一个简单的想法是首先看一下内核锁的情况,而Linux往往更关注CPU上运行的进程。Windows系统中executive resource是一种非常常见的内核锁,关于eresource的具体描述可以参考:https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/introduction-to-eresource-routines。简而言之他是Windows内核层面比较常用的锁形式,并且是Windows特有,在内核层面,一些全局的大锁往往是由eresource的形式实现的。我们首先来看一下他的情况:

我们可以看到有大量的内核取锁的线程,而一般我们首先看一下第一个共享锁的所有者:

我们可以看到executive resource的所有者正在获取另外一个锁,因此我们要做的是把他正在尝试获取的锁的所有者线程堆栈打印出来。首先取得锁的地址:

使用!locks命令打印出锁的竞争情况:

我们可以从输出中看到对应锁的所有者为线程 fffffa800b61bb50。所以我们可以再次应用!thread命令打印出该线程的堆栈:

我们可以看到该线程目前正在CPU上运行,但是不幸的是我们针对Windows虚拟机的core dump抓取和转换是有些问题的,对于正在CPU上运行的堆栈无法输出。但是我们可以上面等待的线程中获取一些信息,注意看Ticks一项:

Ticks代表该线程处于等待未运行状态的时间,可以看到该等待线程已经等待锁仅有1秒钟左右,因此可以判断该问题并不是一个锁死的问题,这意味着对应在CPU上运行的这个线程并不会一直占据CPU,而是过一会儿会释放CPU。所以这仅是一个比较忙的问题,并不是整个内核都被锁死而无法运行的问题。那么下个问题就是,这些线程在忙什么?

我们来看看正在运行的这个线程的IRP吧。IRP即是Windows是分层IO的结构,Windows是通过IRP来实现IO的层层传递的,大家可以参考:https://en.wikipedia.org/wiki/I/O_request_packet 来具体了解一下。我们可以使用windbg的!irp命令来打印出IO结构,其地址来自于!thread输出的"IRP List"部分:

可以看到IRP的分层结构,IO是有输出的底层向上层传递,当前已经传递到文件系统驱动层面Ntfs。注意我们在这里要始终记住一点,就是线程等待的时间并不长,说明他是忙着做一些事情,并不是停滞不前。所以面对这个IRP,我们会更关注Ntfs在忙着做什么。因此我们可以挑选IRP中的操作文件对象的地址来看看这个IO是发向那个文件的,或者说线程是在操作哪个文件:

我们发现了该线程是在操作c:\Windows\Temp目录下的一些临时文件,如果下一步骤自然是我们会去看看这个目录里就是有些什么样的问题。

验证阶段

当我们去访问c:\Windows\Temp该目录是,真相就大白了,其中包含了大量的sess_xxx的文件,导致explorer直接访问都会夯住很长时间,如果采用命令行dir的方式需要等待很长时间才能打印完所有文件。

当然用户会关注是哪些进程产生了这些文件,利用我们之前文章里提到的process monitor可以轻松地确认文件是由业务进程php-cgi创建的。解决方法当然是删除这些临时文件,这事实上需要一个晚上的时间!

目录
相关文章
|
2月前
|
监控 安全 网络协议
windows服务器权限分析
windows服务器权限分析
17 1
windows服务器权限分析
|
2月前
|
安全 Linux 开发工具
Linux与Windows系统的差异分析
Linux与Windows系统的差异分析
35 0
|
3月前
|
Java Android开发 Windows
Java for Windows Missing问题原因分析以及完美解决方案
Java for Windows Missing问题原因分析以及完美解决方案
20 0
|
4月前
|
SQL 关系型数据库 MySQL
数据库数据恢复—windows server下Mysql数据库数据恢复案例
mysql数据库数据恢复环境: 本地服务器,windows server操作系统 ,部署有mysql单实例,数据库引擎类型为innodb,独立表空间,无数据库备份,未开启binlog。 mysql数据库故障: 工作人员使用Delete命令删除数据时未添加where子句进行筛选,导致全表数据被删除,删除后未对该表进行任何操作。
|
4月前
|
NoSQL MongoDB 数据库
数据库数据恢复—Windows server环境下MongoDB数据库数据恢复案例
MongoDB数据库数据恢复环境: 一台Windows Server操作系统的虚拟机,虚拟机上部署有MongoDB数据库。 MongoDB数据库故障&检测: 在未关闭MongoDB服务的情况下,工作人员将MongoDB数据库文件拷贝到其他分区,然后将原数据库文件所在分区进行了格式化的操作,格式化完成后将数据库文件拷回原分区,重新启动MongoDB服务,发现MongoDB服务无法启动并报错。
数据库数据恢复—Windows server环境下MongoDB数据库数据恢复案例
|
6月前
|
Unix Linux 开发工具
【Git使用】关于Windows系统下的git提示“warning: LF will be replaced by CRLF”的原因分析和解决方案
【Git使用】关于Windows系统下的git提示“warning: LF will be replaced by CRLF”的原因分析和解决方案
141 0
|
10月前
|
数据挖掘 Linux 芯片
windbg抓一个windows蓝屏分析
windbg抓一个windows蓝屏分析
|
10月前
|
C++ Windows
windows 下C++生成Dump调试文件与分析
windows 下C++生成Dump调试文件与分析
427 0
|
IDE 测试技术 开发工具
自动化测试实操案例详解 | Windows应用篇
自动化测试实操案例详解 | Windows应用篇
473 0