WinDbg命令详解--断点

来源:互联网 发布:php高级工程师是什么 编辑:程序博客网 时间:2024/05/16 05:06
  • 一般断点
## 线程断点bp常用执行断点bm设置执行符号断点,可以同时对多个符号下断bu设置一个延时断点,可以对一个还未加载的模块执行代码下断。当模块加载时,此断点自动激活ba设置内存访问断点## 断点管理bl查看断点列表bd 1禁用一号断点be 2启用二号断点bc *清除所有断点


  • 条件断点《转》

在调试时,避免不了使用断点。但是只使用简单的断点会存在如下问题:
1. 如果某个函数会被频繁调用,频繁被断下影响执行怎么办?
2. 我只想当某个值变了的时候断下它该怎么办?
3. 我只想让函数被调用第20次的时候断下它怎么办?
4. 字符串条件断点怎么写?
5. 我想下一个记录断点(只输出信息,不断下)怎么写?


字符串条件断点
如果想在加载某个模块时(如USER32.DLL)该怎么做呢?


下面咱们看一个例子。
当前程序有两个模块组成:break.exe和breakdll.dll。
break.exe在执行的过程中会加载breakdll.dll。


那怎么在加载breakdll.dll的时候断下呢 ?
//ascii字符串条件断点设置方法
代码 :

0 : 000 > bp kernel32!LoadLibraryA "as /ma ${/v:dllname} poi(esp+4); .if($sicmp(\"${dllname}\",\"breakdll.dll\")==0){.echo ${dllname};}.else{gc;}"0:000 > g*** WARNING: Unable to verify checksum for break.exebreakdll.dlleax = cccccccc ebx = 7ffd8000 ecx = 00000000 edx = 00000001 esi = 0012fe78 edi = 0012ff68eip = 7c801d7b esp = 0012fe70 ebp = 0012ff68 iopl = 0         nv up ei pl nz na pe nccs = 001b  ss = 0023  ds = 0023  es = 0023  fs = 003b  gs = 0000             efl = 00000206kernel32!LoadLibraryA :7c801d7b 8bff            mov     edi, edi

//Unicode字符串条件断点设置方法
代码 :

0 : 000 > bp kernel32!LoadLibraryExW "as /mu ${/v:dllname} poi(esp+4); .if($sicmp(\"${dllname}\",\"breakdll.dll\")==0){.echo ${dllname};}.else{gc;}"0:000 > gbreakdll.dlleax = 7ffddbf8 ebx = 7ffde000 ecx = 7ffddc00 edx = 004157bc esi = 0012fe78 edi = 0012ff68eip = 7c801af5 esp = 0012fe40 ebp = 0012fe50 iopl = 0         nv up ei pl nz na po nccs = 001b  ss = 0023  ds = 0023  es = 0023  fs = 003b  gs = 0000             efl = 00000202kernel32!LoadLibraryExW:7c801af5 6a34            push    34h


多重断点设置方法
在加载完breakdll.dll的时候,会调用该模块的GetRandom函数(此函数用来生成随机数)。
现在我想在breakdll.dll加载完毕后,马上在GetRandom上下断点。
代码 :

0 : 000 > bp kernel32!LoadLibraryA "as /ma ${/v:dllname} poi(esp+4); .if($sicmp(\"${dllname}\",\"breakdll.dll\")==0){.echo ${dllname};gu; bp breakdll!GetRandom;g;}.else{gc;}"0:000 > g*** WARNING: Unable to verify checksum for break.exebreakdll.dllModLoad : 10000000 1001b000   D : \test\windbgtest\break\Debug\breakdll.dll  *** WARNING: Unable to verify checksum for D : \test\windbgtest\break\Debug\breakdll.dll  Breakpoint 1 hit  eax = 10011091 ebx = 7ffd6000 ecx = 7c937de9 edx = 7c99b178 esi = 0012fe78 edi = 0012ff68  eip = 10011420 esp = 0012fe74 ebp = 0012ff68 iopl = 0         nv up ei ng nz ac pe cy  cs = 001b  ss = 0023  ds = 0023  es = 0023  fs = 003b  gs = 0000             efl = 00000297  breakdll!GetRandom:10011420 55              push    ebp

