我从一个目录执行一个exe,例如"C:/test“
DLLs位于目录"C:/test/dlls“中,因此,在这个exe中,我调用:
SetDllDirectory("C:/test/dlls");然后我打电话
lib1 = LoadLibrary("lib1.dll)和
ptrType pr = (ptrType) ::GetProcAddress(lib1, "test")lib1.dll需要目录"C:/test/ DLLs“中的其他dlls,但是当我执行来自GetProcAddress的pr(...) get时,会得到一个错误:
“程序无法启动,因为您的计算机中缺少lib2.dll。请尝试重新安装该程序以解决此问题。”
如果我将lib2.dll移动到"C:/test",就会找到它。这意味着SetDllDirectory()仅对加载第一个DLL有效。
有谁知道为什么和如何修复它吗?
发布于 2017-06-16 12:13:45
这应该能行。SetDllDirectory会“级联”,因此会影响加载依赖DLL的方式。基本上,SetDllDirectory允许您修改进程的DLL的默认搜索顺序,对此所做的任何更改都会影响整个进程,包括可能加载到该进程中的任何DLL。Windows在隐式加载子进程的依赖项时也使用此搜索顺序。
然而,正如在SetDllDirectory中所指出的,文献资料中有一个致命的缺陷
每次调用
SetDllDirectory函数时,它都会替换上一次SetDllDirectory调用中指定的目录。
如果您的流程中有其他代码正在调用SetDllDirectory,那么它将取消您的第一个调用。如果是lib1.dll中的代码在尝试加载lib2.dll之前做到了这一点,那么加载lib2.dll的尝试就会失败。
当然,这是lib1.dll的不良行为。DLLs是客人在申请过程中,因此不应去换地毯。。但并不是所有的代码都表现良好,这使得这是一个脆弱的策略。
另一种可能出错的方法是,如果lib1.dll通过调用LoadLibraryEx并传递覆盖默认搜索顺序(如LOAD_LIBRARY_SEARCH_APPLICATION_DIR )的多个标志之一加载lib2.dll。
最好的解决方案是将您所依赖的所有all放在应用程序目录中。在Windows上,应用程序的目录是应用程序包,所以这是放置它们的最佳地方。用户永远不应该在这个目录中挖掘,所以“乱七八糟”并不是一个问题。它解决了各种问题,包括依赖注入攻击,即有人在当前目录中放置同名的DLL。(您可以通过调用SetDllDirectory并传递一个空字符串从搜索顺序中删除当前目录来防止这种攻击,但现在我们又回到了问题1。如果您家里有客人正在修改DLL搜索顺序,这不是安全问题的可靠解决方法。如果将DLL放在应用程序目录中,将首先找到它们,然后搜索当前目录,在攻击矢量被攻击之前关闭它。)
如果您确实有一个很好的理由将DLL放在不同的目录中,那么您就有了有限的选项。
您不能像上面引用的文档所建议的那样使用AddDllDirectory,因为您不能控制lib1.dll中的代码,因此不能修改它以使用LOAD_LIBRARY_SEARCH_USER_DIRS标志调用LoadLibraryEx。
通过指定完整路径来加载lib1.dll是行不通的,因为“如果DLL有依赖项,系统就会搜索依赖DLL,就好像它们只是加载了它们的模块名一样。即使第一个DLL是通过指定完整路径加载的,也是如此。”
https://stackoverflow.com/questions/44588618
复制相似问题