首页
社区
课程
招聘
[原创]记一次有教益的焦点窗口查找过程—— 一定注意 spy++ 的这个坑
2022-8-28 22:19 13664

[原创]记一次有教益的焦点窗口查找过程—— 一定注意 spy++ 的这个坑

2022-8-28 22:19
13664

缘起

前一阵子,同事遇到了一个诡异的 bug,新版本发出来后之前运行好好的功能不好使了。原来的逻辑是:点击板上某个埋件的时候,会弹出四个定位编辑框,其中的一个编辑框需要获得焦点,方便用户直接修改,按 tab 会切换到下一个编辑框。但是新程序的行为发生了变化——点击埋件的时候,四个编辑框没有一个获得焦点。本文记录了使用 spyxxaccevent.exe 定位此问题的过程。

初步调查

同事演示了一下现象,大概现象如下:

 

 

可以发现,左侧的编辑框先是获得了焦点(获得焦点的时候会选中全部文字),然后很快被抢走了。

 

因为之前在开发其它功能时也遇到过焦点被命令编辑框(软件底部中央的编辑框)抢走的情况,所以经过一定的观察后,断定跟上次是一样的问题。由于之前遇到的那个问题是通过其它方式解决的,这次的问题不能用相同的方式解决,于是建议同事跟客户反馈一下,让平台同事帮忙处理一下抢焦点的问题。

再次调查

过了一天,客户那边反馈可以使用某个命令禁止命令编辑框抢焦点。执行这个命令后,发现命令编辑框确实不抢焦点了,但是焦点还是会被抢走。

 

跟同事了解完相关代码逻辑后,找到了被抢走焦点的编辑框类。该类中包含一个响应函数 OnKillFocus(CWnd* pNewWnd)。从名字可以看出,该函数是处理失去焦点事件的,该函数只有一个参数,从名字看该参数是新获得焦点的窗口对象指针。于是,果断在这里设置断点,并且设置中断时输出调试信息后继续执行代码。经过几次观察,可以发现,焦点总是被某个固定的窗口抢走。

 

 

既然焦点总被固定的窗口抢走,说明这个窗口是固定存在的,不是临时窗口。既然是固定存在的窗口,就可以通过 spyxx 查看到底是哪个窗口。但是当我在 spyxx 中输入这个窗口句柄时,却怎么也找不到这个句柄对应的窗口!真是怪事!

保存调用栈

虽然没能通过 spyxx 找到对应的窗口,但是却发现了一条非常有用的信息 —— 每次焦点都会被同一个窗口抢走。那么可以在 OnKillFocus() 函数内部设置条件断点,当 pNewWnd 是特定值时才中断。这样就可以在目标编辑框失去焦点时中断下来。中断下来后,简单查看调用栈,由于缺少调试符号,没有发现什么有用信息。保存一份完整转储文件,后面可以发给平台同事,让他们帮忙查看具体原因。

提示: 转储文件是程序某个时刻的快照。调试时保存转储文件个非常好的习惯,尤其是那种不轻易重现的问题。好不容易抓到一次,一定要先拍个照。防止调试器意外退出,追悔莫及。懂得都懂,对吧。

 

其实,这个问题调查到这一步已经够了。因为这个问题已经很明确了(焦点被其它窗口抢走了),而且外网没有相关代码,只能等平台同事处理。但是,我特别好奇到底是哪个窗口把焦点抢走了,为什么在调试输出中看到焦点每次都被同一个窗口抢走,但是在 spyxx 中却查不到这个窗口。

继续折腾

之前做读屏软件开发的时候了解到,除了 spyxx,还有其它工具可以查看窗口信息。比如,可以通过 Inspect, UISpy, accevent 等工具以追踪焦点的方式自动获取当前获得焦点的窗口。但是,这次在使用这几个工具的过程中,发现很大概率会导致主程序发生 StackOverflow 异常(在这里浪费了很长时间)。最后发现,使用 accevent32,并且只监听 OBJ_FOCUS 事件的时候,不会发生异常。

 

 

按上图设置好之后,点击 OK 按钮,即可监听焦点变化事件。终于抓到了这个偷抢焦点的窗口。

 

 

好像抢焦点的是主窗口?赶紧用 spyxx 查看主窗口句柄,果然主窗口的句柄是 00541376,与使用 accevent 捕获到的窗口句柄是一样的。

 

这次,终于知道是哪个窗口抢走了焦点,但是为什么主窗口会抢焦点,还是需要平台同事帮忙调查原因了。

为什么 spyxx 找不到窗口

为什么之前在 spyxx 里输入窗口句柄,但是却找不到对应的窗口呢?在 vs 输出窗口中显示的窗口句柄是 0x0000000000541376,在 spyxx 中输入的也是 0x0000000000541376,没道理找不到。但是在 accevent 里看到的窗口句柄是 00541376,难道在spyxx 中输入 00541376 就可以查找到了?赶紧试试。

 

 

果然,输入 00541376 是可以找到对应的窗口的。但是当我尝试使用 0x00541376 查找窗口时,却无法找到匹配的窗口。看来,在 spyxx 中通过输入句柄查找窗口时不能输入 0x 前缀。

反思

在整个过程中有一点做的特别不好:本来可以修改 OnKillFocus() 函数中的代码,多打印一些信息,比如获取窗口范围,窗口类名等信息。这样就可以直接在代码里定位到是哪个窗口抢走了焦点。但是根据之前的经验,编译一次比较耗时,所以潜意识里不想修改代码,只是想着通过为断点设置输出信息的方式打印了一些辅助信息。

总结

  • Inspect, UISpy, accevent 等工具也是一种可以查看窗口信息的工具,在某些情况下可能非常有用。

  • spyxx 中通过输入窗口句柄查找窗口时不能输入 0x 前缀,否则会出现找不到窗口的情况。


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞7
打赏
分享
最新回复 (6)
雪    币: 8887
活跃值: (3334)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
chengdrgon 2022-8-29 10:42
2
0
感谢分享
雪    币: 12059
活跃值: (15389)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
pureGavin 2 2022-8-31 09:44
3
0
感谢分享
雪    币: 1358
活跃值: (1313)
能力值: ( LV6,RANK:99 )
在线值:
发帖
回帖
粉丝
KEEEY 1 2022-9-2 11:15
4
0
 感谢分享
雪    币: 8511
活跃值: (9112)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
编程难 3 2022-9-10 17:08
5
0
chengdrgon 感谢分享
感谢阅读
雪    币: 8511
活跃值: (9112)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
编程难 3 2022-9-10 17:08
6
0
pureGavin 感谢分享
感谢阅读
雪    币: 8511
活跃值: (9112)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
编程难 3 2022-9-10 17:08
7
0
KEEEY 感谢分享
感谢阅读
游客
登录 | 注册 方可回帖
返回