Windbg調試命令詳解(1)

轉載註明>> 作者張佩】【鏡像:http://www.yiiyee.cn/Blog

1. 概述

用戶成功安裝微軟Windows調試工具集後,能夠在安裝目錄下發現四個調試器程序,分別是:cdb.exe、ntsd.exe、kd.exe和Windbg.exe。其中cdb.exe和ntsd.exe只能調試用戶程序,Kd.exe主要用於內核調試,有時候也用於用戶態調試,上述三者的一個共同特點是,都只有控制檯界面,以命令行形式工作。

Windbg.exe在用戶態、內核態下都能夠發揮調試功能,尤其重要的是,它不再是命令行格式而是採用了可視化的用戶界面。所以絕大部分情況下,我們在談及Windows調試工具的時候,都直接指向Windbg,而不大談及前三者。

Windbg在用戶態和內核態下,都支持兩種調試模式,即“實時調試模式(Living)”和“事後調試模式(Postmortem)”。所謂實時模式,是被調試的目標對象(Target)當前正在運行當中,調試器可以實時分析、修改被調試目標的狀態,如寄存器、內存、變量,調試exe可執行程序或雙擊實時調試都屬於這種模式;所謂事後模式,是被調試的目標對象(Target)已經結束了,現在只是事後對它保留的快照進行分析,這個快照稱爲轉儲文件(Dump文件)。

Windbg另一個重大優點,還在於它支持源碼級的調試,就像VC自帶的調試器一樣。

雖然提供了用戶界面,但Windbg歸根結底還是需要用戶一個個地輸入命令來指揮其行動。這就是他的Command窗口。

每個調試命令都各有使用範圍,有些命令只能用於內核調試,有些命令只能用於用戶調試,有些命令只能用於活動調試。但用戶也不必記得這許多,一旦在某個環境下,使用了不被支持的命令,都會顯示“No export XXX found”的字樣。就拿!process命令來說吧,它顯示進程信息,但只能用於內核調試中,如果在用戶調試中使用,就是下面的情景:

0:001> !process
No export process found

1.1 尋求幫助

我們首先來看如何在使用過程中獲取有用的幫助。Windbg中的調試命令,分爲三種:基本命令,元命令和擴展命令。基本命令和元命令是調試器自帶的,元命令總是以“.”開頭,而擴展命令是外部加入的,總是以感嘆號“!”開頭。各種調試命令成千上萬,我們首先要想辦法把它們都列舉出來,並取得使用方法。

基本命令最少了,大概40個左右。列舉所有的基本命令,使用如下命令:

  • ?

元命令有一百多個,使用下面命令列舉所有元命令:

  • .help  [/D]

如使用“/D”參數,命令列表將以DML格式顯示。DML是一種類似於HTML的標識語言,下面會講到。下圖以DML格式顯示所以有字母a開頭的元命令:

dotcommand

最後講擴展命令。所謂擴展命令,顧名思義是可以“擴展”的。擴展命令從動態連接庫中暴露出來,一般以DLL文件名來代表一類擴展命令集,首先我們要搜索出系統中有多少個這樣的DLL文件,使用下面命令:

  • .chain  [/D]

此命令能夠給出一個擴展命令集的鏈表。和.help命令一樣,也可以使用/D參數以DML格式顯示。如下所示:

0:001> .chain
Extension DLL search Path:
    C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\WINXP;
Extension DLL chain:
    dbghelp: image 6.2.9200.20512, API 6.2.6, built Fri Sep 07 13:45:49 2012
        [path: C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\dbghelp.dll]
    ext: image 6.2.9200.16384, API 1.0.0, built Thu Jul 26 10:11:33 2012
        [path: C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\winext\ext.dll]
    exts: image 6.2.9200.16384, API 1.0.0, built Thu Jul 26 10:15:20 2012
        [path: C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\WINXP\exts.dll]
    uext: image 6.2.9200.16384, API 1.0.0, built Thu Jul 26 10:15:09 2012
        [path: C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\winext\uext.dll]
    ntsdexts: image 6.2.9200.16384, API 1.0.0, built Thu Jul 26 10:16:01 2012
        [path: C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x64\WINXP\ntsdexts.dll]

            最上面兩行顯示了擴展模塊的搜索路徑。接下來共列出了六個Windbg自帶的擴展模塊:wdfkd、dbghellp、ext、exts、uext和ntsdexts。可以查看到這些擴展模塊的版本信息、鏡像文件路徑。如何列出某個擴展庫中所包含的擴展命令列表呢?絕大部分擴展模塊可使用如下命令:

  • !模塊名.help

此外,擴展命令模塊是可“擴展”的。如果讀者從第三方處獲取,或自己編寫了一個擴展調試模塊,則可通過.load/.unload命令動態加載/卸載。

