DLL劫持可用于权限维持
、权限提升、进程注入,属于经久不衰的必备技能
0x01 DLL介绍
DLL是Dynamic Link Library的缩写,叫做动态链接库
一个dll文件可以由多个程序同时调用
dll的使用意义是某个大型程序在启动时和启动后,可以不加载某部分功能代码,只有用户使用时
再去调用对应功能的dll模块,从而达到减少软件启动速度的目的
0x02 DLL劫持前置知识点
劫持的方法了解到的有两种,在之前要先知道一下exe程序加载dll的知识点
exe程序在调用dll时,查找dll文件的目录优先级顺序
- 1.程序所在目录
- 2.程序加载目录(SetCurrentDirectory)
- 3.系统目录即 SYSTEM32 目录
- 4.16位系统目录即 SYSTEM 目录
- 5.Windows目录
- 6.PATH环境变量中列出的目录
在win7及以上系统对应dll的一个安全机制--KnownDLLs
KnownDLLs
是一个注册表的名称,如果有exe程序调用的dll名称存在于此目录下,那么这个DLL会被禁止从EXE自身所在目录下调用,而只能从系统目录即SYSTEM32目录下调用
注册表位置:\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
0x03 DLL劫持
-
- 劫持EXE应用调用的缺少的DLL(exe发出请求,在某个路径寻找对应的dll,结果对应路径不存在此dll)
-
- 劫持EXE应用正常调用的DLL(类似端口转发,使用一个恶意dll冒充原先dll,执行完恶意代码后在将请求转发到原先dll,不影响应用正常使用)
使用第一种方法劫持微信
- 首先要找到wechat.exe发出请求后加载dll的结果为NOT FOUND的,我这里使用辅助工具
Process Monitor
(一款系统进程监视软件),然后再一一验证可行性
打开Process Monitor
↓
打开微信
↓
设置Process Monitor的过滤器,添加wechat.exe进程的PID将显示的其他进程过
滤掉,再添加其他一些过滤规则(见下图)
↓
保存结果为csv文件,目的为了用execl里的筛选,将EXE程序加载的dll单独列出来
↓
正常是将恶意dll改成加载的不在KnownDLLs注册表中的dll名称,放在EXE应用同目录,这里使用anhkgg师傅的批量检验,可以帮助我自动重命名文件然后执行验证的一些自动化操作
↓
找到目标,将恶意dll改名放入wechat.exe同目录(因为加载顺序同目录优先级最高,当然其他地方也可以)
↓
↓
↓
gif效果图
使用第二种方法劫持QQ
- 首先找到一个EXE程序加载的dll,两个硬性要求(一是exe确实加载了此dll,二是此dll不在KnownDLLs注册表中,不过既然在同目录下找到的加载dll,那肯定不在KnownDLLs里),用来中间人转发他也就是劫持,一般找小点的,小点的需要转发函数的数量会少点,查阅一些文章总算找到一个自动化的工具
dll-hijacking
,这样我就不用手动复制函数了
在QQ.exe同目录寻找目标dll
↓
复制目标dll到dll-hijacking工具下进行加工
↓
处理好的恶意dll改好原本的名字复制到QQ.exe目录下,将刚才复制的此
目录原本的dll名字改为 原名字_.dll(这样此目录就有 原名字.dll 原名字_.dll)
↓
启动QQ, over了
↓
↓
↓
gif效果图
- dllmain.cpp弹框代码
/*
https://itm4n.github.io/dll-proxying/
https://www.codeproject.com/Articles/17863/Using-Pragmas-to-Create-a-Proxy-DLL
to implement: hooking specific functions
*/
#include "definitions.h"
#include <thread>
#include <chrono>
#include <random>
extern "C"{
#include <stdlib.h>
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>
#include <ws2tcpip.h>
}
using namespace std;
#pragma comment(lib,"Ws2_32.lib")
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved) // reserved
{
srand(time(NULL));
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
MessageBox(NULL, "Success", "", MB_OK);
break;
}
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
return true;
}
0x04 参考链接
https://payloads.online/archivers/2018-12-22/1
https://mp.weixin.qq.com/s?__biz=MzU2NTc2MjAyNg==&mid=2247483851&idx=1&sn=8813719d4d3ac8b20bec495fcd5f2974&chksm=fcb7834ecbc00a58da8a6408abe183e71175b442d0f02016ad3c67c9cf719927881bec14af49#rd