Win7系统中使用WinDbg与虚拟机调试驱动程序的方法和要点(2)

编辑:quers 2016-06-06 13:56:59 来源于:系统城 1. 扫描二维码随时看资讯 2. 请使用手机浏览器访问: http://wap.xtcheng.cc/xtjc/11729.html 手机查看

  条件断点

  以上所提到的断点指令通过与J指令很容易形成条件断点。比如:

  bp USER32!GetMessageW “r $t1=poi(esp+4);r $t2=poi(@$t1+4); j(@$t2 = 0x102 ) ‘du @$t1+8 L2;gc’;‘gc’”

  这个条件断点,截取WM_CHAR消息,并将字符(包括中文)显示出来。

  条件断点的最简形式:bp Address “j (Condition) ‘OptionalCommands’; ‘gc’ ”

  Address是指令的地址,Condition是一个条件表达式,如果@eax=1,‘OptionalCommands’是在断点被击中并且表达式成立时要执行的指令;gc指定是从一个条件断点返回,是不可少的一部分。

  数据查看指令 d{a|b|c|d|D|f|p|q|u|w|W}

  d{b|c|d|D|f|p|q}分别是显示:

  byte&ASCII, double-word&ASCII,double-word,double-precision,float,pointer-sized,quad-word数据;

  DA用于显示ASCII,DU用于显示UNICODE;

  BYB,BYD,显示binary和Byte及binary和DWORD

  补充一个DV,用于查看本地变量用的

  这些指令区分大小。
 

  栈指令k[b|p|P|v]

  这四条指令显示的内容类似,但是每个指令都有特色,KB显示三个参数,Kp显示所有的参数,但需要Full Symbols或Private PDBSymbols支持。KP与Kp相似,只是KP将参数换行显示了。Kv用于显示FPO和调用约定,KD,用于显示Stack的Dump,在跟踪栈时比较有用。

  这些指令区分大小。

  KD显示的内容

  0012fbd0 0012fbf0

  0012fbd4 77e2158f USER32!UserCallWinProc+0x18

  0012fbd8 0016011e

  0012fbdc 00000030

  0012fbe0 750a0c3f

  0012fbe4 00000000

  0012fbe8 00000000

  0012fbec dcbaabcd

  0012fbf0 0012fc2c

  0012fbf4 77e1279c USER32!DefDlgProcWorker+0xbf

  0012fbf8 004018e0 DGGuarder!MainDLGproc [j:/mydriver/dgguarder2/dgguarder.c @ 350]

  0012fbfc 0016011e

  0012fc00 00000030

  0012fc04 750a0c3f

  0012fc08 00000000

  0012fc0c 00629d08

  0012fc10 00000030

  0012fc14 00619828

  0012fc18 77e0f626 USER32!__ClientLoadMenu+0x38

  0012fc1c 77e0f635 USER32!__ClientLoadMenu+0x47
 

  KP显示的内容

  ChildEBP RetAddr

  0012fbd0 77e2158f DGGuarder!MainDLGproc(

  struct HWND__ * hwnd = 0x0016011e,

  unsigned int message = 0x30,

  unsigned int wParam = 0x750a0c3f,

  long lParam = 0)+0x227 [j:/mydriver/dgguarder2/dgguarder.c @ 415]

  0012fbf0 77e1279c USER32!UserCallWinProc+0x18

  0012fc5c 77e0b981 USER32!DefDlgProcWorker+0xbf

  0012fd14 77e140bb USER32!InternalCreateDialog+0x695

  0012fd44 77e1410f USER32!InternalDialogBox+0xaa

  0012fd64 77df41ec USER32!DialogBoxIndirectParamAorW+0x34

  0012fd90 00401cdc USER32!DialogBoxParamA+0x4a

  0012fe88 00408684 DGGuarder!WinMain(

  struct HINSTANCE__ * hInstance = 0x00400000,

  struct HINSTANCE__ * hPrevInstance = 0x00000000,

  char * lpCmdLine = 0x00132902 “”,

  int nCmdShow = 10)+0x5c [j:/mydriver/dgguarder2/dgguarder.c @ 469]

  0012ffc0 77e88989 DGGuarder!WinMainCRTStartup(void)+0x194 [f:/vs70builds/3077/vc/crtbld/crt/src/crt0.c @ 251]

  0012fff0 00000000 KERNEL32!BaseProcessStart+0x3d
 

  数据修改指令e{b|d|D|f|p|q|w}

  反汇编指令u,uf

  u @$exentry L10

  0:001》 u @$exentry L10

  notepad!WinMainCRTStartup:

  01006420 55 push ebp

  01006421 8bec mov ebp,esp

  01006423 6aff push 0xff

  01006425 6888180001 push 0x1001888

  0100642a 68d0650001 push 0x10065d0

  0100642f 64a100000000 mov eax,fs:[00000000]

  01006435 50 push eax

  01006436 64892500000000 mov fs:[00000000],esp

  0100643d 83c498 add esp,0xffffff98

  01006440 53 push ebx

  01006441 56 push esi

  01006442 57 push edi

  01006443 8965e8 mov [ebp-0x18],esp

  01006446 c745fc00000000 mov dword ptr [ebp-0x4],0x0

  0100644d 6a02 push 0x2

  0100644f ff1560110001 call dword ptr [notepad!_imp____set_app_type (01001160)]

  uf (Unassemble Function)指令对整个函数进行反汇编

  uf GetLanguageCount

  0:000》 uf GetLanguageCount

  DGGuarder!GetLanguageCount [j:/mydriver/dgguarder2/language.c @ 54]:

  54 00403c00 55 push ebp

  54 00403c01 8bec mov ebp,esp

  54 00403c03 81ecc0000000 sub esp,0xc0

  54 00403c09 53 push ebx

  54 00403c0a 56 push esi

  54 00403c0b 57 push edi

  54 00403c0c 8dbd40ffffff lea edi,[ebp-0xc0]

  54 00403c12 b930000000 mov ecx,0x30

  54 00403c17 b8cccccccc mov eax,0xcccccccc

  54 00403c1c f3ab rep stosd

  56 00403c1e 6a00 push 0x0

  56 00403c20 6828b44100 push 0x41b428

  56 00403c25 6820b44100 push 0x41b420

  56 00403c2a e8b1edffff call DGGuarder!ReadInt (004029e0)

  56 00403c2f 83c40c add esp,0xc

  58 00403c32 5f pop edi

  58 00403c33 5e pop esi

  58 00403c34 5b pop ebx

  58 00403c35 81c4c0000000 add esp,0xc0

  58 00403c3b 3bec cmp ebp,esp

  58 00403c3d e85e0f0000 call DGGuarder!_RTC_CheckEsp (00404ba0)

  58 00403c42 8be5 mov esp,ebp

  58 00403c44 5d pop ebp

  58 00403c45 c3 ret

  跟踪指令T,TA,TB,TC,WT,P,PA,PC

  T指令单步执行,在源码调试状态下,可指源码的一行,根据不同的选项也可以为一行ASM指令;

  TA单步跟踪到指定地址,如果没有参数将运行到断点处。

  TB执行到分支指令,分支指令包括calls, returns, jumps, counted loops, and while loops

  TC执行到Call指令

  WT Trace and Watch Data,一条强大指令,对执行流程做Profile,执行一下看看结果吧

  P,PA,PC相信不用多做解释,大家也都明白了
 

  源代码操作指令 。,lsf,lsc,ls,l,lsp

  。指令打一个源文件,可以打开一个全路径的文件,也可以通过函数地址来打开并定位到源文件中函数的位置,如。 –a myapp!main,。 j:/mydriver/mydriver.c

  lsf指定一个源文件为当前源文件,使用lsc可显示当前指定的源文件ls可显示源文件的代码。Lsf可以使用全路径,如果源路径已经设置,也可以直接指定源文件名称。如lsf mydriver.c,lsf j:/mydriver/mydriver.c

  lsc显示当前源文件

  ls显示当前源文件的代码,如ls 200显示第200行

  l 用于设置源文件选项

  lsp 设置源文件行在调试时显示范围比如,显示当前行的前50,后50,lsp 100

  但通常使用Windbg时,可以直接用Ctrl+O来打开并查看源文件
 

  寄存器指令 r

  相信大家对这个指令都很熟悉,在Windbg中r指令除了可以显示修改CPU寄存器之外,Pseudo-Register可使用这个命令来修改。对eax 操作,r eax 显示其值,r eax=2,修改其值;r $t2=10,修改Pseudo-Register的值,r @$t2显示其值。


  Search 指令 s,#

  S 指令对内存区别进行查找,可用于查找数字,字符串,但不支持模式查找。s -d @esp L100 8187bc40,从esp指向的内存地址0x100个字节内查找 DWORD 8187bc40。查找字符串 s -a 0012ff40 L20 “Hello” 。s -sa 和 s -su 显示内存可打印的ASCII和Unicode字符串。

  #指令可以查询汇编指令模式, # “call[ ]+esp” kernel32 L1000查找call esp 指令。
 

  其他常用指令 lm,!peb,x,dt

  lm 查看当前载入的模块

  !peb 查看当前进程环境块(PEB)

  x 查看模块的符号,如x mydriver!*FastIo*,显示所有与*FastIo*匹配的符号列表

  dt 查看类型数据,还可用于查看模块类型的符号列表,如 dt dgguarder!_IMAGE_DOS_HEADER 00400000

  从00400000处查看_IMAGE_DOS_HEADER类型的数据
 

  上下文的概念

  Windbg下上下文的概念很重要,根据文档中说明有多种上下文概念。

  Session Context

  Process Context

  Register Context(其实也就是线程上下文)

  Local Context(这个关系的本地如果解析本地变量的问题)

  调 试Win32应用程序,Session Context和Process Context是确定的,主要是Register Context,也即Thread Context,可以使用~指令来查看,改变当前的Thread Context 。~*显示所有线程列表,~xs用于切换上下文(x是数字),如:~1s,将上下文切换到1号线程。

  .frame用来设置Local Context。

  PAUSE

  好了,基本的指令都已经列出了来了,Kernel Debug现在先不写了,其实跟Win32也差不多。如果再有时间再写吧。本文对指令没有说的太细,详细说明见Windbg文档,希望见谅。

  WINDBG Script简易教程

  声明: 希望更多人使用WINDBG,然后大概就能看到debugging tools for windows的帮助文件的中文翻译了吧。花了 几天时间才在翻译软件的帮助下看完debugger commands部分,痛苦死了。也找不到WINDBG的插件,还是WINDBG没插件功能?为了简化调试过程,只有学习使用SCRIPT了,现在把这几天的经验跟大家分享。附件中所有代码经NOTEPAD,REGEDIT等调试,花了几小时,基本通过。

  废话多了,现在是正文。WINDBG的指令比较多,还是英文的,所以我只挑了一部分经常会用到的,并通过实例去告诉大家那些指令的作用和格式。正如大多数高级语言教程一样,我们先来看看如何写一个HELLO WORLD的程序。

  如果使用.echo “HELLO WORLD”作为例程就太简单了,我希望介绍更多的指令。所以我在OD直接用汇编写了个程序:

  PUSH 0

  PUSH 12345678 ;TITLE跟显示内容都在这个跟下一个PUSH

  PUSH 12345678 ;我比较懒。。。就用一样的字符了

  PUSH 0

  MOV EAX,OFFSET MESSAGEBOXW

  CALL EAX

  先用EAX保存MESSAGEBOXW的指针,然后再CALL。这是为了你在任何一个程序下都能用使用这个SCRIPT。如果直接 CALL MESSAGBOXW的指针,翻译成机器码是相对于当前位置的偏移,这样写出来的SCRIPT文件在这个程序能用,别的程序就不能用了。

  机器码 6A 00 68 78 56 34 12 68 78 56 34 12 6A 00 b8 68 3d e2 77 ff d0

  我虚拟机使用的是WIN 2000 连SP1都不是。。所以我不保证你的机器仍然能正常运行这个程序。为了能正常使用,你可以随便找一个程序,然后 BP MESSAGEBOXW,中断之后当前的EIP就是了,把ff d0前面的68 3d e2 77换掉了就可以了。我的目的并不是介绍如何写一个兼 容性差的程序,重点是学会如何写SCRIPT。

  准备工作做好了,在看代码之前,先解释一些指令:

  $exentry伪寄存器,数值上等于EP

  $t0-$t19,WINDBG为我们提供了20个自定义的伪寄存器

  R指令能改变几乎所有寄存器的值,包括EAX等

  .dvalloc [/b] size 申请内存空间,带/b 地址,可在指定地址申请空间,不带则自动分配,指定地址时不一定成功,暂时的经验指定地址越大越容易成功。

  e* 地址 在指定内存中写入数据,EW 写入WORD,EB写入BYTE,ED写入DWORD

  注意: EW 00400000 12345会产生溢出错误,同理EB 00400000 123也是错的,正确的例子可见后面的代码

  f 地址 L长度 BYTE 在长度的地址写入数据,你可以在示例中看到效果。同样BYTE的位置只能是BYTE,多于8位的数据都会造成溢出错误。

  m 源地址 L源地址长度 目的地址 复制内存区域

  d* 地址 显示地址中的数据,其中db的效果可在示例中看到。

  .dvfree /d 地址 size 释放指定地址的内存,这里指定地址用的是/d要与 .dvalloc的/b相区别。

  附件中helloworld.txt的代码:

  ---------------------------------------helloworld.txt--------------------------------

  g $exentry

  r $t0=00ff0000; $$ $t0:源内存基址

  r $t2=@$exentry; $$ $t2:目的内存基址

  r $t1=@$t0; $$ $t1:当前指针

  .dvalloc /b $t0 1000; $$在00b90000申请1000BYTE的内存空间

  ew $t1 006A 0068

  db $t0

  .echo “ew指令的效果”

  r $t3 = @$t1 + 3; $$PUSH DWORD的机器码=68 DWORD

  $$这里应该输入字符串的首址

  r $t1 = @$t1 + 7; $$懒得计算,所以用$t3存起DWORD的指针

  $$输入字符串的时候一起搞定

  eb $t1 68 12 34

  db $t0

  .echo “eb指令的效果”

  r $t4 = @$t1 + 1; $$同上

  r $t1 = @$t1 + 5

  f $t1 l20 6A 00 b8 68 3d e2 77 ff d0

  db $t0

  .echo “f指令的效果”

  r $t1 = @$t1 + 9

  r $t5 =$t1 - $t0 + $t2

  ed $t3 $t5; $$ 添加字符串的指针回去

  ed $t4 $t5

  f $t1 l20 ‘h’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ ‘w’ ‘o’ ‘r’ ‘l’ ‘d’ ‘!’ 00 00

  $$ 把字符串写进内存中

  m $t0 l30 $t2

  r $ip=$t2; $$ 修改EIP

  .dvfree /d $t0 1000; $$ 释放内存

  g

分享到:

热门图文

热门搜索

返回顶部