首页
社区
课程
招聘
[原创]XCon 2022议题分享:Beacon完整逆向工程研究
2022-10-13 10:48 13474

[原创]XCon 2022议题分享:Beacon完整逆向工程研究

2022-10-13 10:48
13474

9月19日,国内信息安全领域知名技术峰会--XCon 2022安全焦点信息安全技术峰会在北京举办。本届大会以“为技·敢破”为主题,围绕网络安全领域前沿技术动向、热点技术话题展开多场高级别主题演讲。华云安安全工程师栗云磊(WBG)受邀以“Beacon完整逆向工程研究”为题在峰会进行了精彩分享。


华云安在攻防对抗方面有着深厚的技术积累,凭借着强大的攻击溯源能力,华云安安全研究院分析了目前市面上最流行的远控工具Cobalt Strike的大量Beacon行为,本次分享是Beacon逆向工程研究成果的集中呈现。


01 Beacon loader流程


WBG首先提到,Beacon的基本加载流程分为两种,分阶段与无阶段,这两种方式基本没有太大区别,只是分阶段比起无阶段多了一遍shellcode远程下载beacon.dll,后面的部分基本没有区别,但是在实际的使用过程中,一般推荐使用无阶段加载,并禁用分阶段以减少特征。



在流程开始,通过Patch Beacon Dll文件头部将反射Dll转为shellcode,反射dll修补后的结构如图所示,MZ,然后是引导部分,引导下面则是剩余的DOS头与PE头,这个引导的目的就是调用反射函数,获取dll的入口点并进入执行。




Reflective Dll Patch


02 Beacon初始化过程


反射函数的实现其实与普通的内存加载并没有太大区别,只是在函数最后会调用一下Dllmain并返回Dllmain函数的地址,但是需要注意这里调用Dllmain其中的第二参数传递的是1表示对Beacon进行初始化。


接下来是Beacon初始化过程,在Dllmain里可以看到,当第二个参数等于1的时候会调用初始化函数,而初始化函数主要就是解密内嵌的Beacon配置将其复制到堆中,因为没有加密并且具有明显的内存特征,所以这里也是很多杀软EDR内存查杀的一个点,在Dllmain首次执行完返回到反射函数后,反射函数在回到引导代码里时正好再次调用Dllmain,并根据前面的反汇编代码可以知道这次传递给Dllmain的第二个参数是4,这次调用就是为了正式启动Beacon。



曾经这里让BeaconEye砍中要害

                     


分配在堆中未加密的配置信息成为了内存特征

                                       

首先Beacon启动函数获取前面解密的配置,如IP、端口、请求头、请求URL等等信息,随后开始调用构造元数据的函数,而元数据包括以下这些信息,如系统编码、beaconid、aeskey、计算机名、用户名、自身进程名、重要API地址等等,在构造完成后就可以把这些数据打包发送给服务端。




Beacon Start   

                           

Beacon在发送数据的时候首先会获取通信规则,然后按照规则组织好通信的数据包(如果想更加灵活,可以动态下发通信规则,随时修改),并通过http发送给服务端,并等待服务端的返回数据。




Beacon请求通信   

                                                           

03 Beacon基本通信流程


接下来,WBG介绍了Beacon的基本通信流程,首先判断一下服务端处理元数据请求代码的长度,然后进行解析,然后判断一下这个Beacon的任务队列里有没有任务,如果有就返回发送给Beacon。接下来,WBG先后分析了元数据的解析与客户端对任务数据的解析。


Server处理请求    

                            

首先是元数据的解析,先进行RSA解密,然后获取加密的aes key,以及其他一些信息,如ID、用户名、系统版本、pid、用户名、进程名等等。


接下来是任务数据的解析,如图,Beacon请求发送完成后查询返回数据大小并读取到内存中,然后根据c2配置的规则进行解码,然后返回解码后的数据大小,完成请求。完成解码后就来到了解密的部分,发送完成后判断一下解码后的数据大小,然后调用解密函数对任务数据进行解密,并判断解密后的数据大小,如果大于零,则进行任务分发。




发送元数据请求完成后,查询返回数据并根据配置进行解码


04 Beacon任务分发


