Cobaltstrike狩猎与对抗

共 6943字,需浏览 14分钟

 ·

2022-07-16 11:56

STATEMENT

声明

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测及文章作者不为此承担任何责任。

雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

安恒信息星火实验室专注于实战攻防与创新研究,主要方向包括实战演练、攻击模拟、威胁分析、漏洞挖掘等。团队成员均来自行业具备多年实战经验的攻防专家。本着以攻促防的核心理念,通过落地ATT&CK攻防全景知识库,实战化度量安全风险、赋能企业建设与运营。


概述

Cobalt Strike是一款渗透测试工具,简称为CS。它拥有多种协议主机上线方式,并集成了文件操作、命令执行、提权、凭据导出、端口转发、socket代理、宏病毒、文件捆绑、钓鱼等功能。其ATT&CK的官方映射如下图,可见CS从初始访问阶段(TA0001)横跨到渗出阶段(TA0010)都有覆盖:

下面我们会先从cs的profile进行分析,cs的profile设置讲解网上挺多的,但没有深入的探究为什么会增加这个选项,这个选项最终会起到什么的作用,加了选项后根据现有的规则能否进行检测等。然后我们会站在狩猎对抗的角度出发,从不同的角度思考怎么检测出可疑的进程。

profile设置详解

流量侧:

流量侧的伪装主要在http-get和http-post这两个标签中,两标签中的设置也是类似的,set uri是设置回传teamserver端的URI地址,client设置请求头中的信息,metadata中是设置回传元数据的格式,这是设置了把回传的元数据以base64编码后再netbios编码,最后拼接在cookie中输出,所涉及到算法netbios、base64url、mask、netbiosu的详细分析可参见这篇文章https://unit42.paloaltonetworks.com/cobalt-strike-metadata-encoding-decoding/:

http-get {set uri "/web /api/gallery /updates /about";
client {header "Accept" "*/*";header "Connection" "Close";header "Host" "baidu.com";
metadata {base64;netbios;prepend "cf=";header "Cookie";}}
server {output {print;}}}

同样http-post也是类似,id标签是将beaconID先后netbios、base64url编码后拼接在自定义的key参数后,output标签是beacon执行完后把数据base64编码后回传给teamserver端:

http-post {set uri "/web/auth.php /admin/login.php";
client {header "Accept" "*/*";header "Host" "baidu.com";header "Connection" "Close";
id {netbios;base64url;parameter "key";}
output {base64;print;}}
server {header "Pragma" "no-cache";header "Connection" "close";
output {print;}}}

主机侧:

在Profile文件中的stage、process-inject、post-ex三个标签可以更自由的操作beacon在内存中的、后渗透中等行为。下面分析stage标签在内存中的行为。

stage标签

在stage标签中可以设置beacon的元数据修改、在内存中的属性、数据的替换、加解密混淆等,是一个强大的设置。
set userwx "false";
这个选项是设置执行反射dll所分配的内存属性,true为RWX,false为RX:

所以我们则可以关注进程中内存属性为RWX的区域进行重点的检测对象。
set cleanup "true";
这个选项在设置true后,会抹去存放在内存中的反射DLL,false则不会。

而CobaltStrikeScan检测则是通过获取到内存中Dll进行解密后获取到相关的配置,当我们设置为cleanup则能防止其配置读取.
set sleep_mask "true";
当这个选项设置为true时,Beacon会加入一段加解密函数,会对数据和代码进行异或加密,3.11版本是单字节异或,4.2版本是13字节异或。
13字节的密钥:

在内存中被13字节异或加密后的beacon:

解密后的beacon内容:

set stomppe "true";
stomppe选项当设置为true时能对MZ、PE和e_lfanew的值进行混淆,这样能使根据MZ等关键字的内存匹配失效:

set obfuscate "true";
当obfuscate设置为true时,能混淆dll的导入表、区段名等信息,使得根据导入表匹配的规则失效,0x00039ad8开始是被混淆的导入表:

被混淆的区段名:

transform-x86的strrep标签中主要是修改替换反射dll中的固定字符,以防止被文件静态特征所匹配到,prepend则是在MZ头前加"\x90\x90\x90",防止在内存中的MZ头被匹配到。

