DLL劫持漏洞原理

来源:互联网 发布:求生之路2不用网络 编辑:程序博客网 时间:2024/06/04 18:04

DLL劫持

最近一段时间实在是忙,乱七八糟的,都没空写博客,但是学习还得继续,最近看了下DLL劫持,严格上说这不能算是漏洞,但是第一次接触感觉有点意思,写出来记录一下吧,老年人了记性不好,小白文章欢迎指正。

0x01 劫持原理

1.什么是DLL
DLL(Dynamic Link Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。一个应用程序可使用多个DLL文件,一个DLL文件也可能被不同的应用程序使用,这样的DLL文件被称为共享DLL文件。
2.什么是DLL劫持
每个DLL都有一个入口函数(DLLMain),系统在特定环境下会调用DLLMain。在发生DLL装载、卸载、创建新线程、线程终止时,就会调用dll的入口函数。
另外,每个DLL文件中都包含有一个导出函数表也叫输出表(存在于PE的.edata节中)。使用一些PE文件查看工具如LoadPE,就可以查看导出函数的符号名即函数名称和函数在导出函数表中的标识号。

应用程序导入函数与DLL文件中的导出函数进行链接有两种方式:隐式链接(load-time dynamic linking)也叫静态调用和显式链接(run-time dynamic linking)也叫动态调用。隐式链接方式一般用于开发和调试,而显式链接方式就是我们常见的使用LoadLibary或者LoadLibraryEx函数(注:涉及到模块加载的函数有很多)来加载DLL去调用相应的导出函数。调用LoadLibrary或者LoadLibraryEx函数时可以使用DLL的相对路径也可以使用绝对路径,但是很多情况下,开发人员都是使用了相对路径来进行DLL的加载。那么,在这种情况下,Windows系统会按照特定的顺序去搜索一些目录,来确定DLL的完整路径。关于动态链接库的搜索顺序的更多详细资料请参阅MSDN。根据MSDN文档的约定,在使用了DLL的相对路径

调用LoadLibrary函数时,系统会依次从下面几个位置去查找所需要调用的DLL文件。

1.程序所在目录
2.系统目录即 SYSTEM32 目录。
3.16位系统目录即 SYSTEM 目录。
4.Windows目录。
5.加载 DLL 时所在的当前目录。
6.PATH环境变量中列出的目录。

微软为了防止DLL劫持漏洞的产生,在XP SP2之后,添加了一个SafeDllSearchMode的注册表属性。注册表路径如下:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
Manager\SafeDllSearchMode

当SafeDllSearchMode的值设置为1时,DLL查找的目录顺序就发生了变化:

1.程序所在目录
2.系统目录即 SYSTEM32 目录。
3.16位系统目录即 SYSTEM 目录。
4.Windows目录。
5.加载 DLL 时所在的当前目录。
6.PATH环境变量中列出的目录。

大佬博客中提到XP以后发布的版本中默认都是未开启DLL安全搜索的(我没装XP虚机,只有win7和win10,找不到这个注册表,如果有人知道原因麻烦跟我说一声),这就让DLL劫持有了可乘之机,但为了进一步防止被劫持,微软又将常被利用的DLL放在system32目录下,并禁止这些注册表被非system32下的调用,路径:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs

win10下的KnowDLLs:

win7下的KnowDLLs:

这就意味着,利用上述存在于KnowDLLs注册表项下的dll去进行劫持,是不会被系统加载的。
但是在加载DLL过程中,系统都是先在程序目录加载DLL,如果没有找到就按照规定的顺序去搜索,但如果DLL的路径没有在system32中,攻击者就有可能伪造一个dll被程序加载(注意:该DLL需要与系统加载的DLL名称相同,导出函数表相同,并将DLL中的函数转向到原有的DLL,这时程序的加载流程为:程序启动→系统加载伪造DLL→真实DLL→原流程)

以上漏洞原理皆为参考Freebuf上的一篇文章,侵删
原文传送门