C军

不玩博客了!

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

  Windbg.exe是Windows的一个调试工具,它支持两种调试模式,即“实时调试模式(Living)”和“事后调试模式(Postmortem)”。

  • 实时模式:被调试的程序正在运行当中,调试器可以实时分析、修改被调试目标的状态,如寄存器、内存、变量,调试exe可执行程序或双击双机实时调试都属于这种模式;
  • 事后模式:被调试的程序已经执行结束,现在只是事后对它保留的快照进行分析,快照就是转储文件(Dump文件)。

  Windbg的一个非常强大的功能是支持源码级的调试,就像VS自带的调试器一样。

  虽然Windbg提供了用户界面,但Windbg还是要以输入命令行的方式来操作。这些命令行通过Command窗口执行。

  每个调试命令都各有使用范围,有些命令只能用于内核调试,有些命令只能用于用户调试,有些命令只能用于实时调试。这些不必记住,一旦在某个环境下,使用了不被支持的命令,都会显示“No export XXX found”的字样。

一、基本命令

  Windbg中的调试命令分为三种:

  • 基本命令;
  • 元命令;
  • 扩展命令;

  基本命令和元命令是调试器自带的,元命令总是以"."开头,而扩展命令是外部加入的,总是以感叹号"!"开头。各种调试命令成千上万,我们要向办法把他们都列举出来,并取得使用方法。

  1、基本命令

  基本命令最少了,大概40个左右。列举所有的基本命令,使用"?"。

?

  2、元命令

  元命令有一百多个,使用下面命令列举所有元命令。

.help  [/D]

  如使用“/D”参数,命令列表将以DML格式显示。DML是一种类似于HTML的标识语言,下面会讲到。下图以DML格式显示所以有字母a开头的元命令:

0:009> .help /D a*
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z All

. commands matching a*:
   .abandon - abandon the current process
   .allow_exec_cmds [0|1] - control execution commands
   .allow_image_mapping [0|1] - control on-demand image file mapping
   .apply_dbp [<options>] - add current data breakpoint state to a
                            register context
   .asm [<options>] - set disassembly options
   .asm- [<options>] - clear disassembly options
   .attach <proc> - attach to <proc> at next execution

Use ".hh <command>" or open debugger.chm in the debuggers directory to get
detailed documentation on a command.

  3、扩展命令

  顾名思义是可以“扩展”的。扩展命令从动态连接库中暴露出来,一般以DLL文件名来代表一类扩展命令集。

  首先我们要搜索出系统中有多少个这样的DLL文件,使用下面命令:

.chain  [/D]

  此命令能够给出一个扩展命令集的链表。如:

0:009> .chain
Extension DLL search Path:
    C:\Program Files\Debugging Tools for Windows (x86)\WINXP;C:\Program Files\Debugging Tools for Windows (x86)\winext;C:\Program Files\Debugging Tools for Windows (x86)\winext\arcade;C:\Program Files\Debugging Tools for Windows (x86)\pri;C:\Program Files\Debugging Tools for Windows (x86);C:\Program Files\Debugging Tools for Windows (x86)\winext\arcade;%JAVA_HOME%/bin;c:\oracle\product\10.2.0\client_1\bin;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files\TortoiseSVN\bin;C:\Program Files\VisualSVN\bin;C:\Program Files\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\DTS\Binn\;C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\;C:\strawberry\c\bin;C:\strawberry\perl\bin;C:\Program Files\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\;C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\;C:\Program Files\Microsoft Windows Performance Toolkit\;C:\Program Files\Windows Kits\8.1\Windows Performance Toolkit\;C:\Program Files\Microsoft SQL Server\110\Tools\Binn\
Extension DLL chain:
    C:\Program Files\Debugging Tools for Windows (x86)\clr20\sos.dll: image 2.0.50727.5420, API 1.0.0, built Wed Sep 29 12:03:13 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\clr20\sos.dll]
    dbghelp: image 6.12.0002.633, API 6.1.6, built Tue Feb 02 04:08:26 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\dbghelp.dll]
    ext: image 6.12.0002.633, API 1.0.0, built Tue Feb 02 04:08:31 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\winext\ext.dll]
    exts: image 6.12.0002.633, API 1.0.0, built Tue Feb 02 04:08:24 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\WINXP\exts.dll]
    uext: image 6.12.0002.633, API 1.0.0, built Tue Feb 02 04:08:23 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\winext\uext.dll]
    ntsdexts: image 6.1.7650.0, API 1.0.0, built Tue Feb 02 04:08:08 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\WINXP\ntsdexts.dll]

  绝大部分扩展模块通过使用如下命令就能够列出扩展库中所包含的的所有命令

!模块名.help

  如:

0:009> !ext.help
diskspace <DriveLetter>[:] - Displays free disk space for specified volume
address [address]          - Displays the address space layout
        [-UsageType]       - Displays the address space regions of the given type
