安全矩阵

 找回密码
 立即注册
搜索
查看: 3871|回复: 0

CobaltStrike4.X之License认证分析

[复制链接]

855

主题

862

帖子

2940

积分

金牌会员

Rank: 6Rank: 6

积分
2940
发表于 2021-11-19 10:18:57 | 显示全部楼层 |阅读模式
原文链接:CobaltStrike4.X之License认证分析

声明
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测及文章作者不为此承担任何责任。
雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
NO.1 前言
本文以cs4.3为例,进行License认证分析。
NO.2 证书认证流程
cobaltstrike.auth认证密钥文件,为rsa加密,解密内容格式类似:
  1. -54, -2, -64, -45,  # 文件头
  2. 0, 77,  # 后续长度
  3. 1, -55, -61, 127,   # 证书时间限制29999999(永久)
  4. 0, 0, 0, 1,   # watermark(水印)
  5. 43,   # 版本限制
  6. 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
  7. 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
  8. 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
  9. 16, 58, 68, 37, 73, 15, 56, -102, -18, -61, 18, -67, -41, 88, -83, 43, -103
复制代码

aggressor/Aggressor.class中License.checkLicenseGUI(new Authorization());开始license认证:

License.checkLicenseGUI中isValid、isPerpetual、isExpired、isAlmostExpired对授权是否有效、授权是否过期进行判断,判断的值来源Authorization类:

Authorization类中是cobaltstrike.auth文件的处理,读取文件内容,调用AuthCrypto().decrypt对内容进行处理:

AuthCrypto()中构造函数中调用load(),load()函数中对resources/authkey.pub进行md5判断,再获取了RSA的公钥:

decrypt()中调用_decrypt对cobaltstrike.auth文件内容用公钥进行RSA解密赋值给数组var2,再用DataParser做转换赋值给var3,readInt()方法获取var3的前四位进行文件头判断(-889274181为3.x版本;-889274157为4.x版本)。再从var3中readShort()获取两位作为长度赋值给var5,再var6 = var3.readBytes(var5)获取该长度内容赋值给var6并返回:

在Authorization类中得到的arrayOfByte2数组是去除前六位之后的内容,继续对arrayOfByte2数组进行处理,先获取四个数字赋值给i,再获取4个数字赋值给watermark,再获取一个数字赋值给b1,判断b1小于43,判断i是否等于29999999,在common/ListenerConfig中判断watermark为0时候会增加杀毒检测水印:


去除前6位后,再去除i、watermark、b1这9位,剩余的为4.0到4.3以来的key,为:16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20结构:
  1. byte b2 = dataParser.readByte();  //获取1位,即16
  2. byte[] arrayOfByte3 = dataParser.readBytes(b2);    //获取16位,为4.0的key
  3. byte b3 = dataParser.readByte();  //获取1位,即16
  4. byte[] arrayOfByte4 = dataParser.readBytes(b3);    //获取16位,为4.1的key
  5. byte b4 = dataParser.readByte();  //获取1位,即16
  6. byte[] arrayOfByte5 = dataParser.readBytes(b4);    //获取16位,为4.2的key
  7. byte b5 = dataParser.readByte();  //获取1位,即16
  8. byte[] arrayOfByte6 = dataParser.readBytes(b5);    //获取16位,为4.3的key赋值给arrayOfByte6
复制代码

在Authorization类中调用SleevedResource.Setup方法对arrayOfByte6进行处理。在SleevedResource中把key设定为AES、HmacSHA256解密的秘钥,在_readResource中的this.data.decrypt(arrayOfByte1);进行解密调用,解密的内容为/sleeve/中的dll文件:

在SleeveSecurity中设定AES、HmacSHA256解密的秘钥,使用传入的值计算一个长度为256的摘要,再取0-16作为AES的密钥,取16-32作为HmacSHA256的密钥

如果得不到对应的key,就无法对sleeve文件夹中的dll进行解密,连接服务端时候会提示[Sleeve] Bad HMAC的错误提示:

