在这个关于 DLL 注入的问题中,多个答案提到 DLL 注入可用于修改游戏,也许是为了编写机器人。能够检测 DLL 注入以防止这种情况发生似乎是可取的。这可能吗?
如何检测DLL注入?
您可以使用多种可能有效的方法(有关可能无效的原因,请参见下文)。这里有两个:
- 一个进程可以调试自己,然后它会收到 DLL 加载的通知。
- 一个进程可以承载一个 TLS 回调,然后它会收到线程创建的通知。这可以拦截线程创建,例如 CreateRemoteThread 生成的线程。如果线程起始地址是 LoadLibrary(),那么您就有一个很好的迹象表明有人将要强制加载 DLL。
除此之外,您可以定期枚举 DLL 名称列表,但是所有这些技术都可以被确定的攻击者击败(可以暂时停止调试;可以关闭线程通知;注入的 DLL 可能不会保持加载足够长的时间,因为它可能使用动态分配的内存来托管自己,然后卸载文件等)。
如果攻击者是经验丰富的游戏黑客并且作弊的细节未知,那么您尝试做的事情将非常困难。
一般来说,如果您想注入一个更难检测且不会显示在进程的模块列表中的 DLL,您可以使用称为手动映射的东西。它的作用是模拟 LoadLibrary 的行为,而无需将 DLL 放入进程模块列表中。我个人是MemoryModule的粉丝。如果您想了解一种非常常见的隐藏技术,请研究一下。即使您的 hack 从未公开,也建议确保您的 DLL 永远不会出现在崩溃报告或类似内容中。
问题是,一旦知道您正在注入进程的事实,您尝试攻击的模块就可以访问您的代码。正确实现的客户端反作弊将枚举所有映射的内存区域,并将所有映射内存段的各种偏移量的散列集发送到服务器。服务器然后存储这些哈希集,以便如果您的作弊被公开,您将被追溯禁止。
如果您想避免进程检测到您的代码,您必须要么将所有内容都包装在虚拟机中,然后从虚拟机外部与该进程进行交互。其他较弱的选择是编写一个驱动程序并尝试隐藏在环 0 中,简单地创建一个与进程交互的调试器或使用断点和一种进程中调试器来处理硬件断点事件,以避免检测到您的钩子。
正确实施的游戏不会在乎客户端是否受到损害,因为一旦您信任您的玩家,您就会遇到问题。理想情况下,游戏客户端只会渲染状态,对服务器的输出做出反应,并将输入与所有逻辑服务器端一起发送到服务器。不幸的是,由于延迟和性能原因,这并不总是可行的。对于客户做出的每一个决定,问问自己客户承担该责任的最坏结果是什么。因为它会发生。
修补游戏的可执行文件 + 使用加载顺序技巧
- 您应该在加载之前检查游戏可执行文件的完整性,因为有办法对其进行修补以加载恶意 Dll 文件,如果添加了这些文件(病毒等)
- 检查游戏目录中的未知 dll 文件 - 奇怪的名称,模仿系统库文件的 dll
- 另一件事是 - 一些加载器将与原始文件的名称一起放置,它将处理所有事情,最后将加载实际游戏 - 因此监视整个游戏目录的完整性。
进程注入 - 它不必是 dll 而是一些任意代码
- 通过修补
a来监视“入侵”API调用(例如)。写入进程内存 B. VirtualAlloc(Ex)
c. 虚拟保护
D. ZwWriteProcessMemory
e. NtMapViewOfSection
f. 创建远程线程 g. CreateProcess - 带有挂起状态 h 的标志。开放进程 - 创建看门狗线程以监控敏感游戏内存区域的完整性
对的,这是可能的。您可以采用几种通用方法来检测注入的进程(不仅仅是 dll)。第一个是枚举操作系统通过注册表项注入的 DLL。两个已知的键/值是 AppCertDLL 和 AppInitDLL。第二种是搜索所有标记为 RWX 的内存,然后从内存中解析出可执行文件或注入代码的线索。第三是搜索包含可执行代码或注入代码的私有内存。另一种方法是搜索 API 的内联挂钩。解析出处理程序地址,然后查询处理程序的内存地址。处理程序可能是一个注入进程。
过去几周我一直在这方面进行研究。我的主要重点是检测注入的恶意软件。这是我本周发布的一个名为injdmp的工具,用于检测注入的进程。