首页
社区
课程
招聘
[原创]魔改CobaltStrike:协议全剖析
发表于: 2021-4-25 16:26 22313

[原创]魔改CobaltStrike:协议全剖析

2021-4-25 16:26
22313

这次文章将较详细介绍下Cobalt Strike 4.1的agressor端登录teamserver端的通讯和beacon端与teamserver端通讯,包括元数据、心跳包、执行任务等数据传输。帖子写到一半IDEA授权就掉了,所以就拖到现在才写完,附项目地址:
https://github.com/mai1zhi2/CobaltstrikeSource/

运行Teamserver端,首先会创建SecureServerSocket对象,然后循环调用acceptAndAuthenticate()接受认证信息:

点击connet按钮后:
Aggressor端首先在dialogAction()方法获得相应的登录信息:

然后传入host、port创建安全套接字:

SecureSocket的构造方法中设置了相关的socket属性, 调用createSocket()传入要连接的ip地址和port:

agressor端调用完createSocket()后,teamserver端acceptAndAuthenticate()会接受到信息,其中跟入authenticate(Socket var1, String var2, String var3)方法负责处理接受到的信息:

跟入该方法,当var4没读取到足够的字符就一直阻塞:

Aggressor端构建完SecureSocket对象后,调用其authenticate(string var1)方法,并传入登录的密码,该方法主要通过密码构造相应的数据包,其数据包先传入48879这个数值(标志),然后再传密码的长度,接着传入密码的内容,最后以0x41进行填充:

数据包var3内容:

当var3.flush()调用向server端发送数据,teamserver的authenticate(Socket var1, String var2, String var3)方法就会停止阻塞,接受到相应的数据并对密码进行判断:

若密码相等则发送51966标志数给aggressor端:

然后返回执行PostAuthentication对象实现的clientAuthenticated():


新建线程,等待后续接受aggressor端所发送的信息:

aggressor端接受到后进行判断:

至此teamserver端校验aggressor端密码完毕。

接着Aggressor端再通过SecureSocket对象构造出TeamSocket对象:


传入TeamSocket对象来创建TeamQueue对象,其中TeamReader与TeamWriter均为TeamQueue的内部类,均实现Runnable接口负责与TeamServer通信:


然后调用TeamQueue的call()方法,把消息类型aggressor.authenticate、用户名、密码、版本信息均传入,再把请求通过TeamWriter属性发送给teamserver端:





TeamServer端收到aggressor的aggressor.authenticate类型请求数据包:

跟入process(),先比较数据包的类型,再判断版本号,接着校验密码和是否重复登录,最后向aggressor回复success:

最后新建名为write for nickname的线程向各个客户端回复消息:

Aggressor端收到Success回复:

Aggressor端继续向teamserver端发送:aggressor.metadata类型请求:

TeamServer端收到aggressor.metadata请求后,调用process()方法:

继续跟入process(),该函数主要用hashmap存放相关的数据,最后向aggressor端返回了aggressor.matedata类型和hashmap数据:


aggressor客户端接收teamserver端返回的aggressor.matedata类型和hashmap数据:

跟入processread()函数,函数主要获取消息包中数据类型和数据:

再跟入result(),可见该函数负责处理从teamserver端返回的aggressor.authenticate和aggressor.metadata类型的信息:

传入metadata数据hashmap var2来构造AggressorClient对象,跟入该对象的构造方法:

继续跟入setup()方法,该方法主要是注册各类Bridge对象,储存teamserver端返回的metadata,加载插件框,以及发送aggressor.ready给teamserver告知其准备完。

最后调用该对象的showTime(),至此显示出主界面,后续同步相关数据:

下面图是360空间测绘的,顺手帮他们改了图中的小错误:

至此,我们知道了cs的agressor端登录teamserver端通讯方式,所以可以进行相应简单的修改来规避cs登录爆破:
1、 teamserver端避免使用默认的端口号50050。
2、 如果修改48879这个标识数,需要修改的地方有三个,涉及到修改aggressor端:
SecureSocket的authenticate方法:

AsymmetricCrypto的decrypt()方法:

SecureServerSocket的authenticate方法:

我们先生成不分段的后门beacon.exe,因为不分段的beacon更好调,其通信过程都一样的。
当启动teamserver后,会把cobaltstrike.beacon_keys反序列化为Keyparis对象:

然后把该对象传入AsymmetricCrypto构造函数中,并把publickey和privatekey保存为AsymmetricCrypto对象中相应的属性:

所反序列化出来的公私钥:


公钥会在后门生成时放进去,但不是在上述的函数中,详见之前发的后门生成的帖子。而私钥则是为后续通信做加解密处理准备的。

下面我们继续操作:先直接上x32dbg,createthread()下断,查看线程调转的地方再相应下断,然后执行到反射dll,再等所导出的解析函数解析完dll后,再通过导入表搜相关的通信函数,因为这次文章主要是协议分析,相关中间的相关功能先省略掉,有必要再从栈回溯查看相关的函数调用,然后我们看到相关的通信函数:winnet的HttpOpenRequestA、HttpSendRequestA、InternetCloseHandle、InternetopenA等,还有ws2_32的socket、send、recv、accept等,通过观察ws2_32用的是select网络模型,则先排除掉:

所以从winnet的相关api下断入手,

程序先在InternetOpen()函数断下,传入相关的agent信息:

接着InternetConnect()函数,传入相关的url:192.168.202.1和port:80

