DLL劫持

参考:
http://security.tencent.com/index.php/blog/msg/20
http://blog.csdn.net/magictong/article/details/6931520

DLL(Dynamic Link Library),全称动态链接库,是Windows系统上程序正常运行必不可少的功能模块,是实现代码重用的具体形式。简单的说,可以把DLL理解成帮助程序完成各种功能的组件。

DLL劫持漏洞(DLL Hijacking Exploit),这个漏洞它是通过一些手段来劫持或者替换正常的DLL,欺骗正常程序加载预先准备好的恶意DLL的一类漏洞的统称。利用DLL劫持漏洞,病毒木马可以随着文档的打开(或者其他一些程序正常行为)而激活自身,进而获得系统的控制权。

传统dll劫持

DLL劫持漏洞之所以被称为漏洞,还要从负责加载DLL的系统API LoadLibrary来看。熟悉Windows代码的同学都知道,调用LoadLibrary时可以使用DLL的相对路径。这时,系统会按照特定的顺序搜索一些目录,以确定DLL的完整路径。根据MSDN文档的约定,在使用相对路径调用LoadLibrary(同样适用于其他同类DLL LoadLibraryEx,ShellExecuteEx等)时,系统会依次从以下6个位置去查找所需要的DLL文件(会根据SafeDllSearchMode配置而稍有不同)。

  1. 程序所在目录
  2. 系统目录
  3. 16位系统目录
  4. Windows目录
  5. 当前目录
  6. PATH环境变量中的各个目录

通过注册表开启HKLMSystemCurrentControlSetControlSession Manager键值下的属性SafeDllSearchMode的值设置为1时是上面所说的顺序。关闭的时候是这样的顺序:

  1. 程序所在目录
  2. 当前目录
  3. 系统目录
  4. 16位系统目录
  5. Windows目录
  6. PATH环境变量中的各个目录

而所谓的劫持的,就发生在系统按照顺序搜索这些特定目录时。只要黑客能够将恶意的DLL放在优先于正常DLL所在的目录,就能够欺骗系统优先加载恶意DLL,来实现“劫持”。

从Windows 7的KB2533623补丁开始,微软给我们带来了三个解决DLL劫持问题的新API:SetDefaultDllDirectories,AddDllDirectory,RemoveDllDirectory。这几个API配合使用,可以有效的规避DLL劫持问题。可惜的是,这些API只能在打了KB2533623补丁的Windows7,2008上使用。

Satellite DLL 劫持

微软从VS2003/MFC7.0开始就提供对Satellite DLL的增强支持,主要用于创建针对多种语言进行本地化的应用程序。Satellite DLL属于纯资源DLL,它包含应用程序针对特定语言进行本地化的资源。当应用程序开始执行时,MFC会自动加载最适合于当前运行环境的本地化资源,比如在中文系统上,应用程序会优先使用中文资源,若是英文系统,则使用英文资源。Satellite DLL的命名规范为ApplicationNameXXX.dll,其中ApplicationName是使用MFC的*.EXE或者*.DLL的名称,而XXX为由资源语言的三个字母组成,比如中文为CHS,英文为ENU。由于经MFC编译的应用程序会自动加载相应语言的本地化资源(即Satellite DLL),且对加载的资源文件的合法性未作有效检测,因此可能被恶意程序利用DLL劫持来实现任意代码执行。

MFC主要按照以下顺序加载每种语言的资源DLL,找到一个后将停止加载下面的其它DLL:

  1. 当前用户的默认界面语言(UI Language)(适用于 Windows 2000 或更高版本),该语言从 GetUserDefaultUILanguage() Win32 API 返回;
  2. 当前用户的默认界面语言(适用于Windows 2000 或更高版本),没有任何特定子语言(即 ENC [加拿大英语] 变成 ENU [美国英语]);
  3. 系统的默认界面语言(适用于Windows 2000 或更高版本),这是从 GetSystemDefaultUILanguage() API 返回的语言。 在其他平台上,这是操作系统本身的语言;
  4. 系统的默认界面语言,没有任何特定的子语言;
  5. 具有 3 个字母代码 LOC 的“虚设”语言。

比如使用MFC的应用程序Example.exe,系统的用户界面语言是ENU(美国英语),而当前用户的用户界面语言为FRC(加拿大法语),那么MFC将按照以下顺序查找资源DLL文件:

  1. ExampleFRC.dll(当前用户的界面语言,此例为加拿大法语);
  2. ExampleFRA.dll(当前用户的界面语言,不包含子语言,此例为法语(法国));
  3. ExampleENU.dll(系统默认的用户界面语言,此例为美国英语);
  4. ExampleLOC.dll。

如果未找到上面DLL中任何一个,则MFC会使用Example.exe自带的资源。当应用程序自带有界面语言资源DLL文件时,它也会按照上述顺序来加载。比如在Win7简体中文系统上,应用程序Example.exe拥有自己的UI资源文件MainUI.dll,那么就会首先去加载MainUICHS.dll。

因此,恶意程序如果在程序相当目录下,比如上面MainUI.dll所在目录下,再放置一个包含恶意代码的MainUICHS.dll后,打开主程序Example.exe后,就会优先加载包含恶意代码的MainUICHS.dll,而非MainUI.dll,从而执行任意代码。由于多数MFC程序默认会动态链接mfc70.dll、mfc80.dll、mfc90.dll等dll文件(具体文件名与MFC版本号相关),因此在中文系统下,如果在相应的程序目录下放置mfc**chs.dll或者mfc**loc.dll都有可能达到DLL劫持的目的。

避免dll劫持

[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerKnownDLLs]在此注册表项下定义一个“已知DLL名称”,那么凡是此项下的DLL文件就会被禁止从EXE自身目录下调用,而只能从系统目录,也就是system32目录下调用。

调用LoadLibrary,LoadLibraryEx,CreateProcess,ShellExecute等等会进行模块加载操作的函数时,指明模块的完整(全)路径,禁止使用相对路径。

在应用程序的开头调用SetDllDirectory(TEXT(“”));从而将当前目录从DLL的搜索列表中删除,也就是搜索时不搜索当前目录。

打上最新的系统补丁,确保安全DLL搜索模式是开启状态。

发表评论

电子邮件地址不会被公开。 必填项已用*标注