cobalt strike beacon dll 功能分析笔记
前言:cobalt strike beacon dll功能分析笔记,主要学习的方面就是beacon与服务端之间通信的流程
参考文章:https://www.cnblogs.com/zpchcbd/p/15885892.html
参考文章:https://bbs.pediy.com/thread-274702.htm
参考文章:https://github.com/WBGlIl/ReBeacon_Src
前置知识点
ssl.SecureServerSocket:通信之间封装的套接字,并且其中提供了acceptAndAuthenticate认证的功能
aggressor.Aggressor(客户端)
aggressor.AggressorClient:整体的一个客户端界面
aggressor.dialogs:提供了客户端界面的各个子窗口
- aggressor.dialogs.Connect:连接服务端的时候进行使用的,主要用于收发aggressor.authenticate阶段和收发aggressor.metadata阶段
aggressor.windows.BeaconConsole:专门处理用户输入到控制台的指令,将其指令进行封装发送给服务端
common.TeamQueue:任务队列
-
TeamReader专门接收读取服务端请求过来的信息(common.Reply对象)
-
TeamWriter专门发送请求服务端信息(common.Request对象)
server.TeamServer(服务端)
server.ManageUser:客户端发送过来的请求,在服务端专门通过ManageUser对象的process方法中的common.TeamSocket#readObject来进行读取,读取出来的都是Request对象处理
server.ManageUser.BroadcastWriter:通过广播返回客户端的请求的响应数据
server.Beacons:处理各种关于Beacon中的操作
- 其中实现server.ServerHook接口的都是处理对应的操作,实现server.ServerHook接口的有下面这些类,server.Beacons只是其中一个
server.Resources:类似全局一样的对象,包含了连接多少个服务端以及相关的日志对象,提供了请求功能
server.ServerBus:服务端自处理,比如要做什么DUMP出来的凭证需要保存的操作的话,服务端Resources会生成一个ServerRequest,然后ServerBus获取该ServerRequest对象进行处理
Beaon(被控端)
beacon.BeaconC2:处理beacon和服务端之间的通信,比如metadata的解析加密解析,然后将其反馈到服务端
beacon.TaskBeacon:客户端发送任务的时候,都会将在TaskBeacon类中指令封装,最后进行发送到TeamWriter
beacon.BeaconData:提供要执行指令的数据,比如反射dll的时候就需要提供数据给beacon端
beacon.BeaconHTTP:处理beacon发送过来的http-get和http-post的类型的请求
beacon.BeaconCharsets:解析数据的时候进行根据对应的编码来进行解密解析
beacon.BeaconPayload:客户端生成payload的就需要通过该类进行使用,比如x86 x64 什么类型的payload,以及stageless的时候进行patch引导操作的时候都需要用到该类
beacon.Settings:beacon中的配置文件config,比如stageless的时候如何知道自己的服务端的地址以及监听端口和相关的profile都是封装在settings中,然后将其签入到stageless的程序中的
beacon.jobs.NetViewJob:当beacon端进行netview的操作的时候,此时提供NetView的dll,让beacon端进行反射dll注入执行
- 下面实现beacon.Job类在利用的时候都是基于反射dll来进行操作的
beacon dll分析
前面的过程看文章https://www.cnblogs.com/zpchcbd/p/15885892.html,下面直接从MZ头特征中进行dump来进行分析,dump的操作如下所示
dump到本地之后aaaaa.bin来进行保存,然后拉到ida中进行分析,因为是dll,所以入口点则是DllMain函数,如下图所示
这里一个分支结构,分别fdwReason为1和fdwReason为4的情况
知识点:github wbg师傅写的https://github.com/WBGlIl/ReBeacon_Src项目就是通过逆向写了对应的一份beacon.dll的功能实现,到时候可以继续来学习
fdwReason为1的部分主要就是解析相关的配置,其中包含了请求信息以及相关的profile信息(ReBeacon_Src项目中可以看到)
知识点:这里解析的相关配置是哪里来的呢,在客户端生成的时候会将相关的c2 profile配置项和连接服务端的信息都会写入到木马中,到时候木马启动之后就会解析这些配置项
关于stageless生成的过程可以参考:https://www.cnblogs.com/zpchcbd/p/16879313.html
fdwReason为4的情况下执行了sub_1000131B
跟到sub_1000131B中下面这一部分是读取配置信息,另外一部分是创建相关的信息轮询模式(ReBeacon_Src项目中可以看到)
接着开始构建元数据,将系统编码、beaconid、aeskey、计算机名、用户名、自身进程名、重要API地址发送给cs的服务端,这个时候服务端接收到了此时就开始展示beacon
接着下面就是一个死循环,不停的接收相关的服务端发送过来的命令进行执行(ReBeacon_Src项目中可以看到)
跟进去可以看到存在一个有101个分支结构的switch语句(ReBeacon_Src项目中可以看到)
ReBeacon_Src项目(beacon端如何发送给服务端上线信息)
自己觉得大家看上面干看也不好看,何况自己写笔记进行记录,想了下还是直接来看WBG作者逆的ReBeacon_Src项目来进行学习会比较好点
首先beacon会进行初始化beacon_init,会读取相关的配置信息,也就是要请求的服务端的地址以及路径,相关通信使用的rsa公钥,profile的信息等等,全部都存储到CsC2Config变量中
然后后面根据偏移来对CsC2Config中进行读取
接着就会构造metadata,这个generate_encryption_metadata方法的作用就是让客户端中显示对应的beacon条目
这里跟进去具体学习下流程,首先random_bytesarray随机生成16个字节的aes密钥存储到beacon_key数组中
再接着通过init_beacon_aes_key对aes的16个字节进行sha256摘要计算,然后存储到aes_key_hash_ago_16和aes_key_hash_up_16数组中
接着会通过随机种子生成随机的beaconid,判断x86 x64系统
接下来就开始构造metadata数据,这里通过beaconmetadata结构体进行存储,会将相关的aes的密钥以及codepage和相关的beaconid,当前beacon端的计算机信息都存储到beaconmetadata对象中
上面的基础信息都构造完了之后,再读取c2config对象中的公钥来对这些数据进行加密,用于后面http请求发送
这里继续读取c2config中的http-get http-post的字段,因为我这里没有使用自定义profile,所以这里读取的是默认的profile
接着就开始进行call_send_metadata,准备开始发送metadata的数据,初始化beaconhttprequest结构体,然后开始进行填充httpGetUrl字段
char* http_get_client_config = get_str(12);,读取http-get的配置信息,默认的profile的http-get默认为7号
所以在encode_Metadata函数中走的就是7号分支,所以你会看见这里的加密数据和上面的rsa加密完的数据一样,原封不动的复制到beaconhttprequest的字段中
接着还会走一次三号分支,进行base64编码,这里的话应该是profile中会默认进行base64编码一次
我这里特地把resources/default.profile看了下,确实有对应的base64编码,如下图所示
接下来又回到send_Metadata函数中,这里开始进行http请求
当http请求完成了之后,此时beacon的信息就出现在了客户端上面,如下图所示
到了这里大概走了一遍beacon是如何进行上线协议的过程,接下来回到服务端看下是如何接收beacon端的信息进行解析的
服务端(如何解析beacon端的信息)
这里直接来看这个地方即可beacon.BeaconC2#process_beacon_metadata,这个地方就是进行接收beacon端发送过来的metadata
当上面beacon端发送了metadata数据之后
此时服务端就会触发断点,如下图所示
dns.AsymmetricCrypto#decrypt首先进行解密操作,因为前面beacon端发送metadata是通过RSA密钥对中的公钥加密的,所以这边通过私钥来进行解密
这里先读取16个字节,对应的就是aes的密钥,总共16个字节,但是这个并不是传输过来的最前面的十六个字节,前面还有几个字节代表的是当前数据的长度
16-20字节是相关的编码格式
接下来就通过BeaconEntry对象进行对之后的数组数据进行格式化,可以看到读取相关的beaconid pid port arch型号以及相关ip等等信息
接着调用dns.BaseSecurity#registerKey,这个函数就开始对前面的16个字节的aes密钥进行注册了,实际上会发现接收到的16个字节并不是真正的aes密钥,而是将其作为SHA-256信息摘要,得到32个字节,其中前16个字节才是真正作为服务端的aes密钥,然后后16个字节作为HmacSHA256的密钥
最后通过server.Beacons#checkin将相关BeaconEntry信息写入到beaconz数组中
此时就会发现客户端中就已经出现了对应的beacon信息
客户端(如何解析服务端的信息进行展示beacon条目)
上面说到了"最后通过server.Beacons#checkin将相关BeaconEntry信息写入到beaconz数组中",此时客户端就出现了对应的beacon条目
这里的话就继续学习客户端是如何进行接收beacon的条目的过程,这个找了半天都没找到,之后找到再来补上好了。。。。
ReBeacon_Src的一个小bug
当自定义profile的http-get或者post的时候mask属性值comm.cpp的xor_decode会进行操作,如果v8+v9为赋值则导致数组取值错误,这里需要改为v11 = *(char*)(out + v8 + v9) ^ in[v8 & 3];
即可
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY