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

时间:2016-05-16 11:07:14

标签: redirect dll windows-7-x64 ntdll

我正在处理一个保存自定义进程状态的应用程序,然后从停止的位置恢复它。

目前存在以下问题。系统重启时,系统模块的所有基地址都是随机的(ntdll.dllkernelbase.dllkernel32.dll等等。操作系统是Windows 7 x64 Enterprise。在重新启动后尝试恢复应用程序时,它显然会崩溃(但在重新启动之前从恢复点运行良好)。我看到了两个解决方案:

  1. 在应用程序中加载系统模块时,使其地址静态
  2. 修补应用程序中目标模块的所有引用(堆栈上的函数地址,可以保存在堆中的地址等)
  3. 显然,第二种方式很难。我们要进行完整的应用程序分析,不同的数据代码,不同的数据,从引用到系统模块可能是简单的整数...所以我选择了第一种方式。

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

    MSDN我们了解以下内容("桌面应用程序的搜索顺序" ):

      

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

    因此,至少有两种方法可以实现这一目标。

    在关于DLL重定向的页面上,我们看到:

      

    无法重定向已知的DLL。有关已知DLL的列表,请参阅以下注册表项: HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ KnownDLLs 。系统使用Windows文件保护来确保除了操作系统更新(如Service Pack)之外,不会更新或删除这些系统DLL。

    我想重定向的模块是已知的DLL,因此无法应用此变体。

    保留清单。关于使用它们有一个很好的article。本文作者创建存根DLL来替换原始DLL(user32.dll),然后使应用程序加载此替换的DLL。关键是在搜索导入的函数时加载此DLL,而不是在应用程序的最开始时加载,如ntdll.dll

    更具体地说,让我们参考" Windows Internals,Sixth Edition",p。 359 解释了流程创建的细节。那里有7个阶段:

    1. 转换和验证参数和标志
    2. 打开要执行的图像
    3. 创建Windows Executive Process Object
    4. 创建初始线程及其堆栈和上下文
    5. 执行Windows子系统特定的后 初始化
    6. 开始执行初始线程
    7. 在上下文中执行进程初始化 新流程
    8. 这里最重要的一点是:

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

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

        

      此时,Kernel32.dll向Windows子系统发送一条消息,以便它可以设置SxS   信息(有关并排装配的更多信息,请参见本节末尾)   清单文件,DLL重定向路径,以及新进程的进程外执行。

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

      但是,ntdll.dll在任何情况下都会在很早的阶段加载到应用程序中。

      使用我目前收集的所有信息,我能够在应用程序的目录中使用kernel32.dll进行应用程序搜索(使用本段中的链接)。但我无法重定向搜索ntdll.dll

      完全可以从用户模式开始吗?

      P.S。有一种方法可以全局禁用ASLR,请参阅此post。但是,这是一种非常粗鲁的方式,Internet ExplorerAdobe Reader等应用程序无法运行,整个操作系统都容易受到漏洞的攻击。<​​/ p>

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

有一些(理论上的)选择:

  • 在Windows 10上使用委托的ntdll进行WOW64进程(我从未尝试过这个,但理论上你应该可以指定注册表设置来执行此操作。请参阅http://redplait.blogspot.de/2017/07/delegatedntdll.html
  • 设置一些兼容性选项(以确保加载apphelp.dll)并使用清单文件加载自定义apphelp.dll,您可以使用它来加载您自己的ntdll并修补已加载的模块列表以使您自己的dll成为一个用作任何其他模块的导入。 我到目前为止没做到这一点(我喜欢在找到时间时尝试它),但我能够加载自定义win32u.dll,它将大多数导出转发到原始win32u.dll的副本并挂钩到某些win32系统调用。 另请参阅http://stackoverflow.com/questions/2100973/dll-redirection-using-manifests