hmac解密部分可参考:Cobaltstrike 4破解之 我自己给我自己颁发license
(https://mp.weixin.qq.com/s/Pneu8R0zoG0ONyFXF9VLpg)
所以完成破解的关键是对应cs版本的key。
NO.3 解密方式
方法一:硬编码key
对AuthCrypto().decrypt进行RSA解密后赋值的参数写死:

中间4.0、4.1、4.2的key是没有用到的可以随便写,最后一组写4.3泄露出来的key。
方法二:自己生成证书
生成代码可参考:https://xz.aliyun.com/t/8557# toc-4
  1. import javax.crypto.BadPaddingException;
  2. import javax.crypto.Cipher;
  3. import javax.crypto.IllegalBlockSizeException;
  4. import javax.crypto.NoSuchPaddingException;
  5. import java.io.*;
  6. import java.security.*;

  7. public class RSAKeyPairGenerator {
  8.     private PrivateKey privateKey;
  9.     private PublicKey publicKey;

  10.     public RSAKeyPairGenerator() throws NoSuchAlgorithmException {
  11.         KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
  12.         keyGen.initialize(2048);
  13.         KeyPair pair = keyGen.generateKeyPair();
  14.         this.privateKey = pair.getPrivate();
  15.         this.publicKey = pair.getPublic();
  16.     }

  17.     // 将byte 写入文件
  18.     public void byte2File(String path, byte[] data) throws IOException {
  19.         File f = new File(path);
  20.         f.getParentFile().mkdirs();

  21.         FileOutputStream fos = new FileOutputStream(f);
  22.         fos.write(data);
  23.         fos.flush();
  24.         fos.close();
  25.     }

  26.     public PrivateKey getPrivateKey() {
  27.         return privateKey;
  28.     }

  29.     public PublicKey getPublicKey() {
  30.         return publicKey;
  31.     }

  32.     // 加密数据
  33.     public byte[] encryptPri(byte[] data, PrivateKey privateKey) throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {
  34.         Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
  35.         cipher.init(Cipher.ENCRYPT_MODE, this.privateKey);
  36.         return cipher.doFinal(data);
  37.     }

  38.     public static void main(String[] args) throws NoSuchAlgorithmException, IOException, IllegalBlockSizeException, InvalidKeyException, NoSuchPaddingException, BadPaddingException {
  39.         RSAKeyPairGenerator PairGenerator = new RSAKeyPairGenerator();
  40.         //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 };
  41.         byte[] data ={-54, -2, -64, -45, 0, 77, 1, -55, -61, 127, 0, 0, 0, 1, 43,
  42.                 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
  43.                 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
  44.                 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
  45.                 16, 58, 68, 37, 73, 15, 56, -102, -18, -61, 18, -67, -41, 88, -83, 43, -103};
  46.         byte[] rsaByte = PairGenerator.encryptPri(data, PairGenerator.getPrivateKey());
  47.         PairGenerator.byte2File("RSA/cobaltstrike.auth", rsaByte);
  48.         PairGenerator.byte2File("RSA/authkey.private", PairGenerator.getPrivateKey().getEncoded());
  49.         PairGenerator.byte2File("RSA/authkey.pub", PairGenerator.getPublicKey().getEncoded());
  50.     }
  51. }
复制代码

将生成的authkey.pub放入src/resources/,将生成的cobaltstrike.auth放到打包好的jar包同目录,修改common/AuthCrypto.load()函数中md5数为authkey.pub的值:

Javaagent方式
​​
Javaagent原理:
https://www.cnblogs.com/rickiyang/p/11368932.html
破解工具可参考:
https://github.com/Twi1ight/CSAgent
破解的核心还是需要cs对应版本的key
NO.4 去除暗桩
beacon/BeaconData中将shouldPad方法的值固定为false:




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2025-4-22 23:02 , Processed in 0.016439 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表