
cobaltstrike4.5版本破/解、去除checksum8特征、bypass BeaconEye、修复错误路径泄漏stage、增加totp双因子验证、修复CVE-2022-39197等
Crack cobaltstrike4.5, remove checksum8 feature, bypass BeaconEye, fix stage leakage via wrong path, add TOTP two-factor authentication, add encrypted username display, fix foreign spawn bug in 4.5, rename client configuration file, etc.
cobalt strike4.5 crack
cobaltstrike4.5 crack
[TOC]
This tool and article content are for security research only. Users assume all legal and related responsibilities arising from the use of this tool and article content! The author assumes no legal responsibility! If you engage in any illegal activities while using this tool or article content, you shall bear the corresponding consequences yourself. We will not assume any legal or joint liability. Otherwise, please do not install or use this tool. Your use of this tool or any other express or implied acceptance of this agreement shall be deemed as your having read and agreed to be bound by this agreement. When using this tool for security research, you should ensure that the behavior complies with laws and regulations and that sufficient authorization has been obtained. Do not use it against unauthorized targets.
Yes, I'm back, continuing the original cobaltstrike4.4_cdf: https://github.com/lovechoudoufu/about_cobaltstrike4.4_cdf This time it's version 4.5. The previous 4.4 was deleted by GitHub, and it's estimated that this project will also be deleted soon.
It is recommended to join the Telegram group. Subsequent updates and deleted projects can be downloaded from the group:

Before use, please carefully verify the corresponding version's jar file hash.
Certificate authentication process (using 4.3 as an example): slightly modified in version 4.5.
Official decryption keys for each version:
4.0 1be5be52c6255c33558e8a1cb667cb06
4.1 80e32a742060b884419ba0c171c9aa76
4.2 b20d487addd4713418f2d5a3ae02a7a0
4.3 3a4425490f389aeec312bdd758ad2b99
4.4 5e98194a01c6b48fa582a6a9fcbb92d6
cobaltstrike.auth authentication key file, RSA encrypted. Decrypted content:
4.3
-54, -2, -64, -45, // file header
0, 77, // subsequent length
1, -55, -61, 127, // certificate time limit 29999999 (perpetual)
0, 0, 0, 1, // watermark
43, // version
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
With each version update, the corresponding length increases by 17, and the key increases by 17 bytes.
In aggressor/Aggressor.class, License.checkLicenseGUI(new Authorization()); starts the license authentication:

License.checkLicenseGUI uses isValid, isPerpetual, isExpired, isAlmostExpired to determine if the license is valid or expired:

The Authorization class handles the cobaltstrike.auth file, reads the file content, and calls AuthCrypto().decrypt to process it:

In the AuthCrypto() constructor, load() is called, which performs an MD5 check on resources/authkey.pub and then retrieves the RSA public key:

In decrypt(), _decrypt is called to RSA-decrypt the content of the cobaltstrike.auth file using the public key, assigns the result to array var2, then converts it using DataParser to var3. readInt() retrieves the first four bytes of var3 for file header verification (-889274181 for 3.x; -889274157 for 4.x). Then readShort() gets two bytes as the length, assigned to var5, and var6 = var3.readBytes(var5) retrieves that length of content and returns it:

In the Authorization class, the obtained arrayOfByte2 is the content after removing the first six bytes. It continues processing arrayOfByte2: first retrieves four bytes assigned to i, then four bytes assigned to watermark, then one byte assigned to b1. It checks if b1 < 43, if i == 29999999. In common/ListenerConfig, when watermark is 0, an antivirus detection watermark is added:


After removing the first six bytes, then removing the nine bytes for i, watermark, b1, the remaining content is the keys from 4.0 to 4.3, structured as: 16, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20:
byte b2 = dataParser.readByte(); // get 1 byte, i.e., 16
byte[] arrayOfByte3 = dataParser.readBytes(b2); // get 16 bytes, which is the key for 4.0
byte b3 = dataParser.readByte(); // get 1 byte, i.e., 16
byte[] arrayOfByte4 = dataParser.readBytes(b3); // get 16 bytes, which is the key for 4.1
byte b4 = dataParser.readByte(); // get 1 byte, i.e., 16
byte[] arrayOfByte5 = dataParser.readBytes(b4); // get 16 bytes, which is the key for 4.2
byte b5 = dataParser.readByte(); // get 1 byte, i.e., 16
byte[] arrayOfByte6 = dataParser.readBytes(b5); // get 16 bytes, which is the key for 4.3, assigned to arrayOfByte6
In the Authorization class, SleevedResource.Setup is called to process arrayOfByte6. In SleevedResource, the key is set as the decryption key for AES and HmacSHA256. In _readResource, this.data.decrypt(arrayOfByte1); is called for decryption, and the decrypted content is the dll files in /sleeve/:

