YSC 的频道 头像

消息来源频道

YSC 的频道

@yscschan

频道814 位成员公开可见持续更新

Channel Owner: @ysc3839

成员规模814 位成员
在线情况待同步
消息总数5,288 条消息
浏览量总数0 次浏览

在这个频道里搜索消息……

t.me/yscschan

看到有人在问有没有 Windows 下的 Notch Simulator,于是想到了 Windows 下窗口置顶的问题。
传统的 WS_EX_TOPMOST 还是会被别的 top most 窗口挡住,而且像任务管理器,开始菜单还是能在其之上。
曾经个人调查过背后的原因,是从 Win8 开始引入了 Window Band 的功能,任务管理器或开始菜单把它们自己设置到了更高层次的 Band 上,于是能比 top most 更 top。具体可见这篇文章。
其中一种显示在上层的方法是使用 UIAccess,但是这要求应用程序有签名,且还要放到 Program Files 文件夹中。于是我就想到了上述文章提到的方法。
其中一种方法是使用 CreateWindowInBand,这个函数会检查进程的签名,所以实际实现只能注入DLL进去,在目标进程里面创建窗口。
还有一种方法是 SetWindowBand,不过文章作者的说法是需要注入 explorer,hook SetWindowBand,然后打开开始菜单,会触发 hook SetWindowBand 的函数,此时才可以成功调用 SetWindowBand,还说不知道内部的工作流程。
于是我开始逆向,发现 twinui.pcshell.dll 在调用 SetWindowBand 之前都会调用 EnableIAMAccess,去掉 EnableIAMAccess 后 SetWindowBand 就失败了。EnableIAMAccess 需要传递一个 key 进去,而这个 key 是在之前调用 AcquireIAMKey 获取的,于是尝试注入进 explorer 调用 AcquireIAMKey,发现失败了。
因为 AcquireIAMKey 是直接调用 NtUserAcquireIAMKey system call,百思不得其解之下,我尝试逆向 win32kfull.sys,看看内部的实现逻辑,发现限制了只能获取一次,而且这个 key 是在调用 SetShellWindowEx 的时候才会生成。
也就是说,explorer 启动时先调用了 SetShellWindowEx,然后 twinui.pcshell.dll 调用 AcquireIAMKey 获取到 key,后续就没人能再获取了。而 SetShellWindowEx 在当前 shell 进程还在运行时是不能再次调用的。
所以说要实现随意调用 SetWindowBand,只能结束当前的 explorer 进程,启动新的 explorer 进程并注入 DLL,hook NtUserAcquireIAMKey 获取到 key。