用Windbg+脚本,设置消息断点

转自:http://bbs.pediy.com/showthread.php?t=180556&highlight=windbg


以鼠标左键按下消息为例, 用WinDbg来捕获.


对于Win7X64下的计算器程序, 用Spy++监视单独一个按钮的消息(e.g. 清除按钮C), 当排除无关消息后.

可以看到按钮按下的消息是 WM_LBUTTONDOWN

代码:
<00001> 00020314 P WM_LBUTTONDOWN fwKeys:MK_LBUTTON xPos:14 yPos:10
<00002> 00020314 S WM_SETFOCUS hwndLoseFocus:0009047E
<00003> 00020314 R WM_SETFOCUS
<00004> 00020314 S BM_SETSTATE fState:True
<00005> 00020314 R BM_SETSTATE
<00006> 00020314 P WM_LBUTTONUP fwKeys:0000 xPos:14 yPos:10
<00007> 00020314 S BM_SETSTATE fState:False
<00008> 00020314 R BM_SETSTATE
<00009> 00020314 S WM_CAPTURECHANGED hwndNewCapture:00000000
<00010> 00020314 R WM_CAPTURECHANGED
<00011> 00020314 S WM_KILLFOCUS hwndGetFocus:000B048E
<00012> 00020314 R WM_KILLFOCUS
用WinDbg下断点 到 USER32!TranslateMessage, 由脚本(d:\\ windbg -script.txt)判断是否鼠标左键按下.
代码:
bp USER32!TranslateMessage "$$>< d:\\windbg-script.txt" 
X64版本脚本
x64程序的区别: 进入目标API后, MSG * 入参在rcx中
代码:
$$ /// @file    d:\\windbg-script.txt
$$ Windbg脚本

$$ 试验目的: 用WinDbg设置一个断点, 在断点条件发生时, 执行一个WinDbg脚本
$$ e.g. bp USER32!TranslateMessage "$$>< d:\\windbg-script.txt"

$$ 试验环境: win7X64Sp1 + WinDbg 6.12.0002.633

$$ 试验步骤:
$$ * bc *
$$ * bp USER32!TranslateMessage "$$>< d:\\windbg-script.txt"
$$ * 当断点触发后, 自动调用 d:\windbg-script.txt
$$ 只有符合脚本中约定的条件时,才会停下. 否则自动继续执行
$$ e.g. 例如只有 WM_LBUTTONDOWN 发生时, WinDbg才会停下来

$$ @note
$$ 当断点触发后, 进入USER32!TranslateMessage, 
$$ 参考此API的反汇编, 可以看到 MSG * 入参在rcx中

