windbg调试命令1(k、u、x)

k*命令显示给定线程的调用堆栈,以及其他相关信息

~0 k表示打印0号线程的调用堆栈,直接用k表示打印当前线程的调用堆栈

kd>~0k
  1. ChildEBPRetAddr
  2. 0007fddc77d191bentdll!KiFastSystemCallRet
  3. 0007fdfc010021b0USER32!NtUserGetMessage+0xc
  4. 0007ff1c010125e9calc!WinMain+0x25f
  5. 0007ffc07c817077calc!WinMainCRTStartup+0x174
  6. 0007fff000000000kernel32!BaseProcessStart+0x23
  7. 0:002>k
  8. ChildEBPRetAddr
  9. 00bfffc87c972119ntdll!DbgBreakPoint
  10. 00bffff400000000ntdll!DbgUiRemoteBreakin+0x2d
  11. 0:002>~2k
  12. ChildEBPRetAddr
  13. 00bfffc87c972119ntdll!DbgBreakPoint
  14. 00bffff400000000ntdll!DbgUiRemoteBreakin+0x2d

我们注意到2号线程的堆栈,这是windbg创建一个远程线程来执行DbgUiRemoteBreakin函数,它内部会调用DbgBreakPoint执行断点指令,以触发断点异常,强制把程序断了下来,所以windbg打印出来的线程总多了一条,所以不要惊讶为什么线程多了点。

其实我想弄清楚那个ChildEBP/RetAddr分别具体指什么:先K看下堆栈:

kd>k
  1. ChildEBPRetAddr
  2. 0012fb1c7c95e612ntdll!DbgBreakPoint
  3. 0012fc947c94108fntdll!LdrpInitializeProcess+0xffa
  4. 0012fd1c7c92e437ntdll!_LdrpInitialize+0x183
  5. 0000000000000000ntdll!KiUserApcDispatcher+0x7


再打开反汇编窗口:

ntdll!DbgBreakPoint:
  1. 7c92120eccint3

当前运行到这一行:再用r ebp查看下值:

kd>rebp
  1. ebp=0012fc94

这个值是LdrpInitializeProcess前面的ChildEBP,F10单步调试到ret(也就是7c92120f)

ntdll!DbgBreakPoint:
  1. 7c92120eccint3
  2. 7c92120fc3ret

再F10调试一步,退回到LdrpInitializeProcess中(7c95e612):

7c95e60de8fc2bfcffcallntdll!DbgBreakPoint(7c92120e)
  1. 7c95e6128b4368moveax,dwordptr[ebx+68h]ds:0023:7ffd3068=00000070

我们发现这个7c95e612就是DbgBreakPoint的返回地址,也就是返回地址应该是指函数退出后下个EIP的值,我以前还一直以为是那个ret/leave对应的地方,原来是ret运行后的值.

kb 显示传递给堆栈回溯中的每个函数的前三个参数kp 显示传递给堆栈回溯中的每个函数的所有参数。参数列表包含参数的数据类型、名字和值。p命令是区分大小写的。使用该参数需要完整符号信息。 (事实上我看到的结果和k一样)kPp参数一样,显示传递给堆栈回溯中的每个函数的所有参数。但是,使用P ,函数参数在第二行中显示,而不是作为数据的结尾在行末显示。 (事实上我看到的结果和k一样)

kd>kb
  1. ChildEBPRetAddrArgstoChild
  2. 00bfffc87c972119000000050000000400000001ntdll!DbgBreakPoint
  3. 00bffff4000000000000000000000008000060c0ntdll!DbgUiRemoteBreakin+0x2d
  4. 0:002>kp
  5. ChildEBPRetAddr
  6. 00bfffc87c972119ntdll!DbgBreakPoint
  7. 00bffff400000000ntdll!DbgUiRemoteBreakin+0x2d
  8. </SPAN>
kp在有符号文件存在时显示会大不一行,我这贴一个debug下的kp打印:

kd>kp

  1. ChildEBPRetAddr
  2. 0012f78c7c92daeantdll!KiFastSystemCallRet
  3. 0012f7907c932298ntdll!ZwRequestWaitReplyPort+0xc
  4. 0012f7b07c872a51ntdll!CsrClientCallServer+0x8c
  5. 0012f8ac7c872b98kernel32!ReadConsoleInternal+0x1be
  6. 0012f9347c8018b7kernel32!ReadConsoleA+0x3b
  7. 0012f98c102c207ckernel32!ReadFile+0x64
  8. 0012fa20102c19c9MSVCR90D!_read_nolock(intfh=0,void*inputbuf=0x10316740,unsignedintcnt=0x1000)+0x62c[f:\dd\vctools\crt_bld\self_x86\crt\src\read.c@233]
  9. 0012fa7010253e43MSVCR90D!_read(intfh=0,void*buf=0x10316740,unsignedintcnt=0x1000)+0x219[f:\dd\vctools\crt_bld\self_x86\crt\src\read.c@93]
  10. 0012fa98102523e8MSVCR90D!_filbuf(struct_iobuf*str=0x103113e8)+0x113[f:\dd\vctools\crt_bld\self_x86\crt\src\_filbuf.c@136]
  11. 0012faf010252440MSVCR90D!getc(struct_iobuf*stream=0x103113e8)+0x208[f:\dd\vctools\crt_bld\self_x86\crt\src\fgetc.c@76]
  12. 0012fafc1025245aMSVCR90D!_fgetchar(void)+0x10[f:\dd\vctools\crt_bld\self_x86\crt\src\fgetchar.c@37]
  13. 0012fb040041160bMSVCR90D!getchar(void)+0xa[f:\dd\vctools\crt_bld\self_x86\crt\src\fgetchar.c@47]
  14. 0012fbe4004114b2test2!MyCls::hold(void)+0x2b[d:\project1\test2\test2\test2.cpp@28]
  15. 0012fcec0041167atest2!foo1(void)+0xa2[d:\project1\test2\test2\test2.cpp@39]
  16. 0012fdc0004116eatest2!foo2(void)+0x3a[d:\project1\test2\test2\test2.cpp@45]
  17. 0012fe9400411743test2!foo3(void)+0x3a[d:\project1\test2\test2\test2.cpp@51]
  18. 0012ff6800411ce8test2!main(void)+0x23[d:\project1\test2\test2\test2.cpp@56]
  19. 0012ffb800411b2ftest2!__tmainCRTStartup(void)+0x1a8[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c@586]
  20. 0012ffc07c817077test2!mainCRTStartup(void)+0xf[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c@403]
  21. 0012fff000000000kernel32!BaseProcessStart+0x23
可以看到,函数参数列表都被显示出来了.

u 命令 显示指定的内存中的程序代码的反汇编。

如果要反汇编某一个地址,直接用u 命令加地址

kd>u77d2929a
  1. USER32!SendMessageW:
  2. 77d2929a8bffmovedi,edi
  3. 77d2929c55pushebp
  4. 77d2929d8becmovebp,esp
  5. 77d2929f56pushesi
  6. 77d292a08b750cmovesi,dwordptr[ebp+0Ch]
  7. 77d292a3f7c60000fefftestesi,0FFFE0000h
  8. 77d292a90f85be800100jneUSER32!SendMessageW+0x11(77d4136d)
  9. 77d292af8b4d08movecx,dwordptr[ebp+8]
如果存在符号文件,也可以这样直接加函数名:
kd>uuser32!SendMessagew
  1. USER32!SendMessageW:
  2. 77d2929a8bffmovedi,edi
  3. 77d2929c55pushebp
  4. 77d2929d8becmovebp,esp
  5. 77d2929f56pushesi
  6. 77d292a08b750cmovesi,dwordptr[ebp+0Ch]
  7. 77d292a3f7c60000fefftestesi,0FFFE0000h
  8. 77d292a90f85be800100jneUSER32!SendMessageW+0x11(77d4136d)
  9. 77d292af8b4d08movecx,dwordptr[ebp+8]
注意的是,函数只支持全名,你要是写成u user32!SendMessage,windbg是认不出来的,当然你可以按TAB来让windbg自动匹配

ub 指示要反汇编的区域是向后计算的。如果使用了ubAddress ,反汇编区域是以Address结束的8或9条指令。如果用ubAddressLLength语法指定区域,则反汇编以Address结尾的指定长度的内容。

kd>ubUSER32!SendMessageW
  1. USER32!SendMessageWorker+0x4ed:
  2. 77d292905bpopebx
  3. 77d29291c9leave
  4. 77d29292c21400ret14h
  5. 77d2929590nop
  6. 77d2929690nop
  7. 77d2929790nop
  8. 77d2929890nop
  9. 77d2929990nop
我们可以发现ub的结束后一条刚好是u的开始

同样如果存在符号文件,我们可以用uf来反汇编整个函数:

uf 命令显示内存中指定函数的反汇编代码。

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

kd>xuser32!send*
  1. 77d53948USER32!SendNotifyMessageA=<notypeinformation>
  2. 77d2fb6bUSER32!SendMessageTimeoutA=<notypeinformation>
  3. 77d6b88fUSER32!SendOpenStatusNotify=<notypeinformation>
  4. 77d6b49eUSER32!SendIMEMessageExA=<notypeinformation>
  5. 77d2d64fUSER32!SendNotifyMessageW=<notypeinformation>
  6. 77d2cdaaUSER32!SendMessageTimeoutW=<notypeinformation>
  7. 77d65b26USER32!SendHelpMessage=<notypeinformation>
  8. 77d6b823USER32!SendMessageToUI=<notypeinformation>
  9. 77d6b48dUSER32!SendIMEMessageExW=<notypeinformation>
  10. 77d2cd08USER32!SendMessageTimeoutWorker=<notypeinformation>
  11. 77d203fcUSER32!SendRegisterMessageToClass=<notypeinformation>
  12. 77d3c2e7USER32!SendDlgItemMessageA=<notypeinformation>
  13. 77d2d6dbUSER32!SendMessageCallbackW=<notypeinformation>
  14. 77d6b129USER32!SendMessageCallbackA=<notypeinformation>
  15. 77d273ccUSER32!SendDlgItemMessageW=<notypeinformation>
  16. 77d61930USER32!SendWinHelpMessage=<notypeinformation>
  17. 77d291b3USER32!SendMessageWorker=<notypeinformation>
  18. 77d2929aUSER32!SendMessageW=<notypeinformation>
  19. 77d2f3c2USER32!SendMessageA=<notypeinformation></SPAN>

所以,这个可以用来定位函数,

这里介绍下字符串通配符语法

一个星号(*)表示零个或多个字符。这个前面的例子用到了,

一个问号(?)表示任意单个字符,如下例:

kd>xuser32!sendMessage?
  1. 77d2929aUSER32!SendMessageW=<notypeinformation>
  2. 77d2f3c2USER32!SendMessageA=<notypeinformation></SPAN>

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

一个加号(+)匹配一个或多个前一个字符

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

你可能感兴趣的:(命令)