使用 ReadProcessMemory 时目标应用程序崩溃

逆向工程 记忆 例外
2021-06-24 21:48:34

我有一个有趣的应用程序,它似乎在使用ReadProcessMemory读取特定内存区域时崩溃我知道它对 RPM 没有任何特别之处,因为:

  1. 注入 DLL 以直接读取该内存区域也会导致崩溃。
  2. 使用CheatEngine 等应用程序扫描区域也会导致崩溃。

它也不是警戒区或带有特殊保护标志的区域。这只是一个私有的 R+W 区域。

起初我以为他们正在安装这里描述的硬件数据断点,但在检查所有线程的调试寄存器并看到它们都为零后,我得出结论,使用了另一种技术。

我怀疑每当读取那段内存时,它们都会以某种方式引发异常。我希望了解他们在做什么以及如何检测它,或者至少让 RPM 不会使应用程序崩溃。

PS 我无法将调试器附加到此应用程序,并且可执行文件已加密,但我知道各种 TLS 回调与 VEH 异常处理程序一起使用。

4个回答

好吧,看来我们对此有了答案。它比我想象的要简单得多,而且实际上很酷。

基本上,他们分配一些没有物理支持的页面,直到页面被访问。这意味着任何访问(即使在内核模式下)都将验证页面,从而允许应用程序看到页面已被验证并迅速使游戏崩溃。

为避免这种情况,您可以使用QueryWorkingSetExNtQueryVirtualMemory,如果返回结构的“有效”属性为零,那么您可能不应该阅读该页面。

我不能肯定地说这是正确的答案,但它符合我的分析。如果有人有关于这种技术的更多信息,特别是如何使用VirtualAlloc 之类的东西来实现它,我很想了解更多。

PS 该应用程序似乎没有任何内核模式访问权限,它只是一个普通的用户模式应用程序。

编辑:可以在此处找到示例 C++ 实现

检查以非侵入性模式连接windbg 是否有效。如果是,请检查目标地址范围的页面权限

有没有内核模式反调试?ReadProcessMemory 正在使用 KeAttachProcess。也许有一个内联钩子可以阻止你。

使用 PCHunter 等 ARK 工具可以轻松搜索系统中的钩子。

而且我不认为应用程序可以在用户模式下检测 RPM。实际上,要检测 RPM,需要挂钩 NtReadVirtualMemory 或挂钩系统页面错误处理程序。更重要的是,即使页面受 PAGE_NO_ACCESS 保护,应用程序也不应该崩溃。

所以我怀疑有内核模式挂钩。

VirtualProtect 或 WriteProcessMemory 受此影响

因为 Windows 使用名为“MiCheckForConflictingNode”的内部函数检查 Vad 表 Windows 对 0x00200000 做出反应 2 = VVadImageMap = 2 到值 0x00400000 VadTypeVadWriteWatch = 4 到值 0x0008000 这个标志是“NoChange”是no (0) 要么包含 0 要么包含 1

KeAttachProcess 还调用了一个触发器,我不确定它是一个标志还是一个被设置的函数

来自目标的触发器被延迟执行,然后读出从 KeAttachProcess 留下的信息

在此之后,目标会打印错误,但它只是一个触发器

为避免这种情况,请不要使用该函数或模拟它们,以免它们也以其他方式调用触发器或标志

微软提供了一个 .txt 文件,其中包含纯骗局的文本,并用 10 页的篇幅谈论微软正在保护这些公司

并说诸如“堆栈错误”之类的话,事实并非如此,这只是诈骗和拖钓

我还发现这部分是通过所谓的“安全更新”添加到 Windows 中的

这就是为什么我从不喜欢 Windbg 它有很多依赖项

你可以在这里看到这个问题