这应该有效。SetDllDirectory
会“级联”,因此会影响相关 DLL 的加载方式。基本上,SetDllDirectory
允许您修改进程对 DLLs 的默认搜索顺序,并且对此进行的任何更改都会影响整个进程,包括可能加载到该进程中的任何 DLL。当 Windows 隐式加载子进程的依赖项时,也会使用此搜索顺序。
但是,如文档SetDllDirectory
中所述,存在一个致命缺陷:
每次SetDllDirectory
调用该函数时,它都会替换上一次SetDllDirectory
调用中指定的目录。
如果您的进程中的其他代码正在调用SetDllDirectory
,那么它正在撤消您的第一次调用。如果是 lib1.dll 中的代码在尝试加载 lib2.dll 之前执行此操作,则加载 lib2.dll 的尝试将失败。
现在,当然,这是 lib1.dll 的不良行为。DLL 是应用程序进程中的客人,因此不应该去改变地毯。但并非所有代码都表现良好,这使得这是一个脆弱的策略。
另一种可能出错的方法是,如果 lib1.dll 通过调用LoadLibraryEx
和传递覆盖默认搜索顺序的众多标志之一来加载 lib2.dll,例如LOAD_LIBRARY_SEARCH_APPLICATION_DIR
.
最好的解决方案是将所有依赖的 DLL 放在应用程序目录中。在 Windows 上,应用程序的目录是应用程序包,所以这是放置它们的最佳位置。用户永远不应该翻遍这个目录,所以“把它弄得乱七八糟”不是问题。它解决了各种问题,包括依赖注入攻击,即有人将同名的 DLL 放在当前目录中。(您可以通过调用来防止这种类型的攻击SetDllDirectory
并传递一个空字符串以从搜索顺序中删除当前目录,但现在我们回到问题 #1。如果您家中有客人正在修改 DLL 搜索顺序,则这不是解决安全问题的可靠方法。如果将 DLL 放在应用程序目录中,它们将在当前目录被搜索之前首先被找到,从而在攻击向量被利用之前关闭它。)
如果您有充分的理由将 DLL 放在不同的目录中,那么您的选择数量有限。
您不能使用AddDllDirectory
上面引用的文档继续建议,因为您不控制 lib1.dll 中的代码,因此无法修改它以LoadLibraryEx
使用LOAD_LIBRARY_SEARCH_USER_DIRS
标志调用。
通过指定完整路径加载 lib1.dll 将不起作用,因为“如果 DLL 具有依赖项,系统会搜索依赖的 DLL,就好像它们只加载了它们的模块名称一样。即使加载了第一个 DLL,也是如此。通过指定完整路径。”
这使您可以选择使用 DLL 重定向,或在应用程序的清单中添加有关您的依赖项的信息。