CobaltStrike 4.3 破解及Sleeve相关问题
0x00 前言
此篇文章为了记录在破解CobaltStrike 4.3 中遇到的一些问题及最终解决方式。
破解目标
- 自行签发auth 文件
- 对资源解密,方便二次发开
- 使用官方原版自行破解,更放心
关于Cobalt Strike 4.3 的破解我个人认为可以分为两步,一是Authorization,二是SleevedResource
其中这里坑比较大的是sleeve
0x01 反编译
这里我使用jd-gui Save All Sources 导出反编译后的源码
新建Idea项目-导入原版cobaltstrike.jar和反编译的源码。结构如下
lib中使用原版
Reserve_Cobalt_src中存放反编译源码
破解第三步:
修改文件→项目结构如下
修改运行配置
破解第四步
从反编译源码中获取如下java源文件放入src目录,目录对应好
(上面的直接抄 maka8ka老哥的作业 ,懒得截图了)
就此,环境算是搭建好了,我们现在来修改几个认证的地方和暗桩
0x02 破解认证
- 修改 src/common/AuthCrypto.java 中对公钥md5的验证
这里我把"!"删掉了,跳出如果公钥md5不匹配,退出的问题(后期生成自己的RSA不用在算公钥的md5了)
- 修改src/common/Authorization.java 验证
watchmark 改为1 vaild 改为true
3.修改 src/beacon/BeaconData.java 修复自动退出beacon的问题
到这里 Authorization 基本已经搞完了,我们来生成自己的RSA并替换公钥
0x03 生成RSA及Sleeve解密
如果这里我们用maka8ka老哥提供的脚本,欸,你就会发现,CS gui 可以正常运行,Teamserver 可以正常运行,但是一连接,欸,就不行了。
根据TeamServer 报错[Sleeve] Bad HMAC on 208928 byte message from resource 这里查了一下,就是在解密SleevedResource的时候,密钥错误,导致dll文件无法正常解密,所以报错了,解密Sleeve的Key 存在于CobaltStrike.auth 文件中,具体的文件组成可以参考rcoil.me 大佬的文章
将 .auth 文件读取成 byte[],处理之后得出 26 位的 byte[],将其拆分为:
4位 -> 经过有符号转换 int,结果为29999999 -> 用于判断是否永久有效(是否为发行版)
4位 -> 经过有符号转换 int,结果不为 0 即可 -> 水印
1位 -> 该 byte 值必须是大于 40 且小于 128 -> 判断认证是否适合 4.x
1位 -> 该 byte 值必须是 16 -> key 的长度
16位 -> 该 key 理论上无法逆推
要注意的是:处理 .auth 文件的时候,还需要判断文件头...,因此还需要填充文件头,但按照分析下来,是 4 个字节,但在实测过程中,发现是 6 个字节
因此 .auth 文件的必要数据是 32 位 -> 6 + 4 + 4 + 1 + 1 + 16
所以说,我们如果要解密dll的话,需要一个正版auth文件,并解密出Sleeve 解密的byte data
这里,我在Authorization 第77行 SleevedResource.Setup(arrayOfByte6); 下一个断点,开启IDEA debug
这里的话,就解析到一个bytes[] 来解密dll,下面我给大家提供一个按照大佬脚本修改好后的,CobaltStrike 4.3 RSA Key 生成的脚本
package KeyGen;
import common.CommonUtils;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.security.*;
import java.util.Base64;
public class RSAKeyPairGenerator {
private PrivateKey privateKey;
private PublicKey publicKey;
public RSAKeyPairGenerator() throws NoSuchAlgorithmException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair pair = keyGen.generateKeyPair();
this.privateKey = pair.getPrivate();
this.publicKey = pair.getPublic();
}
// 将byte 写入文件
public void byte2File(String path, byte[] data) throws IOException {
File f = new File(path);
f.getParentFile().mkdirs();
FileOutputStream fos = new FileOutputStream(f);
fos.write(data);
fos.flush();
fos.close();
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public PublicKey getPublicKey() {
return publicKey;
}
// 加密数据
public byte[] encryptPri(byte[] data, PrivateKey privateKey) throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, this.privateKey);
return cipher.doFinal(data);
}
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, IllegalBlockSizeException, InvalidKeyException, NoSuchPaddingException, BadPaddingException {
RSAKeyPairGenerator PairGenerator = new RSAKeyPairGenerator();
//byte[] data = {-54, -2, -64, -45, 0, 77, 1, -55, -61, 127, 0, 0, 0, 1, 43, 16, 58, 68, 37, 73, 15, 56, -102, -18, -61, 18, -67, -41, 88, -83, 43, -103 };
byte[] data ={-54, -2, -64, -45, 0, 77, 1, -55, -61, 127, 0, 0, 0, 1, 43, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 16, 58, 68, 37, 73, 15, 56, -102, -18, -61, 18, -67, -41, 88, -83, 43, -103};
byte[] rsaByte = PairGenerator.encryptPri(data, PairGenerator.getPrivateKey());
PairGenerator.byte2File("RSA/cobaltstrike.auth", rsaByte);
PairGenerator.byte2File("RSA/authkey.private", PairGenerator.getPrivateKey().getEncoded());
PairGenerator.byte2File("RSA/authkey.pub", PairGenerator.getPublicKey().getEncoded());
}
}
其中,byte类型的 data 比较重要,这关系到后续CS能否正常运行,以上想法可能存在错误,欢迎各位师傅指正
都1202年了还用CS?
@Helen 八嘎
这个生成代码怎么编译 编译报错那
CobaltStrike 4.3 RSA Key 生成的脚本
@粉丝 如果报的是程序包common不存在 ,把最开始那个引用注释掉就好