1.2 DML語言

DML(Debugger Markup Language調試器標記語言)像HTML一樣,可從一處鏈接到另一處。不同處在於,DML的鏈接內容需要用戶點擊後纔會動態生成。一般用來以精簡方式顯示大量信息和擴展功能。

DML有很多實用的功能,如果使用者一時不知道從何下手,最好就是輸入.dml_start命令,開始DML之旅。

dml

DML鏈接以更加可視化的方式,引導用戶查看調試信息,使得調試工具的使用相比純指令格式而言,更爲友好。DML如同是對原指令的一層輕微的包裝一樣,讓生硬的指令更加溫和了。所以建議讀者總是把DML默認開啓。

  • .prefer_dml  1

開始DML。

  • .prefer_dml  0

關閉DML。

一旦開啓DML後,像k等支持DML的調試命令,將默認以DML格式顯示輸出內容。

DML還能以一種很特殊的方式爲函數畫流程圖。它主要的原理是使用反彙編,類似於uf,但在邏輯分支處,它會停止反彙編並顯示分支讓用戶選擇。另外,它能顯示彙編代碼對應的行號,這一點真的非常好。如果稍加精進,他就能畫出非常漂亮的流程圖了。他的一個特點是反彙編的順序是從後往前推。只要細想一想,就會覺得很有道理。如果正推的話,分支太多;而反推則分支順序在用戶的參與下(即用戶進行分支選擇),是固定了的。

  • .dml_flow  FindAllInfFilesA  FindAllInfFilesA+30

這是一個非常簡單、實用的例子,對Kernel32庫中的FindAllInfFilesA接口函數進行反彙編,效果類似uf命令卻更強大。

1.3 基本信息

本節講解和調試器軟件本身相關的命令,比如:查看軟件版本、啓動參數,以及最基本的軟件設置命令。首先看版本命令:

  • version

此命令顯示操作系統的版本信息以及Windbg本身的版本信息,Windbg的配置和操作系統密切相關,所以將操作系統的版本信息一併顯示出來是很有必要的。在內核環境與用戶環境下運行此命令,會得到不同的輸出。下圖爲內核環境下輸出結果:

0:001> version
Windows 7 Version 7601 (Service Pack 1) MP (8 procs) Free x64
Product: WinNt, suite: SingleUserTS
kernel32.dll version: 6.1.7601.18015 (win7sp1_gdr.121129-1432)
Machine Name:
Debug session time: Thu Aug 22 10:11:04.000 2013 (UTC + 8:00)
System Uptime: 14 days 17:26:44.613
Process Uptime: 14 days 17:14:25.000
  Kernel time: 0 days 0:09:02.000
  User time: 0 days 0:42:36.000
Full memory user mini dump: C:\Users\mozhang\AppData\Local\Temp\dwm.DMP

Microsoft (R) Windows Debugger Version 6.2.9200.16384 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

除了Windbg版本信息,上面的輸出中還包括目標系統信息。如果純粹是爲了查看目標系統的版本信息,可使用下面的vertarget命令:

  • vertarget

Windbg支持對多個調試系統中的多個調試目標同時進行調試。上面我們通過version或vertarget命令列出了當前調試系統的版本信息,還可以查看當前目標系統的狀態:

  • ||

如Windbg中同時打開多個調試對象,“||”命令將列出對象列表。筆者爲了演示此種情況,先在Windbg中開啓Local Debug環境,然後兩次調用.opendump命令打開兩個DUMP文件,這樣就同時擁有了三個被調試的目標對象。下圖顯示了這個情況:

multi-target

            上圖中的活動對象是0號對象(可從數字0前面的小數點看出)。調試器需要在多個調試目標之間進行切換的話,使用“s”參數。如要切換到1號目標可使用下面的命令:

  • ||  1  s

最後一個命令用來查看系統時間。這包括系統當前時間,以及系統正常運行持續時間;用戶模式下還會顯示當前進程的持續時間。命令格式如下:

  • .time
0:001> .time
Debug session time: Thu Aug 22 10:11:04.000 2013 (UTC + 8:00)
System Uptime: 14 days 17:26:44.613 // 系統運行時間
Process Uptime: 14 days 17:14:25.000// 當前進程運行時間
  Kernel time: 0 days 0:09:02.000
  User time: 0 days 0:42:36.000

1.4 基本設置

首先看一個清屏命令:

  • .cls

當命令窗口中的內容太亂的時候,這個命令幫你快刀斬亂麻。

下面看一個設置默認數字進制的命令:

  • n  [8|10|16]

軟件默認是16進制,但有時候我們也需要把默認進制改成八進制或十進制的。下面嘗試在八進制下面求數字11的值,如下:

