DLL劫持漏洞的价值

一般大厂SRC对于客户端的DLL劫持都是忽略态度(尴尬),但是DLL劫持的确是恶意软件驻留的一个好方法,在特定条件下,挖掘客户端的DLL劫持,不但可以绕过免杀得到权限,如果客户端被用户自启动了,那么DLL也会自启动。所以说DLL劫持是APT32很执着的方式。

DLL加载顺序

"安全DLL查找模式"默认是启用的,禁用的话,可以将注册表HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode设为0。

软件缺省的DLL文件的搜索顺序如下:

一、应用程序加载的目录
二、系统目录(即 %windir%\system32 )
三、16位系统目录(即 %windir%\system)
四、Windows目录(即 %windir%)
五、当前目录
六、PATH环境变量中列出的目录

Windows从XP sp2开始默认开启SafeDllSearchMode(安全dll搜索模式)。默认情况下 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode 处于开启状态;如果手动设置为 0,关闭该安全选项,搜索顺序为:在以上顺序基础上,将 5.当前目录 修改至 2.系统目录 的位置,其他顺移。

如果"安全DLL查找模式"被禁用,查找顺序如下:

a. 应用程序所在目录;
b. 当前目录。GetCurrentDirectory返回的目录;(因为很多情况下当前目录会因为SetCurrentDirectory或者OpenFile的操作而改变)
c. 系统目录。GetSystemDirectory返回的目录,通常是系统盘\Windows\System32;
d. 16位系统目录。该项只是为了向前兼容的处理,可以不考虑;
e. Windows目录。GetWindowsDirectory返回的目录,通常是系统盘\Windows;
f. 环境变量PATH中所有目录。

验证Windows下DLL加载顺序

#include <windows.h>
#include <iostream>

int main(int argc, char ** argv)
{
    using std::cout;
    using std::endl;

    // 随便设置一个不存在的dll名
    HMODULE hMod = LoadLibrary("123.dll");

    if (NULL != hMod)
        FreeLibrary(hMod);

    cout << "LoadLibrary Test" << endl;

    return 0;
}

Dll劫持验证性代码

#include "pch.h"
#include <stdlib.h>

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        system("calc.exe");
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

远程DLL劫持

网络前提环境
目前比较常见的远程DLL劫持环境为WebDAV(Web-based Distributed Authoring and Versioning)与SMB(Server Message Block )。
WebDAV一种基于 HTTP 1.1协议的通信协议.它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法,使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。WebDAV常用于广域网络,因此更容易被黑客利用。
而SMB是Windows之间以及Windows与其它系统之间最常用的共享资源协议,可用于在计算机间共享文件、打印机、串口等,平时我们使用\ServerName\Share路径格式打开的共享文件夹即是使用的此协议。SMB在局域网环境使用比较多。
由于局域网有一定的封闭性,相对WebDAV想实施远程DLL的劫持攻击更难。以下以SMB为环境进行描述。

2011年9月,在测试的SMB网络环境中发现,当打开SMB服务器上共享一个名为attack_test.ppt的普通文件时,微软Office中的POWERPNT.EXE程序会加载一个名为imm32.dll的DLL文件。通过ProcessMonitor对POWERPNT.EXE进程的跟踪监视(如图2所示),可以观察到进程试图从\192.168.3.84\wb 这个远程共享文件目录加载imm32.dll,这已经能够满足远程DLL劫持攻击的条件了。对最后三条记录观察发现,POWERPNT.EXE进程对imm32.dll的搜索目录顺序为:

(1)目录D:\Program Files\Microsoft Office\Office12\,此目录为office软件的可执行程序加载的目录,即POWERPNT.EXE所在的目录。
(2)远程目录\192.168.3.84\wb,此目录为应用程序打开某文件的所在目录,即打开的目标文件attack_test.ppt所在的目录。
(3)目录C:\WINDOWS\system32\,此目录为笔者测试PC的Windows系统目录。

安全防御建议

DLL劫持漏洞微软尚未给出直接的修复方法。
一、这是开发者的失误,换用绝对路径就能避免这个问题
二、利用的前提是攻击者已经能够在同级目录放置文件,这代表系统已经被攻破。
开发人员必须要做更多来保护应用程序自身。

对于以下两种情况的DLL,系统将不会查找,而是直接加载:

a. 对于已经加载到内存中的同名DLL,系统使用已经加载的DLL,并且忽略待加载DLL的路径。(注意对某个进程而言,系统已经加载的DLL一定是唯一的存在于某个目录下。)

b. 如果该DLL存在于某个Windows版本的已知DLL列表(unkown DLL)中,系统使用已知DLL的拷贝(包括已知DLL的依赖项)。已知DLL列表可以从如下注册表项看到:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs。

修改Dll加载顺序
1、使用LOAD_WITH_ALTERED_SEARCH_PATH标志调用LoadLibraryEx函数;

这种方式调用LoadLibraryEx函数,需要设置lpFileName参数(绝对路径)。与标准查找策略不同的是,使用LOAD_WITH_ALTERED_SEARCH_PATH标志调用LoadLibraryEx函数的DLL查找顺序将"查找应用程序所在目录"修改为lpFileName指定的目录。

2 、调用SetDllDirectory函数。

注意:SetDllDirectory函数在Windows XP SP1开始支持的。
函数SetDllDirectory在调用参数lpPathName是一个路径时,可支持修改DLL搜索路径。

当然win8或者windows server 2012提供更多的可定制方法,这个可以参考MSDN上介绍。比如:SetDefaultDllDirectories、 AddDllDirectory、RemoveDllDirectory。

延迟加载DLL

WINSTA.dll、LINKINFO.dll、ntshrui.dll、srvcli.dll和cscapi.dll
共享 DLL
DtFrame32.dll和DtsFrame32.dll都是系统保护的底层dll,winspool.drv.dll,winhafnt.dll
https://github.com/knight0x07/ImpulsiveDLLHijack

自动化检测DLL劫持的项目

参考文献

https://bbs.pediy.com/thread-260733.htm
http://www.h3c.com/CN/D_201110/727410_30008_0.htm