以lockbit为例对COM组件进行深入学习
唧*用 发表于 北京 二进制安全 581浏览 · 2024-05-22 08:54

一、COM组件简介
COM定义了适用于多操作系统和平台的二进制互操作性标准,包括标准线路格式和协议,促进不同硬件平台上对象之间的交互。COM组件独立于实现语言,可用不同编程语言创建COM库,支持跨平台软件重用。COM规范涵盖支持跨平台软件重用的基本概念,允许组件协同工作创建可重用组件生成的应用程序。类、接口和类型库可通过注册表查看,它们被定义为COM设置。在客户端和服务器通信时,可以使用服务器中的方法,无需将库编译到应用程序中,这些接口是COM的成员函数集合。

二、对象和接口
COM提供了一套允许同一台计算机上的客户端和服务器之间进行通信的接口,COM客户端通常是程序。要调用COM接口,需要调用一个名为"drive"的方法。为了调用"drive",必须首先创建一个接口实例和对象,然后通过指定ClassID和RIID找到所需的驱动信息。ClassID是全局唯一标识符,也称为CLSID,用于唯一标识一个类对象。类对象应该将其ClassID注册到注册表中,以便客户端能够定位并加载与该对象相关的可执行代码。ClassID包含一个指向实现所请求类的“服务器”的引用,该“服务器”通常是存储在磁盘上的文件。
CLSID结构体如下:

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

前置知识:
1、GUID是全球唯一标识符,是一个128位长的数字,用来标识com组件,核心思想是结合网卡、时间、随机数来生成GUID,要保证所有的com对象都有唯一的id。
2、Riid:引用接口标识符,也是一个全局唯一标识符。
3、CoCreateInstance的作用是创建并默认初始化与指定 CLSID 关联的类的单个对象。当调用CoCreateInstance的时候,要先拥有该对象指定的classid和接口id,然后创建该接口的对象实例,随后可以调用drive。可以在任何语言中调用com组件

三、com与注册表
Com对象相关的设置在注册表中,注册表使用一些特殊的数据类型来存储一些数据满足应用要求,如:HKEY_CLASSES_ROOT 用于存储一些文档类型、类、类的关联属性、HKEY_CURRENT_CONFIG 用户存储有关本地计算机系统的当前硬件配置文件信息、HKEY_CURRENT_USER 用于存储当前用户配置项、HKEY_CURRENT_USER_LOCAL_SETTINGS 用于存储当前用户对计算机的配置项、HKEY_LOCAL_MACHINE 用于存储当前用户物理状态、HKEY_USERS 用于存储新用户的默认配置项

注册表项介绍
HKEY_LOCAL_MACHINE-SOFTWARE-Classes

HKEY_CLASSES_ROOT-WScripShell是一个com类,他有一些接口定义了函数的运行,这些接口称为宏。在WScripShell中可以查看到classid,{72C24DD5-D70A-438B-8A42-98424B88AFB8},

接下来去找到这个classid类中定义的接口

ProgID相当于这个com对象的名字,InProcServer32表示该com对象在哪个pe文件中,这里的ocx是一个基于com的dll,它表示该com对象调用此ocx中的方法和接口的代码,是com的服务器:

procID是一个编程标识符,大约20%的对象已经定义了
复制TypeLib能找到基于com的dll

wshom.ocx是Window本地脚本对象运行时相关文件

举例:
在VBScript中,可以使用以下方式创建并使用该对象:
'''Set wshShell = CreateObject("WScript.Shell")'''

这行代码通过引用CLSID 72C24DD5-D70A-438B-8A42-98424B88AFB8 关联的ProgID WScript.Shell 来创建一个Shell对象,从而允许脚本与Windows Shell进行交互,如运行外部程序、操作环境变量等。

OCX(Object Linking and Embedding Control Extension)是一种Windows平台下的可重用软件组件技术。OCX文件通常用于实现用户界面元素或其他功能,并可以被其他程序调用和重复使用。接口函数的具体名称取决于特定的OCX文件,因为不同的OCX文件可能会提供不同的功能和接口。

以下是一些常用的ocx接口函数:
1.Init: 用于初始化OCX控件。
2.LoadFile: 用于加载文件到OCX控件中。
3.SaveFile: 用于保存OCX控件中的内容到文件中。
4.SetProperty: 用于设置OCX控件的属性。
5.GetProperty: 用于获取OCX控件的属性。
6.Execute: 用于执行特定的操作或功能。
7.OpenConnection: 用于建立连接到其他系统或服务。
8.CloseConnection: 用于关闭与其他系统或服务的连接。
9.StartProcess: 用于启动一个进程或操作。
10.StopProcess: 用于停止一个正在运行的进程或操作。

使用CFF查看 wshom.ocx详细信息,由于在导入导出表中没有看到提供给客户端的接口函数,因此检查资源表,他的数据可能全部存储在资源表中,将资源表保存下来。

寻找一个方法非常耗时,只有用同一个classid表示的com对象如何找到类型库,如何找到接口,并且类型库是可选的,不是每个classid或com对象都有自己的类型库,所以可以使用oilviewdotnet以及comview来查看com对象的所有内容。
Comview中有一个操作系统类型库中定义了所有classid。在typelib中可以查看到所有的类型库,并使用COMView打开该文件查看该类型库提供给用户的接口。
寻找方法:clsid中寻找wscript.shell.1

查看对应的接口提供的函数调用:

因此顺序是类对象-接口实例-方法调用,跟c++中的类、对象、方法调用是一个意思,相当于给c++做了个底层封装,使得他可以在不同的平台不同的语言之间灵活的调用,当一个应用程序想要调用某个对象时,是通过CLSID来寻找对象的。

Powershell内部也会创建一个com对象实例,可以将powershell作为com客户端调用com服务器。

四、COM劫持
Com组件能劫持.com文件、pe文件、api文件等。Com对象是注册表中对磁盘上没有实现文件的对象引用,在一些程序卸载后,注册表内的com键没删干净,依旧处于注册状态,这个com键会指向一个路径里面的文件,通过修改com指向自己的dll完成加载,实现com劫持。

五、样本分析
5.1组织介绍
Lokibot最初于2015年被发现,是一种恶意软件家族,经常被黑客用于攻击目标系统。Lokibot 是一种银行木马(Banking Trojan),其主要功能是从受感染的系统中窃取敏感信息。它可以监视用户在受感染计算机上的活动,截取键盘输入,窃取存储的凭据等,通常通过恶意软件分发方式传播,比如钓鱼邮件、恶意链接、潜在的恶意下载等。一旦用户下载并运行了感染了 Lokibot 的文件,该恶意软件便会开始在系统中活动。

5.2 静态分析
从peb链表开始查询并获取dll基地址,计算函数名并与目标hash比对,比对成功后获取到函数GetCommandLineW的地址。

推测此样本通过动态获取api的方式进行函数加载
动态获取RegOpenKeyA(),RegQueryValueExA(),和RegCloseKey()这三个函数获取MachineGuid的值

'''
知识点补充:
MachineGUID 是一个用于标识计算机或设备的唯一标识符。
GUID 是一种全局唯一标识符,用于在分布式系统中确保对象的唯一性。
MachineGUID 用于标识特定的计算机或设备,而 GUID 用于在软件开发中确保对象的唯一性。两者在作用和范围上有所不同。
'''

对MachineGuid进行hash计算,获得一个固定长度且唯一的标识符,用于代表该设备或计算机。

Sub_4065A2():

Lokibot 查询文件系统和注册表,以枚举系统信息、凭据、cookie 和其他敏感数据。使用函数窃取各种数据,窃取软件列表如下:

窃密逻辑如下:
去注册表中寻找firefox这个软件,如果有的话获取他的版本信息

获取user-agent字段的数据

从内存中解密上线地址http://63.141.228.141/32.php/SczbkxCQZQyVr

Lokibot遍历读取指定目录下以“.lck”为后缀的文件

持久化
复制自身到C:\Users\USERS\AppData\Roaming\88B33F路径下并设置为隐藏文件

5.3静态分析com组件
通过Windows api调用创建CoCreateInstance实例,根据根据classid和接口id-riid初始化com组件,启动com对象的实例。
由于ida没有对clsid正确解析,因此无法显示调用的com组件接口

根据classid手工找到对应的名称,是创建shell自动化服务 (推荐使用ida8.3,不用自己修结构体)

CoCreateInstance参数详解:第一个参数:待创建组件的CLSID;第二个参数:用于聚合组件;第三个参数:dwClsContext的作用是限定所创建的组件的执行上下文;第四个参数:iid为组件上待使用的接口的iid;CoCreateInstance 将在最后一个参数中返回此接口的指针。通过将一个IID传给CoCreateInstance,客户将无需在创建组件之后去调用其QueryInterface函数。

找到ppv偏移36的方法,实际上是com接口虚表函数的指针位置。可以看到正确的com接口是namespace,手动修改变量类型。该com组件实现了多个接口类,需要riid进行二次判定。

Ppv是返回的接口对象指针,将ppv的类型修改为IShellDispatch,查看对应的TypeLib,为shell32.dll

Com对象中偏移36的位置正好是Namespace,而Namespace返回值是指向文件夹的文件夹指针Folder

修改变量v11的类型为Folder之后可以看到v11最终调用了CopyHere

在这个案例中,总结下来:CoCreateInstance定义了com组件ShellAutomation Service,IShellDispatch是组件包含的com对象,namespace是对象包含的接口。
去folder对象中查看一下:

Ida分析com组件的插件:https://github.com/airbus-cert/comida

5.4动态分析com组件
样本创建com对象,使用namespace命名空间方法,SysAllocString的参数是一个指向zip的文件路径,并使用folder-copyhere将文件夹的内容复制到该zip文件,zip文件经过com组件的一系列操作后被视为了目标存档。

5.5方法复现
复制该guid={13709620-C279-11CE-A49E-444553540000}(样本中指定的guid)

创建一个空的压缩文件

'''
$object_instance=[System.Activator]::CreateInstance([type]::GetTypeFromCLSID("{13709620-C279-11CE-A49E-444553540000}”))
$folder_object=$object_instance.NameSpace("C:\test\test.zip")
$folder_object.CopyHere("C:\Users\user\Desktop\COMView (1)")
'''

去test.zip中检查,已成功拷贝。

复现完毕

APLib是一款基于LZ-based压缩算法的32位压缩引擎库,压缩后数据没有可识别的常量,样本中有相关字符串,但并未对其进行调用,猜测在后续的攻击中该恶意软件作者会将其投入使用。

六、总结
为了防范 Lokibot 等恶意软件的攻击,用户应当保持软件和系统更新,谨慎打开陌生邮件附件和链接,使用信任的安全软件进行扫描和保护等。

Hash
f5b7d5b47c868d84298da69639557445

0 条评论
某人
表情
可输入 255
目录