0:001> n 8
base is 8
0:001> ? 11
Evaluate expression: 9 = 00000000`00000009

最後再來說一個處理器模式指令。關於處理器模式很值得一說,很重要。處理器模式的設置,反映了Windbg軟件的強大。舉例來說,主機爲32位的系統,卻可以同時調試X86、IA64、X64的目標系統——前提是先將主機的處理器模式設置正確了。可用處理器模式值有:x86、adm64、ia64、ebc。

  • .effmach  x86

命令.effmach表示Effective Machine Type,即有效的機器類型。此命令將當前的處理器模式設置爲x86模式。

1.5 格式化顯示

將一個整數以各種格式顯示,包括:16進制、10進制、8進制、二進制、字符串、日期、浮點數等。是不是很方便?這個命令是:

  • .formats  整數

下面以0x123abc爲例:

0:001> .formats 0x123abc
Evaluate expression:
  Hex:     00000000`00123abc
  Decimal: 1194684
  Octal:   0000000000000004435274
  Binary:  00000000 00000000 00000000 00000000 00000000 00010010 00111010 10111100
  Chars:   ......:.
  Time:    Thu Jan 15 03:51:24 1970
  Float:   low 1.67411e-039 high 0
  Double:  5.90252e-318

1.6 開始調試

現在領大家進入調試階段。首先看看如何讓調試器附載到一個已運行的進程中去?比如IE軟件在運行過程中發生了崩潰,打開Windbg後如何調試呢?第一步就是把Windbg附載到發生崩潰的IE進程上。使用如下命令格式:

  • .attach  PID

或者通過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子進程,但這個選項只能被執行一次(之後會灰掉)。

使用上述命令可將調試器連續附載到多個進程,也就是說,能夠同時調試多個進程,這一點看上去很神奇哦。下例中,調試器先創建子程序IOCTL.exe,然後又調用.attach命令附加到記事本進程,使用命令“|”列出所有被調試進程。

讀者可能會奇怪,多個進程同時調試怎麼兼顧呢?只要有一個切換指令就可以了,這樣就能夠切換到任意的進程(令其爲當前進程)並對之進行調試。比如上圖顯示1號進程爲當前進程(注意1前面的小點),如何將當前進程切換到0號進程呢?可以使用進程列表命令“|”輕鬆切換,比如:

  • |  0  s

此命令把當前調試環境切換到0號IOCTL.exe進程。另外需注意的是,多個用戶進程調試目標都處於同一個調試會話中,使用“||”命令會看到,它們屬於同一個 “Live user mode”調試會話。

下面看dump文件調試,使用命令:

  • .opendump  文件名

此命令打開一個dump文件,並建立一個DUMP調試會話。如何手動創建一個dump文件呢?比如在調試過程中,遇到了無法解決的問題,希望獲得異地幫助,則把當前調試環境保存到Dump文件中發送給能提供幫助的人,不失爲一種好辦法。

  • .dump  文件名

Dump文件一般以.dmp爲後綴,系統生成的Dump文件都默認以.dmp爲後綴的,但使用.dump命令時,使用者可以設置任意後綴,甚至無後綴。下例中,首先爲當前進程生成一個dump文件保存到a.txt中(即後綴名爲.txt),然後將之打開並分析:

0:001> .dump a.txt
Creating a.txt - mini user dump
Dump successfully written
0:001> .opendump a.txt
Loading Dump File [C:\Program Files (x86)\Windows Kits\8.0\Debuggers\a.txt]
User Mini Dump File: Only registers, stack and portions of memory are available

Opened 'a.txt' // 打開成功

上文講到進程掛載命令,當需要解除掛載時,可使用解掛命令,如下:

  • .detach

此命令結束當前調試會話, Windbg解除和被調試進程之間的調試關係(不管是通過掛載,還是通過創建方式建立的調試關係),解掛後,被調試進程能夠獨立運行;如果當前的調試會話是一個Dump文件,此命令直接結束對dump文件的調試,即結束調試會話。

如果需要徹底結束調試,下面的命令更有用:

  • q | qq | qd

q是Quit的縮寫。結束當前調試會話,並返回到最簡單的工作空間,甚至把命令行界面也關閉掉。q和qq兩個命令將結束(close)被調試的進程,qd不會關閉調試進程,而是進行解掛操作。

雙機調試的時候,如果你感覺調試已經陷入僵局,比如目標機Hang住了動都動不了,此時通過主機讓目標機強制宕機或重啓,不失爲一個好主意。

  • .crash
  • .reboot

crash命令能引發一個系統藍屏,並生成dump文件;而.reboot使系統重啓,不產生dump文件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章