使用DirectX防止屏幕捕获

时间:2010-02-09 15:17:58

标签: c# c++ directx vlc

我想使用DirectX渲染单个图像。 它应该类似于VLC播放器的“directx视频输出”,如果不能使用简单的屏幕捕获软件或printscreen-key捕获帧。 制作屏幕截图不应该(或非常困难)!

有谁知道这在VLC播放器中是如何工作的?

还有其他可能的解决方案吗? 也许使用“输出保护管理器”(参见http://msdn.microsoft.com/en-us/library/dd388980(VS.85).aspx

我在学校大约有3年的C#编程经验。 我也做过一些C ++编程,但是我会使用WPF或Managed DirectX来预测C#解决方案。

对不起我的英文,感谢您的帮助!

2 个答案:

答案 0 :(得分:9)

首先,当您使用打印屏幕或其他屏幕捕获技术时,未捕获VLC内容的原因是(至少在旧版本的Windows上),他们使用“叠加”来呈现视频。这是一种特殊的GPU结构,允许渲染到正常屏幕表面上方的虚拟“平面”。由于这绕过了其他所有内容并直接进入GPU,因此没有任何直接的方法来捕获它。注意:在Windows的最后几个版本中,规则改变了很多关于叠加的内容。应用程序不能假设支持D3D9 / DDraw叠加,现在应用程序不应该使用它们,因为系统有更好的方法来呈现具有相同高性能的内容。

Direct3D 9叠加

如果您使用Direct3D 9显示视频内容,您也可以使用叠加层。有关如何操作的信息,请参阅this page on MSDN。对D3D9叠加的使用有很多限制,很多硬件都不支持它们,所以我将介绍其他一些方法。

此技术不会阻止其他应用将其注入您的地址空间并捕获您的礼物。此外,由于某些硬件不支持它,而某些捕获API实际上禁用了覆盖,因此它不能提供非常强大的保护保障。

基于GPU的内容保护

如果您有足够的时间来了解GPU内容保护,并且您知道您将显示非标准的受DRM保护的视频格式,则可以使用GPU内容保护来滚动自己的受保护媒体路径。我不是这方面的专家,而且很少有人。我不推荐这个,但我想指出来。 This page on MSDN讨论了如何在Direct3D 9和this other page中实现它如何使用Direct3D 11实现它。

此技术提供保证内容未被捕获,因为密钥交换几乎完全通过硬件(例如HDCP)发生。

Media Foundation受保护媒体路径(PMP)

如果您使用支持良好的基于​​DRM的媒体格式显示视频,则可以使用Media Foundation的受保护媒体路径,该路径利用前面介绍的基于GPU的内容保护。它还将大多数功能封装在一个单独的受保护进程中,而其他应用程序无法拦截或以其他方式与之交互。如果有人试图安装测试签名的驱动程序或以其他方式注入未受信任的根权限进行代码签名的二进制文件,Windows将不允许解密内容并且您的内容将保持安全。此技术提供保证未捕获内容。 Netflix在Windows,Blueray播放器和其他播放器上使用它。

DXGI交换链标志

假设您使用Direct3D 10.x / 11.x呈现内容(希望现在是,而不是D3D 9,2014年),您可以在交换链上使用多个标记来锁定您的内容内容。

如果系统没有HDCP或类似HDCP的输出保护,您可以在交换链标志中传递DXGI_SWAP_CHAIN_FLAG_RESTRICTED_CONTENT以使交换链失败。这可能不是出于您的目的所必需的,但如果您担心人们捕获HDMI或模拟输出,那就很好。

你绝对想要的旗帜叫做DXGI_SWAP_CHAIN_FLAG_DISPLAY_ONLY。这可以防止所有屏幕捕获API看到您的交换链。它只会显示为黑色矩形。

有关所有DXGI交换链标记,请参阅this page

这种技术并不能提供基于GPU的内容保护提供的强有力的保证,但如果您非常确信其他应用程序没有做出疯狂的事情,例如将自己注入地址空间并挂钩当前的呼叫,您可以请相信这可以防止其他人看到您的内容(当然除了显示器)。

全窗保护

有时您可能想要保护的不仅仅是DXGI呈现的内容。在这种情况下,您实际上可以使用类似的机制来简单地保护整个窗口不被各种屏幕捕获技术捕获。这是一个名为SetWindowDisplayAffinity的API。它在强度和功能上等同于为交换链传递DXGI_SWAP_CHAIN_FLAG_DISPLAY_ONLY标志,但它也保护了使用GDI,旧版DirectX技术等提供的内容。传递WDA_MONITOR标志以启用给定的保护HWND,或通过WDA_NONE来禁用保护。

为了完全披露,我在Microsoft处理显示逻辑的团队,包括某些形式的屏幕捕获和内容保护。

答案 1 :(得分:1)

也许通过它的声音,您需要通过挂钩到全局Windows过程来拦截WM_PRINTCLIENT,如果使用WM_PRINTCLIENT消息,只需从钩子窗口过程返回。有关WM_PRINTCLIENT的详细信息,请参阅此处。另一种方法是截取剪贴板函数,其中数据来自特定应用程序,剪贴板包含位图。请参阅Larry Osterman关于this的博客。这是一篇关于实现全局Windows钩子的CodeProject的文章,我可以提供另外两个链接herehere。 (全部在CodeProject上)

希望这有帮助, 最好的祝福, 汤姆。