Windbg使用介绍.ppt
一个一个简单简单的的上手程序-windbg调试调试紀勝奎NEC ConfidentialNEC Confidential接下来用一个简单的例子演示一下Windbg的基本使用。下面这段代码的目的是把字符串6969,3p3p中的所有3都修改为4。#include stdafx.h#include stdlib.hchar*getcharBuffer()return 6969,3p3p;void changeto4p(char*buffer)while(*buffer)if(*buffer=3)*buffer=4;buffer+;int _tmain(int argc,_TCHAR*argv)printf(%sn,Any key continue.);getchar();char*str=getcharBuffer();changeto4p(str);printf(%s,str);return 0;这段代码会导致崩溃。崩溃后看到的接口如图2.1所示。一个简单的上手程序 2NEC Confidential图2.1接下来,一起用Windbg来看看上述对话框的具体含义是什么。在启动Windbg调试以前,首先把程序对应的PDB文件放到一个指定的文件夹。上面程序的EXE叫做crashscreen-shot.exe,把编译时候生成的crashscreen-shot.pdb文件拷贝到C:PDB文件夹。同时把程序的主CPP文件拷贝到C:SRC文件夹。接下来启动Windbg。像用Visual Studio调试程序一样,我们需要在调试器中运行对应的EXE。所以在Windbg的主窗口中,使用FileOpen Executable菜单找到crashscreen-shot.exe,然后打开。一个简单的上手程序 3NEC ConfidentialWindbg不会让目标进程立刻开始运行。相反,Windbg这时会停下来,让用户有机会对进程启动过程进行排错,或者进行一些准备工作,比如设定断点,如图2.2所示。一个简单的上手程序 图 2.24NEC Confidential上面的主窗口就是Windbg输出结果的地方。下面的0:000提示符后面是用户输入命令的地方。输入命令g,让程序继续运行,如图2.3所示。一个简单的上手程序 图 2.35NEC Confidential从程序的输出可以看到,程序已经开始运行了,在等待用户的输入。如果要用调试器让程序暂停接受检查,可以在Windbg中用Ctrl+Break快捷键,或者用DebugBreak命令完成,如图2.4所示。一个简单的上手程序 图 2.46NEC Confidential接下来让我们在getcharBuffer和changeto4p函数上分别设定断点。要通过函数名设定断点,首先要让Windbg加载对应的PDB文件。通过Windbg的FileSymbol File Path菜单可以设定PDB文件的搜索路径。通过这个菜单我们把路径设定到C:PDB。设定好了后,接下来可以用x命令找到程序中getcharBuffer和changeto4p函数的二进制入口地址。找到地址后,就可以用bp命令在这两个地址上设定断点了,如图2.5所示。一个简单的上手程序 图 2.57NEC Confidential设定好断点后,继续用g命令恢复程序的执行,输入任一键后,会看到程序在getcharBuffe断点上停下,如图2.6所示。一个简单的上手程序 图 2.68NEC Confidential输入k命令,可以检查当前的callstack,如图2.7所示。一个简单的上手程序 图 2.79NEC Confidential一个简单的上手程序 图 2.8从上面的输出可以看到,_tmainCRTStartup函数调用了wmain函数,然后wmain函数调用了getcharBuf函数。同时还可以看到每个函数的源代码路径,以及函数对应的行数。Windbg也同时支持源代码级别的调试。通过FileOpen菜单,打开放到C:SRC中的源代码文件,看到Windbg UI变为如图2.8所示。10NEC Confidential一个简单的上手程序 左边窗口是对应的源代码,右边窗口是Windbg的输入和输出。由于已经通过了bp命令在getcharBuffer和changeto4p函数上设定了断点,所以右边窗口对应函数前有红色小方块表示断点。除了使用bp命令,还可以直接在右边窗口中用鼠标定位光标,然后摁F5设定条件断点。如果要单步执行,可以像在Visual Studio里一样用F10或者F11。接下来继续调试。首先输入bc 1命令清除第二个断点,然后输入命令g让程序继续运行,会发现调试器会停在如图2.9中所示的位置。左边窗口中changeto4p前的红色方块消失,原因是我们取消了第二个断点。左边*buffer=4反蓝显示,表示这一行是当前进程正在执行指令对应的源代码。右边窗口中下面这3行表明了调试器暂停进程执行的原因是发生了Access Violation,就是访问违例错误:(df8.9a0):Access violation-code c0000005(first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.11NEC Confidential一个简单的上手程序 图 2.912NEC Confidential一个简单的上手程序 下面的两行输出说明当前导致问题的指令位于004117f6地址上,是一个mov指令。该指令正把十六进制值36(就是4的ASCII)写入EAX寄存器指向的内存。该指令位于函数crashscreen_shot!changeto4p入口偏移0 x36的地方。crashscreen_shot!changeto4p+0 x36:004117f6 c60034 mov byte ptr eax,34h ds:0023:004157a5=33该条指令其实就是导致崩溃的指令。指令位于地址0 x004117f6上,跟崩溃时看到的错误截图中所描述的指令地址一样。该指令试图写内存的时候发生了问题。用DC命令可以看目标内存(EAX)上的数据是什么(图2.10)。dc命令的输出结果是:0:000 dc eax004157a5 70337033 25000000 00000a73 00000000 3p3p.%s.004157b5 5f000000 6e005f00 74006100 76006900 ._._.n.a.t.i.v004157c5 5f006500 74007300 72006100 75007400 .e._.s.t.a.r.t.u004157d5 5f007000 74007300 74006100 20006500 .p._.s.t.a.t.e.004157e5 3d003d00 5f002000 69005f00 69006e00 .=.=._._.i.n.i004157f5 69007400 6c006100 7a006900 64006500 .t.i.a.l.i.z.e.d00415805 00000000 00000000 00000000 00000000 .00415815 53000000 6b636174 6f726120 20646e75 .Stack around13NEC Confidential一个简单的上手程序 图2.1014NEC Confidential一个简单的上手程序 该输出的左边一列是内存地址,第一个地址是需要显示的起始地址004157a5,接下来每一行地址的间距是4个DWORD。右边中间内存地址上的资料,用DWORD方式显示。最右边是这些数据对应的ASCII字符。这里看到,eax指向的地址是004157a5,值是0 x70337033,对应的ASCII资料是3p3p,跟程序设计相吻合。同时该内存地址也跟崩溃时看到的错误界面中所描述的指令地址一样。接下来!address命令的输出就有点让人沮丧了。Windbg提示对应的Symbol没有设定正确。!address命令可以检查对应内存页的属性,而内存页的属性是操作系统维护的。所以这里需要加载操作系统模块的PDB文件。在我们的C:PDB目录中,并没有操作系统的PDB文件,所以命令无法正常执行。微软提供了操作系统对应的PDB文件的下载地址,下面一篇文章介绍了设定的方法:http:/ eax 00400000:00415000-00002000 Type 01000000 MEM_IMAGE Protect 00000002 PAGE_READONLY State 00001000 MEM_COMMIT Usage RegionUsageImage FullPath crashscreen-shot.exe由于这块内存是只读的,所以mov指令会导致崩溃。15NEC Confidential一个简单的上手程序 图2.1116NEC Confidential一个简单的上手程序 Visual Studio调试器中能方便地检查局部变量的值。在Windbg中,可以通过x命令完成,或者通过ViewLocals菜单打开局部变量窗口查看(图2.12)。图2.1217NEC Confidential一个简单的上手程序 从这个例子中可以看到,Windbg除了能用多种方式完成基本的断点设定,单步执行,变量检查,检查内存资料,显示callstack外,还可以看到系统相关的更多信息,比如内存页的属性,这是Visual Studio做不到的。后面的例子会演示更多的Windbg命令,包括线程切换,显示DLL信息,反汇编,搜索内存,异常上下文恢复和复杂的条件断点。1819