transform-x86 {prepend "\x90\x90\x90";strrep "ReflectiveLoader" "";strrep "beacon.dll" "";strrep "This program cannot be run in DOS mode" "";}

狩猎对抗

流量侧:

在没有设置profile中的http-get、http-post标签时,其CS回传数据给teamserver端是有默认的URI,所以对于使用默认profile的流量通信是比较好捕获的:

Beacon执行命令的结果默认是通过post请求/submit.php?id=发回给服务器。
即使配置了profile,但通常每次提交post请求后的响应包数据大小基本一致的,同时能结合默认的连接频率:

同时也可以把网上开源的profile加入检测流量规则中,如检测伪装amazing的

https://github.com/rsmudge/Malleable-C2-Profiles/blob/master/normal/amazon.profile:

默认UA也可以作为检测标准

https://docs.google.com/spreadsheets/d/1bpeziZ-ObG8zKronKGyhXg2UsETk_fqY5dD4Tx0q_eY/edit# gid=1635920259这里有约100多条的,可见这里基本上是IE浏览器的UA,而如果在一个使用火狐浏览器的机子有IE的UA则比较可疑:

可以根据默认证书进行检测:

DNS上线可以通过单个域内的大量查询检测或者 TXT 记录数据量来检测 :

JA3/JA3S 可以用客户端和服务器之间的SSL通信创建指纹。签名可以从客户端数据包中的字段进行收集:SSL 版本、接受的密码、扩展列表、椭圆曲线、椭圆曲线格式。

主机侧

在主机侧我们可以从不同的角度去进行分析,下面我们将从文件、进程、线程、内存及其它行为等方面出发分析。

文件

提到文件特征YARA规则是不能缺少的,YARA规则是VT发布的,用于样本的批量检索和查杀,目前很多知名软件也使用YARA。其中YARA规则常以hash(文件的hash或导入表之类的hash)、PE头、pdb、全局字符串、互斥体、特定的函数等信息作为特征。
如以Elastic的yara规则为例,该规则定位了在rdata段的数据:

rule cobaltstrike_beacon_strings{meta:author = "Elastic"description = "Identifies strings used in Cobalt Strike Beacon DLL."strings:$a = "%02d/%02d/%02d %02d:%02d:%02d"$b = "Started service %s on %s"$c = "%s as %s\\%s: %d"condition:2 of them}

但在加sleep_mask选项后,其字符串和数据会被进行混淆,但我们可以对代码段中特定的函数进行标记,下面这条规则内容就是对解密函数进行标记:

rule HKTL_CobaltStrike_Beacon_4_2_Decrypt {meta:author = "Elastic"description = "Identifies deobfuscation routine used in Cobalt Strike Beacon DLL version 4.2"reference = "https://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures"date = "2021-03-16"strings:$a_x64 = {4C 8B 53 08 45 8B 0A 45 8B 5A 04 4D 8D 52 08 45 85 C9 75 05 45 85 DB 74 33 45 3B CB 73 E6 49 8B F9 4C 8B 03}$a_x86 = {8B 46 04 8B 08 8B 50 04 83 C0 08 89 55 08 89 45 0C 85 C9 75 04 85 D2 74 23 3B CA 73 E6 8B 06 8D 3C 08 33 D2}condition:any of them}

其对应的函数为加解密函数:

但在CS4.5的版本中已经支持了自定义其加解密函数并通过can证书进行设置。

进程

进程的异常行为

如notepad.exe进程存在网络连接:

<RuleGroup name="" groupRelation="or"><NetworkConnect onmatch="include"><Image name="Usermode" condition="begin with">C:\Users</Image><Image condition="image">notepad.exe</Image></NetworkConnect></RuleGroup>

进程的父进程

cobaltstrike在运行宏病毒时会拉起一个新的进程(如rundll32.exe)进行注入,而其进程的父进程为winword.exe,这显然是不合理的,所以我们可以从父子进程进行判断。

进程参数

Cobaltstrike默认注入的是rundll32.exe进程,但rundll32.exe的进程通常会带有一系列dll作为参数,如rundll32.exe shell32.dll,Control_RunDLL,如果没有dll参数则是比较异常的:

线程的地址

