【问题标题】:Resolve shared library path on Windows and *nix systems解析 Windows 和 *nix 系统上的共享库路径
【发布时间】:2019-05-04 13:33:54
【问题描述】:

在加载指定名称的共享库时,系统会根据搜索顺序或缓存在某些目录中搜索实际文件(例如 .dll)。

如何以编程方式获取 DLL 的解析路径,但不实际加载它?例如。在 Windows 上,对于kernel32kernel32.dll,它可能会返回C:\windows\system32\kernel32.dll,而给定foo 它可能是C:\Program Files\my\app\foo.dll

如果不能这样做,是否有另一种方法来确定某个库是否属于系统?例如。 user32.dlllibc.so.6 是系统库,但 avcodec-55.dllmyhelperslib.so 不是。

我对适用于 Windows、Linux 和 Mac OS 的解决方案感兴趣。

【问题讨论】:

标签: c linux windows winapi


【解决方案1】:

在 Windows 上,LoadLibraryEx 具有 LOAD_LIBRARY_AS_DATAFILE 标志,该标志打开 DLL 而不执行您称为“实际加载”的操作。

这可以与任何搜索顺序标志结合使用(是的,不止一个搜索顺序)。

很遗憾,您不能使用GetModuleFilename。请改用GetMappedFileName

LoadLibraryEx 文档还特别指出 使用 SearchPath 函数来定位 DLL, 使用 cmets 中提到的 DONT_RESOLVE_DLL_REFERENCES 标志。


对于 Linux,有一个现有的工具 ldd 可以使用它的源代码。它确实加载了共享库,但是设置了一个特殊的环境变量LD_TRACE_LOADED_OBJECTS,按照惯例,它会导致它们跳过做任何事情。因为这只是一个约定,请注意malicious files can perform actions when loaded by ldd CVE-2009-5064

【讨论】:

  • 如何获取GetMappedFileName表单句柄返回的LoadLibraryEx所需要的内存地址?
  • @mcpiroman:除了用作标志的低位之外,LoadLibraryEx 返回的HMODULE 是库的基地址。因此,您可以将 HMODULE 转换为指针,或者您可以先屏蔽标志位并进行转换,两者都可以。
  • LOAD_LIBRARY_AS_DATAFILE 有一个单独的实现,它通过CreateFileW 等加载和映射文件,而不是使用加载器函数LdrLoadDll,因此它不是特殊情况下的“已知 DLL”和API 设置为加载程序,不会将 DLL 作为模块加载。请改用DONT_RESOLVE_DLL_REFERENCES。然后通过FreeLibrary释放它。
  • @eryksun:文档说不要使用DONT_RESOLVE_DLL_REFERENCES。如果您知道LOAD_LIBRARY_AS_DATAFILE 与正常的 DLL 位置逻辑不匹配的方式,请向 Microsoft 提交错误。不作为模块加载是重点。
  • 我知道它说不要使用它,但我怀疑 API 中对标志的支持是否会消失,特别是因为它的实现方式与将 EXE 作为模块加载完全相同.我认为他们弃用了它,这是可以理解的,因为如果不调用 FreeLibrary 就会出现问题,并且如果尚未加载模块,它会受到竞争条件的影响。所以当然要谨慎使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
  • 2013-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多