analyze [-v]               - Analyzes current exception or bugcheck
cpuid [processor]          - Displays CPU version info for all CPUs
elog_str <message>         - Logs simple message to host event log
cppexr <exraddress>        - Displays a C++ EXCEPTION_RECORD
error [errorcode]          - Displays Win32 & NTSTATUS error string
exchain                    - Displays exception chain for current thread
for_each_frame <cmd>       - Executes command for each frame in current
                             thread
for_each_local <cmd> $$<n> - Executes command for each local variable in
                             current frame, substituting fixed-name alias
                             $u<n> for each occurrence of $$<n>
gle [-all]                 - Displays last error & status for current thread
imggp <imagebase>          - Displays GP directory entry for 64-bit image
imgreloc <imagebase>       - Relocates modules for an image
list [-? | parameters]     - Displays lists
obja <address>             - Displays OBJECT_ATTRIBUTES[32|64]
owner [symbol!module]      - Detects owner for current exception or
                             bugcheck from triage.ini
rtlavl <address>           - Displays RTL_AVL_TABLE
std_map <address>          - Displays a std::map<>
str <address>              - Displays ANSI_STRING or OEM_STRING
ustr <address>             - Displays UNICODE_STRING

  此外,扩展命令模块是可“扩展”的。如果自己编写了一个扩展调试模块,则可通过.load/.unload命令动态加载/卸载。

二、DML语言

  DML(Debugger Markup Language调试器标记语言)像HTML一样,可从一处链接到另一处。不同处在于,DML的链接内容需要用户点击后才会动态生成。通常用来以精简方式显示大量信息和扩展功能。

  DML链接像HTML的<a>标签一样,引导用户查看调试信息,使得调试工具的使用相比纯指令格式而言,更为友好。DML如同是对原指令的一层轻微的包装一样,让生硬的指令更加温和了。

.prefer_dml  1  //开启DML

.prefer_dml  0  //关闭DML

  一旦开启DML后,像k等支持DML的调试命令,将默认以DML格式显示输出内容。

  DML还能以一种很特殊的方式为函数画流程图。它主要的原理是使用反汇编,类似于uf,但在逻辑分支处,它会停止反汇编并显示分支让用户选择。另外,它能显示汇编代码对应的行号,这一点真的非常好。如果稍加精进,他就能画出非常漂亮的流程图了。他的一个特点是反汇编的顺序是从后往前推。只要细想一想,就会觉得很有道理。如果正推的话,分支太多;而反推则分支顺序在用户的参与下(即用户进行分支选择),是固定了的。

三、基本信息

  下面开始了解一下调试器软件本身相关的命令,比如:查看软件版本、启动参数,以及最基本的软件设置命令。

  • version 查看版本命令

  下面以w3wp.exe为例,看看输出什么信息

0:028> version
Windows 7 Version 7601 (Service Pack 1) MP (4 procs) Free x86 compatible
Product: WinNt, suite: SingleUserTS
kernel32.dll version: 6.1.7601.17932 (win7sp1_gdr.120820-0419)
Machine Name:
Debug session time: Wed May 14 17:22:47.691 2014 (UTC + 8:00)
System Uptime: 0 days 8:44:39.675
Process Uptime: 0 days 0:00:33.999
  Kernel time: 0 days 0:00:00.561
  User time: 0 days 0:00:03.276
Live user mode: <Local>

Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
Copyright (c) Microsoft Corporation. All rights reserved.

  除了Windbg版本信息,上面的输出中还包括目标系统信息。如果纯粹是为了查看目标系统的版本信息,可使用下面的vertarget命令。

  • vertarget 只查看目标系统版本信息

  以w3wp.exe为例。

0:028> vertarget
Windows 7 Version 7601 (Service Pack 1) MP (4 procs) Free x86 compatible
Product: WinNt, suite: SingleUserTS
kernel32.dll version: 6.1.7601.17932 (win7sp1_gdr.120820-0419)
Machine Name:
Debug session time: Wed May 14 17:26:03.402 2014 (UTC + 8:00)
System Uptime: 0 days 8:47:55.386
Process Uptime: 0 days 0:03:49.711
  Kernel time: 0 days 0:00:00.561
  User time: 0 days 0:00:03.276

  如果Windbg中同时打开多个调试对象,“||”命令将列出对象列表。

  • ||
||0:0:000> ||
.  0 Full memory user mini dump: C:\Users\ChenZhuo\Desktop\chrome.DMP
   1 Full memory user mini dump: C:\Users\ChenZhuo\Desktop\notepad.DMP

  显示所有windbg中打开的调试对象。

  调试器需要在多个调试目标之间进行切换的话,使用“s”参数。如要切换到0号目标可使用下面的命令:

  • || 0 s

  如果要查看目标系统时间,可使用如下命令。

  • .time
0:000> .time
Debug session time: Thu May 15 08:53:59.000 2014 (UTC + 8:00)
System Uptime: 0 days 0:19:20.909
Process Uptime: 0 days 0:08:04.000
  Kernel time: 0 days 0:00:01.000
  User time: 0 days 0:00:12.000

  包括目标系统当前时间,以及系统正常运行持续时间;用户模式下还会显示当前进程的持续时间。