Cobaltstrike在spawn时默认会拉起rundll32进程并进行远程线程注入,而当在进程中的一个线程的起始地址没有关联到模块,同时该线程堆栈调用到sleepex()函数,这是值得我们去注意的。

sysmon对线程的监控

Sysmon的ID 8和 ID10分别对应创建远程线程、进程访问的监控,其中监控创建远程线程的原理是在内核中使用PsSetCreateThreadNotifyRoutine、

ObRegisterCallbacks注册了回调进行相应的过滤:
而cobaltstrike默认的dllinject、shinject功能均涉及到openprocess()和CreateRemoteThread():

内存的属性

在内存方面我们可以注意进程中所申请的内存是否没关联到模块、内存属性是否为RWX,而cobaltstrike的profile选项中能设置通过set userwx设置内存属性:

内存的内容(MZ\PE标志)

同时我们可以观察其内存区域的内容,可以简单通过MZ头标志进行匹配,但这样的不准确,cobalstrike可以通过配置在MZ增加nop或设置混淆选项进行绕过:

当然也可以匹配内存中的cobaltstrike的特定字符串,但cobaltstrike可以设置sleep_mask对各区段的内容进行解密,不过当设置了set userwx false的时候,代码段是没被异或的。
其他手段

管道名:

Cobaltstrike执行mimikatz等与反射dll相关的命令后,后续会使用管道来进行进程间的通信,把执行的结果返回到控制端。所以我们通过监控管道的创建来进行检测。Sysmon可以监控到系统程序的管道创建和连接,分别对应17、18号事件,下面为cobaltstrike的默认管道名,在4.2版本后管道名可以在profile中进行自定义:

<RuleGroup name="" groupRelation="or"><PipeEvent onmatch="include"><!-- Cobalt Strike Pipe Names --><PipeName condition="contains all">MSSE-;-server</PipeName><PipeName condition="begin with">\postex_</PipeName><PipeName condition="begin with">\postex_ssh_</PipeName><PipeName condition="begin with">\status_</PipeName><PipeName condition="begin with">\msagent_</PipeName></PipeEvent></RuleGroup>

敏感行为

在使用Cobaltstrike渗透过程中,常有比较敏感的行为,如steal_token、hashdump、jump psexec等,下面是令牌窃取的比较经典的实现步骤:
1) 通过 OpenProcess 获取 SYSTEM 权限进程的句柄
2) 通过 OpenProcessToken 获取该进程的访s问令牌
3) 通过 DuplicateTokenEx 函数复制该令牌
4) 通过 CreateProcessWithTokenW 创建具备同样访问令牌的进程
我们能通过对上述相关API进行hook或令牌窃取所产生的日志进行监控。
而Jump psexec则可通过监控特定文件夹的文件创建、进程创建、管道名称、进程调用链等进行检测。其会先调用上传文件:

将文件保存在目标ip的ADMIN\$下,名字随机为f9febc5.exe

然后通过任务号100 inline-execute调用该文件。进程调用链如下:

调用不常见的程序

在后渗透的阶段,使用run或shell命令运行whoami.exe、net.exe、tasklist等程序进行信息收集,我们可以通过对相关程序的原始文件名进行监控,从而知道系统中的可疑程序。

小结

通过这篇文章我们从Cobalt Strike的profile选项出发,探究了CS的狩猎对抗,认识到profile选项是相当丰富,可扩展性和实战意义都很强。对抗在不断发展,当我们在思考cs的profile选项的同时,尽可能更多的发现其检测点,做到以攻促防,以防验攻。
最后,谢谢观看。
参考:
https://www.unh4ck.com/
https://thedfirreport.com/2022/01/24/cobalt-strike-a-defenders-guide-part-2/
https://github.com/SigmaHQ/sigma
https://www.trustedsec.com/blog/tailoring-cobalt-strike-on-target


安恒信息

杭州亚运会网络安全服务官方合作伙伴

成都大运会网络信息安全类官方赞助商

武汉军运会、北京一带一路峰会

青岛上合峰会、上海进博会

厦门金砖峰会、G20杭州峰会

支撑单位北京奥运会等近百场国家级

重大活动网络安保支撑单位


END

长按识别二维码关注我们

浏览 94
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报