windbg調試命令1(k、u、x)


k*命令顯示給定線程的調用堆棧,以及其他相關信息

~0 k表示打印0號線程的調用堆棧,直接用k表示打印當前線程的調用堆棧

kd> ~0k  
  1. ChildEBP RetAddr    
  2. 0007fddc 77d191be ntdll!KiFastSystemCallRet  
  3. 0007fdfc 010021b0 USER32!NtUserGetMessage+0xc  
  4. 0007ff1c 010125e9 calc!WinMain+0x25f  
  5. 0007ffc0 7c817077 calc!WinMainCRTStartup+0x174  
  6. 0007fff0 00000000 kernel32!BaseProcessStart+0x23  
  7. 0:002> k  
  8. ChildEBP RetAddr    
  9. 00bfffc8 7c972119 ntdll!DbgBreakPoint  
  10. 00bffff4 00000000 ntdll!DbgUiRemoteBreakin+0x2d  
  11. 0:002> ~2k  
  12. ChildEBP RetAddr    
  13. 00bfffc8 7c972119 ntdll!DbgBreakPoint  
  14. 00bffff4 00000000 ntdll!DbgUiRemoteBreakin+0x2d  

我們注意到2號線程的堆棧,這是windbg創建一個遠程線程來執行DbgUiRemoteBreakin函數,它內部會調用DbgBreakPoint執行斷點指令,以觸發斷點異常,強制把程序斷了下來,所以windbg打印出來的線程總多了一條,所以不要驚訝為什么線程多了點。

 

其實我想弄清楚那個ChildEBP/RetAddr分別具體指什么:先K看下堆棧:

kd> k  
  1. ChildEBP RetAddr    
  2. 0012fb1c 7c95e612 ntdll!DbgBreakPoint  
  3. 0012fc94 7c94108f ntdll!LdrpInitializeProcess+0xffa  
  4. 0012fd1c 7c92e437 ntdll!_LdrpInitialize+0x183  
  5. 00000000 00000000 ntdll!KiUserApcDispatcher+0x7  


再打開反匯編窗口:

ntdll!DbgBreakPoint:  
  1. 7c92120e cc              int     3  

當前運行到這一行:再用r ebp查看下值:

kd> r ebp  
  1. ebp=0012fc94  

這個值是LdrpInitializeProcess前面的ChildEBP,F10單步調試到ret(也就是7c92120f)

ntdll!DbgBreakPoint:  
  1. 7c92120e cc              int     3  
  2. 7c92120f c3              ret  

再F10調試一步,退回到LdrpInitializeProcess中(7c95e612):

7c95e60d e8fc2bfcff      call    ntdll!DbgBreakPoint (7c92120e)  
  1. 7c95e612 8b4368          mov     eax,dword ptr [ebx+68h] ds:0023:7ffd3068=00000070  

我們發現這個7c95e612就是DbgBreakPoint的返回地址,也就是返回地址應該是指函數退出后下個EIP的值,我以前還一直以為是那個ret/leave對應的地方,原來是ret運行后的值.

kb 顯示傳遞給堆棧回溯中的每個函數的前三個參數kp 顯示傳遞給堆棧回溯中的每個函數的所有參數。參數列表包含參數的數據類型、名字和值。p命令是區分大小寫的。使用該參數需要完整符號信息。 (事實上我看到的結果和k一樣)kPp參數一樣,顯示傳遞給堆棧回溯中的每個函數的所有參數。但是,使用P ,函數參數在第二行中顯示,而不是作為數據的結尾在行末顯示。 (事實上我看到的結果和k一樣)

kd> kb  
  1. ChildEBP RetAddr  Args to Child                
  2. 00bfffc8 7c972119 00000005 00000004 00000001 ntdll!DbgBreakPoint  
  3. 00bffff4 00000000 00000000 00000008 000060c0 ntdll!DbgUiRemoteBreakin+0x2d  
  4. 0:002> kp  
  5. ChildEBP RetAddr    
  6. 00bfffc8 7c972119 ntdll!DbgBreakPoint  
  7. 00bffff4 00000000 ntdll!DbgUiRemoteBreakin+0x2d  
  8. </SPAN>  