bu命令的用法
这个条件断点好长啊,很不好写,有没有更好的方法?这时候我想起了bu命令。
bu命令可以对那些还没加载的模块设置断点
代码 :
0 : 000 > bu breakdll!GetRandom0:000 > g*** WARNING: Unable to verify checksum for D : \test\windbgtest\break\Debug\breakdll.dllModLoad : 10000000 1001b000   D : \test\windbgtest\break\Debug\breakdll.dll //模块被加载  Breakpoint 0 hit  eax = 10011091 ebx = 7ffd4000 ecx = 7c937de9 edx = 7c99b178 esi = 0012fe78 edi = 0012ff68  eip = 10011420 esp = 0012fe74 ebp = 0012ff68 iopl = 0         nv up ei ng nz ac pe cy  cs = 001b  ss = 0023  ds = 0023  es = 0023  fs = 003b  gs = 0000             efl = 00000297  breakdll!GetRandom:10011420 55              push    ebp


命中次数
break.exe中会对breakdll!GetRandom函数执行20遍,我想在第10遍的时候断下它,怎么办呢?
代码 :
ntdll!DbgBreakPoint :7c92120e cc              int     30 : 000 > r @$t0 = 00:000 > bu breakdll!GetRandom "r $t0=@$t0+1; .printf \"$t0=%d\\n\", @$t0;.if(@$t0==0n10){}.else{gc;}"0:000 > g*** WARNING: Unable to verify checksum for D : \test\windbgtest\break\Debug\breakdll.dllModLoad : 10000000 1001b000   D : \test\windbgtest\break\Debug\breakdll.dll  *** WARNING: Unable to verify checksum for break.exe  $t0 = 1  $t0 = 2  $t0 = 3  $t0 = 4  $t0 = 5  $t0 = 6  $t0 = 7  $t0 = 8  $t0 = 9  $t0 = 10  eax = 00000004 ebx = 7ffd7000 ecx = c8c29a13 edx = 00391ec0 esi = 0012fe78 edi = 0012ff68  eip = 10011420 esp = 0012fe74 ebp = 0012ff68 iopl = 0         nv up ei ng nz na pe cy  cs = 001b  ss = 0023  ds = 0023  es = 0023  fs = 003b  gs = 0000             efl = 00000287  breakdll!GetRandom:10011420 55              push    ebp


记录断点
我想知道每次breakdll!GetRandom执行完的返回值是多少,这个时候的写法为:
代码 :
ntdll!DbgBreakPoint :7c92120e cc              int     30 : 000 > bu breakdll!GetRandom "gu;.printf \"GetRandom ret: %d\\n\", @eax;g;"0:000 > g*** WARNING: Unable to verify checksum for D : \test\windbgtest\break\Debug\breakdll.dllModLoad : 10000000 1001b000   D : \test\windbgtest\break\Debug\breakdll.dll  *** WARNING: Unable to verify checksum for break.exe  GetRandom ret : 19267  GetRandom ret : 32169  GetRandom ret : 24352  GetRandom ret : 7475  GetRandom ret : 5700  GetRandom ret : 16672  GetRandom ret : 11921  GetRandom ret : 19360  GetRandom ret : 30209  GetRandom ret : 7458  GetRandom ret : 29727  GetRandom ret : 3199  GetRandom ret : 9226  GetRandom ret : 20818  GetRandom ret : 27630  GetRandom ret : 31281  GetRandom ret : 9424  GetRandom ret : 5549  GetRandom ret : 24090  GetRandom ret : 11321  eax = 00000000 ebx = 00000000 ecx = 7c800000 edx = 10361e40 esi = 7c92de50 edi = 00000000  eip = 7c92e4f4 esp = 0012fdf0 ebp = 0012feec iopl = 0         nv up ei pl zr na pe nc  cs = 001b  ss = 0023  ds = 0023  es = 0023  fs = 003b  gs = 0000             efl = 00000246  ntdll!KiFastSystemCallRet :  7c92e4f4 c3              ret


监控变量值被修改
在break.exe中有一个全局变量g_nValue, 默认值为100; 在执行过程中,此值会改变。我想知道此值被修改时的调用栈和修改后的值为多少,以及当时的汇编指令
代码 :
CommandLine : D : \test\windbgtest\break\Debug\break.exeSymbol search path is : srv*c : \symbols*http://msdl.microsoft.com/download/symbolsExecutable search path is :ModLoad : 00400000 0041b000break.exeModLoad : 7c920000 7c9b3000ntdll.dllModLoad : 7c800000 7c91e000C : \WINDOWS\system32\kernel32.dllModLoad : 10200000 10372000C : \WINDOWS\system32\MSVCR100D.dll(d08.b60) : Break instruction exception - code 80000003 (first chance)eax = 00251eb4 ebx = 7ffdb000 ecx = 00000003 edx = 00000008 esi = 00251f48 edi = 00251eb4eip = 7c92120e esp = 0012fb20 ebp = 0012fc94 iopl = 0         nv up ei pl nz na po nccs = 001b  ss = 0023  ds = 0023  es = 0023  fs = 003b  gs = 0000             efl = 00000202ntdll!DbgBreakPoint :7c92120e cc              int     3//执行到入口处0 : 000 > g break!wmaineax = 00392bd8 ebx = 7ffdb000 ecx = 00392b40 edx = 00000001 esi = 0125f75a edi = 0125f6eeeip = 00412f10 esp = 0012ff6c ebp = 0012ffb8 iopl = 0         nv up ei pl nz na po nccs = 001b  ss = 0023  ds = 0023  es = 0023  fs = 003b  gs = 0000             efl = 00000202break!wmain: 00412f10 55           push    ebp//保存变量原先的值0 : 000 > r $t1 = @@(break!g_nValue)0:000 > ? @$t1Evaluate expression : 100 = 00000064//设置写入断点0 : 000 > ba w4 break!g_nValue ".if(@$t1!=@@(break!g_nValue)){?? break!g_nValue;kp 5;ub eip l5;}.else{gc;}"0:000 > gModLoad : 10000000 1001b000   D : \test\windbgtest\break\Debug\breakdll.dll//打印当前值int 0n305//打印调用栈ChildEBP RetAddr0012fe60 00412f9a break!SetValue(int n = 0n305) + 0x26[d:\test\windbgtest\break\break.cpp @ 14]0012ff68 0041194f break!wmain(int argc = 0n1, wchar_t ** argv = 0x00392b40) + 0x8a[d:\test\windbgtest\break\break.cpp @ 24]0012ffb8 0041177f break!__tmainCRTStartup(void) + 0x1bf[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 552]0012ffc0 7c817067 break!wmainCRTStartup(void) + 0xf[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 371]0012fff0 00000000 kernel32!BaseProcessStart + 0x23break!SetValue + 0x12[d:\test\windbgtest\break\break.cpp @ 12]://打印反汇编00411a02 b930000000      mov     ecx, 30h00411a07 b8cccccccc      mov     eax, 0CCCCCCCCh00411a0c f3ab            rep stos dword ptr es : [edi]00411a0e 8b4508          mov     eax, dword ptr[ebp + 8]00411a11 a314704100      mov     dword ptr[break!g_nValue(00417014)], eax //此处为修改g_nValue 变量位置eax = 00000131 ebx = 7ffdb000 ecx = 00000000 edx = 00391ec0 esi = 0012fe6c edi = 0012fe60eip = 00411a16 esp = 0012fd94 ebp = 0012fe60 iopl = 0         nv up ei pl nz na pe nccs = 001b  ss = 0023  ds = 0023  es = 0023  fs = 003b  gs = 0000             efl = 00010206break!SetValue + 0x26:00411a16 5f              pop     edi



只针对某个线程被断下
在break.exe中有一个全局变量g_nValue被多个线程修改,我只关心1号线程,这个时候我针对1好线程下断:
代码 :
0 : 000 > ~0 ba w4 break!g_nValue



bm bp bu 指令同样可以对指定线程下断点

0 0
原创粉丝点击