In SleeveSecurity, the key for AES and HmacSHA256 decryption is set. It uses the passed value to compute a 256-bit digest, then takes bytes 0-16 as the AES key and bytes 16-32 as the HmacSHA256 key:

If the corresponding key is not obtained, the dll in the sleeve folder cannot be decrypted, and when connecting to the server, the error message "[Sleeve] Bad HMAC" will appear:

For the HMAC decryption part, refer to: Cobaltstrike 4 crack: I issue a license to myself
Therefore, the key to a successful crack is the corresponding CS version key.
According to the official description, version 4.5 adds license security, which is indeed the case:

So we need to decrypt the leaked auth file to see what's added:

Behind the key position in 4.5, there is an extra string. This extra part is the newly added watermarkHash for this version:

The watermarkHash is related to beacon generation and the dll in the sleeve folder. Without it or if it's incorrect, the beacon cannot go online. It is speculated that the official can trace back to the source of the leak through this watermarkHash.

Comment out other code and hardcode the parameters assigned after RSA decryption in AuthCrypto().decrypt:

byte[] var4 = {1, -55, -61, 127, 0, 1, -122, -96, 45, 16, 27, -27, -66, 82, -58, 37, 92, 51, 85, -114, -118, 28, -74, 103, -53, 6, 16, -128, -29, 42, 116, 32, 96, -72, -124, 65, -101, -96, -63, 113, -55, -86, 118, 16, -78, 13, 72, 122, -35, -44, 113, 52, 24, -14, -43, -93, -82, 2, -89, -96, 16, 58, 68, 37, 73, 15, 56, -102, -18, -61, 18, -67, -41, 88, -83, 43, -103, 16, 94, -104, 25, 74, 1, -58, -76, -113, -91, -126, -90, -87, -4, -69, -110, -42, 16, -13, -114, -77, -47, -93, 53, -78, 82, -75, -117, -62, -84, -34, -127, -75, 66, 0, 0, 0, 24, 66, 101, 117, 100, 116, 75, 103, 113, 110, 108, 109, 48, 82, 117, 118, 102, 43, 86, 89, 120, 117, 119, 61, 61};
Javaagent principle: https://www.cnblogs.com/rickiyang/p/11368932.html
Crack tool reference: https://github.com/Twi1ight/CSAgent
The core of the crack still requires the key for the corresponding CS version.
Set the shouldPad method's return value to false in beacon/BeaconData:

New backdoor in 4.4
(Previously analyzed license authentication with 4.3; after switching to 4.4, it was found that the program exits during runtime, indicating a new backdoor.)
Compared to this.shouldPad's exit, a .class check was added in common/Helper. Just comment it out:

A .class check added in common/Starter. Comment it out:

A .class check added in common/Starter2. Comment it out:

A .class check added in beacon/CommandBuilder: (This backdoor is really sneaky — after the client and teamserver continuously connect for 4 hours, commands cannot be executed. I've never connected that long, so I didn't notice it. ggg)

New backdoor in 4.5
Version 4.5 adds a bunch of backdoors targeting javaagent. If you decompile the jar for cracking, you can ignore them; just search for "javaagent" and modify each occurrence:

After removing these, group activities can resume.
The checksum8 feature is not described in detail. It is necessary to modify it to avoid being scanned by nmap and space search engines.
Change the XOR value in BeaconPayload to a new one:
Any decimal number will do; later, change the corresponding hexadecimal value in the dll.

Use CrackSleeve to decrypt the dll: https://github.com/ca3tie1/CrackSleeve/
javac -encoding UTF-8 -classpath cobaltstrike.jar CrackSleeve.java)java -classpath cobaltstrike.jar;./ CrackSleeve decode) # Execute in Windows command lineAlt+T to search for the keyword: 2Eh