httpopenRequestA()函数,get请求,uri为/pixel.gif

httpSendRequest()发送请求,注意cookie的值经过编码:

Wireshark所捕捉到的数据包:

可见cookie对应的数据经过编码或加密的,我们往上翻找到相应的函数sub_1000783E(),跟进该函数,可见函数有16个不同的case,当发送第一个数据包(元数据)时先后走case7和case3,case7只是复制操作:

Case3是自实现的base64:

根据所编码的内容&unk_100398A8 继续找相应的赋值和加密操作sub_1000671C(),在该函数中,收集受害者主机的代码页、时间戳、程序id等信息并生成hash值:

生成hash:

最后调用sub_1000969e()函数,对收集的信息进行rsa加密:

用来加密的RSA公钥:

RSA加密前所收集的数据内容:

被RSA加密后的数据内容:

至此,beacon.exe端第一次发包(元数据)分析完,流程总结为以下:
收集数据->RSA加密->base64编码

下面开始分析Teamserver端接受beacon.exe元数据的请求:

跟入_server(),该函数经过Useragent等判断后,先把url、method等相关参数传入webservice.serve()进行构造相关响应头并返回,其中MalleableHook实现了相关的webservice接口,跟入MalleableHook.serve():

在该方法中调用了GetHandler.serve()并把相应参数传入,继续跟入,该函数中先解析出相应的URI、method等:

我们先跟入BeaconHTTP.this.c2profile.recover()函数,在该函数中先将cookie数据拿出来:

然后再进行base64解码:

解码完成后,会判断解码后数据的长度,接着传入被加密的数据到process_beacon_metadata()进行解析,继续跟入:

跟入decrypt(),首先把反序列化处RSA私钥,然后对原数据解密,接着判断标志数是否为48879,如果不相等则解密失败,然后再判断数据长度,如果大于117则失败:

回到process_beacon_metadata(),解密完后先读取前16字节备用,然后用16-20字节判断windowscharts:

把ip、windowscharts、listen地址、截取后的元数据传入到BeaconEntry()的构造方法进行解析:

跟入该方法,方法中先跳过前20字节,然后获取到id、pid、port、系统位数、受害者ip等信息:



构造完后返回到process_beacon_metadata()函数,再传入元数据中hash值给registerkey()该函数是注册AESkey和HmacSHA256key的,对传入的hash值进行一次sha256,然后前一半作为AESkey,后一半作为hmacSHA256key:

最后构造response数据包返回给beacon.exe:



心跳包和发送元数据包的流程是相一致的,都是先复制加密后的数据再base64编码最后拼接cookie,只是没有再走sub_1000671C()函数获取元数据了,只是走sub_100024F4()发送数据,数据的内容也是与元数据相一致的。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 10
支持
分享
最新回复 (11)
雪    币: 968
活跃值: (6818)
能力值: (RANK:462 )
在线值:
发帖
回帖
粉丝
2
666   牛逼牛逼,感谢鸡哥分享
2021-4-25 16:48
0
雪    币: 2865
活跃值: (8493)
能力值: ( LV13,RANK:390 )
在线值:
发帖
回帖
粉丝
3
顾何 666 牛逼牛逼,感谢鸡哥分享
2021-4-25 16:53
0
雪    币: 1025
活跃值: (239)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
4.1版本的哪里可以下载到
2021-4-25 17:36
0
雪    币: 2865
活跃值: (8493)
能力值: ( LV13,RANK:390 )
在线值:
发帖
回帖
粉丝
5

我在星球有师傅分享出来的老哥需要就m我下

最后于 2021-4-25 20:37 被快乐鸡哥编辑 ,原因:
2021-4-25 20:25
0
雪    币: 4005
活跃值: (2183)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
鸡哥牛逼,感谢分享
2021-4-26 09:55
0
雪    币: 4694
活跃值: (4639)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7

收藏了
2021-4-26 21:50
0
雪    币: 1449
活跃值: (4971)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
大神您好!请教个问题,Cobalt Strike key怎么使用的?找到一个正版key,却不知如何使用?搜索官方文档,说key是需要经过加密,然后保存到cobaltstrike.auth这个文件。请问如何使用这个KEY?
2021-5-3 19:11
0
雪    币: 2865
活跃值: (8493)
能力值: ( LV13,RANK:390 )
在线值:
发帖
回帖
粉丝
9
byhk 大神您好!请教个问题,Cobalt Strike key怎么使用的?找到一个正版key,却不知如何使用?搜索官方文档,说key是需要经过加密,然后保存到cobaltstrike.auth这个文件。请问 ...
惭愧,我没用过正版的,cobaltstrike.auth经过私钥签名的,会读取authkey.pub去验证,里面存有aes密钥等信息,负责来解密相应的资源
2021-5-4 15:09
0
雪    币: 192
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
大神,请问怎么才能debug?咋设置,我源码是idea自带的工具反编译的。

咋设置点绿色的虫,没用。。。
2021-5-5 05:01
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
快乐鸡哥 我在星球有师傅分享出来的老哥需要就m我下
大佬求魔改后的cs4.1,GitHub上面找不到了
2022-6-8 20:40
0
雪    币: 220
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
快乐鸡哥 我在星球有师傅分享出来的老哥需要就m我下
大佬给一份魔改的4.1把,想对照着学一下
2022-12-8 17:44
0
游客
登录 | 注册 方可回帖
返回
//