反编译
首先,我们需要一个确认无改动的官方原包
官方HEX
https://verify.cobaltstrike.com/
# Cobalt Strike 4.3 (March 17, 2021) [bug fixes]
c3c243e6218f7fbaaefb916943f500722644ec396cf91f31a30c777c2d559465 Cobalt Strike 4.3 Licensed (cobaltstrike.jar)
certutil -hashfile cobaltstrike.jar SHA256
SHA256 的 cobaltstrike.jar 哈希:
c3c243e6218f7fbaaefb916943f500722644ec396cf91f31a30c777c2d559465
目前成熟的反编译方案,借助idea自带的反编译工具完成:
在idea安装目录中找到反编译工具java-decompiler.jar
IDEAPATH\plugins\java-decompiler\lib\java-decompiler.jar
新建Decompile用来存放反编译后的jar包,并进行反编译,时间略久
java -cp java-decompiler.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -dgs=true cobaltstrike.jar Decompile/
将反编译后生成的cobaltstrike.jar文件解压即可,不再是class文件,而是java文件
查看Decompile\cobaltstrike\META-INF\MANIFEST.MF
其主类如下:
Main-Class: aggressor.Aggressor
#aggressor.Aggressor
package aggressor;
import aggressor.dialogs.ConnectDialog;
import aggressor.ui.UseSynthetica;
import common.Authorization;
import common.License;
import common.Requirements;
import sleep.parser.ParserConfig;
public class Aggressor {
public static final String VERSION = "4.3 (20210317) " + (License.isTrial() ? "Trial" : "Licensed");
public static final String VERSION_SHORT = "4.3";
public static MultiFrame frame = null;
public static MultiFrame getFrame() {
return frame;
}
public static void main(String[] var0) {
ParserConfig.installEscapeConstant('c', "\u0003");
ParserConfig.installEscapeConstant('U', "\u001f");
ParserConfig.installEscapeConstant('o', "\u000f");
(new UseSynthetica()).setup();
Requirements.checkGUI();
License.checkLicenseGUI(new Authorization());
frame = new MultiFrame();
(new ConnectDialog(frame)).show();
}
}
新建Java项目,此处为MyCS,并在src下配置package aggressor
将Decompile\cobaltstrike\aggressor\Aggressor.java 放入软件包并添加原始cobaltstrike.jar作为依赖
为后门二次编译顺便在这里创建工件,指定主类:
启动报错,我们按照命令行启动加入相关参数
有个小坑坑,新版idea默认隐藏,手动勾上,并输入 -XX:+AggressiveHeap -XX:+UseParallelGC
至此,反编译完成,进入认证破解。
顺便一提再编译,这里我们仅拉取了主类进行测试,实际魔改中根据需求拉取,建议使用到什么文件拉什么文件,不然所有代码中有因Java版本及语法兼容问题导致构建不通过。
因为上面已经进行了工件配置和主类的指定,直接构建工件即可重新打包生成自己的cobaltstrike.jar
MyCS\out\artifacts\MyCS_jar\MyCS.jar
https://mp.weixin.qq.com/s/cRlHoilJa8HPX9L2ZNE77A CobaltStrike二次开发环境初探
破解
生成并替换authkey.pub文件
关键点在于key值,这里抄下师傅们的作业,生成脚本可在文中获得
https://f4x.me/archives/50.html CobaltStrike 4.3 破解及Sleeve相关问题
https://bbs.ichunqiu.com/thread-61581-1-1.html Cobalt Strike破解思路
demo:4.0 data
byte[] decrypt = {
-54, -2, -64, -45, 0, 0, //文件头
1, -55, -61, 127, //时间
0, 0, 0, 1, //水印
50, //版本
16, //key长度
27, -27, -66, 82, -58, 37, 92, 51, 85, -114, -118, 28, -74, 103, -53, 6 //key
};
4.1的key为:
byte[] key41 = {-128, -29, 42, 116, 32, 96, -72, -124, 65, -101, -96, -63, 113, -55, -86, 118 };
4.2的key为:
byte[] key42 = {-78, 13, 72, 122, -35, -44, 113, 52, 24, -14, -43, -93, -82, 2, -89, -96};
4.3的key为:
byte[] key43 = {58, 68, 37, 73, 15, 56, -102, -18, -61, 18, -67, -41, 88, -83, 43, -103};
================================================================================================
将 .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
修改源码中authkay.pub的md5值
certutil -hashfile authkey.pub MD5
MD5 的 authkey.pub 哈希:
1d311afeca0476a7eda972611fb27bcc
# common.AuthCrypto line28
if (!"1d311afeca0476a7eda972611fb27bcc".equals(CommonUtils.toHex(var2))) {
CommonUtils.print_error("Invalid authorization file");
System.exit(0);
}
修改过期时间
common.Authorization line9
// protected boolean valid = false;
protected boolean valid = true;
修复becon/BeaconData.class中暗桩
beacon.BeaconData line49
public void shouldPad(boolean var1) {
// this.shouldPad = var1;
this.shouldPad = false;
this.when = System.currentTimeMillis() + 1800000L;
}
坑点一
[-] [Sleeve] Bad HMAC on 209952 byte message from resource
这个问题参考上面给到的f4x师傅的文章对key进行处理。
坑点二
在idea中替换原来的authkey.pub后,需要重建项目,否则你会发现公钥校验部分"resources/authkey.pub"没有使用你替换的,而且使用了原始jar包中的公钥
如果你明明替换了,却一直提示Invalid authorization file,那就是这样了~
byte[] var1 = CommonUtils.readAll(CommonUtils.class.getClassLoader().getResourceAsStream("resources/authkey.pub"));
byte[] var2 = CommonUtils.MD5(var1);
System.out.println(CommonUtils.toHex(var2));
至此,CS完成破解。