kp在有符號文件存在時顯示會大不一行,我這貼一個debug下的kp打印:

 kd> kp  

  1. ChildEBP RetAddr    
  2. 0012f78c 7c92daea ntdll!KiFastSystemCallRet  
  3. 0012f790 7c932298 ntdll!ZwRequestWaitReplyPort+0xc  
  4. 0012f7b0 7c872a51 ntdll!CsrClientCallServer+0x8c  
  5. 0012f8ac 7c872b98 kernel32!ReadConsoleInternal+0x1be  
  6. 0012f934 7c8018b7 kernel32!ReadConsoleA+0x3b  
  7. 0012f98c 102c207c kernel32!ReadFile+0x64  
  8. 0012fa20 102c19c9 MSVCR90D!_read_nolock(int fh = 0, void * inputbuf = 0x10316740, unsigned int cnt = 0x1000)+0x62c [f:\dd\vctools\crt_bld\self_x86\crt\src\read.c @ 233]  
  9. 0012fa70 10253e43 MSVCR90D!_read(int fh = 0, void * buf = 0x10316740, unsigned int cnt = 0x1000)+0x219 [f:\dd\vctools\crt_bld\self_x86\crt\src\read.c @ 93]  
  10. 0012fa98 102523e8 MSVCR90D!_filbuf(struct _iobuf * str = 0x103113e8)+0x113 [f:\dd\vctools\crt_bld\self_x86\crt\src\_filbuf.c @ 136]  
  11. 0012faf0 10252440 MSVCR90D!getc(struct _iobuf * stream = 0x103113e8)+0x208 [f:\dd\vctools\crt_bld\self_x86\crt\src\fgetc.c @ 76]  
  12. 0012fafc 1025245a MSVCR90D!_fgetchar(void)+0x10 [f:\dd\vctools\crt_bld\self_x86\crt\src\fgetchar.c @ 37]  
  13. 0012fb04 0041160b MSVCR90D!getchar(void)+0xa [f:\dd\vctools\crt_bld\self_x86\crt\src\fgetchar.c @ 47]  
  14. 0012fbe4 004114b2 test2!MyCls::hold(void)+0x2b [d:\project1\test2\test2\test2.cpp @ 28]  
  15. 0012fcec 0041167a test2!foo1(void)+0xa2 [d:\project1\test2\test2\test2.cpp @ 39]  
  16. 0012fdc0 004116ea test2!foo2(void)+0x3a [d:\project1\test2\test2\test2.cpp @ 45]  
  17. 0012fe94 00411743 test2!foo3(void)+0x3a [d:\project1\test2\test2\test2.cpp @ 51]  
  18. 0012ff68 00411ce8 test2!main(void)+0x23 [d:\project1\test2\test2\test2.cpp @ 56]  
  19. 0012ffb8 00411b2f test2!__tmainCRTStartup(void)+0x1a8 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 586]  
  20. 0012ffc0 7c817077 test2!mainCRTStartup(void)+0xf [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 403]  
  21. 0012fff0 00000000 kernel32!BaseProcessStart+0x23  
可以看到,函數參數列表都被顯示出來了.

 

u 命令 顯示指定的內存中的程序代碼的反匯編。

 如果要反匯編某一個地址,直接用u 命令加地址

kd> u 77d2929a   
  1. USER32!SendMessageW:  
  2. 77d2929a 8bff            mov     edi,edi  
  3. 77d2929c 55              push    ebp  
  4. 77d2929d 8bec            mov     ebp,esp  
  5. 77d2929f 56              push    esi  
  6. 77d292a0 8b750c          mov     esi,dword ptr [ebp+0Ch]  
  7. 77d292a3 f7c60000feff    test    esi,0FFFE0000h  
  8. 77d292a9 0f85be800100    jne     USER32!SendMessageW+0x11 (77d4136d)  
  9. 77d292af 8b4d08          mov     ecx,dword ptr [ebp+8]  