Directly modify the xor value. First, Change byte to find 2Eh and modify it, then Apply patches to input file to save. (Don't forget to save)

DLLs that need modification: beacon.dll, beacon.x64.dll, dnsb.dll, dnsb.x64.dll, pivot.dll, pivot.x64.dll, extc2.dll, extc2.x64.dll (4.5 added several rl100k.dll, which also need modification)
Then use CrackSleeve to encrypt the dll. Finally, place the dll from the encode directory into the IDEA project directory and recompile and package.
After testing, although the URI address can still be requested, the content can no longer be decrypted by nmap scripts, thus avoiding recognition by space search engines:

In addition to modifying the XOR value, you can also change the checksum8 algorithm by referring to https://mp.weixin.qq.com/s?__biz=MzA3MDY2NjMxMA==&mid=2247484641&idx=1&sn=014f6c4ad5343e3f5034c33dffa66f26&chksm=9f3815c8a84f9cde1c7493ff29cfc89c0474fec48ede52be618727e7b9a5ab321c4743e1a44c&mpshare=1&scene=23&srcid=1202NA46yt71CvD3BMGKS10c&sharer_sharetime=1606892728447&sharer_shareid=ff83fe2fe7db7fcd8a1fcbc183d841c4#rd However, this method can only use a fixed URI for access and requires a profile to work. Each time the URI is changed, repackaging is needed. Each method has its pros and cons.
The modification idea to remove BeaconEye features comes from link. Using 4.3 and 4.4 as examples, the bytes that need modification are as follows.
Use CrackSleeve to decrypt the dll: https://github.com/ca3tie1/CrackSleeve/
javac -encoding UTF-8 -classpath cobaltstrike.jar CrackSleeve.java)java -classpath cobaltstrike.jar;./ CrackSleeve decode) # Execute in Windows command line4.3 key: 58, 68, 37, 73, 15, 56, -102, -18, -61, 18, -67, -41, 88, -83, 43, -103 4.4 key: 94, -104, 25, 74, 1, -58, -76, -113, -91, -126, -90, -87, -4, -69, -110, -42
Address: 10009FBB
Change 6A 00 to 6A 09 (change 00 to any value)

Address: 000000001800186C3
In beacon.x64.dll, the instruction is xor edx, edx. Change to mov edx, esi

Address: 1000A0B9
Change 6A 00 to 6A 09 (change 00 to any value)

Address: 000000018001879B
In beacon.x64.dll, the instruction is xor edx, edx. Change to mov edx, esi

Re-encrypt using: java -classpath cobaltstrike.jar;./ CrackSleeve encode


Address: 1000A65D

Address: 000000018000CA3F

(4.5 added several rl100k.dll, which also need modification)

The method is to add a / check on the URI. If it doesn't start with /, respond with 404:
Modification for 4.4

Modification for 4.3

To prevent leaking the TOTP password or the login name in the Event Log, the name field is displayed with MD5 salted. After modification:

Added TOTP two-factor authentication to enhance login security and prevent brute force cracking of passwords.
On the teamserver side, a TOTP QR code link is added to the teamserver output:

(Delete nohup.out after copying the QR code. Each time teamserver is started, a new QR code is generated, so you need to scan it again each restart.)
Open the link in a browser (requires VPN) and scan the QR code with Google Authenticator or a TOTP verification app. Alternatively, copy the secret after secret%3D and configure it in the app:

On the connect side, host, port, and password remain the same. In the user field, the last six digits are the TOTP dynamic number for connection:

If the TOTP dynamic number is missing or incorrect, a prompt appears:

Note: Sometimes you may not have your phone. You can use a browser TOTP plugin or write a simple TOTP script in Python.
When using windows/foreign/reverse_http(s) for spawn, the following error occurs:

In this version, related Custom getScalar operations were added in ScListener, but the foreign case was not considered, causing an error when var1.customDLL and customFileName are empty:

The temporary fix is to check if the payload is foreign and directly return the shellcode. If there are other bugs, please submit issues:

After the fix, it works normally:

To prevent MySQL honeypots from reading the configuration, the CS client configuration file name is no longer default and generates an 11-character file name (11 characters from the MD5 of the MAC address).
