新的缓解措施 模块篡改保护
发布时间:2022-08-27 09:40:03 所属栏目:安全 来源:互联网
导读:什么是模块篡改保护? 模块篡改保护是一种缓解措施,可防止对进程主映像的早期修改,例如 IAT 挂钩或进程空心化。它一共使用了三个 API:NtQueryVirtualMemory、NtQueryInformationProcess 和 NtMapViewOfSection。如果启用,加载程序将在调用入口点之前检查
什么是模块篡改保护? 模块篡改保护是一种缓解措施,可防止对进程主映像的早期修改,例如 IAT 挂钩或进程空心化。它一共使用了三个 API:NtQueryVirtualMemory、NtQueryInformationProcess 和 NtMapViewOfSection。如果启用,加载程序将在调用入口点之前检查主图像标头和 IAT 页面中的更改。它通过使用信息类 MemoryWorkingSetExInformation 调用 NtQueryVirtualMemory 来做到这一点。返回的结构包含有关页面共享状态的信息,以及是否从其原始视图修改。如果标头或 IAT 已从其原始映射修改。例如,如果主图像已被取消映射,并且已在其位置映射了另一个图像,则加载器将使用类 ProcessImageSection 调用 NtQueryInformationProcess 以获取主图像部分,然后将使用 NtMapViewOfSection 重新映射它。这样,新部分将被使用,篡改的图像副本将被忽略。 此缓解从 RS3 开始可用,并且可以使用 PROCESS_CREATION_MITIGATION_POLICY2_MODULE_TAMPERING_PROTECTION_MASK 在进程创建时启用。 模块篡改保护缓解措施是如何发现的 如果微软从未宣布或记录某些缓解措施,那人们如何才能发现这些缓解措施?因此,一个值得关注的好地方是 EPROCESS 结构中的各种 MitigationFlags 字段。目前存在三个 MitigationFlags 字段(MitigationFlags、MitigationFlags2、MitigationsFlags3),每个字段包含 32 位。在前两个中,整个32位已经被使用,所以最近添加了MitigationFlags3,目前包含三个缓解措施,我相信很快会添加更多。这些标志代表进程中启用的缓解措施。例如,我们可以使用 WinDbg 为当前进程打印 EPROCESS.MitigationFlags: 新的缓解措施:模块篡改保护 最后,在位 28 和 29 中,我们可以看到值 EnableModuleTamperingProtection 和 EnableModuleTamperingProtectionNoInherit。不幸的是,搜索这些名称并没有得到任何好的结果。有几个网站只显示结构而没有解释,一个模糊的堆栈溢出答案简要提到了 EnableModuleTamperingProtectionNoInherit 而没有添加细节,还有这条推文: 新的缓解措施:模块篡改保护 不出所料,最详细的解释是 Alex Ionescu 2017 年发布的一条推文。这虽并不是完整的文档,但它是一个开始。如果你已经了解并理解构成此缓解措施的概念,那么这一系列的推文可能会非常清楚地解释有关该特性的所有内容。 开始搜索进程缓解实现的第一个地方通常是内核:ntoskrnl.exe。然而,这是一个巨大的二进制文件,不容易搜索。似乎没有与此缓解措施完全相关的函数名称,所以没有明显的地方可以开始。 相反,你可以尝试不同的方法并尝试找到对 EPROCESS 的 MitigationFlags 字段的引用,并可以访问这两个标志中的一个。但除非你可以访问 Windows 源代码,否则没有简单的方法可以做到这一点。但是,你可以做的是利用 EPROCESS 是一个大型结构并且 MitigationFlags 存在于它的末尾,偏移量 0x9D0 的事实。一种非常粗暴但有效的方法是使用 IDA 搜索功能并搜索所有对 9D0h 的引用: 新的缓解措施:模块篡改保护 这会很慢,因为它是一个很大的二进制文件,并且一些结果与 EPROCESS 结构无关,因此你必须手动搜索结果。此外,仅查找对该字段的引用是不够的,MitigationFlags 包含 32 位,其中只有两个与当前上下文相关。所以,你必须搜索所有的结果,找出以下情况: 0x9D0被用作EPROCESS结构的偏移量——因为无法保证知道每种情况使用的结构类型,尽管对于较大的偏移量,只有少数选项可以是相关的,它主要可以通过函数名称和上下文来猜测。 比较或设置MitigationFlags字段为0x10000000 (EnableModuleTamperingProtection)或0x20000000 (EnableModuleTamperingProtectionNoInherit)。或者通过诸如bt或bts之类的汇编指令,按位数测试或设置位28或位29。 运行搜索后,结果看起来像这样: 新的缓解措施:模块篡改保护 你现在可以浏览结果并了解内核使用了哪些缓解标志以及在哪些情况下使用。然后我会告诉你,这个努力完全没有用,因为 EnableModuleTamperingProtection 在内核中的一个地方被引用:PspApplyMitigationOptions,当创建一个新进程时调用: 新的缓解措施:模块篡改保护 因此,内核会跟踪是否启用了此缓解措施,但从不对其进行测试。这意味着缓解措施本身在其他地方实现。这种搜索可能对这种特定的缓解措施毫无用处,但它是找出缓解措施实现位置的几种方法之一,并且对其他流程缓解措施很有用,所以我想提一下它。 现在让我们回到模块篡改保护,有时会实现进程缓解的第二个位置是 ntdll.dll,它是每个进程中要加载的第一个用户模式映像。此 DLL 包含所有进程所需的加载程序、系统调用存根和许多其他基本组件。在这里实现这种缓解是有意义的,因为顾名思义它与模块加载有关,这通过 ntdll.dll 中的加载器发生。此外,这是一个包含 Alex 在他的推文中提到的功能的模块。 即使我们没有这条推文,只要打开 ntdll 并搜索“tampering”,我们就能很快找到一个结果:函数 LdrpCheckPagesForTampering。寻找这个函数的调用者,我们看到它是从LdrpGetImportDescriptorForSnap调用的: 新的缓解措施:模块篡改保护 在截图的第一行,我们可以看到两个检查:第一个验证当前正在处理的条目是主图像,因此该模块被加载到主图像模块中。第二个检查是 LdrSystemSllInitBlock.MitigationOptionsMap.Map中的两个位。我们可以看到这里检查的确切字段只是因为我对 LdrSystemDllInitBlock 应用了正确的类型,如果你在没有应用正确类型的情况下查看这个函数,你会看到一些随机的、未命名的内存地址被引用。 LdrSystemDllInitBlock 是一个数据结构,包含加载程序所需的所有全局信息,例如进程缓解选项。它没有记录,但具有符号中可用的 PS_SYSTEM_DLL_INIT_BLOCK 类型,因此我们可以在此处使用它。请注意,虽然此结构在 NTDLL 符号中不可用,而是你可以在 ole32.dll 和 combase.dll 的符号中找到它。 MitigationOptionsMap 字段只是三个 ULONG64 的数组,其中包含标记为此过程设置的缓解选项的位。我们可以在 WinBase.h 中找到所有缓解标志的值。 (编辑:信阳站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |