简介
CobaltStrike,曾经的渗透工具之王,正在受到新兴工具Sliver的挑战。Sliver是一个用Golang编写的跨平台通用植入框架,旨在替代CobaltStrike。它由BishopFox公司的Joe DeMesy和Ronan Kervella在2019年summercon会议上提出并设计,具有稳定、高性能和安全的通信载荷。作为一个开源且跨平台的工具,它可供安全组织或个人进行测试使用。Sliver推出后受到欢迎,其github仓库在短时间内获得了4k的star数,并已被勒索集团DEV-0237等组织使用。预计不久的将来,这个新兴的后渗透工具将会大放异彩。Sliver自2019年开始到如今已有三年时间,版本更新十分频繁,这也代表该工具正逐步走向成熟阶段。
Sliver自2019年开始到如今已有三年时间,版本更新十分频繁,这也代表该工具正逐步走向成熟阶段;
服务端、客户端以及有效载荷均支持Windows、Linux及Android等三种流行系统和架构,且服务端和客户端通信采用mtls加密通信,防止被检测;
载荷使用mTLS, WireGuard, HTTP(S)以及 DNS等多协议保护对外通信,并使用TCP和SMB等进行内网通信;
Windows下存在进程迁移/注入、文件操作、注册表操作和内存命令执行等多种控制功能;
以下将简述该工具的使用及与CobaltStrike等老牌后渗透工具进行对比,看一看Sliver的优缺点。
2 Sliver介绍及使用
Sliver是作为跨平台植入和协作使用的目的设计而成,根据其官方所述,Sliver的原理控制图如下图所示(笔者略有增加)。
可以发现,Sliver同CobaltStrike一样均采用服务器进行核心控制,转发客户端和被控机的通信消息,稍显不同的是,Sliver的服务器也可直接对被控机进行控制。
2.1 安装协作
Sliver官方提供了不同客户端及服务端的安装文件,包括windows、linux和macos系统,基本覆盖了流行系统,做到了大部分平台适配,下载地址为https://github.com/BishopFox/sliver/releases。如下图所示:
原则上服务端及客户端均可以使用对应的安装包进行安装运行,且安装包安装不需要额外的环境配置,但是由于windows服务器存在功能限制,Sliver官方建议服务端使用linux或macos的服务器进行配置。而CobaltStrike限于使用java打包,服务端与客户端的运行依赖于java环境,而客户端则需要布置在具有图形界面的服务器上。
在实用性上,CobaltStrike依赖于java环境跨平台,Sliver则使用go语言在指定平台进行编译跨平台,Sliver的服务端及客户端兼容性均略高,也省去了安装环境的必要。
笔者这里使用kali虚拟机当作服务器,ip地址为192.168.83.166,运行服务端文件,运行界面如下图:
开启Multiplayer Mode模式,可以存在不同系统下的多客户端共同管理。首先需要在服务端创建相关配置文件,然后客户端使用并开启相关配置,如下图所示:
该配置文件为校验信息,使用ECC非对称加密算法实现登录通信,如下图所示:
然后拷贝该配置文件到客户端,只需要运行对应的客户端文件,并导入配置然后运行即可。这里使用的客户端分别是win10系统(ip:192.168.83.164)以及linux系统下自身(ip:192.168.83.165),如下图所示:
通过服务端生成的配置信息可以看出,服务端与客户端通信验证方式为ECC非对称加密算法。CobaltStrike客户端是向Teamserver(CobaltStrike服务端)发送指定的java通信打包的登陆密码即可登录,存在爆破的可能性,而且由于登录返回信息与正常流量存在差异,对于暴露在外的服务器可以进行全网扫描探测,所以不得不对CobaltStrike进行二次开发以规避风险。而Sliver只有获取相应私钥才能与之服务端进行通信,安全性会得到很大的保障。
2.2 载荷制作
Sliver将生成的载荷称之为Implants,这与CobaltStrike工具中生成的stageless和stager拉取的stage (beacon)功能一致,均属于第二阶段的有效载荷,也是稳定控制被控机的有效载荷。
2.2.1 植入方式
Sliver在植入载荷方式同CobaltStriket以及Meterpreter一样均有两种方式,非阶段式与阶段式植入,由于非阶段式的载荷与阶段式下载的载荷一致,所以主要关注阶段式即可,如下表所示:
Sliver | CobaltStriket | Meterpreter | |
分阶段 | 1.stager(Meterpreter)+ Implant 2.url download(*.woff)+ Implant | stager+ beacon | stager+ stage |
控制载荷 | Implant | beacon(Reflective自加载) | stage(Reflective自加载) |
优点 | 下载的Implant可以使用非对称算法加密,下载后无法进行解密 | 体积小 | 体积小 |
缺点 | 下载路径为任意名称+.woff,后期可能会被作检测,且文件体积较大 | 下载及解密算法已知 | 下载及多重解密算法已知 |
对于需要限制载荷长度的环境下,Sliver使用两种方式进行分阶段注入。可以采用Meterpreter框架生成stager,下图为Sliver生成stager过程。
可以看到生成的stager是Meterpreter框架下未加密的的x64位的stager,将stager在内存中运行即可下载运行Sliver的Implants。
而且Sliver也支持自定义下载方式,即使用指定的url路径进行获取Implant,且支持使用AES加密下载的Implants文件,如下图所示:
可以使用任意名称拼接woff后缀下载Implants载荷,如下图所示:
2.2.2 载荷类型
2.2.2.1 系统分类
在使用CobaltStrike工具时,有一个很大的缺点就是生成的载荷只能上线Windows主机,其他系统类型则需要插件(如CrossC2)辅助,配置上线过程相当麻烦,Sliver在此基础上进行了一定程度的拓展,Meterpreter则是基本支持了所有系统以及脚本和Web类的代码生成功能。以下是Sliver、 CobaltStriket和Meterpreter生成载荷运行系统的类型对比表,可以发现Sliver基本覆盖流行系统,除此之外Sliver还包含shellcode、 service以及可执行文件,不需要像Meterpreter生成的载荷一样进行二次加工,便利性大大提高。
Sliver | CobaltStrike | Meterpreter | |
windows | √ | √ | √ |
linux | √ | × | √ |
macos | √ | × | √ |
Android | × | × | √ |
… |
2.2.2.2 通信分类
在使用CobaltStrike中会根据被控机的特点使用不同的通信方式以达到上线目的,其中根据使用场景分为出网通信以及内网通信两种方式,内网通信需要建立在出网通信成功的基础才能运行,出网通信载荷在内网通信载荷中充当流量转发的桥梁,这里内网通信不做引述。
CobaltStrike | 出网 | HTTP(S) | 通过HTTP(S)协议,并结合cdn转发技术或者御前置技术隐藏真实C2 |
DNS | 使用DNS解析内容传递数据,在只有DNS协议换环境下使用,且较为隐蔽 | ||
内网 | SMB | 目标机器须开启445端口,使用命令管道控制 | |
Bind TCP | 使用TCP协议,可更改端口 |
Sliver的通信方式包含了多种方式进行通信。其中内网通信方式与CobaltStrike相同。而外网通信则新增加的通信方式有MTLS(相互身份验证协议)和WireGuard(VPN协议),这两种通信方式都十分隐蔽,不容易被流量设备发现。
值得注意的是,Sliver开发了一个多协议多ioc控制功能,即可以使用多种通信方式不同的ioc进行控制,避免生成的单一通信或者ioc连接失败。通信协议顺序优先级由高到低依次为MTLS -> WG -> HTTP(S)-> DNS。
多通信如下图:
多ioc随机--连接如下图:
2.2.2.3 模式分类
另外的,Sliver设计的Implants具备两种模式:beacon模式和session模式,区别在于beacon模式属于异步通信方式,即执行累计的任务后,定期连接服务端返回数据,该模式与CobaltStrike的通信方式相同,而session模式则进行持久连接,前者通信更加隐蔽,后者执行命令响应速度更快。当前Implants可由beacon模式切换至session模式,反之的功能官方尚未实现。
2.3 载荷上线
2.3.1 开启监控
与CobaltStrike和Meterpreter相同,Sliver投放载荷前需要对载荷中ioc以及端口进行监控,值得注意的是需要根据对应的协议去开启不同的监控,这点Sliver官方并未详细说明,否则无法上线,如下图所示:
2.3.2 投递载荷
作为后渗透工具,CobaltStrike具有官方默认的载荷投递方式,包括钓鱼攻击、邮件攻击或者利用漏洞模板等直接投递木马。
而Sliver没有相关默认的投递载荷方式,需要使用者自己编写相关代码进行投递,笔者直接复制生成的木马在windows(ip:192.168.83.163)和系统为linux(ip:192.168.83.167)的被控机直接运行。
使用use指令观察被控机上线情况,发现存在上线的session或者beacon。
使用use [uuid]选择对被控机进行控制,下图分别是对windows系统和Linux系统进行相关指令控制。
查看相关控制指令如下图所示,发现按照功能分为window特殊指令和常规指令,但linux的Implant中没有特殊指令。
Sliver载荷基本功能对比如下表所示,与CobaltStrike对比发现目前功能仍相对较少,尤其是一些权限提取及数据获取方面稍显不足。
但Sliver也做出了一些新的有意思的功能,比如migrate功能。migrate功能为进程迁移,可以将自身转移到同等权限的其他进程下。
相关样本由于是双击打开,所以父进程是explore.exe,准备转移的进程为calc.exe,pid为2136。
执行migrate命令进行转移,可以看到calc.exe产生了流量,但进程树没有发生变化,起到了很好的隐藏效果。
3 Sliver分析及调试
以上简述了关于Sliver的基本使用情况,接下来将通过源码介绍Sliver的核心功能实现方法及防范措施。
3.1 环境准备
3.1.1 调试方法
3.1.1.1 server/client调试
原理:使用delve远程调试sliver-go-v1.18.5源码。
环境准备:ubuntu20.04,vscode,go1.18.5.linux-amd64, sliver-go-v1.18.5(版本一一对应)。
1.首先安装go以及delve工具,配置相应go环境变量,以及安装好Sliver的静态数据(完整成功运行Sliver源码下的go-assets.sh文件)
2.设置.vscode文件下的配置文件,包括task.json、launch.json和setting.json文件。
task.json |
{ "label": "Run Debug Server", "type": "shell", "command": "dlv", "args": [ "debug", "--build-flags=\\"-tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension,server -ldflags="-X github.com/bishopfox/sliver/client/version.Version=0.0.0 -X github.com/bishopfox/sliver/client/version.CompiledAt=Never -X github.com/bishopfox/sliver/client/version.GithubReleasesURL=https://api.github.com/repos/BishopFox/sliver/releases -X github.com/bishopfox/sliver/client/version.GitCommit=debug -X github.com/bishopfox/sliver/client/version.GitDirty=Dirty -X github.com/bishopfox/sliver/client/assets.DefaultArmoryPublicKey=RWSBpxpRWDrD7Fe+VvRE3c2VEDC2NK80rlNCj+BX0gz44Xw07r6KQD9L -X github.com/bishopfox/sliver/client/assets.DefaultArmoryRepoURL=https://api.github.com/repos/sliverarmory/armory/releases"\\"", "--headless", "--listen=:2345", "--api-version=2", "--log", "github.com/bishopfox/sliver/server" ], "presentation": { "echo": true, "reveal": "always", "focus": true, "showReuseMessage": false, "clear": true, "panel": "new", }, "problemMatcher": [ "$go" ] } |
launch.json |
{ "version": "0.2.0", "configurations": [ { "name": "Debug Server", "type": "go", "request": "attach", "mode": "remote", "remotePath": "${workspaceFolder}", "port": 2345, "host": "127.0.0.1", "trace": "log" }, ] } |
setting.json (linux amd64环境) |
{ "go.toolsEnvVars": { "GOOS": "linux", "GOARCH": "amd64" } } |
3.运行指定变量生成编译文件,下为server调试代码,如果需要client调试,需要更改x相关位置为client。
dlv debug --build-flags="-tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension,server -ldflags="-X github.com/bishopfox/sliver/client/version.Version=1.1.2 -X github.com/bishopfox/sliver/client/version.CompiledAt=Never -X github.com/bishopfox/sliver/client/version.GithubReleasesURL=github.com -X github.com/bishopfox/sliver/client/version.GitCommit=aabbcc -X github.com/bishopfox/sliver/client/version.GitDirty=Dirty"" --headless --listen=:2345 --api-version=2 --log github.com/bishopfox/sliver/server dlv debug --build-flags="-tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension,client -ldflags="-X github.com/bishopfox/sliver/client/version.Version=1.1.2 -X github.com/bishopfox/sliver/client/version.CompiledAt=Never -X github.com/bishopfox/sliver/client/version.GithubReleasesURL=github.com -X github.com/bishopfox/sliver/client/version.GitCommit=aabbcc -X github.com/bishopfox/sliver/client/version.GitDirty=Dirty"" --headless --listen=:2345 --api-version=2 --log github.com/bishopfox/sliver/client |
4.在主目录下生成了指定的调试文件:
5.在server/client的main.go文件中的main函数下断点,F5进行调试,以下为调试成功界面:
3.1.1.2 mplant调试
结合对源码的分析,可以看出生成Implant时Sliver会通过输入的配置文件对模板源码进行一定的删减修改,然后会在~/.sliver/slivers生成指定的源码,如下图所示:
其中生成源码对比模板源码如下图所示,因此调试时需要对指定的生成源码进行调试才能成功。
1.类似server/client调试配置好基本环境。
2.设置.vscode文件下的配置文件即launch.json文件。
launch.json |
{ "version": "0.2.0", "configurations": [ { "name": "Debug Implant", "type": "go", "request": "attach", "mode": "remote", "port": 2345, "host": "127.0.0.1", "trace": "log" }, ] } |
3.运行指定变量生成编译文件,下为Implant调试代码,监听源端口需要与launch.json保持一致。
dlv exec --api-version 2 --headless --listen 127.0.0.1:2345 --accept-multiclient ./implant |
4.在Sliver的sliver.go文件中的main函数下断点,F5进行调试,以下为调试成功界面:
3.1.2 目录功能
(1)Client/:主要提供客户端功能,其中server对session的控制也使用client的功能。
ncommand/:client的控制台命令,接收event消息并进行分配。
(2)mplant/:主要包含生成Implant植入的模板源码,然后根据配置输入的不同,修改删减模板源码然后编译生成载荷。
nsliver/:模板源码,根据配置信息删减编译生成Implant源码,然后进行编译混淆等措施。
(3)protobuf/:使用grbc协议在serevr及client间传递消息。
nclientpb/: client消息发送到server。
nsliverpb/: server消息发送到client。
(4)server/:主要进行监控session服务以及多用户服务。
nconfig/: 配置文件解析器。
ngenerate/:生成载荷。
nrpc/:远程过程调用实现,通过使用RPC的API调用客户端相关的二进制文件代码。
3.2 源码解析
3.2.1 client上线
Siver使用gRPC框架来搭建server/clinet控制系统,并使用Token进行校验,gRPC是一个高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。以下分别从server/clinet源码进行解析。
clinet上线功能首先需要server开启multiplayer模式,否则无法连接,服务端监听客户端上线端口默认为31337(可以修改);
server开启Token安全验证,并开启监听,使用event循环接受信息;
client运行上线时首先遍历~./sliver-client/config(Linux)文件下config配置进行选择连接,然后初始化event循环时会发送上线;
处理该event后,server显示登录信息,连接正常后client也进入console模式;
server和client采用event结构体进行通信。外部只有获取相应config配置文件才能通过token验证,否则无法进行登录服务端,如下图所示:
3.2.2 mplant生成
Sliver按照输入的配置或者已有配置进行模板化生成,Sliver分为stager及Implant。小马stager生成使用Meterpreter的模板,如下图所示:
生成Implant则是通过选择的配置去构造不同的编译命令,如下图所示编译生成一个使用mtls协议,C2为192.168.83.167:1111。下图为生成session/beacon的调用方式:
complie函数是构造mplant的核心函数,通过识别config调用相关代码编译生成可执行文件、库文件或者恶意代码,其中可执行文件以及库文件默认使用garble工具(地址:https://github.com/burrowers/garble)进行混淆,恶意代码则默认使用donut工具(地址:https://github.com/TheWover/donut)进行混淆,所以可以根据对这两个工具的特征进行判定。
编译命令实质为编译implant/sliver文件夹所有文件打包生成指定的格式,所以也可直接对Implant/sliver源码进行分析。
3.2.3 协议通信
Sliver的整体通信方式如下官方介绍图。其中Implant通信方式C2 Protocol在上面介绍了共有DNS,HTTP/TLS,MTLS,WireGuard等外网通信方式。Implant的通信过程大致可以分为根据对应配置依次循环建立有效连接,发送上线包数据,接收server/client指令执行对应指令等过程。
3.2.3.1 MTLS通信
0.Implant的基本架构如下图所示;
1.准备工作:初始化加密协议及连接服务器、构建信息发送监控循环及信息接收监控循环如下图所示;
2.发送上线包数据,上线成功后定时发送心跳包数据,如下图所示:
3.接收上线包数据,这里server选择指定uuid的Implant,然后选择获取对应进程的ps指令;
4.客户端收取到信息,然后使用函数表调用相关的函数,如下图所示:
5.获取信息后打包返回server并显示,如下图所示:
3.2.3.2 HTTP/TLS通信
HTTP/TLS协议同mtls通信方式一致,差异在于HTTP为明文通信,HTTPS与mtls一致为加密通信,默认使用的Header数据,如下图所示:
Sliver处在高速发展中,相关检测难度也越来越大,这点可以从通信密钥交换以及证书特征就可见一斑。首先需要了解的是Sliver是根据流量通信中不同的文件名来确定消息类型,当前源码。如下图所示:
根据pathtofile研究者在文章https://blog.tofile.dev/2021/09/04/sliver.html中所述,Sliver历史版本通信文件类型。如下图所示:
根据该源码并追本溯源,可以通过.txt通信方式进行获取服务器加密的证书从而进行验证,如下图所示:
而当前版本的Sliver不仅是文件类型及参数分割方式进行了更改,此外更增加了密钥校验功能,确保无法进行相关公钥的获取,如下图所示:
此外历史版本下Sliver的证书特征如下图所示,通过伪造PHP 的 Apache服务器,访问对应的url可以直接获取到该head特征:
而当前版本不仅增加了伪造的服务器类型,还增加了header隐藏方式,如下图所示:
3.2.3.3 DNS通信
由于本地服务器配置上线失败,遂使用线上服务器进行配置,相关域名及dns配置如下所示,创建域名及ns子域名指向vps服务器,然后DNS域名NS指向创建的ns域名即可。
然后开启dns监控,注意linux需要使用root权限才能开启53端口,否则dns监控会开启失败。
Implant的dns协议连接首先会初始化会话密钥。
初始化会话密钥属于随机生成,然后使用内置的非对称加密函数对密钥的公钥进行加密,经过分解后将加密内容发送到服务器,如下图所示:
会话密钥使用的加密公钥为随机产生存放在进程中,如下图所示:
通过ECC加密后,形成数据包,根据长度分割后,使用base58/base32加密结构体。
以63位分割数据并与母体dns域名组合发送到server。
即可以通过访问的指定长度DGA的DNS域名规则进行监控。
3.2.4 内存捕捉
通过分析源码发现Implant中使用的相关配置文件在Implant进程运行中未使用任何加密方式,只使用了相关协议进行加密。如上文中的mtls通信中内存就存在许多的内存痕迹。
如下图所示,可以通过内存特征获取证书,一旦获取到相关证书,便可以构造上线包进行伪造上线。
在内存中也存在相关的C2痕迹,可以通过内存yara进行获取。
上线包内存捕捉如下图所示:
3 总结
作为新兴的后渗透工具,Sliver的缺点比较明显,比如功能不全,使用说明比较模糊以及载荷生成bug问题。但优点在于他基本上弥补了CobaltStrike的诸多缺点,比如易探测,载荷平台覆盖少以及内存特征明显等。
相信在不久的将来,Sliver会和CobaltStrike一样成长为非常流行的后渗透工具。你认为Sliver能撼动CobaltStrike的地位吗?
声明:本文来自微步在线研究响应中心,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。