关于Windbg调试游戏的问题!

正常调试程序的时候我们都会在輸出里面打一些信息来观察在程序操作的过程中发生了什么事件

当然在你的程序安装到客户机后你无法继续debug, 此时仍然需要观察在客户嘚环境中程序运行是否和debug事件序列相同时 则使用windbg。

同时采用事件查看器记录程序异常并保证程序可以继续运行

}

上一篇博文给大家分享了使用Windbg分析内存泄露问题:

本篇我们继续跟大家分享如何分析解决线程阻塞问题。

从根本上讲线程阻塞属于程序Hang的一种,其表现主要有:

1. 随着請求的增加线程数一直增加,可能会把线程池打爆

2. 低CPU使用率(被阻塞后的CPU使用率降低)

3. 请求没有返回客户端一直在等待,直至Timeout

 那么,从线程状态上看什么是阻塞? 一个线程经历的5个状态创建,就绪运行,阻塞终止。各个状态的转换条件如下图:

上图中有个阻塞状态就是说当线程中调用某个函数,需要IO请求或者暂时得不到竞争资源的,操作系统会把该线程阻塞起来避免浪费CPU资源,等到得箌了资源再变成就绪状态,等待CPU调度运行

线程发生阻塞的现象就是,进程的线程数会越来越多!

线程阻塞问题的分析思路:

持续请求過程中抓两个或者三个Dump,看线程增加的速度每次抓Dump间隔30s或者1分钟
对比的看每个Dump中:

  1. 查看阻塞线程的根源线程、线程请求的资源对象 、被阻塞的线程数
  2. 分析线程阻塞的原因,改进代码

1. 查看线程池的大小:!threadpool有时间间隔两个Dump对比着看,看线程池的线程数的增长情况:

2. 查看线程的分类和线程的状态 !threads从下图可以看出,后台线程一直在增加

此时线程阻塞问题已经确定,接下来我们要重点分析阻塞的根源线程(持有什么资源不释放,导致其他线程在等待)95号线程、79号线程

4. 查看阻塞线程的根源线程、线程请求的资源对象 、被阻塞的线程数

1 查看阻塞根源线程的堆栈
 

通过线程堆栈,我们在栈顶发现95号线程,在等待Socket Server返回具体再等哪个Socket Server?

通过以下命令找出当前线程堆栈上的Socket对象

这樣我们就定位出95号线程在做什么在等待什么:

同时我们通过线程堆栈看到了我们自己的一个TCP通讯类TCPInvoker, 在创建一个新的TCP连接,TCPInvoker类的代码需要偅点关注继续看!

我们继续看79号线程:

通过79号线程的堆栈和阻塞情况可以发现:

5. 分析线程阻塞的原因,改进代码

从如下的代码中我们能看到:

随着请求越来越多,超时+重试连接Socket Server导致线程阻塞住了。

解决方案:1. 分析Socket Server为什么连不上 2. 优化改进TCPInvoker内部的业务逻辑减少超时和重试時间,减少阻塞的产生几率

好了,上面就是这次分享的Windbg调试线程阻塞问题的细节和过程总结一下:

线程阻塞问题的分析思路:

  1. 查看阻塞线程的根源线程、线程请求的资源对象 、被阻塞的线程数
  2. 分析线程阻塞的原因,改进代码
}

在本文中我将为读者介绍一种利用windbg本地内核调试技术在Windows内核中执行代码的方法。当然准确的说这并不是一个漏洞,因为这里只用到了windbg的正常功能同时只使用了一个批处理文件(而不是powerhell或者vbs)和一些带有Microsoft的签名的可执行文件(其中一些已经是位于操作系统和windbg中的,我是通过批处理文件转储得到的)

使用该方法,无需在用户模式下启动可执行文件(当然某些Microsoft签名的可执行文件除外)或加载已签名的驱动程序因此,PatchGuard和其他保护措施也無法阻止我们 通过该方法,我们会将代码直接放入内核内存空间中然后通过hook一些线程来执行它。正如我们将演示的那样由一个简单嘚批处理文件组成的恶意软件将能够跳转到内核,通过本地内核调试技术和windbg使其代码得以在内核中执行

在这个脚本中,一些地址是我的目标测试机器这里使用了硬编码方式。目标机器是Windows 8.1 Pro N x64ntoskrnl版本为6.3.。当然要想适应其他机器,或编写没有硬编码地址的通用脚本也并非难事无论如何,由于这只是一个PoC所以我用一些硬编码的地址来完成测试,以防止代码变得过于复杂

对于这个脚本,重点在于通过windbg本地調试器修补内核内存的关键是使用物理地址来写内存。本地内核调试器不运行我们修改一些内核内存地址(例如如果我们要修补NtCreateFile函数,咜是不允许的)然而,我们可以将目标虚拟地址转换为物理地址并将我们的修改写入物理地址。

将VA转换为物理地址的命令是!vtop写入物悝地址的命令是!eb。

此外我们还得从批处理文件中转储windbg。当然嵌入完整的windbg安装太过于疯狂。但是我们这里只需要用到几个命令而已,所以我们只需要嵌入一个windbg二进制文件的子集就行了:

我们将这些文件嵌入到批处理文件中然后将它们一起转储到脚本文件中,最后使用腳本执行windbg 执行脚本后,nt!NtCreateFile函数将被挂接 我们已经使用nt!KeBugCheckEx的内存空间保存了自己的代码,为了调用我们存放在nt!KeBugCheckEx中的代码可以挂接一个针對nt!NtCreateFile的调用。通过我们存放在nt!KeBugCheckEx中的代码可以跳转到调用的原始目的地,所以函数被挂接以便执行我们的代码,但系统不会出现任何问题

这里,我们已经通过前面部分中介绍的所有方法创建了一个概念验证代码您可以通过下面的链接下载概念验证代码和相应的二进制文件:

您可以通过下面的视频来观看概念验证代码的运行情况:

}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信