Dynamic-Link 库安全Dynamic-Link Library Security

当应用程序在未指定完全限定的路径名称的情况下动态加载动态链接库时,Windows 将尝试通过按特定顺序搜索一组定义完善的目录来查找 DLL,如 动态链接库搜索顺序中所述。When an application dynamically loads a dynamic-link library without specifying a fully qualified path name, Windows attempts to locate the DLL by searching a well-defined set of directories in a particular order, as described in Dynamic-Link Library Search Order. 如果攻击者可以控制 DLL 搜索路径上的某个目录,它可以在该目录中放置该 DLL 的恶意副本。If an attacker gains control of one of the directories on the DLL search path, it can place a malicious copy of the DLL in that directory. 这有时称为 DLL 预加载攻击二元种植攻击This is sometimes called a DLL preloading attack or a binary planting attack. 如果系统在搜索已泄露的目录之前找不到 DLL 的合法副本,则会加载恶意 DLL。If the system does not find a legitimate copy of the DLL before it searches the compromised directory, it loads the malicious DLL. 如果应用程序是以管理员权限运行的,则攻击者可能会成功完成本地权限提升。If the application is running with administrator privileges, the attacker may succeed in local privilege elevation.

例如,假设应用程序设计为从用户的当前目录加载 DLL,并且如果找不到 DLL,则会正常失败。For example, suppose an application is designed to load a DLL from the user's current directory and fail gracefully if the DLL is not found. 应用程序只调用 LoadLibrary 的名称,从而使系统搜索 dll。The application calls LoadLibrary with just the name of the DLL, which causes the system to search for the DLL. 假设启用了安全 DLL 搜索模式,并且应用程序未使用其他搜索顺序,则系统会按以下顺序搜索目录:Assuming safe DLL search mode is enabled and the application is not using an alternate search order, the system searches directories in the following order:

  1. 从中加载应用程序的目录。The directory from which the application loaded.
  2. 系统目录。The system directory.
  3. 16位系统目录。The 16-bit system directory.
  4. Windows 目录。The Windows directory.
  5. 当前目录。The current directory.
  6. PATH 环境变量中列出的目录。The directories that are listed in the PATH environment variable.

继续此示例,知道应用程序的攻击者可以控制当前目录,并在该目录中放置 DLL 的恶意副本。Continuing the example, an attacker with knowledge of the application gains control of the current directory and places a malicious copy of the DLL in that directory. 当应用程序发出 LoadLibrary 调用时,系统会搜索 dll,查找当前目录中的 dll 的恶意副本,并将其加载。When the application issues the LoadLibrary call, the system searches for the DLL, finds the malicious copy of the DLL in the current directory, and loads it. 然后,该 DLL 的恶意副本将在应用程序中运行并获得用户的权限。The malicious copy of the DLL then runs within the application and gains the privileges of the user.