$$ 0:000> uf USER32!TranslateMessage
$$ USER32!TranslateMessage:
$$ 00000000`775996f0 fff3            push    rbx
$$ 00000000`775996f2 4883ec20        sub     rsp,20h
$$ 00000000`775996f6 b8e5000000      mov     eax,0E5h
$$ 00000000`775996fb 488bd9          mov     rbx,rcx
$$ 00000000`775996fe 66394110        cmp     word ptr [rcx+10h],ax
$$ 00000000`77599702 0f84ede20100    je      USER32!TranslateMessage+0x14 (00000000`775b79f5)

$$ USER32!TranslateMessage+0x2c:
$$ 00000000`77599708 33d2            xor     edx,edx
$$ 00000000`7759970a 488bcb          mov     rcx,rbx
$$ 00000000`7759970d e81e020000      call    USER32!TranslateMessageEx (00000000`77599930)

$$ ...

$$ 通过观察MSG结构内容, 可以看到 MSG + 8 = message
$$ dt MSG @rcx -r3 -v
$$ ole32!MSG
$$ struct tagMSG, 6 elements, 0x30 bytes
$$    +0x000 hwnd             : 0x00000000`0031040c struct HWND__, 1 elements, 0x4 bytes
$$       +0x000 unused           : ??
$$    +0x008 message          : 0xf
$$    +0x010 wParam           : 0
$$    +0x018 lParam           : 0n0
$$    +0x020 time             : 0xdfd2cd
$$    +0x024 pt               : struct tagPOINT, 2 elements, 0x8 bytes
$$       +0x000 x                : 0n792
$$       +0x004 y                : 0n1042

$$ 经过试验, 注释要放脚本上面. 如果放在脚本体外面, 会有函数执行失败的提示.
$$ /// run results
$$ MSG.message = 0000000000000201
$$ hold WM_LBUTTONDOWN
$$ MK_LBUTTON pressdown

$$ USER32!TranslateMessage:
$$ 00000000`775996f0 fff3            push    rbx
$$ 00000000`775996f2 4883ec20        sub     rsp,20h
$$ 00000000`775996f6 b8e5000000      mov     eax,0E5h
$$ 00000000`775996fb 488bd9          mov     rbx,rcx
$$ 00000000`775996fe 66394110        cmp     word ptr [rcx+10h],ax
$$ 00000000`77599702 0f84ede20100    je      USER32!TranslateMessage+0x14 (00000000`775b79f5)

$$ USER32!TranslateMessage+0x2c:
$$ 00000000`77599708 33d2            xor     edx,edx
$$ 00000000`7759970a 488bcb          mov     rcx,rbx
$$ 00000000`7759970d e81e020000      call    USER32!TranslateMessageEx (00000000`77599930)

$$ USER32!TranslateMessage+0x36:
$$ 00000000`77599712 4883c420        add     rsp,20h
$$ 00000000`77599716 5b              pop     rbx
$$ 00000000`77599717 c3              ret

$$ USER32!TranslateMessage+0x14:
$$ 00000000`775b79f5 4c8b4918        mov     r9,qword ptr [rcx+18h]
$$ 00000000`775b79f9 4c8b4110        mov     r8,qword ptr [rcx+10h]
$$ 00000000`775b79fd 8b5108          mov     edx,dword ptr [rcx+8]
$$ 00000000`775b7a00 488b09          mov     rcx,qword ptr [rcx]
$$ 00000000`775b7a03 ff1587ab0500    call    qword ptr [USER32!gImmApiEntries+0x160 (00000000`77612590)]
$$ 00000000`775b7a09 85c0            test    eax,eax
$$ 00000000`775b7a0b 0f84f71cfeff    je      USER32!TranslateMessage+0x2c (00000000`77599708)

$$ USER32!TranslateMessage+0x30:
$$ 00000000`775b7a11 e9fc1cfeff      jmp     USER32!TranslateMessage+0x36 (00000000`77599712)

$$ rax=0000000000000000 rbx=0000000000000000 rcx=000000000028d300
$$ rdx=000000003a94041d rsi=000000000cd60503 rdi=00000000ffe33460
$$ rip=00000000775996f0 rsp=000000000028d1f8 rbp=00000000ffe33460
$$  r8=000000000028d300  r9=00000000ffe33460 r10=0000000000000000
$$ r11=0000000000000246 r12=0000000000000000 r13=0000000000000000
$$ r14=0000000000000001 r15=0000000000000002
$$ iopl=0         nv up ei pl zr na po nc
$$ cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
$$ USER32!TranslateMessage:
$$ 00000000`775996f0 fff3            push    rbx

$$ ole32!MSG
$$ struct tagMSG, 6 elements, 0x30 bytes
$$    +0x000 hwnd             : 0x00000000`000602e4 struct HWND__, 1 elements, 0x4 bytes
$$       +0x000 unused           : 0n67108868
$$    +0x008 message          : 0x201
$$    +0x010 wParam           : 1
$$    +0x018 lParam           : 0n720923
$$    +0x020 time             : 0x1fdfc81
$$    +0x024 pt               : struct tagPOINT, 2 elements, 0x8 bytes
$$       +0x000 x                : 0n1032
$$       +0x004 y                : 0n412
$$ USER32!TranslateMessage:
$$ 00000000`775996f0 fff3            push    rbx

$$ get message on $t0
r $t0 = poi(@rcx + 0x08)

.echo ">> windbg-script.txt"

$$ get wParam on $t1
r $t1 = poi(@rcx + 0x10)

$$ /// #define WM_LBUTTONDOWN 0x0201
.if ($t0 == 0x0201)
{
  .printf "MSG.message = %N\r\n", @$t0
  .echo "hold WM_LBUTTONDOWN"
  

  $$ /// #define MK_LBUTTON 0x0001

  $$ get MK_LBUTTON on $t2
  r $t2 = ($t1 & 0x0001)
  .if ($t2 == 1)
  {
  $$ 鼠标左右键没有交换的情况下, 鼠标左键按下
  .printf "MK_LBUTTON pressdown\r\n"

  .echo ""
  $$ 反汇编API
  uf USER32!TranslateMessage

  .echo ""
  $$ 显示寄存器组
  r

  .echo ""
  $$ 显示MSG * 入参细节
  dt MSG @rcx -r3 -v

  $$ WinDbg 停住了, 单步调试
  $$ 用WinDbg下消息断点,运行的非常慢, 如果找到了需要的消息断点, 应该bc x, 清除消息断点.
  }
}
.else
{
  $$ 如果不是要捕获的消息, 从条件断点开始执行
  gc
}
X86版本脚本
x86程序的区别: 进入目标API后, MSG * 入参在esi中
代码:
$$ /// @file    d:\\windbg-script.txt
$$ Windbg脚本

$$ 试验目的: 用WinDbg设置一个断点, 在断点条件发生时, 执行一个WinDbg脚本
$$ e.g. bp USER32!TranslateMessage "$$>< d:\\windbg-script.txt"

$$ 试验环境: win7X64Sp1 + WinDbg 6.12.0002.633 + x86目标程序

$$ 试验步骤:
$$ * bc *
$$ * bp USER32!TranslateMessage "$$>< d:\\windbg-script.txt"
$$ * 当断点触发后, 自动调用 d:\windbg-script.txt
$$ 只有符合脚本中约定的条件时,才会停下. 否则自动继续执行
$$ e.g. 例如只有 WM_LBUTTONDOWN 发生时, WinDbg才会停下来

$$ X86程序的MSG * 在esi中

$$ MSG.message = 0000000000000201
$$ hold WM_LBUTTONUP
$$ MK_LBUTTON pressdown

$$ USER32!TranslateMessage:
$$ 763e7809 8bff            mov     edi,edi
$$ 763e780b 55              push    ebp
$$ 763e780c 8bec            mov     ebp,esp
$$ 763e780e 56              push    esi
$$ 763e780f 8b7508          mov     esi,dword ptr [ebp+8]
$$ 763e7812 b8e5000000      mov     eax,0E5h
$$ 763e7817 66394608        cmp     word ptr [esi+8],ax
$$ 763e781b 0f84dd7d0300    je      USER32!TranslateMessage+0x14 (7641f5fe)

$$ USER32!TranslateMessage+0x29:
$$ 763e7821 6a00            push    0
$$ 763e7823 56              push    esi
$$ 763e7824 e810000000      call    USER32!TranslateMessageEx (763e7839)

$$ USER32!TranslateMessage+0x31:
$$ 763e7829 5e              pop     esi
$$ 763e782a 5d              pop     ebp
$$ 763e782b c20400          ret     4

$$ USER32!TranslateMessage+0x25:
$$ 763e782e 85c0            test    eax,eax
$$ 763e7830 74ef            je      USER32!TranslateMessage+0x29 (763e7821)

$$ USER32!TranslateMessage+0x29:
$$ 763e7832 ebf5            jmp     USER32!TranslateMessage+0x31 (763e7829)

$$ USER32!TranslateMessage+0x14:
$$ 7641f5fe ff760c          push    dword ptr [esi+0Ch]
$$ 7641f601 ff7608          push    dword ptr [esi+8]
$$ 7641f604 ff7604          push    dword ptr [esi+4]
$$ 7641f607 ff36            push    dword ptr [esi]
$$ 7641f609 ff15f0014576    call    dword ptr [USER32!gImmApiEntries+0xb0 (764501f0)]
$$ 7641f60f e91a82fcff      jmp     USER32!TranslateMessage+0x25 (763e782e)

$$ eax=00000000 ebx=00000002 ecx=00000000 edx=00000000 esi=0018fed0 edi=00a9be70
$$ eip=763e7809 esp=0018fe8c ebp=0018feb4 iopl=0         nv up ei pl nz na po nc
$$ cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
$$ USER32!TranslateMessage:
$$ 763e7809 8bff            mov     edi,edi

$$ ole32!MSG
$$ struct tagMSG, 6 elements, 0x1c bytes
$$    +0x000 hwnd             : 0x000d0458 struct HWND__, 1 elements, 0x4 bytes
$$       +0x000 unused           : ??
$$    +0x004 message          : 0x201
$$    +0x008 wParam           : 1
$$    +0x00c lParam           : 0n786468
$$    +0x010 time             : 0xe21883
$$    +0x014 pt               : struct tagPOINT, 2 elements, 0x8 bytes
$$       +0x000 x                : 0n812
$$       +0x004 y                : 0n547
$$ USER32!TranslateMessage:
$$ 763e7809 8bff            mov     edi,edi


$$ get message on $t0
r $t0 = poi(@esi + 0x04)

.echo ">> windbg-script.txt"

$$ get wParam on $t1
r $t1 = poi(@esi + 0x08)

$$ /// #define WM_LBUTTONDOWN 0x0201
.if ($t0 == 0x0201)
{
  .printf "MSG.message = %N\r\n", @$t0
  .echo "hold WM_LBUTTONUP"
  

  $$ /// #define MK_LBUTTON 0x0001

  $$ get MK_LBUTTON on $t2
  r $t2 = ($t1 & 0x0001)
  .if ($t2 == 1)
  {
  $$ 鼠标左右键没有交换的情况下, 鼠标左键按下
  .printf "MK_LBUTTON pressdown\r\n"

  .echo ""
  $$ 反汇编API
  uf USER32!TranslateMessage

  .echo ""
  $$ 显示寄存器组
  r

  .echo ""
  $$ 显示MSG * 入参细节
  dt MSG @esi -r3 -v

  $$ WinDbg 停住了, 单步调试
  $$ 用WinDbg下消息断点,运行的非常慢, 如果找到了需要的消息断点, 应该bc x, 清除消息断点.
  }
}
.else
{
  $$ 如果不是要捕获的消息, 从条件断点开始执行
  gc
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windbg是一款微软开发的调试工具,可以用于调试Windows操作系统和应用程序。在使用Windbg调试Windows操作系统时,需要使用虚拟机来模拟一个独立的操作系统环境。以下是使用Windbg和虚拟机进行调试的步骤: 1. 下载并安装Windbg和Windows Driver Kit(WDK)。 2. 在虚拟机中设置Windbg连接的管道串口。 3. 在目标计算机上允许内核调试,并设置串口调试。 4. 在Windbg设置符号路径和调试选项。 5. 在Windbg中连接到虚拟机,并开始调试。 具体步骤如下: 1. 下载并安装Windbg和Windows Driver Kit(WDK)。 可以从微软官网下载Windbg和WDK,安装过程中需要选择安装符号文件和调试工具。 2. 在虚拟机中设置Windbg连接的管道串口。 在虚拟机的设置中,选择“串口”选项卡,勾选“启用串口”和“输出到文件”,并设置输出文件路径。然后在“高级”选项卡中,选择“管道”作为串口类型,并设置管道名称。 3. 在目标计算机上允许内核调试,并设置串口调试。 在目标计算机上,需要以管理员权限运行命令提示符,并执行以下命令: ``` bcdedit /debug on bcdedit /dbgsettings serial debugport:1 baudrate:115200 ``` 其中debugport:1表示选择串口com1,baudrate:115200表示波特率为115200。 4. 在Windbg设置符号路径和调试选项。 在Windbg中,选择“文件”->“符号文件路径”,并添加符号文件路径,例如F:\Study\Symbol\Symbols_Win10_X64。然后选择“文件”->“打开/关闭调试对象”,并选择“内核调试”,设置串口类型为“管道”,并输入管道名称。 5. 在Windbg中连接到虚拟机,并开始调试。 在Windbg中,选择“调试”->“启动调试”,等待虚拟机启动并连接到Windbg。然后可以使用Windbg的各种调试命令进行调试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值