让老师祖传十年的极域瞎掉
随时删库跑路,如果需要请自行保留备份。
前言
在机房使用计算机时,某些应用程序窗口可能会显示摸鱼界面、私人聊天或受版权保护的内容等敏感信息。为了防止这些信息被屏幕截图或极域捕获,我们需要一种有效的技术来保护特定窗口的内容。本文将深入探讨一种利用 Windows 系统原生 API 实现窗口防截屏的技术,并解释其工作原理。
防截屏开启前与开启后的效果对比:
开启防截屏后,系统截图工具无法捕获窗口内容
How - 原理解析
截图的机制与防范思路
在 Windows 操作系统中,屏幕截图的本质是截图工具通过图形设备接口(GDI)或更新的 API(如 DirectX Graphics Infrastructure, DXGI)来访问桌面或特定窗口的图形内容。这些 API 允许程序获取屏幕上所有窗口的句柄(HWND),并读取其像素数据,最终组合成一张完整的截图。
因此,要保护窗口内容,就需要找到一种方法来阻止这种数据读取。主要有两种思路:
- API Hooking:通过技术手段拦截并修改底层截图 API(如
BitBlt)的行为。这种方法功能强大但实现复杂,需要较高的权限,且容易被杀毒软件误报或拦截,同时还面临着系统更新和多架构兼容性的挑战。 - 利用系统原生特性:使用 Windows 操作系统内建的、专为内容保护设计的函数。这正是我们选择的方法,其核心是
SetWindowDisplayAffinity()函数。
核心函数:SetWindowDisplayAffinity()
SetWindowDisplayAffinity() 是一个强大的 Windows API,它允许开发者精细地控制窗口内容的显示方式,尤其是在被其他程序捕获时。
详情可参阅 微软官方文档 (MSDN)。
通过调用此函数并传入 WDA_EXCLUDEFROMCAPTURE 标志位,我们可以达到防截屏的目的。其原理是:它向桌面窗口管理器(Desktop Window Manager, DWM)发出指令,在进行屏幕内容合成时,将该窗口排除掉。 因此,任何依赖 DWM 进行捕获的截图工具(包括系统自带的截图工具、极域、Veyon、Print Screen 键以及大多数第三方软件)在截取该窗口时,只能得到一块黑色或透明的区域,而窗口本身在屏幕上的显示不受任何影响。
这种方法非常“干净”和稳定,因为它利用的是操作系统为数字版权管理(DRM)等场景预留的官方功能。
进程隔离
既然这个函数如此有效,我们能否在自己的程序A里,直接调用它来保护目标程序B的窗口呢?答案是不能。
SetWindowDisplayAffinity() 的官方文档明确指出,该函数有一个至关重要的限制:
参数
[in] hWnd类型:HWND
顶级窗口的句柄。 窗口必须属于当前进程。
这是 Windows 操作系统一个核心的安全设计理念——进程隔离(Process Isolation)。它确保一个进程不能随意修改或干预另一个不相关进程的资源(如窗口属性、内存等),从而防止了恶意程序或意外的程序错误对系统稳定性造成破坏。
DLL 注入
既然无法从“外部”修改,那么思路就变成了:如何让我们的代码在“目标进程内部”运行? 答案就是 DLL 注入(DLL Injection)。
什么是 DLL?
动态链接库(Dynamic Link Library, DLL) 是 Windows 系统中实现共享函数库的一种方式。它是一种包含可由多个程序同时使用的代码和数据的库文件。DLL 允许多个进程共享同一份物理内存中的函数库,从而节约资源并方便代码的复用与更新。
DLL 注入的原理
DLL 注入的核心思想,就是通过某种技术手段,强制一个目标进程去加载我们预先编写好的 DLL 文件。一旦 DLL 被加载到目标进程的地址空间中,它就成为了该进程的一部分。这意味着:
- DLL 中的代码将与目标进程共享相同的内存、句柄和权限。
- DLL 代码可以调用该进程加载的所有 API。
- DLL 代码可以访问该进程的任何资源,包括它的窗口句柄。
此时,我们就可以在 DLL 的代码中,名正言顺地获取到目标进程自己的窗口句柄,并为其调用 SetWindowDisplayAffinity() 函数,从而完美达成防截屏的目的。
常见的注入技术
CreateRemoteThread+LoadLibrary:这是一种非常直接且精准的注入方法。它通过在目标进程中创建一个远程线程,该线程唯一的任务就是调用LoadLibrary()函数来加载我们的 DLL。此方法影响范围小,针对性强。SetWindowsHookEx(Windows 钩子):这是一种经典且影响范围广泛的注入方法。通过安装一个全局钩子(例如监视键盘或鼠标事件),可以监视系统中发生的特定事件。当这些事件发生时,Windows 系统为了将钩子事件通知给所有相关的 GUI 进程,会自动将包含钩子处理函数的 DLL 加载到这些进程的地址空间中。我们正是利用这一机制,实现了 DLL 的“被动”注入。
代码实现
仅公开命令行版工具(64位)的代码:项目链接(仅代码)
示例工具与使用
工具下载
不要滥用传播,闷声发大财。
这里提供一个基于上述原理实现的示例项目及其二进制文件。密码为 114514。
- 命令行版(64位)
- 下载链接: 蓝奏云
- 图形化加强版(由 wrongaaa 开发)
- 特性:支持图形化界面,自动识别进程架构 (x86/x64) 并注入,使用 Python 前端实现图形化和进程架构识别,C++ 后端实现注入。
- 下载链接: 蓝奏云
命令行版使用方法
-
将下载的压缩包解压,建议将内部所有文件放置于一个纯英文路径下。
-
打开命令行(CMD)或 PowerShell,并切换到程序所在目录。
-
输入
injector.exe并回车,命令执行后,将显示程序的帮助文档,说明其用法:C:\path\to\tool> injector.exe Usage: injector.exe <target_process.exe | -pid PID> [dll_path] [options] Options: -notopmost Disable window topmost -nocapture Disable anti-capture -pid PID Inject to specific process ID -
用法示例: 假设您希望保护 Edge 浏览器的窗口内容不被截取,并且不希望它被置顶,可以执行以下命令:
injector.exe msedge.exe -notopmost
反制方法
此防截屏技术的反制原理也十分直接。既然保护是通过调用 SetWindowDisplayAffinity(hwnd, WDA_EXCLUDEFROMCAPTURE) 实现的,那么只需通过同样的方法,再次对目标窗口调用该函数,并将第二个参数修改为 WDA_NONE 即可恢复其可被截取的状态。这同样需要通过 DLL 注入等方式,在目标进程的上下文中执行相应的代码来完成。