引言:
在工作当中,产生了一个需求,就是云电脑退出连接的时候主动帮用户点击Win+D来将全部窗口最小化,这样可以减少系统因为渲染而参数的消耗,然后在重新登录云电脑的时候主动帮用户点击Win+D帮用户恢复窗口,那么在退出以及重新登录云桌面的时候就要知道当前系统的窗口状态。
解决步骤:
- 首先Win+D快捷键能将桌面最小化以及还原这个功能是那个程序实现的呢,我们只需要知道他怎么判断当前桌面窗口状态我们就可以参照他来实现我们的功能了。
- 首先我怀疑是Explorer实现的这个功能,为了验证自己的想法,我将Explorer强杀之后,按win+D快捷键,发现该功能失效了,那说明实现该功能的程序是Explorer程序。
- 那么下一步就要逆向Explorer进程了。
- 首先逆向找到窗口的消息处理函数来处理快捷键操作,发现改函数是LPARAM __fastcall CTray::v_WndProc(CTray *this, HWND a2, __int64 a3, HMONITOR a4, LPARAM lParam);
- 通过对多个api的hook:
- 发现是v_WndProc接收到0x312这个条msg后,调用CTray::_OnDesktopState(this, v9),然后发送一个0x582的msg,然后调用_HandleGlobalHotkey,再调用_RaiseDesktop再调用EnumWindows进行枚举,然后再MinizeAllWindow:
这里再post一条0x582的msg:
通过日志发现_RaiseDestop的第二个参数在按快捷键的时候这个值会发生相应的状态改变:
其实这个函数是_HandleGlobalHotkey调用的: - 这里我们发现这里有个g_fDesktopRaised这个变量,那么这个变量是哪里改变的呢:
并最后发现他是msg:0x558来设置的:
也是这个状态是通过0x558消息里的lparam参数来设置的: - 通过apimonitor发现他是Shell32.dll发送的消息。
- 通过查看g_fDesktopRaised这个变量的引用,发现:
跳转到下面: - 这里发现这个窗口处理了一条0x5c6这个消息来返回g_fDesktopRaised这个状态,并通过查找窗口句柄发现这个窗口是“Shell_TrayWnd”这个窗口:
解决方案实现:

继续跟踪:
发现该方案可以解决win7、server2008以上系统的问题,但是对于win7、server2008并不生效,经过ida查看相关代码,发现win7以下版本系统并没有在消息处理函数里面留出相应的接口。那么这个时候再进行跟踪0x558这个条消息了:
-
hook Explorer的PostMessageW这个API并用MessageBox拦截显示0x558这条消息,然后用windbg打印相应的堆栈:
-
其实这个变量的设置是通过消息1107的lparam来设置的,那么继续跟踪1107的postmessage的相关堆栈:
-
-
这条路看起来不知道为什么走不了了,走另一条路吧,hook EnumWindows这个api试试:
第二个地方: - 在伪码中发现一个:SetForegroundWindow
- 通过分析得到相关代码: