如何使用 x64dbg 找到 WndProc?

逆向工程 视窗
2021-07-04 10:48:09

我正在尝试从 explorer.exe 中找到处理这些消息的 WndProc,我在 Spy++ 中找到了:

<000001> 00000000000B01C8 P message:0xC02B [Registered:"SHELLHOOK"] wParam:00000025 lParam:000F0184
<000002> 00000000000B01C8 P message:0xC02B [Registered:"SHELLHOOK"] wParam:00008006 lParam:000F0184

我试图阻止 explorer.exe 闪烁任务栏按钮,它破坏了我的 Windows 10 体验。在 Windows 10 中,闪烁的任务栏按钮出现在所有桌面中,当专注于另一个虚拟桌面上的工作时,这简直令人抓狂。不是我想要的功能。上面的消息被发送到 explorer.exe 中的任务切换器,如果我可以阻止它们被处理,我可以打败它。

我对 WndProc 有丰富的知识,我想查看并从 Spy++ 修改,以下窗口是 Spy++(64 位版本)的属性检查器:

(注意:Spy++ 的 32 位版本根本不显示 Window Proc,只是 (Unavailable)(Unicode)

窗口处理地址?

线程 ID

在 x64dbg 中,我打开了线程:

x64dbg 在同一个线程上打开

但我就是不知道如何在 x64dbg 中找到 Window Proc?

1个回答

spy++ 在您的屏幕截图中显示 wndproc(它可能是子类;您可能需要跟踪但 wndproc 显示在您的屏幕截图中,因为361c9880 我不知道 x64 dbg 中的命令是什么,但如果您使用的是 ollydbg,您只需执行ctrl+g (goto) 键入地址,如 spy++ 所示,并中断并记录消息以进行过滤。

calc.exe -> comctl32.dll 中的退格按钮窗口 wndproc 的屏幕截图(32 位和 64 位在概念级别上应该无关紧要)

在此处输入图片说明

raymond chen 的一篇文章谈到了返回 cookie 而不是 wndproc:http :
//blogs.msdn.com/b/oldnewthing/archive/2003/12/01/55900.aspx

如果所有其他方法都失败,则组装 GetWindowLongPtrW 以获取实际的 WndProc

  • 暂停进程(f12 或 esc)
  • 使用 ctrl+g 转到 user32.GetWindowLongPtrW
  • 右键单击在此处设置新原点(在此之前保存 rip)
  • 将寄存器状态保存在某处
  • 修改 rcx 并将句柄放入 rcx(在屏幕截图中为 b01c8)
  • 使用最新的窗口句柄,如 spy++ 所示
  • 对于现有会话不要放 0xb01c8
  • 修改 edx 以保持 -4(GWLP_WNDPROC 的索引)
  • 单步执行函数
  • 在函数返回 rax 之前应该保存实际的 WndProc
  • 在 Wndproc 上保存或设置 bp
  • 恢复寄存器并撕裂到原始状态并继续探索

我下载了 x64dbg 并运行了 64 位 calc.exe spy++ 32 位不显示 wndproc。我编写了一个脚本来在 calc.exe 的进程内存中分配一个页面,并使用脚本语言组装了一个弯路并获取了实际的 WndProc。

截图如下:

在此处输入图片说明

调试对象必须处于暂停状态。

该脚本使用 alloc 在被调试对象地址空间中分配内存;标签后状态栏应显示新分配的地址。另外变量 $lastalloc $result 应该保存新分配的内存地址;如果你做d address了一堆 00 00 应该盯着你看。

  • 确认分配
  • 如果内存分配选项卡在脚本的一步
  • push rcx 应该在新分配的地址中组装
  • 使用 d address 或 d $lastalloc 确认
  • 像聪明人一样组装所有指令
  • 在 ecx 中使用正确的句柄值(陈旧或重复使用的窗口句柄可能会提供不正确的信息,确认您正确组装 mov rcx , HWND
  • 现在你需要确保你在 eax 中放置了正确的地址,地址应该是 user32.GetWindowLongPtrW
  • 组装所有清理说明
  • 你已经这样做了
  • 将现有的 rip 保存在某个地方(写在纸上)
  • 右击选择新分配地址中的第一条指令,设置为origin(这里是new origin),rip就会改成新分配的地址
  • 按 f8 并逐个执行指令
  • 当调用 eax 完成时,eax 将持有 Wndproc
  • 保存这个(写在纸上)
  • 执行清理指令
  • 按 ctrl+g 并输入旧的 RIP
  • 右键单击 -> 此处新建原点(当您暂停调试对象时,RIP 现在将指向旧值

这就对了; 现在您在论文中有 Wndproc 并且您已返回到原始状态。

这是绕道(在debuggee的代码流中故意绕过,做一些额外的工作,回到绕过的地方,就好像什么都没做一样继续原来的流程)。

使用 bp 在纸上的 wndproc 中设置断点。