开发人员可遵循以下准则来帮助保护应用程序免遭 DLL 预加载攻击:Developers can help safeguard their applications against DLL preloading attacks by following these guidelines:

  • 如果可能,请在使用 LoadLibraryLoadLibraryExCreateProcessShellExecute 函数时指定完全限定的路径。Wherever possible, specify a fully qualified path when using the LoadLibrary, LoadLibraryEx, CreateProcess, or ShellExecute functions.

  • 将 LOAD _ LIBRARY _ 搜索标志与 LoadLibraryEx 函数结合使用,或将这些标志与 SetDefaultDllDirectories 函数结合使用,为进程建立 DLL 搜索顺序,然后使用 AddDllDirectorySetDllDirectory 函数修改该列表。Use the LOAD_LIBRARY_SEARCH flags with the LoadLibraryEx function, or use these flags with the SetDefaultDllDirectories function to establish a DLL search order for a process and then use the AddDllDirectory or SetDllDirectory functions to modify the list. 有关详细信息,请参阅 动态链接库搜索顺序For more information, see Dynamic-Link Library Search Order.

    Windows 7、Windows server 2008 R2、Windows Vista 和 Windows server 2008: 这些标志和函数在安装了 KB2533623 的系统上可用。Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: These flags and functions are available on systems with KB2533623 installed.

  • 在安装了 KB2533623 的系统上,将 _ 加载 _ 库搜索标志与 LoadLibraryEx 函数结合使用,或将这些标志与 SetDefaultDllDirectories 函数结合使用,以便为进程建立 DLL 搜索顺序,然后使用 AddDllDirectorySetDllDirectory 函数修改列表。On systems with KB2533623 installed, use the LOAD_LIBRARY_SEARCH flags with the LoadLibraryEx function, or use these flags with the SetDefaultDllDirectories function to establish a DLL search order for a process and then use the AddDllDirectory or SetDllDirectory functions to modify the list. 有关详细信息,请参阅 动态链接库搜索顺序For more information, see Dynamic-Link Library Search Order.

  • 请考虑使用 dll 重定向清单 ,以确保应用程序使用正确的 DLL。Consider using DLL redirection or a manifest to ensure that your application uses the correct DLL.

  • 使用标准搜索顺序时,请确保已启用安全 DLL 搜索模式。When using the standard search order, make sure that safe DLL search mode is enabled. 这会在以后的搜索顺序中放置用户的当前目录,提高 Windows 在恶意副本之前查找 DLL 的合法副本的机会。This places the user's current directory later in the search order, increasing the chances that Windows will find a legitimate copy of the DLL before a malicious copy. 默认情况下,从 Windows XP Service Pack 2 (SP2) 开始启用安全 DLL 搜索模式,该模式由 HKEY _ 本地 _ 计算机 \ 系统 \ CurrentControlSet \ 控制 \ 会话管理器 \ SafeDllSearchMode 注册表值控制。Safe DLL search mode is enabled by default starting with Windows XP with Service Pack 2 (SP2) and is controlled by the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode registry value. 有关详细信息,请参阅 动态链接库搜索顺序For more information, see Dynamic-Link Library Search Order.

  • 请考虑从标准搜索路径中删除当前目录,方法是调用 SetDllDirectory ( "" ) 的空字符串。Consider removing the current directory from the standard search path by calling SetDllDirectory with an empty string (""). 这应该在进程初始化初期完成,而不是在调用 LoadLibrary之前和之后完成。This should be done once early in process initialization, not before and after calls to LoadLibrary. 请注意, SetDllDirectory 会影响整个过程,并且具有不同值的多个线程调用 SetDllDirectory 会导致未定义的行为。Be aware that SetDllDirectory affects the entire process and that multiple threads calling SetDllDirectory with different values can cause undefined behavior. 如果你的应用程序加载第三方 Dll,请仔细测试以确定任何不兼容性。If your application loads third-party DLLs, test carefully to identify any incompatibilities.

  • 除非启用了安全进程搜索模式,否则不要使用 SearchPath 函数为后续的 LOADLIBRARY 调用检索 DLL 的路径。Do not use the SearchPath function to retrieve a path to a DLL for a subsequent LoadLibrary call unless safe process search mode is enabled. 如果未启用安全进程搜索模式, SearchPath 函数将使用与 LoadLibrary 不同的搜索顺序,并且可能首先在用户的当前目录中搜索指定的 DLL。When safe process search mode is not enabled, the SearchPath function uses a different search order than LoadLibrary and is likely to first search the user's current directory for the specified DLL. 若要为 SearchPath 函数启用安全进程搜索模式,请使用 SETSEARCHPATHMODE 函数和基本 _ 搜索 _ 路径 _ enable _ safe _ SEARCHMODE。To enable safe process search mode for the SearchPath function, use the SetSearchPathMode function with BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE. 这会在进程的生存期内将当前目录移动到 SearchPath 搜索列表的末尾。This moves the current directory to the end of the SearchPath search list for the life of the process. 请注意,不会从搜索路径中删除当前目录,因此,如果系统在到达当前目录之前找不到该 DLL 的合法副本,则该应用程序仍然容易受到攻击。Note that the current directory is not removed from the search path, so if the system does not find a legitimate copy of the DLL before it reaches the current directory, the application is still vulnerable. SetDllDirectory一样,调用 SetSearchPathMode 应在进程初始化初期完成,并会影响整个过程。As with SetDllDirectory, calling SetSearchPathMode should be done early in process initialization and it affects the entire process. 如果你的应用程序加载第三方 Dll,请仔细测试以确定任何不兼容性。If your application loads third-party DLLs, test carefully to identify any incompatibilities.

  • 不要对基于搜索 DLL 的 LoadLibrary 调用的操作系统版本做出假设。Do not make assumptions about the operating system version based on a LoadLibrary call that searches for a DLL. 如果应用程序正在某个环境中运行,而该环境中的 DLL 不存在,但该 DLL 的恶意副本在搜索路径中,则可能会加载 DLL 的恶意副本。If the application is running in an environment where the DLL is legitimately not present but a malicious copy of the DLL is in the search path, the malicious copy of the DLL may be loaded. 请改用 获取系统版本中所述的推荐技术。Instead, use the recommended techniques described in Getting the System Version.

进程监视器工具可用于帮助确定可能易受到攻击的 DLL 加载操作。The Process Monitor tool can be used to help identify DLL load operations that might be vulnerable. 可以从下载进程监视器工具 https://technet.microsoft.com/sysinternals/bb896645.aspxThe Process Monitor tool can be downloaded from https://technet.microsoft.com/sysinternals/bb896645.aspx.

下面的过程介绍如何使用进程监视器来检查应用程序中的 DLL 加载操作。The following procedure describes how to use Process Monitor to examine DLL load operations in your application.

使用进程监视器检查应用程序中的 DLL 加载操作To use Process Monitor to examine DLL load operations in your application

  1. 启动进程监视器。Start Process Monitor.
  2. 在进程监视器中,包括以下筛选器:In Process Monitor, include the following filters:
    • 操作为 CreateFileOperation is CreateFile
    • 操作为 LoadImageOperation is LoadImage
    • 路径包含 cplPath contains .cpl
    • 路径包含 .dllPath contains .dll
    • 路径包含 winspool.drvPath contains .drv
    • 路径包含 .exePath contains .exe
    • 路径包含 .ocxPath contains .ocx
    • 路径包含 .scrPath contains .scr
    • 路径包含 .sysPath contains .sys
  3. 排除以下筛选器:Exclude the following filters:
    • 进程名称为 procmon.exeProcess Name is procmon.exe
    • 进程名称为 Procmon64.exeProcess Name is Procmon64.exe
    • 进程名称为系统Process Name is System
    • 操作以 IRP _ MJ 开头_Operation begins with IRP_MJ_
    • 操作始于 FASTIO_Operation begins with FASTIO_
    • 结果成功Result is SUCCESS
    • 路径以 pagefile.sys 结尾Path ends with pagefile.sys
  4. 尝试使用将当前目录设置为特定目录来启动应用程序。Attempt to start your application with the current directory set to a specific directory. 例如,双击扩展名为的文件,并将其文件处理程序分配给应用程序。For example, double-click a file with an extension whose file handler is assigned to your application.
  5. 对于看起来可疑的路径,请检查进程监视器输出,如调用当前目录来加载 DLL。Check Process Monitor output for paths that look suspicious, such as a call to the current directory to load a DLL. 此类调用可能指示应用程序中的漏洞。This kind of call might indicate a vulnerability in your application.