在开发一个测试软件时,我需要防止通过TeamViewer、AnyDesk、Ammyy等应用程序进行桌面共享,或者至少要检测到它。我们的考试软件是用C#开发的,它是一个winform,一个一个地呈现问题。
我不认为检测是那么容易,因为它们有很多方法来捕获屏幕桌面复制API、BitBlt、Direct3D、DirectX、DirectShow等等。
因此,我开始探索如何防止在桌面共享启动时显示我的c# winform。为了做到这一点,到目前为止,我已经尝试了以下几点:
SetWindowDisplayAffinity设置为WDA_MONITOR,以启用对winform的保护。通过这样做,当我开始桌面共享时,远程计算机可以看到窗体上的黑色层。但是并不是所有的桌面共享应用程序都有相同的行为。与TeamViewer一样,AnyDesk的行为与预期相同,但Admin则不然。一些应用程序如何显示黑色层,而有些应用程序没有显示?我还能做些什么吗?if (winForm != null)
{
if (Protect)
result = SetWindowDisplayAffinity(winForm.Handle, WDA_MONITOR);
else
result = SetWindowDisplayAffinity(winForm.Handle, WDA_NONE);
}对于所有桌面共享应用程序,我编码的这个方法并不是完全的证明,那么是否有任何100%的解决方案来防止/检测桌面共享呢?
如果您尝试了VLC播放器的"DirectX (DirectDraw)视频输出“,那么这种输出方法也会像SetWindowDisplayAffinity__一样,在任何桌面共享应用程序启动时都会在视频中添加黑层,我测试了这一功能,测试了几乎9个桌面共享应用程序,知道它是如何实现的吗?它能用c# winform来完成吗?
更新29-05-2019年
在检查了VLC代码之后,我才知道他们使用的是使用DirectDraw的硬件覆盖。因此,我创建了vc++项目,使用了d3d9,并创建了带有红色表面的覆盖,现在如果我使用远程机器,那么带有红色的表单就会显示黑色。宾果!!一半的问题解决了。
现在,我试图设置透明的窗口,这样,覆盖将在我的C#应用程序和考生可以进行考试,如果远程采取,然后覆盖将显示为黑色。为了使窗口透明,我使用了DwmExtendFrameIntoClientArea winapi,但是现在在远程上它也是透明的。有什么办法吗?
发布于 2019-05-31 08:28:53
我想补充这个问题作为答案,因为很多讨论都是在moved to chat的评论中进行的,所以我想对它进行总结,以便即将到来的观众能够了解讨论和我最终得到的解决方案。
首先,我想澄清一下VLC的"DirectX (DirectDraw)视频输出“是如何工作的?VLC的这一特殊输出模式使用DirectDraw创建硬件覆盖,并在上面播放视频。而屏幕捕获(不是从移动或外部摄像头)大多数捕获机制是通过请求屏幕GDI来捕获屏幕,但是硬件覆盖是直接呈现在GPU上的,而GDI不能访问GPU。就像GDI->CPU+RAM,DirectX->GPU+VRAM,这就是为什么屏幕捕捉VLC的视频播放部分显示为黑色。有关更多信息,https://stackoverflow.com/a/21535254/1629242
但作为RomanR。在聊天中提到“使用用于视频的覆盖将无助于隐藏应用程序的UI”。
我也确认了同样的情况,正如我在更新中提到的,我已经创建了一个vc++项目,它使用D3D9创建硬件覆盖,如果我在它上播放视频,然后在屏幕记录显示黑色区域,但我没有找到任何方法使该覆盖透明,以便它可以放在我的应用程序上,或者把应用程序内容放在覆盖上,这样当屏幕被记录下来时,应用程序内容就不会被看到。
Riddel提出了“反病毒工作方式和遍历所有进程和散列检查常见屏幕共享工具”的新想法,但我个人认为这将不是一般的解决方案,因为我必须维护这类应用程序的列表和它的哈希,如果发现了任何新的应用程序,然后更新该列表。而且,任何人都可以编辑字节来破坏散列,从而使这个错误。
我接受的解决方案:
Windows提供了一个只在监视器上显示窗口内容的函数。也就是说,SetWindowDisplayAffinity,这就像魅力!!
最低支持操作系统的问题:
尽管MSDN文档提到了“最低支持客户端::windows 7”,但在windows 7上,它并不适用于所有的屏幕捕获应用程序。RomanR。在一条评论中说:“从Windows 8(可能还有Windows 7的平台更新)开始,这将正确工作。在纯Windows 7上,您将暴露在免费桌面共享中,并且无法保护您的内容。”
因此,目前,我已经完成了SetWindowDisplayAffinity --我将其实现为:
private const uint WDA_NONE = 0x0;
private const uint WDA_MONITOR = 0x1;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetWindowDisplayAffinity(IntPtr hWnd, uint dwAffinity);
public static bool SetDRM(Form winForm, bool Protect)
{
bool result = false;
if (winForm != null)
{
if (Protect)
result = SetWindowDisplayAffinity(winForm.Handle, WDA_MONITOR);
else
result = SetWindowDisplayAffinity(winForm.Handle, WDA_NONE);
}
return result;
}https://stackoverflow.com/questions/56302217
复制相似问题