四、基本设置

  1、清屏命令

  • .cls

  当命令窗口太多不需要的内容时,可以执行此命令全部清除。

  2、设置进制命令

  • n[8|10|16]

  软件默认是16进制,但有时候我们也需要把默认进制改成八进制或十进制。下面给出在8进制下求16的值的示例

0:000> n 8
base is 8
0:000> ? 16
Evaluate expression: 14 = 0000000e

  3、处理器模式指令

  • .effmach []

  命令.effmach表示Effective Machine Type,即有效的机器类型。

0:000> .effmach x86
Effective machine: x86 compatible (x86)

  示例中将当前的处理器模式设置为X86模式。

五、格式化显示

  将一个整数以各种格式显示,包括16进制、10进制、8进制、二进制、字符串、日期、浮点数。使用如下命令:

  • .formats 整数

  下面以0xa为例:

0:000> .formats 0xa
Evaluate expression:
  Hex:     0000000a
  Decimal: 10
  Octal:   00000000012
  Binary:  00000000 00000000 00000000 00001010
  Chars:   ....
  Time:    Thu Jan 01 08:00:10 1970
  Float:   low 1.4013e-044 high 0
  Double:  4.94066e-323

六、开始调试

  1、挂载进程

  • .attach PID

  让调试器负载到一个已运行的进程中去,使用该命令。如果某软件在运行过程中崩溃,打开Windbg后如何调试呢?第一步就是把Windbg附载到发生崩溃的IE进程上。

  或者通过Windbg的启动参数进行挂载:

  • Windbg –p PID

  上面两种方式都需要用PID指定进程ID,如果觉得指定PID不方便,也可以通过进程名进行挂载。

  • Windbg -pn 进程名

  挂载记事本可以示例如下:

  • windbg -pn notepad.exe

  上面的命令是把调试器挂载到已经存在的进程上,另外调试器可以创建新进程并对它进行调试,这二者使用了不同的侵入方法。使用下面的命令:

  • .create 程序启动命令行

  或者Windbg启动参数

  • Windbg 程序启动命令行

  如果要创建并调试一个记事本子进程,可以使用.create notepad或者windbg notepad命令。也可以打开Windbg后,在File菜单中选择"Open Executable..."启动Notepad子进程,但这个选项只能被执行一次(之后会变灰,不能再点击)。

  而使用命令可将调试器连续附载到多个进程,也就是说,能够同时调试多个进程。

  多个进程的切换,就是通过前面的 "| 0 s" 命令切换。注意,多个用户进程调试目标都处于同一个调试会话中,使用"||"命令会看到,它们属于同一个"live user mode"调试会话。

  下面看dump文件调试,使用命令:

  • .opendump 文件名

  此命令打开一个dump文件,并建立一个dump调试会话。在调试过程中,遇到无法解决的问题,希望获得其他人的帮助,则把当前调试环境保存到Dump文件中发送给其他人就可以了。使用此方式可以打开多个dump文件。

0:000> .opendump C:\Users\ChenZhuo\Desktop\notepad.DMP

Loading Dump File [C:\Users\ChenZhuo\Desktop\notepad.DMP]
User Mini Dump File with Full Memory: Only application data is available

Opened 'C:\Users\ChenZhuo\Desktop\notepad.DMP'
  • .dump 文件名

  dump文件一般以.dmp为后缀,系统生成的dump文件都默认以.dmp为后缀的,但使用.dump命令时,使用者可以设置任意后缀,甚至无后缀。下例中,首先为当前进程生成一个dump文件保存到a.txt中,然后将之打开并分析。

  2、解挂进程

  上文讲到进程挂载命令,当需要解除挂载时,可使用解挂命令,如下:

  • .detach

  此命令结束当前调试会话,Windbg解除和被调试进程之间的调试关系(不管是通过挂载,还是通过创建方式建立的调试关系),解挂后,被调试进程能够独立运行;如果当前的调试会话是一个Dump文件,此命令直接结束对dump文件的调试,即结束调试会话。

  如果需要彻底结束调试,下面的命令更有用:

  • q|qq|qd

  q是Quit的缩写。结束当前调试会话,并返回到最简单的工作空间,甚至把命令行界面也关闭掉。q和qq两个命令将关闭被调试的进程,qd不会关闭调试进程,而是进行解挂操作。

  双机调试的时候,如果目标机动都动不了,此时通过主机让目标机强制宕机或重启,不失为一个好主意。

  • .crash
  • .reboot

  crash命令能引发一个系统蓝屏,并生成dump文件;而.reboot使系统重启,不产生dump文件。

  一、二、三、四篇都来自于:http://www.yiiyee.cn/Blog/windbg/

posted on 2014-05-14 16:21  逆心  阅读(9144)  评论(0编辑  收藏  举报