如何通过 hook 来拦截截屏

date
Dec 25, 2023
slug
how-to-hook-screen-capture
status
Published
tags
Windows Internals
Programming
summary
这篇内容介绍了如何在Windows系统中进行屏幕捕获的权限管理,特别是拦截截屏操作。文章首先指出在传统Windows应用程序中,系统没有提供直接的权限管控,因此需要采取一些其他方式,如使用hook来进行权限管控。接着,文章演示了如何通过API Monitor来监听目标应用程序的行为,以确定其使用的截屏方式。然后,文章介绍了如何使用BitBlt接口进行hook操作,以实现拦截截屏。最后,文章提供了注入hook DLL到目标进程的方法,以实现权限管理。
type
Post

引入

Windows 传统 APP 中,系统都没有提供权限的管控。所以对于一些截屏、录屏和其他隐私功能,我们只能采取一些其他方式,例如 hook 来进行权限管控。
接下来便以拦截截屏为例,来演示权限管理。

确定对应 App 的方式

因为截屏的方式有很多种,确认应用采取的方式后,可以更好的验证,并且不会误伤到其他行为。
💡
实际真实用的时候,需要考虑的点更多。这里只是演示。

通过 Api Monitor 来监听行为

API Monitor 可以通过这里下载:http://www.rohitab.com/downloads
下载后,会得到两个版本。一个 32 位的,一个 64 位的。
如果想监听 32 位应用,就用 32 位的 api monitor;否则就用 64 位的。
这里以 snipaste.exe 为例。
确认其位数: 64位。
notion image

找到目标进程

然后在左下角的 Running Processes 中找到对应的应用:
notion image
💡
如果找不到你想要的应用。有可能是因为权限的问题,可以用管理员权限打开。或者点击左上方那个管理员盾牌图标。

确定要监听的 API 集合

我们这里要查看的是截屏,所以这里选择这个大类【Graphice and Gaming】
notion image

开始监听

通过双击选中的 snipaste.exe 就可以开始进行监听了。就像下面这样:
notion image
接下来我们尝试截个屏,立马取消,之后暂停监听(左上角工具栏有暂停的图标),就可以看到关键调用:
notion image
可以确定,它采用的是 gdi 的方式来截屏的。

Hook 对应的 API

确定方式之后,根据调用的接口,我们可以选择 BitBlt 这个接口来进行 hook。BitBlt 的作用是从特定位置拷贝颜色数据到另外一个位置。我们只需要不给它拷贝就可以达到我们的目的了。

开始 Hook

我们这里采用微软的 hook 库 detours
只需要通过 vcpkg 进行安装就好了,非常方便快捷。
然后将其编译成一个 dll。这里就叫:HookDll.dll 吧
💡
这里由于我只需要注入到 64 位的应用中,所以只需要编译一个 64 位的 dll。如果有注入到 32 位应用中的诉求的话,需要再编译一个 32 位的 dll。

注入到目标进程

注入进程有很多种方式,这里采用通过 CreateRemoteThread 的方式来注入。新建一个控制台程序,粘贴以下代码:
然后就可以以管理员权限运行起来了。
💡
这里管理员权限不是必须的。结合实际来
💡
上述 HookDll.dll 的路径请根据实际路径修改

看看效果

运行起来,如果没有意外的话,应该就可以在 process exproloer 中看到了。
notion image
然后再截个屏,你就只能得到一个黑屏的图片了。
(效果看自己的~

如何调试

如果发生意外的话,没有成功的 hook。我们就需要来进行调试了
意外我们需要分阶段来分析:

没有注入成功

也就是在 snipaste.exe 中没有看到注入的 dll。
这个可以通过 VS 中单步调试控制太程序,看看在注入的哪步出错了。(也可以用 windbg 来看,不过这里 VS 应该更便捷)
如果都没问题,那很有可能是因为位数的问题。
确认了控制台程序没问题的话,可以看看 API Monitor 中的 Monitoring 窗口,是不是有对应的 dll 被加载:
notion image

注入了,但没生效

相当于需要调试 HookDll 的代码,这就可以通过 Windbg 的附加进程来进行调试了。
附加上去之后,通过以下命令来添加 dll 加载时的断点:
当 hookdll 加载的时候,就会进入断点,显示如下:
然后打个断点到 DllMain
接下来就可以开心的调试了。

特别地

如果要用于生产环境,请注意:
  • hook 的 api 尽量功能单一,避免误杀
  • 对于 hook 的方法的返回和行为尽量多思考,避免导致其他程序崩溃
  • 最好能覆盖较多相同功能的 API,防止拦截失败
  • 等等

© Frend Guo 2022 - 2024