【问题标题】:Resolving PE SxS imports Windows解析 PE SxS 导入 Windows
【发布时间】:2012-06-24 06:29:45
【问题描述】:

我正在编写我自己的 Windows 加载程序版本(尽管是一个非常简单的版本),到目前为止,一切进展顺利。但是,在递归遍历已加载模块的导入表时,我遇到了一些障碍。

对于大多数依赖项,一切都很好,我可以简单地递归加载模块。但是,对于某些依赖项,这只会破坏目标进程。经过进一步调查,我意识到这是因为 Windows 并行程序集。本质上,加载的 PE 中的依赖项是目标进程中使用的模块的不同 SxS 版本。

在一种情况下,我加载的 DLL 引用了 msvcr90.dll,但目标进程使用的是早期版本的运行时:msvcr71.dll。

现在,windows 加载器可以很好地处理这个问题,所以显然有一个“正确”的方法可以做到这一点。我已经阅读了一些关于 Activation Contexts 的内容,但它们并没有真正帮助我理解这个问题。

调用 LoadLibrary 本身也不会将 dll 解析为正确的版本

LoadLibraryW(L"msvcr90.dll");

只返回0。有谁知道

a) 如何检测导入是否为 SxS 程序集

b) 如何解决导入到正确的 SxS 版本的过程。

我真的很困惑如何做到这一点。我现在从研究中知道大部分 PE 文件格式,但我很确定 SxS 超出了 PE 结构的范围。

如果您需要更多信息,请发表评论。可执行文件没有外部清单,其嵌入式清单没有指定运行时版本。但是,它确实在其工作目录中包含 msvcr71.dll 的副本,如果这对任何人都有帮助的话。

干杯。

【问题讨论】:

  • 您只是看到了泰坦尼克号沉没的冰山顶部。您还必须处理作为资源嵌入或在磁盘上提供的清单、发布者策略、绑定重定向、无注册表 COM、通过 CreateActCtx 动态激活、使用 SetDllDirectory 设置的自定义 DLL 搜索路径。文档很糟糕。
  • @HansPassant 我设法让这个工作。你说得对,这只是冰山一角哈哈。最后,我不得不编写一个 Resource Walker 来定位 .dll 的内部清单 (RT_MANIFEST)。接下来,我必须编写一个汇编存根来处理所有Activation Context 的东西。当然,我可以简单地用 C++ 编写它并将它包装在一个带有静态链接(即没有 SxS)的 .dll 中,然后用它来加载所有下一个库,但这似乎有点过头了,所以我在汇编中做了。基本上,我为汇编函数提供了一个以空分隔的所需依赖项的字符串...
  • 以及清单的路径(我将内部清单提取到一个临时文件中,CreateActCtx 需要清单的路径)。然后它创建激活上下文,遍历以 null 分隔的模块列表,并在每个模块上调用 GetModuleHandle。如果GetModuleHandle 返回0,它会继续调用LoadLibrary。如果仍为 0,则退出函数。我知道我通过在Activation Context 中简单地使用LoadLibrary 跳过了最困难的部分,但我真的只想使用我自己的加载程序来处理主dll,而不是它的依赖项。

标签: c++ windows portable-executable winsxs


【解决方案1】:

事实上,SxS 依赖超出了 PE 结构的范围!如您所知,PE 的导入表会枚举依赖项names,但不会枚举它们的版本。在处理这些依赖关系表时,Loader 还会查看 PE 依赖映像的 Manifest。如果 Manifest 记录一个或多个库(例如 msvcr90、advapi32、....),加载程序会在 winsxs 文件夹中查找依赖项。 Here an article 概述了此程序集以及如何在 C++ 中收集这些信息。

【讨论】:

  • 其实你不必自己建立WinSxs依赖的名字。您需要做的就是使用 CreateActCtx 进行“探测”。如果加载程序发现依赖项,它将为您构建正确的路径(例如 x86_microsoft-windows-msvcrt_31bf3856ad364e35_6.1.7601.17744_none_d33c3413fd4084d9)!
  • 并行程序集 (WinSxs) 难以处理。我在实施 PeStudio 时遇到了这个问题 (winitor.com)
  • 感谢您的链接,它让事情变得更加清晰。唯一的问题是,如何检查给定的导入名称是否为 WinSxS?我的意思是,在清单中Microsoft.VC90.CRTmsvcr90.dll 相关联,但是这个链接是如何建立的?如果我首先阅读清单以识别与 WinSxS 兼容的导入,如何将它们映射到特定的导入名称?
  • 好的,我想第一件事是通过首先查找图像的 RT_MANIFEST 资源并从中解决所有可能的 WinSxS 依赖关系来构建所有可能的 WinSxS 导入列表。但是,我正在努力了解如何将清单信息转换为 SxS 目录。我不知道与清单相关的最终标识符是什么,即:C:\Windows\winsxs\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_bcb86ed6ac711f91 在清单中找不到bcb86ed6ac711f91 位,所以我不知道如何解决这个问题:/
  • 加载器的工作(在 WinSxS 管理器的帮助下)解析库的真实路径。正如文章中提到的,路径取决于语言、公钥令牌等......让加载器为您解决这个问题。使用激活上下文 Api (msdn.microsoft.com/en-us/library/windows/desktop/…)
猜你喜欢
  • 1970-01-01
  • 2012-12-15
  • 2020-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多