1. 程式人生 > >windbg 常用命令詳解

windbg 常用命令詳解

一、

1、 !address eax

檢視對應記憶體頁的屬性


2、 vertarget

顯示當前程序的大致資訊


3 !peb

顯示process Environment Block


4、 lmvm

可以檢視任意一個dll的詳細資訊
例如:我們檢視cyusb.sys的資訊



5.reload !sym 載入符號檔案


6、 lmf

列出當前程序中載入的所有dll檔案和對應的路徑


7、 r

命令顯示和修改暫存器上的值
r命令顯示和修改暫存器上的值

0:018> r eax=0 修改了暫存器,把eax的值修改為0x0


8、 d

命令顯示esp暫存器指向的記憶體
如下


用dd命令直接指定054efc14地址


注意第二個d表示DWORD格式,此外還有db(byte),du(Unicode),dc(char)等等。
資料檢視指令 d{a|b|c|d|D|f|p|q|u|w|W}
d{b|c|d|D|f|p|q}分別是顯示:
byte&ASCII, double-word&ASCII,double-word,double-precision,float,pointer-sized,quad-word資料;
DA用於顯示ASCII,DU用於顯示UNICODE;
BYB,BYD,顯示binary和Byte及binary和DWORD
補充一個DV,用於檢視本地變數用的


9、 e

命令可以用來修改記憶體地址
跟d命令一樣,e命令後面也可以跟型別字尾,比如ed命
令表示用DWORD的方式修改。下面的命令把054efc14地址上的值修改為11112222。
0:018>ed 054efc14 11112222
修改後可以用dd命令來檢視記憶體。
0:018>dd 0543fc14 L4 L4引數指定記憶體區間的長度為4個DWORD,這樣輸出只有1行,
而不是8行了。


10、s

命令用來搜尋記憶體具體見help文件
11!runaway 可以顯示每一個執行緒的cpu消耗
0:018> !runaway 結果如下:
0:83c 0 days 0:00:00.406
13:bd4 0 days 0:00:00.046
10:ac8 0 days 0:00:00.046
24:4f4 0 days 0:00:00.031
上面輸出的第一列是執行緒的編號和執行緒ID,後一列對應的是該執行緒在使用者態模式中的
總的繁忙時間。
在該命令加上f引數,還可以看到核心態的繁忙時間,當程序記憶體佔用率比較高的時候
,通過該命令可以方便的找到對應的繁忙執行緒。

12、 ~     命令是用來切換目標執行緒

0:018> ~ 可以顯示執行緒的資訊
0:018> ~0s   把當前的執行緒切換到0號執行緒,也就是主執行緒,切換後提示符會變為0:000.

13 、~* 命令列出當前程序中的所有執行緒的詳細資訊

14、~*kb    命令列出所有執行緒的堆疊

15、 k     命令用來顯示當前執行緒的堆疊,如下

0:018> k
跟d命令一樣,k後面也可以跟很多字尾,比如kb kp,kn,kv,kl等,這些字尾控制了顯示的格式和資訊
棧指令k[b|p|P|v]
這四條指令顯示的內容類似,但是每個指令都有特色;

KB顯示三個引數;

Kp顯示所有的引數,但需要Full Symbols或Private PDBSymbols支援。KP與Kp相似,只是KP將引數換行顯示了;

Kv用於顯示FPO和呼叫約定;

KD,用於顯示Stack的Dump,在跟蹤棧時比較有用。
這些指令區分大小。

16 、u   命令把指定地址上的程式碼翻譯成彙編輸出

0:018> u 7739d023
USER32!NtUserWaitMessage:
7739d023 b84a120000 mov eax,0x124a
7739d028 ba0003fe7f mov edx,0x7ffe0300
7739d02d ff12 call dword ptr [edx]
7739d02f c3 ret
如果符號檔案載入正確,可以用uf命令直接反彙編整個函式,比如uf USER32! NtUserWaitMessage

17 、x    查詢符號的二進位制地址如下

0:018> x msvcr!printf
77bd27c2 msvcrt!printf =
上面的命令找到了printf函式的入口地址在77bd27c2

