Pr0ph3t

char nick[7] = "Pr0ph3t";

printf("https://github.com/%s\n",nick);

printf("%s\x40pr0ph3t\x2e\\\bcom\n","admin");

puts("91B6 191A C2C3 285C 201D  801B B5A3 6B56 8528 E140");

[工具]Cobalt Strike4.3 破解日记

Jun 9, 2021 • CyberSecurity,Tools,RedTeam Page view:

最新生活太难了,继续下去会有点自闭,所以趁着4.3出来还没多久,休闲一下换换情绪。

  • 4.3的验证方式其实相较于4.0来说并没有发生多大的变化,只是在其中加入了一些垃圾数据而已。按需更改就好了,趁着这次把之前4.0没有分析明白的cobaltstrike.auth文件和整个验证流程好好理一理。

  • 原版的话网上也挺多的,这里就不放了。
  • checksum

  • 这里使用的不是最快速的方法,把这当成厕所读物就好了
  • 还是回顾了一下零队的《Cobaltstrike 4破解之 我自己给我自己颁发license》链接 / ca3tie1师傅的《CobaltStrike4.0无Hook蛮力Cracked License思路》链接

准备工作

验证过程

  1. common/Authorization.java :12-28读取加密的cobaltstrike.auth文件,实例化common/AuthCrypto后进行解密工作的准备
  2. 读取resources/authkey.pub取出公钥 common/AuthCrypto.javaAuthCrypto.java 并且从构造器我们可以得知他的加密方式是RSA/ECB/PKCS1Padding需要注意的是Padding方式
  3. 然后简单的验证一下公钥的MD5是否对应,提取公钥。
  4. 回到common/Authorization.java :31开始解密,此时我们再去common/AuthCrypto.java : 47观察函数public byte[] decrypt(byte[] var1)此时真正的解密在protected byte[] _decrypt(byte[] var1)保护函数中,而解密的公共函数中还有验证cobaltstrike.auth的文件魔术头,转换方法在零队的文章中已经解释得很清楚了,这里就不再赘述了。 decrypt 计算过程: -889274157
十进制
1100 1010 0011 0101 0011 0110 -54
1111 1110 0000 0001 0000 0010 -2
1100 0000 0011 1111 0100 0000 -64
1101 0011 0010 1100 0010 1101 -45

最后计算出来前四个bytes是

byte[] header = {-54, -2, -64, -45};
  1. 代码中使用的是步进读取的方式操作的文件,所以我们要分清楚每个操作读了多少个字节 (从common/DataParser.java能得知) readInt() 4个字节 readByte() 1个字节 readShort() 2个字节 readBytes(int n) n个字节 这里要注意的是代码line 64-65中还使用readShort()获取了剩下需要读取的数据长度,所以后面我们要删除垃圾操作/数据的时候需要更改此处 最后回到common/Authorization.java,接下来就是真正的校验环节了,我们需要关注的是他的所有读取操作 Authorization.java主要校验代码
    • 一 line: 36 首先把解密后的raw文件使用DataParser封装,方便读取。
    • 二 line: 38 读取过期时间,如果是29999999就是永久,转换方法和文件头一样
    • 三 line: 39 读取水印值,具体是哪来干嘛的我也不太清楚,只知道如果值为0的话会帮你添加EICAR指纹,这里设置一个非0数值即可
    • 四 line: 40 读取版本号进行简单的版本校验,这里设置一个大于等于43的值即可
    • 五 line: 46-51 其实是一个读取垃圾值的操作,简单来说就是读取一个字节作为接下来的读取长度,然后读取垃圾值后扔掉 循环3次,我嫌麻烦就直接删掉了
    • 六 line: 52 读取sleeve keygen key的长度
    • 七 line: 53 根据长度读取sleeve keygen key
    • 八 line: 54-60 时间校验,根据步骤二中读出的值做判断
    • 九 其实到此为止已经完成了校验过程了,后续的sleeve keygen过程就没有再过多研究了,只是大概知道是生成解密各类dll/bin的key seed,有机会二开的时候再看看吧

文件解释

  • common/AuthCrypto.java 公钥相关的操作,比如读取公钥、解密CobaltStrike.auth、校验文件头等
  • common/Authorization.java 主要的校验代码,解密过后的CobaltStrike.auth中数据就在这检查
  • resources/authkey.pub 公钥匙,要求padding为PKCS#1
  • cobaltstrike.auth 经过私钥签名加密的校验信息,文件结构如下:
header length expire time Version 垃圾数据x3 sleeve keygen key
文件魔术头 length of rest data 过期时间 29999999为永久 版本号 垃圾数据x3 最关键的sleeve keygen key
4个字节 2个字节 4个字节 1个字节 (1个字节的长度+对应长度的垃圾数据)x3 1个字节的长度+对应的key长度(这里为1+16个字节)

开始破解:

我们需要修改的东西为

  1. 使用网上已有的破解版获得authkey.pub和CobaltStrike.auth(如果新版本出来没有的话可以去尝试申请试用版获得)
  2. 使用openssl解密CobaltStike.auth,获得sleeve keygen key (这里哭一下当初找的破解版的CobaltStrike.auth作者把文件头校验和长度校验直接删掉了,在理清文件结构的时候踩了不少坑)
  3. 计算正确的header
  4. 计算正确的文件长度
  5. 填充各类校验字节,如时间/水印/版本/垃圾字符
  6. 重新生成公私钥
  7. 把重新写好的CobaltStrike.auth用私钥签名(使用openssl的时候注意参数是-sign 不是-encrypt,这里也踩了一个坑<-其实是密码学没学好,sign有两种形式,一个是直接把文件用私钥加密,一种是计算文件摘要并用私钥加密,这里我们使用第一种)
  8. 计算公钥的MD5并更改,扔进去
  9. 把CobaltStrike.auth扔进去
  10. 重新build jar,开始愉快的使用

命令相关:

生成公私钥(这里要注意的是使用2048bit和PKCS#1)

openssl genrsa -out pk.pem 2048

导出公钥

openssl rsa -in pk.pem -pubout -out pub.pem

签名

openssl rsautl -sign -inkey pk.pem -in cs4.3-plain.auth -out cobaltstrike.auth

检查签名

openssl rsautl -verify -pubin -inkey pub.pem -in cobaltstrike.auth

打完收工,最后提供一份我的cobaltstrike.auth文件内容(删了垃圾数据的)

c= [0xCA,0xFE,0xC0,0xD3,0x00,0x1A,0x01,0xC9,0xC3,0x7F,0x19,0x69,0xA0,0x8D,0x2B,0x10,0x3A,0x44,0x25,0x49,0x0F,0x38,0x9A,0xEE,0xC3,0x12,0xBD,0xD7,0x58,0xAD,0x2B,0x99]
with open('cs4.3-plain.auth','w+') as f:
    for s in c:
        f.write(chr(s))

神清气爽 继续搬砖去了。。。。

参考: 零队 ca3tie1

Did you like the post? Subscribe to the feed.

Thx!