使用清单的 DLL 重定向

新手上路,请多包涵

我需要可靠地重定向应用程序查找特定 DLL。使用 app.exe.local 方法不起作用,因为如果应用程序具有清单(嵌入或单独的文件),则忽略本地文件。所以我试图通过将 DLL 定义为清单中的私有程序集来进行 DLL 重定向。

我有一个测试应用程序 LoadDll.exe,它只是调用

LoadLibrary("C:\\EmptyDll.dll");

LoadDll.exe 具有清单(作为单独的文件,LoadDll.exe.manifest)

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
  version="1.0.0.1"
  processorArchitecture="x86"
  name="LoadDll"
  type="win32"
/>
<dependency>
  <dependentAssembly>
    <assemblyIdentity
      type="win32"
      name="EmptyDll"
      version="1.0.0.1"
      processorArchitecture="x86"
    />
  </dependentAssembly>
</dependency>
</assembly>

包含 LoadDll.exe(不是 c:\)的应用程序文件夹包含带有嵌入式清单的 EmptyDll.dll。

 <?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<assemblyIdentity
      type="win32"
      name="EmptyDll"
   version="1.0.0.1"
      processorArchitecture="x86"
    />
</assembly>

但是,LoadDll.exe 继续加载 C:\EmptyDll.dll,而不是应用程序文件夹中的 EmptyDll.dll。

如果您破坏任何一个清单(例如更改 EmptyDll.dll 清单标识中的版本号),LoadDll.exe 不会加载,因此清单文件正在被 Windows 读取和处理,但只是被忽略。

有人有什么想法吗?

谢谢!

托比

原文由 WearyMonkey 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 747
1 个回答

因此,使用清单使用绝对路径将调用重定向到 LoadLibrary 似乎是不可能的。

在玩了很多清单之后,似乎一旦你通过了所有糟糕的文档清单,实际上是非常简单的。

基本上,当加载可执行文件时,Windows 会收集所有使用标识和依赖项元素链接的相关清单。然后对于清单文件中包含的每个文件元素,它会在激活上下文中添加一个条目:

 'name attribute of file element' -> 'absolute path of manifest file' + 'name attribute of file element'

现在,当调用加载库时,它会在激活上下文映射中搜索与加载库的路径参数匹配的键,然后使用该键的值调用 Loadlibrary

So if my application c:\foo\foo.exe has a dependency on the manifest in c:\foo\baa\baa.manifest , and baa.manifest contains a file element <file name="empty.dll"/> , then the activation context将有映射: "empty.dll" -> "c:\foo\baa\empty.dll"

所以对 LoadLibrary("empty.dll") 的任何调用都将被重定向到 LoadLibrary("C:\foo\baa\empty.dll")

但是, LoadLibrary("c:\anotherpath\empty.dll") 不会被重定向!

现在证明我的观点是简单的清单文件和激活上下文是多么愚蠢。如果 baa.manifest 的文件元素是 <file name="c:\anotherpath\empty.dll"/> 并且您进行了 LoadLibrary("C:\anotherpath\empty.dll") 调用,则 LoadLibrary 调用将被重定向到 LoadLibrary("C:\foo\baa\C:\anotherpath\empty.dll") 路径错误,是的,路径错误。 ..

文件元素确实有一个名为“loadFrom”的未记录属性,它的功能听起来很像,并且似乎完美地解决了这个问题。使用 loadFrom,我能够重定向绝对路径 loadlibrary 调用,但它似乎以奇怪的方式搞砸了可执行文件中的其他依赖项。如果有人更了解“loadFrom”的工作原理,我会非常感兴趣。

那么我最终是如何解决我的问题的呢?通过使用 Ethical Hacker 中描述的极其严厉的 DLL 木马方法。基本上,您创建了一个虚拟 kernel32.dll,它将所有调用重定向到原始 kenerl32.dll,LoadLibrary 调用除外,您可以在其中放置自己的重定向逻辑。然后在应用程序清单中,放置一个将 kernel32.dll 重定向到虚拟对象的文件元素。乐趣。

所有这些都描述了我在 Windows Xp Sp2 上的实验。为了获得更多乐趣,我相信清单在几乎每个版本的 Windows 上的行为都不同。

原文由 WearyMonkey 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题