如果存在符號文件,也可以這樣直接加函數名:
kd> u user32!SendMessagew  
  1. USER32!SendMessageW:  
  2. 77d2929a 8bff            mov     edi,edi  
  3. 77d2929c 55              push    ebp  
  4. 77d2929d 8bec            mov     ebp,esp  
  5. 77d2929f 56              push    esi  
  6. 77d292a0 8b750c          mov     esi,dword ptr [ebp+0Ch]  
  7. 77d292a3 f7c60000feff    test    esi,0FFFE0000h  
  8. 77d292a9 0f85be800100    jne     USER32!SendMessageW+0x11 (77d4136d)  
  9. 77d292af 8b4d08          mov     ecx,dword ptr [ebp+8]  
注意的是,函數只支持全名,你要是寫成u user32!SendMessage,windbg是認不出來的,當然你可以按TAB來讓windbg自動匹配

ub 指示要反匯編的區域是向后計算的。如果使用了ubAddress ,反匯編區域是以Address結束的8或9條指令。如果用ubAddressLLength語法指定區域,則反匯編以Address結尾的指定長度的內容。  

kd> ub USER32!SendMessageW  
  1. USER32!SendMessageWorker+0x4ed:  
  2. 77d29290 5b              pop     ebx  
  3. 77d29291 c9              leave  
  4. 77d29292 c21400          ret     14h  
  5. 77d29295 90              nop  
  6. 77d29296 90              nop  
  7. 77d29297 90              nop  
  8. 77d29298 90              nop  
  9. 77d29299 90              nop  
我們可以發現ub的結束后一條剛好是u的開始

同樣如果存在符號文件,我們可以用uf來反匯編整個函數:

uf 命令顯示內存中指定函數的反匯編代碼。

 

x命令顯示所有上下文中匹配指定模板的符號。可用字符通配符

kd> x user32!send*  
  1. 77d53948 USER32!SendNotifyMessageA = <no type information>  
  2. 77d2fb6b USER32!SendMessageTimeoutA = <no type information>  
  3. 77d6b88f USER32!SendOpenStatusNotify = <no type information>  
  4. 77d6b49e USER32!SendIMEMessageExA = <no type information>  
  5. 77d2d64f USER32!SendNotifyMessageW = <no type information>  
  6. 77d2cdaa USER32!SendMessageTimeoutW = <no type information>  
  7. 77d65b26 USER32!SendHelpMessage = <no type information>  
  8. 77d6b823 USER32!SendMessageToUI = <no type information>  
  9. 77d6b48d USER32!SendIMEMessageExW = <no type information>  
  10. 77d2cd08 USER32!SendMessageTimeoutWorker = <no type information>  
  11. 77d203fc USER32!SendRegisterMessageToClass = <no type information>  
  12. 77d3c2e7 USER32!SendDlgItemMessageA = <no type information>  
  13. 77d2d6db USER32!SendMessageCallbackW = <no type information>  
  14. 77d6b129 USER32!SendMessageCallbackA = <no type information>  
  15. 77d273cc USER32!SendDlgItemMessageW = <no type information>  
  16. 77d61930 USER32!SendWinHelpMessage = <no type information>  
  17. 77d291b3 USER32!SendMessageWorker = <no type information>  
  18. 77d2929a USER32!SendMessageW = <no type information>  
  19. 77d2f3c2 USER32!SendMessageA = <no type information></SPAN>  

所以,這個可以用來定位函數,

這里介紹下字符串通配符語法

一個星號(*)表示零個或多個字符。這個前面的例子用到了,

一個問號(?)表示任意單個字符,如下例:

kd> x user32!sendMessage?  
  1. 77d2929a USER32!SendMessageW = <no type information>  
  2. 77d2f3c2 USER32!SendMessageA = <no type information></SPAN>  

一個井號(#)匹配零個或多個前一個字符。例如,Lo#p 將匹配 "Lp", "Lop", "Loop", "Looop" 等等

一個加號(+)匹配一個或多個前一個字符

如果你需要使用 # ? [, ]*+ 字符本身,必須在這些字符前面加一個反斜杠(\)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM