Cobalt Strike 4.10 现已推出。此版本引入了 BeaconGate、Postex Kit 和 Sleepmask-VS。此外,我们还彻底改造了 Sleepmask API、刷新了 Jobs UI、添加了新的 BOF API、增加了对热插拔 C2 主机的支持等等。与以前的版本相比,此版本的发布周期更长,使我们能够进行底层架构更改以支持我们的长期目标。
注意: Cobalt Strike 4.10 对更新应用程序进行了重大更改。授权用户需要从头开始下载 4.10 版本。现有的 4.9 更新应用程序不能用于升级到 4.10 版本。
信标之门
过去几年,异常 API 调用的检测逻辑急剧增加。例如,syscall-detect、MalMemDetect、Hunt-Sleeping-Beacons和pe-sieve等开源项目都证明了从未备份的内存中搜寻可疑 API 调用的价值。此外,Elastic 凭借其异常调用堆栈检测逻辑推动了防御行业的发展,这对现代红队行动来说是一个巨大的挑战。
此外,在此版本发布之前,运营商很难解决 Cobalt Strike 的上述挑战。例如,无法在 Beacon 的系统调用实现上进行构建,而获得对 Beacon API 调用的精细控制的唯一方法是通过UDRL 中的 IAT 挂钩,这很复杂,而且进入门槛很高。
由于 Cobalt Strike 擅长通过灵活性进行规避,因此这是一个需要解决的关键问题,也是我们此版本的主要优先事项之一。此外,我们希望提供一种解决方案,避免陷入复杂的实施细节,并让用户可以轻松地将自定义 TTP 应用于 Beacon 的 API 调用。我们对这些问题的解决方案是 BeaconGate。
从高层次来看,Sleepmask 在概念上类似于远程过程调用(RPC),尽管它们位于相同的进程地址空间中。例如,当 Beacon 休眠时,它将调用 Sleepmask BOF、屏蔽和休眠。Beacon 在此处充当“客户端”,而 Sleepmask 是代表Beacon 执行 Sleep 调用的“服务器”。在 Cobalt Strike 4.10 中,我们将这个想法推向了逻辑结论,Sleepmask 现在支持执行任意函数。因此,现在可以配置 Beacon 以将其 Windows API 调用转发到 Sleepmask(又名 BeaconGate)执行。
这为操作员提供了前所未有的控制和灵活性;我们告诉您 Beacon 想要调用什么(以及参数),然后您可以用它做您想做的事情。因此,BeaconGate 使用户能够实现前沿的调用堆栈欺骗 TTP,并将它们普遍应用于 Beacon 的 WinAPI 调用。此外,由于 Beacon 现在与其 WinAPI 调用分离,您还可以在调用潜在可疑 API 时屏蔽 Beacon。这一切都作为 BOF 实现,因此您可以配置不同的门,并通过交换不同的 Sleepmask BOF完全更改您的 TTP 。
默认情况下,如果您启用通过 BeaconGate 代理的 API,则在执行 API 时 Beacon 将被屏蔽。这意味着,Beacon 现在具有开箱即用的屏蔽和调用功能。这对于可能根据内核回调/ ETW TI 事件 触发扫描的 AV 供应商来说是一种有用的缓解措施。
可以通过设置新的 Malleable C2 选项来配置 BeaconGate stage.beacon_gate
,如下所示:
stage {
beacon_gate {
All;
}
}
此选项的有效值为:
-
通信– 目前是
InternetOpenA
(InternetConnectA
即仅限 HTTP(S) WinInet Beacons) -
核心
VirtualAlloc
– 这是Beacon 现有系统调用 API的Windows API 等效版本(即) 。请参阅BeaconGate 文档以获取受支持功能的完整列表。 -
清理– 目前,此功能支持
ExitThread
通过 Sleepmask 进行代理。如果启用此功能,则默认情况下 Sleepmask 将在退出前清除/释放 Beacon 内存。此外,这为操作员提供了在 Beacon 退出前执行自定义清理的机会。 -
全部——通信+核心+清理。
还可以使用以下语法从支持的集合中转发特定函数:
stage {
beacon_gate {
VirtualAlloc;
VirtualAllocEx;
InternetConnectA;
}
}
需要注意的是,ps
如果您启用了核心集,一些更密集的 Beacon 命令(例如)可能会使 CPU 激增。这是预期的行为,因为在屏蔽时ps
会多次调用OpenProcess
/ CloseHandle
。如果需要,您可以通过在运行时禁用 BeaconGate,beacon_gate disable
或者在您自己的 Sleepmask BOF 中禁用特定功能的屏蔽。
还需要指出的是,BeaconGate 和 Cobalt Strike 现有的syscall_method
选项是互斥的;如果您为某个 API 启用 BeaconGate,它将优先于系统调用。但是,您可以为特定 API 启用 BeaconGate,并对其余 API 使用 Beacon 现有的系统调用方法。例如:
stage {
set syscall_method "Indirect";
beacon_gate {
VirtualAlloc; // Only VirtualAlloc is proxied via BeaconGate
}
}
使用定制 Sleepmask BOF 在 BeaconGate 之上进行构建
在上一节中,我们介绍了 BeaconGate 的默认行为。然而,真正的强大之处在于在 BeaconGate 之上构建。这里的潜力是无限的;您自己的门可以实现新颖的系统调用技术、欺骗调用堆栈、伪造返回地址、利用SilentMoonwalk等——所有这些都是在 Beacon 被屏蔽的情况下进行的(如果需要)。
Beacon 提供更高级别的 WinAPI(即VirtualAlloc而不是NtAllocateVirtualMemory)以提供尽可能多的灵活性。因此,您可以为 NT 函数实现自己的系统调用/门(例如RecycledGate 之类的东西),或者取消挂钩并使用欺骗的调用堆栈调用原始 WinAPI 函数等。 为了演示这些可能性,下面是 BeaconGate 的快速 PoC,它为 Beacon 的调用实现了返回地址欺骗(当 Beacon 被屏蔽时)InternetOpenA
:
图 1. 屏幕截图显示了 BeaconGate 实施返回地址欺骗的过程。在 windbg 中触发了一个断点,WININET!InternetOpenA
并显示了调用线程的调用堆栈(通过命令knf
)。调用堆栈显示调用函数为WININET!UrlCacheFindFirstEntry
,但这已被欺骗;调用是通过 Sleepmask 代理的。此外,在命中断点后InternetOpenA
,PowerShell 终端会显示对调试进程的 YARA 扫描。这显示没有命中,因为在进行调用时 Beacon 被屏蔽(在 4.10 之前,Beacon 此时会暴露在内存中)。
此示例表明,现在可以逃避异常调用的检测逻辑InternetOpen/ConnectA
,例如MalMemDetect。但是,同样的技术可以应用于所有受支持的 WinAPI 函数。此外,受支持的 API 涵盖了ETW TI 事件和内核回调中异常调用堆栈的大多数检测用例(有一些例外,例如CreateProcess)。
睡眠面罩-VS
Sleepmask 是 Cobalt Strike 逃避策略的重要组成部分。它最初是一个可以嵌入 Beacon 的小型位置无关代码 (PIC) 块。然而,它后来发展成为一个功能齐全的 BOF。虽然这一变化提供了极大的灵活性,但它的快速增长也使 Sleepmask 变得相当复杂,这意味着(根据我们的经验)用户通常不愿意在其上进行构建。
此外,在内部测试BeaconGate 时,我们发现使用现有工具编写自定义 Sleepmask BOF 非常困难。因此,此版本的目标之一是降低编写自定义 Sleepmask 的门槛。
因此,我们更新了公共BOF-VS 模板以支持 Sleepmask 和 BeaconGate 功能。这意味着我们的 BOF-VS 模板现在是编写 Cobalt Strike 使用的所有各种 BOF 的一站式商店。
此外,为了提供可用的 Sleepmask BOF 示例,我们还发布了Sleepmask-VS。这是一个简单的 Sleepmask 示例,演示了如何使用 BOF-VS 模板编写 Sleepmask/BeaconGate BOF。此存储库将随着时间的推移而增长,以包含各种不同的示例。此外,它将用作 UDRL-VS 加载器的配套 Sleepmask BOF,以便我们可以提供如何一起使用 Cobalt Strike 最重要的规避工具的示例。
Sleepmask-VS 包含runMockedSleepMask()
并可runMockedBeaconGate()
轻松创建自定义 Sleepmask/BeaconGate BOF。这两个函数与原始BOF-VSrunMocked()
函数类似,但它们会创建模拟内存中的 Beacon 以及一些示例堆内存。这允许用户在调试器中逐步执行他们的 Sleepmask 并查看其屏蔽效果。这些函数还允许用户提供他们所需的 Malleable C2 设置来模仿 Beacon 默认加载器的行为。
runMockedSleepMask
下面是一个示例调用:
int main(int argc, char* argv[]) {
bof::runMockedSleepMask(sleep_mask,
{
.allocator = bof::profile::Allocator::VirtualAlloc,
.obfuscate = bof::profile::Obfuscate::False,
.useRWX = bof::profile::UseRWX::False,
.module = "",
},
{
.sleepTimeMs = 5000,
.runForever = true,
}
);
return 0;
Sleepmask-VS 还提供了如何使用该函数的示例runMockedBeaconGate
。该函数复制 Beacon 使用 BeaconGate 调用来调用 Sleepmask,并传入模拟的 Beacon/堆内存以进行屏蔽。这让操作员可以轻松开始开发自己的自定义门控。
例如,下面的示例代码演示了如何VirtualAlloc
通过 BeaconGate 代理呼叫:
// Create a FUNCTION_CALL structure
FUNCTION_CALL functionCall = bof::mock::createFunctionCallStructure(
VirtualAlloc, // Function Pointer
WinApi::VIRTUALALLOC, // Human readable WinApi enum
TRUE, // Mask Beacon?
4, // Number of Arguments (for VirtualAlloc)
GateArg(NULL), // VirtualAlloc Arg1/Rcx
GateArg(0x1000), // VirtualAlloc Arg2 /Rdx
GateArg(MEM_RESERVE | MEM_COMMIT), // VirtualAlloc Arg3/R8
GateArg(PAGE_EXECUTE_READWRITE) // VirtualAlloc Arg4/R9
);
// Run BeaconGate
bof::runMockedBeaconGate(sleep_mask, &functionCall,
{
.allocator = bof::profile::Allocator::VirtualAlloc,
.obfuscate = bof::profile::Obfuscate::False,
.useRWX = bof::profile::UseRWX::False,
.module = "",
}
);
// Free the memory allocated by BeaconGate
VirtualFree((LPVOID)functionCall.retValue, 0, MEM_RELEASE);
该FUNCTION_CALL
结构包含执行“原子”函数调用所需的所有信息,也是 Beacon 作为 BeaconGate 的一部分传递给 Sleepmask 的信息。这createFunctionCallStructure
是一个辅助函数,可以轻松生成这些结构以用于您自己的代码。最后,该bof::runMockedBeaconGate
函数将调用 Sleepmask 入口点并传递给您,FUNCTION_CALL
以供 BeaconGate 执行。有关确切 API 用法和函数定义的详细信息,请参阅Sleepmask-VS。
在 BeaconGate 发布后,将进一步深入研究,演示如何开始开发您自己的自定义 TTP,并演示一些不同的开源门。作为一个尝试者,之前演示的返回地址欺骗 PoC 是使用 Sleepmask-VS 开发的。
此外,我们还发现内联汇编是将RecycledGate等低级技术移植到 BeaconGate 的重要功能。因此,我们还将在下一篇博客中讨论如何做到这一点。
目前可以使用Sleepmask-VS 通过合并两个不同的目标文件ld
来实现这一点,但这并不理想(NB MSVC不支持这一点)。因此,您需要将程序集存根编译为单独的目标文件(即通过MASM/ml64.exe),然后手动将其与Sleepmask-VS 生成的文件合并:link.exe``sleepmask.x64.o
> ml64.exe /Fo asm_funcs.o /c asm_funcs.asm
Microsoft (R) Macro Assembler (x64) Version 11.00.50727.1
Copyright (C) Microsoft Corporation. All rights reserved.
Assembling: asm_funcs.asm
[ ... ]
(In WSL/Linux)
> ld --oformat pe-x86-64 -r sleepmask.x64.o asm_funcs.o -o sleepmask.x64.o
最后,为了让操作员能够充分利用 BeaconGate,我们增加了最大 Sleepmask BOF 尺寸。
Beacon 目标文件更新
我们还做出了一些改变,以帮助用户在此版本中充分利用 BOF。
我们扩展了BOF API,以便向 BOF 公开 Beacon 的系统调用功能。新 API 采用 的形式Beacon<WinAPI>
,即BeaconVirtualAlloc
。我们添加了新 API,以便为操作员提供尽可能多的灵活性。因此,用户可以根据需要“选择”使用 Beacon 的系统调用 API,而不是透明地链接而别无选择。
举例来说,下面的代码将VirtualAlloc
通过 Beacon 的系统调用代码路由调用:
void go(char* args, int len) {
PVOID pMemoryBuffer = NULL;
pMemoryBuffer = BeaconVirtualAlloc(NULL, 8, MEM_COMMIT, PAGE_READWRITE);
}
syscall_method
Beacon 使用的系统调用方法将是通过 Malleable C2选项或通过运行时命令配置的选项syscall-method
。
此外,BeaconGate 也支持这些新的 BOF API。因此,如果您配置了自己的自定义门,则可以代理来自 BOF 的 WinAPI 调用以由自定义门执行。这使操作员可以完全控制 Beacon 的 API 使用/占用空间,并减少 BOF 代码膨胀。
有关新 API 的更多详细信息,请参阅此处的文档。此外,可以在公共 Cobalt Strike GitHub 存储库中的bof_template中找到一个示例 BOF ,它演示了使用新 API 分配和释放内存的简单示例。 还添加了
一个新的 Beacon API BeaconGetSyscallInformation ,这意味着您现在可以在加载器中实现任何您想要的系统调用解析技术,通过 Beacon 用户数据 (BUD) 将解析的系统调用信息传递给 Beacon,然后从 BOF 中检索它。这旨在减少 BOF 内部必须自己重复计算系统调用信息的膨胀。有关 API 的更多详细信息,请参阅此处的文档。
需要注意的是,bud-loader
UDRL-VS 演示了如何通过 BUD 将解析的系统调用信息传递给 Beacon,而我们的公共BOF-VS 模板包含一个模拟BeaconGateSyscallInformation
API,可轻松将其集成到您自己的 BOF 中。
最后,BOF API 限制已扩展到 128 @s4ntiago_p)。
睡眠面罩 Redux
通过与客户交谈,我们了解到 Sleepmask 和 UDRL 之间的互操作性存在混淆。混淆源于这样一个事实:在 Malleable C2 配置文件中设置的转换不适用于通过 hook 生成的 Beacon BEACON_RDLL_GENERATE
。相比之下,无论您是否使用 UDRL, Sleepmask 设置都是从 Malleable C2 配置文件和 Beacon DLL 静态计算的。
例如,stage.obfuscate
可用于混淆 Beacon DLL 的部分内容,它还指示默认加载器不要将 PE 标头复制到内存中作为反射加载过程的一部分。但是,这不适用于具有 UDRL 的 Beacon。这是预期的行为,因为它让开发人员处于主导地位(即,UDRL 必须知道 Beacon 是如何被混淆的,才能将其逆转)。但是,Sleepmask 将使用stage.obfuscate
它来计算需要屏蔽的部分,因此将假设不存在 PE 标头。如果 UDRL 不遵守 Malleable C2 配置文件设置,这显然是问题的根源。
BeaconGate 的引入意味着我们必须对 Sleepmask API 进行一些重大更改,这也为我们提供了解决这个问题的机会。在 CS 4.10 中,我们扩展了Beacon 用户数据以包含一个新ALLOCATED_MEMORY
结构。此结构可用于将有关反射加载器分配的(动态)内存的信息传递给 Beacon。例如,Beacon 在内存中的位置以及每个加载部分的地址。这种设计意味着 Beacon 现在可以向 Sleepmask 传递准确的部分信息,在运行时,这大大简化了 Sleepmask 的设计。此功能还开辟了许多可能性,因为加载器分配的任何内存现在都可以由 Sleepmask 自动屏蔽。
有关具体实施细节, UDRL-VS 中的bud-loader
和obfuscation-loader
包含全面的示例来演示如何ALLOCATED_MEMORY
在 UDRL 中使用。该设计深受 Microsoft 自身关于虚拟内存的抽象的影响,我们计划在未来几个月内发布一篇深入介绍如何充分利用此功能的文章。
值得注意的是,从 4.10 版本开始,通过ALLOCATED_MEMORY
/BEACON_USER_DATA
结构配置 Sleepmask 是预期的工作流程。如果您不传递此信息(即静态传递),Beacon 仍将尽力尝试屏蔽,但可能无法按预期工作。但是,在未来的版本中,我们计划删除向后兼容性。这意味着 UDRL 必须将分配的内存传递给 Beacon 才能使用 Sleepmask。
用户定义的 BOF 内存
我们还为结构添加了支持ALLOCATED_MEMORY
,用于传递可用于 BOF 和 Sleepmask 执行的 Beacon 用户定义内存。因此,如果您想要完全控制用于 BOF 的内存分配方式,您可以在 UDRL 中使用自己的自定义分配技术并将此信息传递给 Beacon。这现在使操作员能够在加载/执行 BOF 时使用诸如模块踩踏之类的技术。UDRL bud-loader
-VS 中包含一个示例,说明如何将用户定义内存传递给 Beacon 以供inline-execute
Sleepmask 使用。
Postex 套件
4.10 中的另一个新增功能是 Postex 套件。Postex 套件开放了 Beacon 的工作架构,允许操作员开发自己的 post-ex DLL 以实现与 Beacon 的互操作性。因此,如果您需要快速 PoC 自定义键盘记录器/会话监视器/TGT 监视器等,您可以使用 Postex 套件开发一个可以无缝插入 Beacon 现有工作架构的 DLL。此外,DLL 通常更易于开发和单元测试复杂/长时间运行的任务,并且不存在任何可能使 BOF 开发变得困难的痛点和限制。
值得强调的是,Postex 套件还通过Aggressor 钩子支持 post-ex UDRL(在 4.9 中引入),并通过 Aggressor 钩子支持进程注入钩子。这让操作员可以完全控制整个 post-ex 攻击链,包括自定义功能以及如何将它们注入/加载到内存中。进程注入套件(根据我们的经验)仍未得到充分利用,值得查看此博客以获取有关如何配置它的更多信息。Postex 套件本身主要用作开发模板。它是一个 Visual Studio 解决方案,可以在 Arsenal 套件中找到,可以轻松开发自定义的长期运行的 post-ex DLL,这些 DLL 通过命名管道将数据返回到 Beacon。它包括一个函数库,这些函数库提供了对作业架构的抽象,使操作员可以专注于开发自定义工具。需要注意的是,Postex 套件的设计方式使其能够在未来的版本中提供对替代通信方法的支持(即不仅仅是命名管道)。 为了支持 Postex 套件,Beacon 控制台中添加了一个新命令。这将获取操作员提供的自定义 post-ex DLL,在其前面添加一个 post-ex 加载器,并将其作为新作业执行。此作业可通过常规 Cobalt Strike 作业输出查看,并通过命令终止。 POSTEX_RDLL_GENERATE
PROCESS_INJECTION_*
execute-dll``jobkill
此外,该execute-dll
命令还支持传递参数。这些参数会自动修补到单独的内存分配中,并可以通过 post-ex DLL 访问postexData->UserArgumentInfo.Buffer
(有关更多信息,请参阅 Postex 套件示例 DLL)。 然而,Cobalt Strike 最强大的功能之一是其脚本语言 Aggressor Script,它为操作员提供了极大的灵活性。因此,我们还添加了一个新的 Aggressor Script 功能beacon_execute_postex_job
。
其工作方式与类似,execute-dll
不同之处在于它支持将 BOF 样式参数(即通过 Aggressor Script 的bof_pack 函数)传递给自定义的 post-ex DLL。这使操作员能够在其 post-ex DLL 中使用熟悉的 Beacon Data Parser 和 Beacon Data Format APIbeacon_execute_postex_job
。下面显示了一个简单的示例:
$argument_string = "example argument string";
$packed_arguments = bof_pack($beacon_id, "iz", 4444, $argument_string);
# example: run the postex task
beacon_execute_postex_job($beacon_id, $pid, $postex_dll, $packed_arguments, $null);
然后,可以通过标准BeaconDataParse/Extract API从 post-ex DLL 中解析打包的参数。与 Aggressor Script 一样,这里有很大的自定义空间。例如,如果需要,您还可以将参数直接放入 post-ex DLL 中并自行检索它们。
此外,我们还添加了另一个 Aggressor 函数。bjob_send_data
这意味着操作员现在可以通过命名管道将任意数据发送到自定义 post-ex 作业。下面是一个演示此操作的示例:
# String to send to the post-ex dll
$pipe_data= "example pipe data string";
# Send the string to target post-ex job over named pipe
bjob_send_data($bid, $jid, $pipe_data);
这为您的工具提供了极大的灵活性。下面是一个简单的示例,inject-assembly
我们内部开发的用于测试 Postex 套件的自定义 PoC 的屏幕截图:
图 2. 展示 Postex 套件使用情况的自定义 PoC 的屏幕截图inject-assembly
。此示例 post-ex DLL 等待通过命名管道传递参数,并DotNetHelloWorld.exe
使用传递的参数重复执行程序集。
上述inject-assembly
命令beacon_execute_postex_job
在后台使用 PoC post-ex DLL 以及用户提供的 .NET 程序集注入远程进程。然后,post-ex DLL 会监听命名管道,等待用户通过 发送一些参数bjob_send_data
。在上面的示例中,我们使用一组不同的参数运行了两次目标程序集。
Postex 套件还包含一个示例 post-ex DLL(必须与结合使用postex-example.cna
),以便开始开发您自己的工具。此示例 post-ex DLL 主要用于在一个地方演示 Postex 套件的不同方面。此外,Postex 套件文档可在此处找到。与其他新的 4.10 功能一样,我们计划在未来几个月内发布对 Postex 套件(以及上面演示的自定义注入程序集 DLL)的深入介绍。
回调更新
回调函数在4.9 版中引入,并在 4.10 版中得到扩展,为用户提供了一种与 Postex 工具包交互的直接方法。 例如,您还可以调用beacon_execute_postex_job
并提供自定义回调函数作为最后一个参数,该函数将在每次作业签入时调用。自定义回调传递一个新的%infomap
哈希映射,其中包含各种信息,例如作业的状态(即作业是否刚刚注册、是否已完成、是否正在发送输出等)及其作业 ID。关键点是回调可以访问作业 ID(一旦作业已注册),然后可以使用该 ID 通过发送进一步的数据bjob_send_data()
。
下面的脚本片段显示了此功能的一个简单示例cna
,它演示了在注册后通过回调将进一步的数据发送到自定义 post-ex DLL:
$pipe_data= "example pipe data string";
# define custom callback function
$callback = lambda({
local('$bid $data $result %info $type');
this('$jid');
# get all arguments passed to lambda
($bid, $result, %info) = @_;
# check the status/type of the job
$type = %info["type"];
# if the job is registered, send data via the pipe
if ($type eq 'job_registered') {
$jid = %info['jid'];
# send the pipe data string to the DLL
bjob_send_data($bid, $jid, $pipe_data);
}
# print output to the console
else if ($type eq 'output') {
bjoblog($1, $jid, "Received output:n" . $result);
}
}, $pipe_data=> $pipe_data;
# run the postex task...
beacon_execute_postex_job($beacon_id, $pid, $postex_dll, $packed_arguments, $callback);
作业浏览器和控制台
为了让您充分利用 Postex 套件,我们通过引入新的作业浏览器和作业控制台对 Cobalt Strike 的作业 UI 进行了更新。这也是客户常见的痛点,因为在 4.10 之前,很难将作业输出映射到特定的作业 ID。
作业浏览器是一个新对话框,用户可利用它处理由一个或多个 Beacon 运行的作业。可以通过选择一个(或多个)Beacon、右键单击并从Jobs
弹出菜单中选择选项,或从View -> All Jobs
主菜单中选择来打开它。
作业浏览器显示分配给给定 Beacon 的每个作业的完整列表,并显示各种信息,例如作业 ID (JID)、作业状态(即作业是否已完成或仍在运行)、作业描述以及开始和停止时间。作业浏览器的示例如下所示:
图 3.显示新作业浏览器 UI 的屏幕截图。
作业控制台是另一个新对话框,允许用户处理特定作业的输出。右键单击作业浏览器中的目标作业并open
从弹出菜单中选择即可调用该对话框。下面显示了端口扫描作业的作业控制台示例:
图 4.显示端口扫描的新作业控制台 UI 的屏幕截图。
还可以从 Beacon 控制台隐藏所选作业的输出。然后,输出将被重定向到仅显示在作业控制台窗口中。这改善了长时间运行的 post-ex 作业(如 SharpHound)的用户体验,因为这意味着输出全部集中在一个地方,并允许用户继续在 Beacon 控制台窗口中操作。此外,如果您需要重新查看特定作业的输出,您现在可以打开作业控制台,而不必浏览 Beacon 控制台历史记录。
主机轮换更新
Cobalt Strike 的主机轮换功能是在4.3 版中引入的,旨在让操作员更好地控制 HTTP/S 和 DNS Beacon 在主机之间的循环方式。虽然这为 C2 通信提供了额外的灵活性,但主机轮换存在两个主要问题:
-
不管响应情况如何,响应迟钝的主机都会被纳入轮换策略。因此,如果三分之一的主机出现故障,三分之一的签到将反复失败。
-
无法更新活动 Beacon 上的主机信息以更改或禁用故障主机。
在 Cobalt Strike 4.10 中,我们对主机轮换做了许多改进,以解决这些问题:
-
Beacon 现在将自动禁用(“保留”)已发生故障的主机,从而实现更加可靠的连接。
-
添加了新的 Beacon 命令
beacon_config
及其对应的 Aggressor Script 函数,bbeacon_config
以便查询和更新活动 Beacon 的主机信息。因此,现在可以热交换 C2 主机(通过添加新主机或更新现有主机)。 -
操作员可以启用失败连接的通知,从而更容易调试主机轮换问题。
例如,我们可以通过 newbeacon config host info
命令查询一个活跃的 Beacon 当前的主机信息,如下所示:
图 5. 显示新beacon_config
命令运行情况的屏幕截图。输出显示,example.yyy
目前在活动 Beacon 上仅配置了一个主机 ( ) 进行 RoundRobin 主机轮换。
下面的截图显示了example.zzz
运行时添加的新主机():
图 6. 显示热插拔 C2 运行情况的屏幕截图。example.zzz
已动态添加新主机 (),现在将用作现有 RoundRobin 主机轮换策略的一部分。
Wireshark 显示 Beacon 立即开始使用新主机进行签到:
图 7.Wireshark 中的 TCP 流演示了 Beacon 使用动态添加的主机(example.zzz
)进行签到。
需要注意的是,添加热插拔 C2 主机的一个限制是 URI 必须先前在 Malleable C2 配置文件中定义。
最后,一些 Web/代理服务器(在阻止请求时)在响应 Beacon 签到时返回 200(OK)状态,而不包含任何其他数据。Beacon 认为这是一个有效的“无事可做”响应,因此不会触发故障转移轮换到下一个主机。为了解决这个问题,用户现在可以自定义“无事可做”任务的格式,以便 Beacon 可以确定给定的响应是否有效。这可以通过新的 Malleable C2 配置文件选项data_required
和来启用data_required_length
。
有关所有这些主机轮换更新的更多信息,请参阅此处的文档。
Java 支持已更新至 Java 11
正如Cobalt Strike 4.9 发布博客文章中提到的,我们已将 Java 的最低支持版本从 Java 8 更改为 Java 11。如果您尝试使用旧版本的 Java 运行客户端,您将看到以下错误:
图 8. 使用旧版本 Java 运行 Cobalt Strike 4.10 客户端时出现的错误消息的屏幕截图。
为避免出现任何问题,请在下载和运行 Cobalt Strike 之前确保您环境中的 Java 版本至少为 Java 11。有关更多指导,请参阅 Cobalt Strike安装指南。
产品安全更新
产品安全控制已作为 4.10 版本的一部分进行了更新。特别是,Linux 软件包现在将客户端和服务器拆分为单独的软件包,每个软件包都需要一个特定的授权文件。这导致 Cobalt Strike 更新方式发生重大变化,您可能需要在任何定制部署脚本中考虑到这一点。
此外,Fortra 还与欧洲刑警组织、英国国家犯罪局和其他几家私人合作伙伴合作,以保护 Cobalt Strike 的合法使用。6 月份,593 个 IP 地址被关闭,以禁用被盗的、未经授权的 Cobalt Strike 版本。Fortra 和执法部门将继续监控并根据需要采取类似行动。您可以在此处阅读有关该行动的更多信息。
更多更新
此外,此版本还包括对系统调用、外部 C2 的更新,以及许多生活质量 (QoL) 变化。这些 QoL 更新包括:
-
改进了制表符补全功能(包括支持自定义命令、shift + tab 功能以及不区分大小写)。
-
UI 改进(包括对话框更好的自动换行和允许用户指定是否希望在最大化窗口中打开 Cobalt Strike 的偏好设置)。
-
能够指定用于日志记录的时区和时间戳格式(可通过 Teamserver.prop 配置)。
要查看 Cobalt Strike 4.10 中的新功能完整列表,请查看 发行说明。
授权用户需要*[**从头下载 4.10 版本*](https://download.cobaltstrike.com/download)*。现有的 4.9 更新应用程序不能用于升级到 4.10 版本。***
Cobalt Strike
原文始发于微信公众号(安全视安):【翻译】Cobalt Strike 4.10:通过 BeaconGate
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论