0:001> x ntdll!GlobalCounter
7c99f72c ntdll!GlobalCounter =
上面的命令表示ntdll!GlobalCounter這個變數儲存的地址是7c99f72c。


注意:符號對應的是變數和變數所在的地址,不是變數的值,上面只是找到GlobalCounter這個變數的值是7c99f72,要找到變數的值,需要用d命令讀取記憶體地址來獲取。

X命令還支援萬用字元,比如x ntdll !*命令列出ntdll模組中的所有的符號,以及對應的二進位制地址。

18、 dds 列印記憶體地址上的二進位制值

同時自動搜尋二進位制值對應的符號。
比如要看看當前**中儲存了那些函式地址,就可以檢查ebp指向的記憶體
0:018>dds ebp
0013ed98 0013ee24
0013ed9c 75ecb30f BROWSEUI!BrowserProtectedThreadProc+0x44
0013eda0 00163820
0013eda4 0013ee50
0013eda8 00163820
0013edac 00000000
0013edb0 0013ee10
0013edb4 75ece83a BROWSEUI!__delayLoadHelper2+0x23a
0013edb8 00000005
0013edbc 0013edcc
0013edc0 0013ee50
0013edc4 00163820
0013edc8 00000000
0013edcc 00000024
0013edd0 75f36d2c BROWSEUI!_DELAY_IMPORT_DESCRIPTOR_SHELL32
0013edd4 75f3a184 BROWSEUI!_imp__SHGetInstanceExplorer
0013edd8 75f36e80 BROWSEUI!_sz_SHELL32
0013eddc 00000001
0013ede0 75f3726a BROWSEUI!urlmon_NULL_THUNK_DATA_DLN+0x116
0013ede4 7c8d0000 SHELL32!_imp__RegCloseKey (SHELL32+0x0)
0013ede8 7c925b34 SHELL32!SHGetInstanceExplorer

這裡dds命令從ebp指向的記憶體地址0013ed98開始列印,第一列是記憶體地址的值,第二列是地址上對應的二進位制資料,第三列是二進位制對應的符號。上面的命令自動找到了75ecb390f對應的符號是BROWSEUI!BrowserProtectedThreadProc +0x44.

Com interface 和c++ vtable裡面的成員函式都是順序排列的。所以,dds命令可以方便的找到虛擬函式表中的具體的函式地址,比如用下面的命令可以找到OpaqueDatinfo型別中虛擬函式的實際函式地址。
首先通過x命令找到OpaqueDataInfo虛擬函式地址
0:000> x ole32!OpaqueDataInfo::vftable’
7768265c ole32!OpaqueDataInfo::`vftable'' =
77682680 ole32!OpaqueDataInfo::`vftable'' =
接下來dds命令可以打印出虛擬函式表中的函式名字
0:000> dds 7768265c


19 .frame

命令在棧中切換以便檢查區域性變數。
要檢視區域性變數的需要如下:
19、1    檢視執行緒的callstack

第一列的號稱為Frame num,通過.frame命令就可以切換到對應的函式中檢查區域性變數,比如我們檢查CYUSB+0x916,這個函式的frame num是0,於是,我們如下:
19、2   iframe    切換到指定行號的函式中

19、3   然後呼叫 x  顯示當前frame的區域性變數,比如這個函式中有兩個區域性變數pcls和rawptr
0:018> x
0012fced pcls = 0x0039ba80
0012fcd8 rawptr = 0x0039ba80

20、 dt  格式化顯示資料

