2

好吧,解释起来可能有点困难:

假设有人创建了一个 Windows 应用程序(使用 C# 或任何其他语言),该应用程序使用GetDesktopWindow()上的函数user32.dll来捕获屏幕截图,然后将此图像发送到任何在线服务。

由于它是定制的应用程序,没有防病毒软件能够确定它是病毒,因为它仍然是一个未知的应用程序。此外,此类 API 也有合法用途,因此不一定是病毒,它可以是无害的窗口捕获工具或某种间谍工具。

我想知道的是:有没有办法查看特定的 EXE 文件对 Windows 功能的作用?我可以知道“myapp.exe”是否使用GetDesktopWindow()user32.dll

这只是一个例子。当任何应用程序使用它们时,我想知道还有很多其他 Windows 端点。

有没有办法做到这一点?

4

1 回答 1

4

这取决于你想要做多长时间。它本质上是一场猫捉老鼠的游戏 - 不良行为者会试图通过跳过一些晦涩难懂的圈子来寻找新的方法来规避您的检测,您将为这些技巧添加更复杂的检测方法,他们会想到新的技巧,等等。

此外,这取决于您是要静态还是动态确定,以及您是否真的想知道是否GetDesktopWindow被调用或“程序是否获得桌面窗口的句柄”(这也可以通过其他方式实现)。

这是一个非详尽的想法列表:

  • 您可以通过查看导入目录来静态确定函数是否被导入。研究 PE 文件结构以了解更多信息。这篇文章可能会有所帮助。
    • LoadLibrary通过使用和动态导入函数,可以轻松绕过这种检测方法GetProcAddress
  • 您可以扫描文件中的字符串GetDesktopWindow以检测动态导入的可能用法。
    • 通过打包、加密或以其他方式混淆动态导入函数的名称,可以轻松绕过这种检测方法。
  • GetDesktopWindow您可以通过注册一个或一个全局挂钩来动态观察该函数是否被调用,AppInit_DLL该挂钩被注入到每个新进程中,并GetDesktopWindow通过跳转到您自己的代码覆盖其第一个字节来从进程内部挂钩该函数,以某种方式通知您的检测组件,执行原始字节并跳回。(Microsoft Detours可以提供帮助。)
    • 如果目标注意到钩子并在调用之前将其删除,则可以绕过这种检测方法,因为它在自己的进程空间中。(您还可以像调试器一样做一些技巧,并在 的第一条指令上设置硬件断点GetDesktopWindow,但由于目标也可以修改调试寄存器,因此仍有办法检测或规避这一点。)
    • 您可以从内核模式构建一个驱动程序来执行此操作,但现在我们已经变得非常深入了。

请注意,到目前为止,我们专注于GetDesktopWindowuser32.dll. 但是,如果目标只是使用不同的方式来实现获取桌面窗口句柄的目标呢?

  • 当前线程的桌面窗口句柄存储在 TIB(线程信息块)中,可通过fs:[18]用户模式访问。您可以在GetDesktopWindowReactOS 的源代码中看到这一点,这与 Microsoft 的实际实现相比非常准确(您可以通过在调试器中查看它来验证)。因此,目标可以直接访问 TIB 并提取此值,甚至根本不需要调用GetDesktopWindow
  • 目标可以只获取一个已知的顶级窗口,例如您将通过的 shell 的隐藏兼容性窗口,GetShellWindow()或者 - 为了避免GetShellWindow也检测到 - 例如FindWindow(NULL, "Program Manager")(甚至是新创建的窗口!)并调用GetAncestor(hWnd, GA_PARENT)它来获取桌面窗口句柄。
  • 我敢肯定,只要有一些创造力,你的对手会想出比这些更聪明的想法。

此外,如果我们更进一步,看看截屏的最终目标,还有其他方法可以实现这一目标。想到的第一个例子:他们可以keybd_event用来模拟按下 PrnSc 键,然后从剪贴板数据中读取屏幕截图。

所以这完全取决于你想走多远。

顺便说一句,您可能会发现该drltrace项目很有趣——它是一个库调用跟踪器。

于 2020-03-09T19:30:27.437 回答