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先初始化内部函数指针,函数的顺序是不能错的,否则会造成调用错误
解析BOF相关代码与数据,并且分配内存
随后修复重定位信息,并修复内部函数指针与系统函数指针,最后跳转到入口点执行,执行完成后释放内存。
修复重定位
修复函数地址
最后转到入口点执行
最后,WBG简述了Beacon二次开发的一些方向,主要包括进程注入部分定制bypass杀软edr,vnc改造成hvnc,目的是与用户互不干扰,内存混淆优化,BOF分离可以让BOF独立于木马进程运行,目的是防止崩溃,横向优化,命令执行优化这块主要还是bypass杀软edr。当然,开发方向还不仅于此,有更多方向可供以后探讨。
完整项目:Http://github.com/WBGIII/ReBeacon_Src
以上就是WBG在XCon 2022上的完整分享,未来,华云安技术团队将继续聚焦网络攻防前沿技术的创新研究,探索实战攻防技术在实际业务场景中的应用实践,助力数字化时代下网络安全的健康发展。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)