Dt   命令格式化顯示變數的資料和結構
0:000> dt pcls
Local var @ 0x12fce4 Type MyCls*
0x0039ba80
+0x000 str : 0x00416648 'abcd'
+0x004 inobj : inner
上面的命令打印出pcls的型別是MyCls指標,指向的地址是0x0039ba80,其中的兩個class成員的偏移分別在+0和+4,對應的值在第2列顯示。加上-b -r引數可以顯示inner class和陣列的資訊:
0:000> dt pcls -b -r
Local var @ 0x12fce4 Type MyCls*
0x0039ba80
+0x000 str : 0x00416648 'abcd'
+0x004 inobj : innner
+0x000 arr : 'abcd'
[00] 97 ''a''
[01] 98 ''b''
[02] 99 ''c''
[03] 100 ''d''
[04] 0 ''''
[05] 0 ''''
[06] 0 ''''
[07] 0 ''''
[08] 0 ''''
[09] 0 ''''
對於任意的地址,也可以手動指定符號型別來格式化顯示。比如把0x0039ba80地址上的資料用MyCls型別來顯示:
0:000> dt 0x0039ba80 MyCls
+0x000 str : 0x00416648 'abcd'
+0x004 inobj : innner

21、  bp   設定除錯斷點

(1)比如可以這樣寫:0:018>bp notepad!WinMain 在notepade的winmain函式處下斷點。
斷點的位置可以用符號來表示,如上,也可以直接用地址以及windbg的Pseudo_Register(虛擬暫存器)。

比如,我們用$exentry表示程序的入口,那麼可以用bp @$exentry在程序的入口設定斷點。

