有没有办法让Windows 7 x64从本地目录加载ntdll.dll,而不是system32?

问题描述:

我正在处理一个应用程序,该应用程序保存自定义进程的状态,然后从停止点处恢复它。有没有办法让Windows 7 x64从本地目录加载ntdll.dll,而不是system32?

现在有以下问题。系统重新引导时,系统模块的所有基址都是随机分配的(ntdll.dll,kernelbase.dllkernel32.dll等)。操作系统是Windows 7 x64企业版。在重新启动后尝试恢复应用程序时,它显然崩溃(但在重新启动之前从恢复点正常工作)。我看到2个解决方案,以这样的:

  1. 使系统模块的静态地址,当他们在应用程序加载
  2. 补丁中所有的引用目标模块的应用程序,它可以保存的堆栈功能,地址(地址在堆等)

显然,第二种方法是困难的。我们要进行完整的应用程序分析,不同于数据的代码,不同的数据,它可能是参考系统模块的简单整数...所以我选择了第一种方法。

在虚拟内存中加载模块时,操作系统首先检查是否已有一个在物理内存中具有这样名称的模块。如果有的话,它只是将这个模块映射到虚拟地址空间。在这种情况下,模块将从其初始位置加载,如果是ntdll.dll - 从C:\Windows\System32\ntdll.dll。即使您将此模块复制到应用程序目录,禁用ASLR标志和补丁映像基础为某个值,该模块仍将从系统目录加载。一些重定向的方式是必要的。

MSDN我们了解以下内容(部分“搜索顺序桌面应用程序”):

桌面应用程序可以控制从一个DLL通过指定一个完整的路径,使用DLL redirection加载的位置,或通过使用manifest。如果没有使用这些方法,则系统会按照本节所述在加载时搜索DLL。

因此,至少有两种方法可以达到目标。

论DLL重定向,我们看到的页面:

已知的DLL不能被重定向。有关已知DLL的列表,请参阅以下注册表项:HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ KnownDLLs。系统使用Windows文件保护来确保诸如此类的系统DLL不会被更新或删除,除非通过操作系统更新(如Service Pack)。

我想重定向的模块是已知的DLL,所以这个变体不能应用。

舱单被遗弃。有关使用它们的优秀article。本文的作者创建存根DLL以替换原始DLL(user32.dll),然后使应用程序加载此替换的DLL。关键是这个DLL在搜索导入函数时加载,而不是在应用程序的开始处加载,如ntdll.dll

更具体地说,请参考“Windows内部函数,第6版”,p。 359其中详细解释了过程创建。有7个阶段有:

  1. 转换和验证的参数和标记
  2. 打开图片要执行
  3. 创建Windows执行过程对象
  4. 创建初始线程及其堆栈和上下文
  5. 执行Windows子系统特定后 初始化
  6. 开始执行初始线程
  7. 在 新进程的上下文这里

最重要的点执行过程初始化:

  • ntdll.dll映射发生在阶段3;

  • 在第5阶段,我们读到的开始(重点是我的):

此时的Kernel32.dll将消息发送到Windows子系统,以便它可以建立的SxS 信息(有关并行程序集的更多信息,请参阅本节末尾部分),例如 清单文件,DLL重定向路径以及新进​​程的进程外执行。

这意味着ntdll.dll在重定向有机会发生之前被加载。关于重定向主题,SO上存在很多问题,但它们都是关于在搜索导入函数时加载的DLL或在应用程序中可能发生重定向时通过LoadLibrary显式加载的DLL。

然而,在任何情况下,ntdll.dll在很早的阶段就被加载。

使用我迄今为止收集的所有信息,例如,我可以在应用程序目录中使用kernel32.dll进行应用程序搜索(使用本段的链接)。但我无法重定向搜索ntdll.dll

从用户模式中完全可能吗?


P.S.有一种全局禁用ASLR的方法,请参见post。然而,这是一种非常粗鲁的方式,Internet ExplorerAdobe Reader等应用程序无法正常工作,整个操作系统都面临漏洞。

+1

* ntdll.dll *包含进程的自引导代码。它必须是映射到过程对象的第一个模块。你不能改变它,而不用重写内核。 – IInspectable

在进程创建过程中,ntdll从内核映射。当进程中的第一个用户模式指令开始执行时(这是来自ntdll的LdrInitializeThunk)ntdll已经映射进程(在开始时只有exe和ntdll映射,所有其他dll由ntdll加载或由exe延迟)。和NTDLL必须在所有的进程中加载​​相同的地址,因为位于NTDLL(LdrInitializeThunk,KiUser *分派器)一些回调的系统使用的地址

有一些(理论值)选项:

  • 使用委派NTDLL在Windows 10 WOW64处理(我从来没有尝试过这一点,但在理论上,你应该能够指定的注册表设置这样做。见http://redplait.blogspot.de/2017/07/delegatedntdll.html
  • 设置一些兼容性选项(以确保apphelp.dll加载),并使用清单文件加载自定义apphelp.dll,你可以用它来加载自己的NTDLL和补丁加载的模块列表,以使自己的dll的一个使用作为任何其他模块的导入。 我到目前为止还没有做到这一点(我喜欢尝试它,当我发现的时候),但我能加载自定义win32u.dll,转发大部分出口到原来的win32u.dll和挂钩的副本放到一些win32系统调用。 另请参见http://*.com/questions/2100973/dll-redirection-using-manifests