zoukankan      html  css  js  c++  java
  • Windbg命令学习6(k和x)

    1.k

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

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

    0:002> ~0k
    ChildEBP RetAddr  
    0007fddc 77d191be ntdll!KiFastSystemCallRet
    0007fdfc 010021b0 USER32!NtUserGetMessage+0xc
    0007ff1c 010125e9 calc!WinMain+0x25f
    0007ffc0 7c817077 calc!WinMainCRTStartup+0x174
    0007fff0 00000000 kernel32!BaseProcessStart+0x23
    0:002> k
    ChildEBP RetAddr  
    00bfffc8 7c972119 ntdll!DbgBreakPoint
    00bffff4 00000000 ntdll!DbgUiRemoteBreakin+0x2d
    0:002> ~2k
    ChildEBP RetAddr  
    00bfffc8 7c972119 ntdll!DbgBreakPoint
    00bffff4 00000000 ntdll!DbgUiRemoteBreakin+0x2d
    

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

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

    0:000> k
    ChildEBP RetAddr  
    0012fb1c 7c95e612 ntdll!DbgBreakPoint
    0012fc94 7c94108f ntdll!LdrpInitializeProcess+0xffa
    0012fd1c 7c92e437 ntdll!_LdrpInitialize+0x183
    00000000 00000000 ntdll!KiUserApcDispatcher+0x7


    再打开反汇编窗口:

    ntdll!DbgBreakPoint:
    7c92120e cc              int     3

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

    0:000> r ebp
    ebp=0012fc94

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

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

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

    7c95e60d e8fc2bfcff      call    ntdll!DbgBreakPoint (7c92120e)
    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一样)
    0:002> kb
    ChildEBP RetAddr  Args to Child              
    00bfffc8 7c972119 00000005 00000004 00000001 ntdll!DbgBreakPoint
    00bffff4 00000000 00000000 00000008 000060c0 ntdll!DbgUiRemoteBreakin+0x2d
    0:002> kp
    ChildEBP RetAddr  
    00bfffc8 7c972119 ntdll!DbgBreakPoint
    00bffff4 00000000 ntdll!DbgUiRemoteBreakin+0x2d
    


     

    kp在有符号文件存在时显示会大不一行,我这贴一个debug下的kp打印:

    0:000> kp
    ChildEBP RetAddr  
    0012f78c 7c92daea ntdll!KiFastSystemCallRet
    0012f790 7c932298 ntdll!ZwRequestWaitReplyPort+0xc
    0012f7b0 7c872a51 ntdll!CsrClientCallServer+0x8c
    0012f8ac 7c872b98 kernel32!ReadConsoleInternal+0x1be
    0012f934 7c8018b7 kernel32!ReadConsoleA+0x3b
    0012f98c 102c207c kernel32!ReadFile+0x64
    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]
    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]
    0012fa98 102523e8 MSVCR90D!_filbuf(struct _iobuf * str = 0x103113e8)+0x113 [f:\dd\vctools\crt_bld\self_x86\crt\src\_filbuf.c @ 136]
    0012faf0 10252440 MSVCR90D!getc(struct _iobuf * stream = 0x103113e8)+0x208 [f:\dd\vctools\crt_bld\self_x86\crt\src\fgetc.c @ 76]
    0012fafc 1025245a MSVCR90D!_fgetchar(void)+0x10 [f:\dd\vctools\crt_bld\self_x86\crt\src\fgetchar.c @ 37]
    0012fb04 0041160b MSVCR90D!getchar(void)+0xa [f:\dd\vctools\crt_bld\self_x86\crt\src\fgetchar.c @ 47]
    0012fbe4 004114b2 test2!MyCls::hold(void)+0x2b [d:\project1\test2\test2\test2.cpp @ 28]
    0012fcec 0041167a test2!foo1(void)+0xa2 [d:\project1\test2\test2\test2.cpp @ 39]
    0012fdc0 004116ea test2!foo2(void)+0x3a [d:\project1\test2\test2\test2.cpp @ 45]
    0012fe94 00411743 test2!foo3(void)+0x3a [d:\project1\test2\test2\test2.cpp @ 51]
    0012ff68 00411ce8 test2!main(void)+0x23 [d:\project1\test2\test2\test2.cpp @ 56]
    0012ffb8 00411b2f test2!__tmainCRTStartup(void)+0x1a8 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 586]
    0012ffc0 7c817077 test2!mainCRTStartup(void)+0xf [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 403]
    0012fff0 00000000 kernel32!BaseProcessStart+0x23

    可以看到,函数参数列表都被显示出来了.

    2.u

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

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

    0:002> u 77d2929a 
    USER32!SendMessageW:
    77d2929a 8bff            mov     edi,edi
    77d2929c 55              push    ebp
    77d2929d 8bec            mov     ebp,esp
    77d2929f 56              push    esi
    77d292a0 8b750c          mov     esi,dword ptr [ebp+0Ch]
    77d292a3 f7c60000feff    test    esi,0FFFE0000h
    77d292a9 0f85be800100    jne     USER32!SendMessageW+0x11 (77d4136d)
    77d292af 8b4d08          mov     ecx,dword ptr [ebp+8]

    如果存在符号文件,也可以这样直接加函数名:

    0:002> u user32!SendMessagew
    USER32!SendMessageW:
    77d2929a 8bff            mov     edi,edi
    77d2929c 55              push    ebp
    77d2929d 8bec            mov     ebp,esp
    77d2929f 56              push    esi
    77d292a0 8b750c          mov     esi,dword ptr [ebp+0Ch]
    77d292a3 f7c60000feff    test    esi,0FFFE0000h
    77d292a9 0f85be800100    jne     USER32!SendMessageW+0x11 (77d4136d)
    77d292af 8b4d08          mov     ecx,dword ptr [ebp+8]

    注意的是,函数只支持全名,你要是写成u user32!SendMessage,windbg是认不出来的,当然你可以按TAB来让windbg自动匹配

    ub 指示要反汇编的区域是向后计算的。如果使用了ubAddress ,反汇编区域是以Address结束的8或9条指令。如果用ubAddressLLength语法指定区域,则反汇编以Address结尾的指定长度的内容。  
    0:002> ub USER32!SendMessageW
    USER32!SendMessageWorker+0x4ed:
    77d29290 5b              pop     ebx
    77d29291 c9              leave
    77d29292 c21400          ret     14h
    77d29295 90              nop
    77d29296 90              nop
    77d29297 90              nop
    77d29298 90              nop
    77d29299 90              nop

    我们可以发现ub的结束后一条刚好是u的开始

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

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

    2.x

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

    0:002> x user32!send*
    77d53948 USER32!SendNotifyMessageA = <no type information>
    77d2fb6b USER32!SendMessageTimeoutA = <no type information>
    77d6b88f USER32!SendOpenStatusNotify = <no type information>
    77d6b49e USER32!SendIMEMessageExA = <no type information>
    77d2d64f USER32!SendNotifyMessageW = <no type information>
    77d2cdaa USER32!SendMessageTimeoutW = <no type information>
    77d65b26 USER32!SendHelpMessage = <no type information>
    77d6b823 USER32!SendMessageToUI = <no type information>
    77d6b48d USER32!SendIMEMessageExW = <no type information>
    77d2cd08 USER32!SendMessageTimeoutWorker = <no type information>
    77d203fc USER32!SendRegisterMessageToClass = <no type information>
    77d3c2e7 USER32!SendDlgItemMessageA = <no type information>
    77d2d6db USER32!SendMessageCallbackW = <no type information>
    77d6b129 USER32!SendMessageCallbackA = <no type information>
    77d273cc USER32!SendDlgItemMessageW = <no type information>
    77d61930 USER32!SendWinHelpMessage = <no type information>
    77d291b3 USER32!SendMessageWorker = <no type information>
    77d2929a USER32!SendMessageW = <no type information>
    77d2f3c2 USER32!SendMessageA = <no type information>

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

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

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

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

    0:002> x user32!sendMessage?
    77d2929a USER32!SendMessageW = <no type information>
    77d2f3c2 USER32!SendMessageA = <no type information>

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

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

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


     


     


     


     


     

  • 相关阅读:
    Android关闭所有Activity、退出应用
    Android混淆打包找不到资源类的…
    Android查看网络是否可用
    Android获取当前系统的语言环境
    AndroidActivity之间跳转动画
    Android获得0n随机排列的数组
    Android记录和恢复listView滚动位置
    Android获取电池信息(Battery&nbsp;in…
    AndroidSurfaceView截屏问题
    Android让Activity finish后不执行onDestroy
  • 原文地址:https://www.cnblogs.com/hgy413/p/3693527.html
Copyright © 2011-2022 走看看