(2)如果notepade的winmain的入口地址為01006420,那麼斷點也可以這麼寫:
Bp 01006420
bp mysource.cpp:143` 'j (poi(MyVar)”0x20) ''''; ''g'' '
意思就是:當myvar的值等於0x20時,g命令繼續執行;
(3)下面一個設定條件斷點
0:001> bp exceptioninject!foo3 “k; .echo ‘breaks’ ; g”
在exceptioninject!foo3上設定斷點後,每次斷下來後,先用k顯示callstack,然後用.echo命令輸出簡單的字串‘breaks’,最後g命令繼續執行。
(4)下面看一個更復雜的設定條件斷點的例子:
ba w4 execptioninject!i ”j(poi(exceptioninject!i)<0n40) ‘.printf//”exceptioninject!i value is :%d//”,poi(exceptioninject!i); g’ ; ‘.echo stop!’ ”
首先ba w4 exceptioninject!i 表示在修改exceptioninject!i這個全域性變數的時候,停下來;
j(judge)命令的作用就是對後面的表示式作條件判斷如果為true,執行第一個單引號裡面的命令,否則執行第2個單引號裡面的命令,
條件表示式是(poi(exceptioninject!i)<0n40),在windbg中excepioninject!i符號表示符號所在的記憶體地址,而不是符號的數值,相當於c語言的&操作符的作用,poi命令就是取這個地址上的值,相當於c語言的*操作符。

所以這個條件判斷的意思就是判斷exceptioninject!i的值,是否小於十進位制的40。如果為真,就執行第一個單引號,‘.printf//”exceptioninject!i value is :%d//”,poi(exceptioninject!i); g’,如果為假,就執行第二個單引號‘.echo stop!’
第一個單引號裡有三個命令,.printf .echo 和g。這裡的printf和c語言的printf函式語法一樣,不過由於這個printf命令本身是在ba命令的雙引號裡面,所以需要用//來轉義print中的引號。第一個引號的作用是:打印出當前exceptioninject!i的值,.echo命令換行 g命令繼續執行
第二個引號的作用就是顯示stop,由於後面沒有g命令,所以windbg會停下。

22、  bm   使用模式匹配設定斷點

這個功能需要符號表的支援,bm可以通過模式一次設定多個斷點,比如
bm mydriver!FastIO* 可以將所有與FastIO*模式匹配的函式下設定斷點,比如FastIoRead ,FastIoWriter等函式都會被設定上斷點。需要注意的是,bm命令需要full or export symbols支援。

23、 ba     對記憶體訪問設定斷點 break on access

就是對於記憶體訪問設定斷點,對於在多核處理或者多核處理器除錯的時候很有用,對於除錯多執行緒也很有用,比如說,我們可以對一個全域性變數設定斷點,
ba mydriver!gMonitoreedDevices , 如果你認為這個變數的值被莫名的修改了,相信通過ba設定的斷點,你可以很快找到是誰修改的。

也可以這樣
ba w4 0x4000000 'kb;g' 當0x4000000地址有寫操作時,進入斷點 。w表示型別為寫 4表示長度為4個位元組

24 、bl 列出所有的斷點 break list
25、 bc 清除斷點 break clear

 bc [斷點號]

26、 be 開啟斷點 break enable
27、 bd禁用斷點 break disable

以上提到的斷點指令通過和j指令很容易形成條件斷點,比如
bp USER32!GetMessageW 'r $t1=poi(esp+4);r $t2=poi(@$t1+4); j(@$t2 = 0x102 ) ''du @$t1+8 L2;gc'';''gc'''
這個條件斷點,擷取WM_CHAR訊息,並將字元(包括中文)顯示出來。
條件斷點的最簡形式:bp Address 'j (Condition) ''OptionalCommands''; ''gc'' '
Address是指令的地址,Condition是一個條件表示式,如果@eax=1,''OptionalCommands''是在斷點被擊中並且表示式成立時要執行的指令;gc指定是從一個條件斷點返回,是不可少的一部分。

28、跟蹤指令T,TA,TB,TC,WT,P,PA,PC

T   指令單步執行,在原始碼除錯狀態下,可指原始碼的一行,根據不同的選項也可以為一行ASM指令
TA   單步跟蹤到指定地址,如果沒有引數將執行到斷點處

TB  執行到分支指令,分支指令包括calls,   returns,   jumps,    counted loops,    and while loops;
TC  執行到Call指令;
WT  Trace and Watch Data,一條強大指令,對執行流程做Profile,執行一下看看結果吧;
P,PA,PC    相信不用多做解釋,大家也都明白了;

29、原始碼操作指令.,lsf,lsc,ls,l,lsp

.指令打一個原始檔,可以開啟一個全路徑的檔案,也可以通過函式地址來開啟並定位到原始檔中函式的位置,如. –a myapp!main,. j://mydriver//mydriver.c
lsf指定一個原始檔為當前原始檔,使用lsc可顯示當前指定的原始檔ls可顯示原始檔的程式碼。Lsf可以使用全路徑,如果源路徑已經設定,也可以直接指定原始檔名稱。如lsf mydriver.c,lsf j://mydriver//mydriver.c
lsc顯示當前原始檔
ls顯示當前原始檔的程式碼,如ls 200顯示第200行
l 用於設定原始檔選項
lsp 設定原始檔行在除錯時顯示範圍比如,
顯示當前行的前50,後50,lsp 100
但通常使用Windbg時,可以直接用Ctrl+O來開啟並檢視原始檔

30 、查詢符號

kd> x nt!KeServiceDescriptorTable*
8046e100 nt!KeServiceDescriptorTableShadow =
8046e0c0 nt!KeServiceDescriptorTable =
kd> ln 8046e100
(8046e100) nt!KeServiceDescriptorTableShadow | (8046e140) nt!MmSectionExtendResource
Exact matches:
nt!KeServiceDescriptorTableShadow =

31、!gle 檢視LastError值
32、指定進位制的形式0x/0n/0t/y 分別表示 16/10/8/2進位制

? 0x12345678+0n10
Evaluate expression: 305419906 = 12345682
33、!sym noice/quiet symbol prompts開關

34、srcpath 設定原始碼的路徑
35、dv檢視本地變數
36、!teb 顯示當前執行緒的執行塊(execution block)
37、!peb 顯示當前程序的執行塊(execution block)
38、ln[Address] 顯示當前地址上的物件型別
39、!locks 顯示死鎖
40、!handle可以獲取整個程序或者某一個handle的詳細資訊

首先執行以下!handle,可以看到當前程序的每個一個handle的型別,以及統計資訊
0:002>!handle
Handle 4
Type key
Handle c
Type keyEvent
…….
然後找到一個key,檢視詳細資訊
0:001>!handle 4 f
就會列出這個handle的詳細資訊。
41!htrace命令檢查操作控制代碼的歷史記錄
!htrace命令可以打印出指定的handle的最近幾次呼叫堆疊
0:001>!htrace 384

42、!cs列出CriticalSection的詳細資訊
43、!threadpool能看到完成埠,線城池工作執行緒和timer回撥佔線程池的情況
44、time 可以看到程序跑了多長時間
45、 !dso 檢視當前執行緒中有哪些物件,分析洩露時用到
46、dump儲存程序的dump檔案

Dump檔案是程序的記憶體映象,

可當在偵錯程式中開啟dump檔案時,使用上面的命令檢查,看到的結果跟用除錯檢查程序看到的一樣
.dump /ma c://testdump.dmp
這個命令把當前程序的映象儲存為c://testdump.dmp,其中/ms引數表示dump的檔案應該包含程序的完整資訊。
在windbg中,通過file—open---open Crash dump選單開啟dump檔案進行分析。開啟檔案後,執行除錯命令看到的資訊和狀態就是dump檔案儲存時程序的狀態。通過dump檔案能夠方便的儲存發生問題時程序的狀態,方便事後分析。

47、
0: kd> !idt                           //檢視中斷向量表內容
0: kd> dt nt!_KINTERRUPT 89c03bb0     //檢視對應中斷向量的詳細內容
0: kd> !ioapic                        //顯示I/O APIC(即連線至裝置的中斷控制部件)
0: kd> !pic                           // 
0: kd> !apic                          //有關PIC的配置情況


kd> !idt執行後顯示為

0: kd> !idt

Dumping IDT:

37:	806e7864 hal!PicSpuriousService37
3d:	806e8e2c hal!HalpApcInterrupt
41:	806e8c88 hal!HalpDispatchInterrupt
50:	806e793c hal!HalpApicRebootService
63:	89ac57e4 USBPORT!USBPORT_InterruptService (KINTERRUPT 89ac57a8)
	         USBPORT!USBPORT_InterruptService (KINTERRUPT 8982abb0)
73:	89d6767c atapi!IdePortInterrupt (KINTERRUPT 89d67640)
	         atapi!IdePortInterrupt (KINTERRUPT 89dc4bb0)
83:	89c1471c VIDEOPRT!pVideoPortInterrupt (KINTERRUPT 89c146e0)
	         HDAudBus!AzController::Isr (KINTERRUPT 89c16ac8)
	         NDIS!ndisMIsr (KINTERRUPT 89847bb0)
94:	8976fbec USBPORT!USBPORT_InterruptService (KINTERRUPT 8976fbb0)
a4:	89770bec USBPORT!USBPORT_InterruptService (KINTERRUPT 89770bb0)
b1:	89d859e4 ACPI!ACPIInterruptServiceRoutine (KINTERRUPT 89d859a8)
b4:	89c03bec USBPORT!USBPORT_InterruptService (KINTERRUPT 89c03bb0)
c1:	806e7ac0 hal!HalpBroadcastCallService
d1:	806e6e54 hal!HalpClockInterrupt
e1:	806e8048 hal!HalpIpiHandler
e3:	806e7dac hal!HalpLocalApicErrorService
fd:	806e85a8 hal!HalpProfileInterrupt
fe:	806e8748 hal!HalpPerfInterrupt
//前部分是使用的中斷型別號。例如83號中斷是有三個硬體複用。

2.0: kd> dt nt!_KINTERRUPT 89c03bb0,執行後顯示為

0: kd> dt nt!_KINTERRUPT 89c03bb0
   +0x000 Type             : 0n22
   +0x002 Size             : 0n484
   +0x004 InterruptListEntry : _LIST_ENTRY [ 0x89c03bb4 - 0x89c03bb4 ]
   +0x00c ServiceRoutine   : 0xb9159e54     unsigned char  USBPORT!USBPORT_InterruptService+0
   +0x010 ServiceContext   : 0x89c38028 Void
   +0x014 SpinLock         : 0
   +0x018 TickCount        : 0xffffffff
   +0x01c ActualLock       : 0x89c03e14  -> 0
   +0x020 DispatchAddress  : 0x805466d0     void  nt!KiInterruptDispatch+0
   +0x024 Vector           : 0x1b4
   +0x028 Irql             : 0xa ''
   +0x029 SynchronizeIrql  : 0xa ''
   +0x02a FloatingSave     : 0 ''
   +0x02b Connected        : 0x1 ''
   +0x02c Number           : 0 ''
   +0x02d ShareVector      : 0x1 ''
   +0x030 Mode             : 0 ( LevelSensitive )
   +0x034 ServiceCount     : 0
   +0x038 DispatchCount    : 0xffffffff
   +0x03c DispatchCode     : [106] 0x56535554

3.0: kd> !ioapic,執行後顯示

0: kd> !ioapic
IoApic @ FEC00000  ID:8 (20)  Arb:170020
Inti00.: 52000000`000100ff  Vec:FF  FixedDel  Ph:52000000      edg high      m
Inti01.: 00c00000`000100ff  Vec:FF  FixedDel  Ph:00C00000      edg high      m
Inti02.: 00000000`000100ff  Vec:FF  FixedDel  Ph:00000000      edg high      m
Inti03.: 00000000`000100ff  Vec:FF  FixedDel  Ph:00000000      edg high      m
Inti04.: 00000000`000100ff  Vec:FF  FixedDel  Ph:00000000      edg high      m
Inti05.: 52c00000`000100ff  Vec:FF  FixedDel  Ph:52C00000      edg high      m
Inti06.: 00c00000`000100ff  Vec:FF  FixedDel  Ph:00C00000      edg high      m
Inti07.: 02000000`000100ff  Vec:FF  FixedDel  Ph:02000000      edg high      m
Inti08.: 01000000`000008d1  Vec:D1  FixedDel  Lg:01000000      edg high       
Inti09.: 03000000`0000d9b1  Vec:B1  LowestDl  Lg:03000000-Pend lvl high rirr  
Inti0A.: 00c00000`000100ff  Vec:FF  FixedDel  Ph:00C00000      edg high      m
Inti0B.: 00000000`000100ff  Vec:FF  FixedDel  Ph:00000000      edg high      m
Inti0C.: 42000000`000100ff  Vec:FF  FixedDel  Ph:42000000      edg high      m
Inti0D.: 00000000`000100ff  Vec:FF  FixedDel  Ph:00000000      edg high      m
Inti0E.: 00000000`000100ff  Vec:FF  FixedDel  Ph:00000000      edg high      m
Inti0F.: 00000000`000100ff  Vec:FF  FixedDel  Ph:00000000      edg high      m
Inti10.: 03000000`0000f983  Vec:83  LowestDl  Lg:03000000-Pend lvl low  rirr  
Inti11.: 00000000`000100ff  Vec:FF  FixedDel  Ph:00000000      edg high      m
Inti12.: 03000000`0000a994  Vec:94  LowestDl  Lg:03000000      lvl low        
Inti13.: 00c00000`000100ff  Vec:FF  FixedDel  Ph:00C00000      edg high      m
Inti14.: 03000000`0000a973  Vec:73  LowestDl  Lg:03000000      lvl low        
Inti15.: 03000000`0000a963  Vec:63  LowestDl  Lg:03000000      lvl low        
Inti16.: 03000000`0000a9a4  Vec:A4  LowestDl  Lg:03000000      lvl low        
Inti17.: 03000000`0000f9b4  Vec:B4  LowestDl  Lg:03000000-Pend lvl low  rirr  

4.0: kd> !pic ,執行後顯示

0: kd> !pic
----- IRQ Number ----- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
Physically in service:  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
Physically masked:      Y  Y  Y  Y  Y  Y  Y  Y  Y  Y  Y  Y  Y  Y  Y  Y
Physically requested:   Y  .  .  Y  .  Y  .  .  Y  Y  Y  Y  .  .  .  .

5.0: kd> !apic,執行後顯示

0: kd> !apic
Apic @ fffe0000  ID:0 (50014)  LogDesc:01000000  DestFmt:ffffffff  TPR FF
TimeCnt: 0fdad680clk  SpurVec:1f  FaultVec:e3  error:40
Ipi Cmd: 02000000`000008e1  Vec:E1  FixedDel  Lg:02000000      edg high       
Timer..: 00000000`000300fd  Vec:FD  FixedDel    Dest=Self      edg high      m
Linti0.: 00000000`0001001f  Vec:1F  FixedDel    Dest=Self      edg high      m
Linti1.: 00000000`000084ff  Vec:FF  NMI         Dest=Self      lvl high       
TMR: 63, 73, 83, 94, A4, B1, B4
IRR: 41, B1, D1
ISR: D1

 48、.cls

 .cls用於清屏

注意:得在windbg處於命令列模式時才可用(即按了Ctro+Break)

 或者直接使用工具欄:

二、

Windbg斷點命令

1. 設定斷點命令bu bp bm ba

1) bu bp bm設定軟體斷點

a). bp設定地址關聯的斷點

b). bu設定符號關聯的斷點

c). bm支援設定含萬用字元的斷點,可以一次建立一個或多個bu或bp (bm /d)斷點

bp和bu的主要區別

a) bp所設斷點和地址關聯,如果模組把該地址的指令移到其它地方,斷點不會隨之移動,而是依然關聯在在原來的地址上; 而bu所設斷點是和符號關聯,如果符號的地址改變了,斷點依然保持和原來的符號關聯。

b) 如果bp所設斷點的地址在載入的模組中被找到,後來軟體模組被解除安裝,斷點會被自動移除;而bu所設斷點則會一直存在。

c) bp設定的斷點不會被儲存windbg的workspace中,bu設定的斷點會則會被儲存下來。

2)ba設定硬體斷點(資料斷點)

硬體斷點是指當一個記憶體地址被訪問(讀、寫、執行)或IO埠被訪問時觸發的斷點。

2. 其它命令bl bc bd be .bpcmds

bl 列舉所有斷點和它們的狀態

bc 刪除對應斷點

bd 禁用對應斷點

be 啟用對應斷點

.bmcmds 列舉所有斷點以及建立它們的命令

3. 軟體斷點和硬體斷點

1) 軟體斷點 - 除錯工具控制的斷點。當偵錯程式在某個地址設定一個斷點,它會首先把該地址的內容儲存,零時插入一條中斷指令(如int3 (0xCC)),當程式執行到該地址是cpu進入除錯狀態,當除錯結束,程式重新載入該地址原先的指令重新執行下去。

2) 硬體斷點 - 又稱為資料斷點,是處理器控制的斷點,可以用來監控某個記憶體地址的訪問(讀、寫、執行)和IO地址的訪問(讀、寫)。處理器中有相應的除錯暫存器,用來記錄資料斷點的地址,當該地址(記憶體地址或IO埠地址)被訪問時,斷點將被觸發,cpu進入除錯狀態。

3) 軟體斷點和硬體斷點的區別

a)理論上我們可以設定無窮多個軟體斷點,但設定軟體斷點會使程式變慢,尤其在核心態影響比較大,偵錯程式大多會對斷點數量加以限制。例如Windbg在核心態最多支援32個軟體斷點,在使用者態則支援任意多個;硬體斷點數量取決於處理器,例如X86支援四個斷點(80386有八個除錯暫存器-DR0~DR3用於斷點,DR4~DR5保留,DR6~DR7用於控制)。

b)軟體斷點需要修改相應程式碼,所以它不能除錯時flash和rom中的程式碼;而硬體則沒有這個限制。

3. 參考資料

1. 使用!process 0 0 獲取使用者空間的所有的程序的資訊

如果有多個相同程序名,!process 0 0 SampleExe.exe

kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS fe5039e0  SessionId: 0  Cid: 0008    Peb: 00000000  ParentCid: 0000
    DirBase: 00030000  ObjectTable: fe529b68  TableSize:  50.
    Image: System

2.使用.process /i 指定程序地址

因為要對使用者態程式碼下斷點,這裡不用/p,而使用/i

If you want to use the kernel debugger to set breakpoints in user space, use the/i option to switch the target to the correct process context.

3. g繼續,再次發生int 3中斷後,程序Context就已切換,使用!process檢視確認。

4. reload符號檔案。

5. bu, bp下使用者態斷點。