windbg分析堆溢出

时间:2024-03-31 22:24:28

  本文实验的例子来自《windows高级调试》第6.2.2节,参考书中的方法进行。

1.通过windbg分析堆块

  (1)在命令行运行程序,输入参数(输入超过10个字符),在出现如下提示的时候,使用windbg attach到该进程。

windbg分析堆溢出

  (2)按任意键继续执行,执行完后,程序崩溃到windbg,使用kb命令查看堆栈如下: 

windbg分析堆溢出

  (3)我们看到报的堆栈信息是在HeapFree函数中,其实我们知道原因是wcscpy函数溢出了,但崩溃点却不在溢出发生的地方,堆破坏的最大问题在于造成错误的代码无法在发生堆破坏时被发现,我们可以通过查看当前堆的一些情况进行分析。 

windbg分析堆溢出

  (4)查看默认堆的详细情况,由于信息比较多,我仅仅把最后一部分打印出来。

windbg分析堆溢出

  (5) 我们看到最后一个堆块是有问题的,可以看下该堆的内容,我们从004e5188地址开始打印。

windbg分析堆溢出

  (6)我们看到了一系列的0x31字符,就是我们参数输入的“1”,我们可以用du命令再打印下: 

windbg分析堆溢出

  (7)果然是我们输入的参数,而且参数越过了堆块004e51a8,我们把该堆块的头打印出来: 

windbg分析堆溢出

  发现堆块的头全都被我们输入的参数覆盖了,这就导致了内存访问异常。 

2.通过windbg+普通页堆分析

  上面的程序很简单,很容易通过分析堆块来找出问题,然而通过分析堆块来查找堆溢出的问题并非总是可行的,还有一种方式可以让我们很快找到堆溢出的原因,就是页堆,我们可以通过Application Verifier工具开启页堆。

windbg分析堆溢出

  通过Add Application菜单,添加我们要分析的应用程序,然后再右边会有Heaps的选项。 

windbg分析堆溢出

  右击Heaps 选择属性,在弹出框中,把full去掉(我们先分析普通页堆,之后再分析完全页堆)。 

windbg分析堆溢出

   完成后我们按照原来的方式执行,程序崩溃后,打印堆栈如下。

windbg分析堆溢出

  上面给了我们堆的内存信息,要转储页堆数据的内容,我们需要将该地址减去32字节然后再转成_DPH_BLOCK_INFORMATION结构,如下: 

windbg分析堆溢出

  上述结构体最重要的一项是StackTrace,可以查找堆栈的回溯,如下: 

windbg分析堆溢出

  通过上述信息,我们很快就能找到有问题堆的分配栈回溯,通过分析代码很容易发现堆的溢出情况。 

3.通过windbg+完全页堆分析

  普通页堆还不是很直观的发现堆溢出的地方,但是开启了完全页堆就不一样了,完全页堆开启后,程序只要发生堆溢出就立马崩溃,这样就很好的发现问题所在了,开启完全页堆:

windbg分析堆溢出

  再次运行程序,崩溃后堆栈情况: 

windbg分析堆溢出

  很快就找到问题所在了,我们可以把wcscpy拷贝的字符打印出来:

windbg分析堆溢出

  就是我们传入的参数导致的溢出。