最近学习了一下其他师傅的精华文章,对于刚掌握Cobalt Strike基本功能使用的我来说受益匪浅,特别是梳理了一遍整个通信流程,虽然对后续的加解密具体细节还未掌握但也学到了不少,下面就分享下我自己从中获得的一些心得,初来乍到还希望各位师傅多多指点。
首先来了解下cs的beacon类型,用的最多的就是stager和stageless这两种。
- stage (有阶段)
- stageless (无阶段)
所谓的stage(有阶段),指的是Beacon会分段的加载shellcode(具体表现为,通过不断的向Listener发起请求,最终获取一个完整的shellcode并执行),stageless(无阶段),则是在生成时则包含完整的shellcode。最明显的就是两者在生成时的文件大小有明显的差异。
这里稍微了解下即可,如果有兴趣可以反编译源码去跟一下函数看看如何执行的。
然后我们讲一下整个通信过程。
首先引用一下其他师傅的图(经典永不过时):
以HTTP-beacon的Stager马子为例,为什么当前网络公司可以对公网上的一些IP进行CS标签的标记?关键点在于第三步和第四步,对CS进行反编译后,找到了对应的checksum()函数,这个函数是干什么的呢?是用来生成为通信期间特定的URL,简而言之,它会根据受害机器的架构(32位或64位)进行随机生成,生成后的URL的每一位ascii码进行十进制转换后再mod256,得到结果和92及93比较,然后分别对应32位和64位系统。(注意:这里第三步的数据包没有cookie字段很关键,为什么?因为没有Cookie字段自然其他人也就可以扫描获取beacon配置信息),这也是为什么后面打攻防基本都是以stageless为主了,我的理解是stageless对比stager是直接从第六步开始的。
ASCII码对照表:https://tool.oschina.net/commons?type=4
所以网络公司判断这个IP到底是不是C2服务器地址,会根据CS常用的一些URL去进行扫描,然后如果扫到了,就会触发第四步和第五步,C2服务端就会把RSA的公钥及自身的服务器信息都发过来,自然也就获取了信息用来完善威胁情报。
比如我这里用虚拟机上线然后抓包,得到的URL地址是cbQF,这里通过上面的方法计算就是(99+98+81+70)÷256=92,所以是x86的系统,然后来到第5步,C2会把完整的beacon信息发送给客户端,客户端解密beacon文件,获取里面的公钥和相关信息(这里使用https://github.com/minhangxiaohui/CSthing/blob/master/1768_v0_0_8/1768.py)进行beacon文件的解密,我搜了一下应该是使用AES去进行一个解密,解密出来后会看到RSA公钥,客户端一些关联信息和客户端自己伪随机生成的密钥
接着就到了第7步,受害机会用公钥加密自身的一些信息以及伪随机生成一个AES的密钥放置到Cookie字段中(RSA是非对称加密,AES是对称加密)
这个Cookie字段中的内容我们也称为CS的元数据(metadata),这一步的数据包其实也对应心跳包或任务执行的数据包(为什么这么说,后面会讲解)
那么既然知道RSA是非对称加密,我们解密的会就需要用到私钥了,私钥哪里来呢?因为这里是我们自己测试,所以私钥理论上是藏在CS的源码中,需要跟进具体代码,我们把CS文件夹下的2个jar文件都拖到jd-gui里面去,关键点在于 beacon_asymmetric()函数
这里会进行一个基本判断,如果没有beacon_keys文件就会自动创建一个,我这里使用虚拟机测试,因为已经用了很久了,自然也就存在这个文件
import sleep.runtime.Scalar;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.security.KeyPair;
import java.util.Base64;
public class GetKey {
public static void main(String[] args) throws Exception {
ObjectInputStream var2 = new ObjectInputStream(new FileInputStream("E:\\shentouceshi\\GUI_TOOLS\\蓝队辅助分析工具\\Java-Decode-test\\src\\main\\java\\cobaltstrike.beacon_keys"));
Scalar var3 = (Scalar) var2.readObject();
var2.close();
KeyPair keyPair1 = (KeyPair) var3.objectValue();
System.out.println("private key: " + new String(Base64.getEncoder().encode(keyPair1.getPrivate().getEncoded())));
System.out.println("public key: " + new String(Base64.getEncoder().encode(keyPair1.getPublic().getEncoded())));
}
}
使用Ga0WeI师傅提供的代码生成RSA的公钥和私钥,注意这里有Scalar类,是在CS的源码里的,需要反编译后拖出来然后自己再新建一个项目执行,不过多叙述。
执行结果:
拿到公钥和私钥和先不着急,可以先把得到的公钥和前面解密得到的公钥进行一个比对,发现是一样的,这样就可以放心进行后面的解密了(Cookie字段需要先进性一个Base64解码然后转成Hex),推荐:https://config.net.cn/tools/HexToBase64.html
然后通过脚本解密Cookie中的元数据信息:https://github.com/minhangxiaohui/CSthing/blob/master/cs-decrypt-metadata_V0_0_1/cs-decrypt-metadata.py
python cs-decrypt-metadata.py -p 私钥 待解密内容
这里把元数据解出来后我们就可以得到受害者的一些基本信息了,同时还有比较关键的Rawkey、Hmackey和Aeskey
接着讲一下第九步-第十一步的流程,如果C2下发任务指定,则会在心跳包的响应体中添加内容,采用AesKey加密,客户端则会通过POST主动请求C2端,并把执行结果也采用AesKey加密放入请求体中
特征:如果请求命令执行的数据包是第N个数据流,那么命令回传就是N+1个数据流
我们把wireshark抓到的数据包保存,然后使用https://github.com/minhangxiaohui/CSthing/blob/master/cs-parse-http-traffic/cs-parse-http-traffic.py脚本进行解密,需要附带上我们的Rawkey,同时需要安装一下tshark,tshark是Wirshark命令行工具,不然会显示不支持
(貌似还需要Wireshark2.2.0版本以上)
这样就顺利得到了任务指令通信的明文。
然后总结一下各阶段数据包的特征。
第五步:
1、对应uri生成使用的是特定算法(checksum()函数生成)。
2、响应头里面的CL字段,这个CL是一个非常大的值,因为要传stagebeacon文件。
第七步和第九步(为什么要放在一起讲):
1、请求的uri是cs的默认心跳uri
2、Cookies是一个base64编码的内容
3、响应头里面的CL字段为0
4、响应头的CT字段是一个可执行type (application/octet-stream)
上面的单挑每一条可能都是弱特征,但是如果组合在一起就是强特征数据包
这种情况对于第九步,只适用于没有任务的默认心跳包,一旦有任务,响应体就会有内容出现
紧接着就会有下一个流的POST请求过来,也就对应第十一步数据包:
1、post的uri是CS默认回传命令执行结果的uri,和参数id
2、post请求头里面的CT字段为(application/octet-stream)
3、 post请求头里面的UA字段,这个UA在cs的ua库里面
参考文章:
https://forum.butian.net/share/1861
https://5ime.cn/cobaltstrike-decrypt.html
4A评测 - 免责申明
本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。
不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!
程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。
侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)