生活随笔
收集整理的這篇文章主要介紹了
.windbg-k*实例分析(查看调用栈分析)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[cpp]?view plaincopy
#include?"stdafx.h"?? ?? int?fun0(int?i)?? {?? ????return?i;?? };?? ?? int?fun1(int?i)?? {?? ????return?fun0(i);?? }?? ?? int?_tmain(int?argc,?_TCHAR*?argv[])?? {?? ?? ????fun1(10);?? ?? ????return?0;?? }??
代碼如上
我們在test!fun1下個斷點,g運行,斷下來后:
我們來觀注下藍色小框的地址是RetAddr,具體指什么,跳轉到此處匯編:
很明顯了,就是運行函數后的下一條要執行的指令
我們再看看ChildEBP的含義:
現在打印下ebp值:
[cpp]?view plaincopy
0:000>?r?ebp?? ebp=002ef930??
很詭異,怎么會是前一個棧的ebp呢,其實我們可以注意到當前匯編是push ebp
而這個函數用到的ebp應該是到mov ebp, esp之后,單步調過此處,再看其值:
也就是ChildEbp就是當前函數需要使用的EBP,不要被ChildEbp的child字面意思搞暈了~~~~
有函數調用的棧中的情況:
上圖中上面是低地址,下面是高地址,保存的EBP就是前一個EBP,它的地址就是當前的EBP
在內存中的一系列的值是可以被識別出來的, 這些值表示當前棧中的某個地址, 并且在這些值之后是一個可執行的地址.
[cpp]?view plaincopy
0:000>?lm?? start????end????????module?name?? 011e0000?011fb000???test?????C?(private?pdb?symbols)??E:\test\Debug\test.pdb?? 53ca0000?53dc3000???MSVCR90D???(deferred)??????????????? 756f0000?7573b000???KERNELBASE???(deferred)?????
再看下轉存的棧
可以看到,藍色的地址和最右排地址相差無幾,極可能是當前棧的某個地址,后面接著紅色部分是在test模塊內的,所以應該是返回地址
以后為重啟了次程序運行結果,我們可以打印出kb看到:
[cpp]?view plaincopy
0:000>?kb?? ChildEBP?RetAddr??Args?to?Child???????????????? 0029fbb4?011f1417?0000000a?0029fd64?00000000?test!fun0+0xb?[e:\test\test\test.cpp?@?7]?? 0029fc8c?011f1465?0000000a?00000000?00000000?test!fun1+0x27?[e:\test\test\test.cpp?@?13]?? 0029fd64?011f19f8?00000001?00331b90?00334800?test!wmain+0x25?[e:\test\test\test.cpp?@?19]?? 0029fdb4?011f183f?0029fdc8?75aaed6c?7ffdd000?test!__tmainCRTStartup+0x1a8?[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c?@?583]?? 0029fdbc?75aaed6c?7ffdd000?0029fe08?7757377b?test!wmainCRTStartup+0xf?[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c?@?403]?? 0029fdc8?7757377b?7ffdd000?764a1a3e?00000000?kernel32!BaseThreadInitThunk+0xe?? 0029fe08?7757374e?011f107d?7ffdd000?00000000?ntdll!__RtlUserThreadStart+0x70?? 0029fe20?00000000?011f107d?7ffdd000?00000000?ntdll!_RtlUserThreadStart+0x1b??
這是fun1用到的ebp,按圖就知道,保存的EBP和返回地址是連續的.
后面的test!fun1+0x27其實是通過尋找上一行的返回地址(011f1417)得來的,可以使用ln 011f1417查看.
?特別注意是棧是向低地址增加,dd 后一個EBP的值就是前一個EBP
[cpp]?view plaincopy
0:000>?p?? eax=00000002?ebx=7efde000?ecx=00000001?edx=00000001?esi=00000000?edi=0034fed8?? eip=00c13613?esp=0034fde4?ebp=0034fed8?iopl=0?????????nv?up?ei?pl?nz?na?po?nc?? cs=0023??ss=002b??ds=002b??es=002b??fs=0053??gs=002b?????????????efl=00000202?? test1!wmain+0x33:?? 00c13613?51??????????????push????ecx?? ?? 0:000>?r?esp?? esp=0034fde0??
push ecx后,esp減了4
另外經常用到的指令如kn 100?
kn用于顯示幀號碼,100表示層級,一般不會到100,所以就是顯示實際的層級
[cpp]?view plaincopy
0:000>?kn?100?? ?#?ChildEBP?RetAddr???? 00?010ff860?776fb2e4?ntdll!LdrpDoDebuggerBreak+0x2b?? 01?010ffa98?776f7744?ntdll!LdrpInitializeProcess+0x14dc?? 02?010ffaec?776f7590?ntdll!_LdrpInitialize+0x178?? 03?010ffaf4?00000000?ntdll!LdrInitializeThunk+0x10??
? ?
又如:
~*kv 1
讓每個線程只顯示前一幀
[cpp]?view plaincopy
:000>?~*kv?1?? ?? .??0??Id:?ae14.5c8?Suspend:?1?Teb:?00ff5000?Unfrozen?? ?#?ChildEBP?RetAddr??Args?to?Child???????????????? 00?010ff860?776fb2e4?a7e95f8e?ffffffff?00000000?ntdll!LdrpDoDebuggerBreak+0x2b?(FPO:?[Non-Fpo])?? ?? ???1??Id:?ae14.b410?Suspend:?1?Teb:?00ff8000?Unfrozen?? ?#?ChildEBP?RetAddr??Args?to?Child???????????????? 00?013cf88c?776c6a61?000000b8?013fc388?00000010?ntdll!NtWaitForWorkViaWorkerFactory+0xc?(FPO:?[5,0,0])?? ?? ???2??Id:?ae14.5ed0?Suspend:?1?Teb:?00ffb000?Unfrozen?? ?#?ChildEBP?RetAddr??Args?to?Child???????????????? 00?015ef96c?776c6a61?000000b8?013fc638?00000010?ntdll!NtWaitForWorkViaWorkerFactory+0xc?(FPO:?[5,0,0])??
總結
以上是生活随笔為你收集整理的.windbg-k*实例分析(查看调用栈分析)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。