在CS里,一个功能可能会拆成多个功能号的组合,比如这个ps横向方法就是由两个功能号10和56组合而成的,这样的功能号在CS里大约有一百多个。


CS中一个功能的实现可能会拆成几个功能号的组合


介绍完CS的任务打包后,WBG介绍了Beacon如何解析执行,解析函数负责循环调用任务分发函数并传递功能号,数据大小以及数据指针。


Parse_Task负责循环解析然后调用Task_handle分发执行


05 Beacon部分功能分析


CS功能有很多,因为时间关系,在分享的最后,WBG选择性分享了后渗透任务功能实现,子Beacon,以及Beacon BOF功能的实现。


首先是后渗透功能,如键盘记录、截屏等等,首先获取实现相关功能的dll,然后设置功能号,获取c2配置文件中的命名管道设置,之后修补到dll中,随后设置任务类型,添加相关参数,最后打包,等客户端回连返回给客户端。


后渗透任务功能实现


客户端接收后,就像前面所讲的那样进行解析执行,后渗透的功能基本都是依靠反射dll执行的,通过注入功能号进行进程注入,然后再利用命名管道与dll保持通信,并将任务添加到任务链表,同时,Beacon会定时遍历链表读取命名管道里任务输出的数据并发送到服务端,如果用户执行查看任务链表则会遍历输出此链表返回给CS服务端。


CS的大部分后渗透功能都是依靠反射dll实现


接下来是子Beacon的相关实现,在CS中已知有两种类型的子Beacon,分别是tcp和smb,但其实这两者在实现上区别并不大。可以看一下图上连接tcp子Beacon的实现,首先创建一个连接,然后进行子Beacon结构体的初始化,tcp和smb都是使用此结构体,初始化完成后再将子Beacon信息添加到全局结构体数组中。


连接tcp Beacon通过86号,smb Beacon通过68号



CS中与子Beacon有关的两个结构体


最后来看一下BOF功能的实现,BOF功能号100,CS内部的部分功能也是基于此功能实现的如获取system权限查询注册表、远程执行,都是作者写的BOF,然后调用100功能号执行,BOF强大也就强大在这里,因为它可以非常灵活的为木马添加新功能,但是需要注意,因为在进程自身运行,所以如果BOF写的有问题则会造成木马进程崩溃。


CS对于BOF文件或者说编译的obj文件并非是直接发送给Beacon,而是先进行抽取,把其中的代码段、数据段、重定位信息等这些部分抽取出来,然后连同参数一起打包后返回给客户端。


Beacon BOF


Beacon执行100功能号时首先会初始化Beacon内部函数指针,然后解析代码段、数据段,重定位信息、参数,然后分配可执行内存用于执行BOF代码。



Beacon先初始化内部函数指针,函数的顺序是不能错的,否则会造成调用错误


随后修复重定位信息,并修复内部函数指针与系统函数指针,最后跳转到入口点执行,执行完成后释放内存。


修复重定位


修复函数地址


最后转到入口点执行


最后,WBG简述了Beacon二次开发的一些方向,主要包括进程注入部分定制bypass杀软edr,vnc改造成hvnc,目的是与用户互不干扰,内存混淆优化,BOF分离可以让BOF独立于木马进程运行,目的是防止崩溃,横向优化,命令执行优化这块主要还是bypass杀软edr。当然,开发方向还不仅于此,有更多方向可供以后探讨。


完整项目:Http://github.com/WBGIII/ReBeacon_Src


以上就是WBG在XCon 2022上的完整分享,未来,华云安技术团队将继续聚焦网络攻防前沿技术的创新研究,探索实战攻防技术在实际业务场景中的应用实践,助力数字化时代下网络安全的健康发展。



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2022-10-13 10:51 被华云安编辑 ,原因:
收藏
点赞1
打赏
分享
最新回复 (2)
雪    币: 223
活跃值: (2539)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
章鱼C 2023-4-6 23:11
2
0
123
雪    币: 107
活跃值: (1427)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
frozenrain 2023-7-19 15:22
3
0
github把代码删了,各位大佬手上还有这份代码的备份么。
游客
登录 | 注册 方可回帖
返回