动态链接库搜索顺序
同一动态链接库 (DLL) 的多个版本通常存在于操作系统 (OS) 内的不同文件系统位置。 可以通过指定完整路径来控制从中加载任何给定 DLL 的特定位置。 但是,如果不使用该方法,则系统会在加载时搜索 DLL,如本主题中所述。 DLL 加载程序是操作系统 (操作系统) 的一部分,用于加载 DLL 和/或解析对 DLL 的引用。
提示
有关 打包 应用和 未打包 应用的定义,请参阅 打包应用的优缺点。
影响搜索的因素
下面是本主题中讨论的一些特殊搜索因素-你可以将其视为 DLL 搜索顺序的一部分。 本主题的后续部分按特定应用类型的相应搜索顺序以及其他搜索位置列出了这些因素。 本部分只是为了介绍概念,并为其提供名称,我们将在本主题的后面部分引用这些概念。
如果 DLL 具有依赖项,则系统会搜索依赖 DLL,就像仅使用其模块名称加载一样。 即使通过指定完整路径加载了第一个 DLL,也是如此。
打包应用的搜索顺序
当打包的应用专门 (加载打包的模块时,库模块( .dll 通过调用 LoadPackagedLibrary 函数) 文件),DLL 必须位于进程的包依赖项关系图中。 有关详细信息,请参阅 LoadPackagedLibrary。 当打包的应用通过其他方式加载模块并且未指定完整路径时,系统会在加载时搜索 DLL 及其依赖项,如本部分所述。
当系统搜索模块或其依赖项时,它始终使用打包应用的搜索顺序;即使依赖项不是打包的应用代码。
打包应用的标准搜索顺序
系统按以下顺序搜索:
如果 DLL 具有依赖项,则系统会搜索依赖 DLL,就好像只加载了其模块名称 (即使第一个 DLL 是通过指定完整路径) 加载的。
打包应用的备用搜索顺序
如果模块通过使用 LOAD_WITH_ALTERED_SEARCH_PATH 调用 LoadLibraryEx 函数更改标准搜索顺序,则搜索顺序与标准搜索顺序相同,只是在步骤 7 中,系统搜索从加载指定模块的文件夹 (顶部加载模块的文件夹) ,而不是可执行文件的文件夹。
未打包应用的搜索顺序
当未打包的应用加载模块且未指定完整路径时,系统会在加载时搜索 DLL,如本节中所述。
重要
如果攻击者控制了搜索的某个目录,则可以在该文件夹中放置 DLL 的恶意副本。 有关帮助防止此类攻击的方法,请参阅 动态链接库安全性。
未打包应用的标准搜索顺序
系统使用的标准 DLL 搜索顺序取决于是否启用了 安全 DLL 搜索模式 。
默认情况下启用的安全 DLL 搜索模式 () 按搜索顺序移动用户的当前文件夹。 若要禁用安全 DLL 搜索模式,请 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode 创建注册表值并将其设置为 0。 当指定文件夹位于搜索路径 () 时,调用 SetDllDirectory 函数可有效地禁用安全 DLL 搜索模式) ,并更改本主题中所述的搜索顺序。
如果启用了安全 DLL 搜索模式,则搜索顺序如下所示:
如果 禁用安全 DLL 搜索模式,则搜索顺序相同,只是 当前文件夹 在步骤 7 之后立即从序列 (从位置 11 移动到位置 8 。应用程序从中加载) 的文件夹 。
未打包应用的备用搜索顺序
若要更改系统使用的标准搜索顺序,可以使用 LOAD_WITH_ALTERED_SEARCH_PATH调用 LoadLibraryEx 函数。 还可以通过调用 SetDllDirectory 函数来更改标准搜索顺序。
注意
在当前进程开始之前,在父进程中调用 SetDllDirectory 函数也会影响进程的标准搜索顺序。
如果指定备用搜索策略,则其行为会一直持续到找到所有关联的可执行模块。 在系统开始处理 DLL 初始化例程后,系统将恢复为标准搜索策略。
如果调用指定LOAD_WITH_ALTERED_SEARCH_PATH,并且 lpFileName 参数指定绝对路径,则 LoadLibraryEx 函数支持备用搜索顺序。
这是他们区别的唯一方式。
如果启用了安全 DLL 搜索模式,则备用搜索顺序如下所示:
步骤 1-6 与标准搜索顺序相同。
如果 禁用安全 DLL 搜索模式,则备用搜索顺序是相同的,只是 当前文件夹 在步骤 7 后立即从顺序 (从位置 11 移动到位置 8 。由 lpFileName 指定的文件夹) 。
如果 lpPathName 参数指定路径,SetDllDirectory 函数支持备用搜索顺序。 备用搜索顺序如下:
步骤 1-6 与标准搜索顺序相同。
如果 lpPathName 参数为空字符串,则调用将从搜索顺序中删除当前文件夹。
当指定文件夹位于搜索路径中时,SetDllDirectory 可有效地禁用安全 DLL 搜索模式。 若要基于 SafeDllSearchMode 注册表值还原安全 DLL 搜索模式,并将当前文件夹还原到搜索顺序,请调用 SetDllDirectory , lpPathName 为 NULL。
使用LOAD_LIBRARY_SEARCH标志搜索顺序
可以通过将一个或多个 LOAD_LIBRARY_SEARCH 标志与 LoadLibraryEx 函数配合使用来指定搜索顺序。 还可以将 LOAD_LIBRARY_SEARCH 标志与 SetDefaultDllDirectories 函数一起使用,以建立进程的 DLL 搜索顺序。 可以使用 AddDllDirectory 或 SetDllDirectory 函数为进程 DLL 搜索顺序指定其他目录。
搜索的目录取决于使用 SetDefaultDllDirectories 或 LoadLibraryEx 指定的标志。 如果使用多个标志,则按以下顺序搜索相应的目录:
如果调用 LoadLibraryEx 时没有 LOAD_LIBRARY_SEARCH 标志,或者为进程建立 DLL 搜索顺序,则系统将使用标准搜索顺序或备用搜索顺序搜索 DLL。