This post is also available in: 日本語 (Japanese)
Executive Summary
Cobalt Strike is commercial threat emulation software that emulates a quiet, long-term embedded actor in a network. This actor, known as Beacon, communicates with an external team server to emulate command and control (C2) traffic. Due to its versatility, Cobalt Strike is commonly used as a legitimate tool by red teams – but is also widely used by threat actors for real-world attacks. Different elements of Cobalt Strike contribute to that versatility, including the encoding algorithm that obfuscates metadata sent to the C2 server.
In a previous blog, “Cobalt Strike Analysis and Tutorial: How Malleable C2 Profiles Make Cobalt Strike Difficult to Detect,” we learned that an attacker or red team can define metadata encoding indicators in Malleable C2 profiles for an HTTP transaction. When Cobalt Strike’s Beacon “phones home,” it sends metadata – information about the compromised system – to the Cobalt Strike TeamServer. The red team or attackers have to define how this metadata is encoded and sent with the HTTP request to finish the C2 traffic communication.
In this blog post, we will go through the encoding algorithm, describe definitions and differences of encoding types used in the Cobalt Strike framework, and cover some malicious attacks seen in the wild. In doing so, we demonstrate how the encoding and decoding algorithm works during the C2 traffic communication, and why this versatility makes Cobalt Strike an effective emulator for which it is difficult to design traditional firewall defenses.
Related Unit 42 Topics | Cobalt Strike, C2, Tutorials |
Metadata Encoding Algorithm
There are five encoding schemes supported by Cobalt Strike. The RSA-encrypted metadata is being encoded to easily transfer the ciphered binary data in network protocol.
Base64 Encoding and Decoding
Base64 Encoding and Decoding is a standard Request for Comments (RFC) algorithm implementation. The author has not made any changes to the Base64 Character set. Here is the list of characters used for encoding and decoding the data.
[ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' ]
Let's understand the use of the Base64 algorithm in Malleable profiles by studying an example.
1. Profile Metadata
Havex.profile uses Base64 encoding to transform metadata information about compromised systems before sending it. Figure 2 shows the metadata is encoded using the Base64 encoding algorithm and the result is placed in the Cookie header.
2. HTTP C2 traffic
Figure 3 shows the HTTP C2 traffic generated from the profiles. The highlighted part is the Base64-encoded metadata about the compromised machine.
3. Base64 Decoding
- Any tool can decode the encrypted metadata. We have used the Python Base64 library to complete the task. Figure 4 shows a sample script to decode the data and print it in hex format.
- Here is the decoded data from the script. This is RSA-encrypted metadata about the compromised system:
“751990bee317e74e4f2aa6f13078ef22dd884e065b738f8373f49dee401a069d5dfd1d3e39e94cc637e21364e1fd71ab3322fb9c7a987fc6aa27dfab981f077e7ddc2f20aba8e9d841250adc4edd4d15082445869278f2bbcf66e145aa74152a22b85c9b6c5f15d69f7d8b3708b33deea7198683d6468bd0424f537617f759b5”
Base64URL Encoding and Decoding
Base64URL is a modified version of the Base64 encoding algorithm. The modified version uses URL and filename-safe characters for encoding and decoding. Here is the character set:
[ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' ]
Compared to the Standard Base64 character set, the modified version has replaced ‘+’ with ‘-’ and ‘/’ with ‘_’. The Pad character ‘=’ is skipped from the encoded data as it is normally percent-encoded in URI.
Let's understand the use of the Base64URL algorithm in Malleable profiles by studying an example.
1. Profile Metadata
Cnnvideo_getonly.profile uses Base64URL encoding to transform the metadata information. (Note that this profile is an example of mimicking legitimate CNN HTTP traffic and has no connection to the organization.) Figure 5 shows the metadata is encoded using the Base64URL encoding algorithm and appends the data to parameter g.
2. HTTP C2 traffic
Figure 6 shows the HTTP C2 traffic generated by the Beacon. The parameter value is the Base64URL-encoded metadata about the victim.
3. Base64URL decoding
A user has a couple of options to decode the data.
- A user can replace the ‘-’ with ‘+’ and ‘_’ with ‘/’ along with adding a pad character ‘=’. The replaced string becomes standard Base64-encoded data. Then any Base64 decoding tool can be used to get the encrypted metadata.
- Use the scripting language to do the job. Figure 7 shows a sample Python script to decode the data. The urlsafe_b64decode instruction only replaces the characters and does not add padding. In the sample, we have added ‘=’ to make the output compatible with Base64 encoding. You can add more padding characters; Python only complains if it sees less padding.
- The output of the script is RSA-encrypted metadata. “60495dff002eddaa0c409aaaae0fda592810993ae0ae319c87d62b65c54d92447daf2c1bc84930c5d90ed3a023227e254d3a2c28763be372bb7444ef5719d5948b99d33ede3775f51c216bba97bc5fd4777e819517e89a737284c784bdc30b1d6b3b7debe2448c1dc28b00e3ac611fd5a8fd070502f3f7f672786f6b5787af51”
NetBIOS Encoding and Decoding
NetBIOS encoding is used to encode NetBIOS service names. The Cobalt Strike tool uses the same algorithm to encode victim metadata when it is being transferred in C2 communication.
In the NetBIOS encoding algorithm, each byte is represented by two bytes of ASCII characters. Each 4-bit (nibble) of the input byte is treated as a separate byte by right adjusting/zero filling the binary number. This number is then added to the value of ASCII character ‘a’. The resulting byte is stored as a separate byte. Here is the character set used for encoding: [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’, ‘o’, ‘p’].
Figure 8 demonstrates the encoding process:
Let's understand the use of the NetBIOS algorithm in Malleable profiles by studying an example.
1. Profile Metadata
Ocsp.profile uses NetBIOS encoding to convert the victim’s metadata. Figure 9 shows the metadata is encoded using the NetBIOS encoding algorithm. The resulting data is appended to the URI.
2. HTTP C2 traffic
Figure 10 shows the HTTP traffic generated by the Beacon using the OCSP profile.
3. NetBIOS decoding
Figure 11 shows a Python implementation to decode the NetBIOS-encoded metadata.
The output of the script is RSA-encrypted metadata about the victim:
“5725245edcb589b305e33e02da1cda208ed083bed8a1ae0b3a87da0f9d6ebe31025ab67c58572acb9757288cc2e78bea414249fa8cb0783485a1b5a3c0863501fc1c89c6ac59b7129c51cacbfa197cc64eea31ec8ac204cbcdbefaecf19762f9efcc56280f3e9b183c37f98f371f5e1c08b645524646d7010af4408f4ebb8a2f”
NetBIOSU Encoding and Decoding
The NetBIOSU algorithm is a slightly modified version of the NetBIOS algorithm discussed above. The slight change is the character set used for encoding the algorithm. In this algorithm, the character set is the uppercase version of the set used in the normal NetBIOS algorithm. Here is the set : [‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘O’, ‘P’].
NetBIOSU uses the same encoding process as in the NetBIOS algorithm. Please refer to Figure 8 for more information.
Let's understand the use of the NetBIOSU algorithm in Malleable profiles by studying an example.
1. Profile Metadata
Asprox.profile uses NetBIOSU encoding to convert the victim’s metadata. Figure 12 shows the metadata is encoded using the NetBIOSU encoding algorithm. The resulting data is appended to the URI.
2. HTTP C2 traffic
Figure 13 shows the HTTP traffic generated by the Beacon using the asprox profile, and the highlighted part is the metadata about the victim.
3. NetBIOSU decoding
Figure 14 shows a Python implementation to decode the NetBIOSU-encoded metadata.
The output of the script is RSA-encrypted metadata about the victim.
“722676e535f86ffc29ba1cafb9856d98d1f697a83b0afc5bb143e2cf2242152a351081fb837192da3e3b2d9021fab75ce32677b6299a24d15e28db883adb36c5fe448d5eb47014f6d2e72eff389f0176efced60380450c87e2015a8c5de6aa90dc8f105683ac5fd96dc33d4d63da62818facda595910cf9aee10f36fe54d4a6a”
Mask Encoding and Decoding
The Mask encoding algorithm can be indicated and combined with other encoding algorithms in the Malleable C2 profile, which can be loaded by the TeamServer and used as C2 communication. The Beacon will generate the random four bytes as Mask xor key, then use the Mask key to xor the 128-byte metadata encrypted and send the Mask key and encoded data to the TeamServer for C2 communication, As an example, we walk through the randomized.profile to explain in more detail below.
1. Figure 15 is a partial profile with metadata encoded by Mask and Base64URL. The partial profile below defines the URI and metadata encoding algorithm as Mask and Base64URL, and the encoded metadata will be appended to the URI.
2. HTTP C2 Traffic
Figure 16 is the C2 traffic based on the Figure 15 profile, so we can reverse the encoding data with the following steps.
- From the traffic captured, we know that the entire URI is: /zChN7QMDhftv10Li9Cu-fm_T_3qDQawT-Z1GzNg1FWfAfSILT-u_rKLvXP-RE0ac-pxJTlGFCUIm4Aw9rGHPCIJVl0zNdCbM_G2VkYXJ5GGGtVh8S0LWMM4YLGZD9okLcFBc402j5zESK71HaR_owJb-AVBfFvAo8q0I2J74rmfGyIROyg
- Remove the prefix /zC. The remaining value is encoded by Base64URL:
hN7QMDhftv10Li9Cu-fm_T_3qDQawT-Z1GzNg1FWfAfSILT-u_rKLvXP-RE0ac-pxJTlGFCUIm4Aw9rGHPCIJVl0zNdCbM_G2VkYXJ5GGGtVh8S0LWMM4YLGZD9okLcFBc402j5zESK71HaR_owJb-AVBfFvAo8q0I2J74rmfGyIROyg
3. Data encoding and decoding
- Base64URL encoding and decoding
The Base64URL-encoded data:
hN7QMDhftv10Li9Cu-fm_T_3qDQawT-Z1GzNg1FWfAfSILT-u_rKLvXP-RE0ac-pxJTlGFCUIm4Aw9rGHPCIJVl0zNdCbM_G2VkYXJ5GGGtVh8S0LWMM4YLGZD9okLcFBc402j5zESK71HaR_owJb-AVBfFvAo8q0I2J74rmfGyIROyg - The Base64URL-decoded data:
84ded030385fb6fd742e2f42bbe7e6fd3ff7a8341ac13f99d46ccd8351567c07d220b4febbfaca2ef5cff9113469cfa9c494e5185094226e00c3dac61cf088255974ccd7426ccfc6d959185c9e46186b5587c4b42d630ce182c6643f6890b70505ce34da3e731122bbd47691fe8c096fe01505f16f028f2ad08d89ef8ae67c6c8844eca0Using the Python Base64 library, as shown by the code in Figure 17, to decode the Base64URL-encoded data, the decoded hex data length is 132 and the first four bytes, 84ded030, are the Mask xor key. The remaining 128 bytes are the metadata encoded by the Mask xor algorithm.Base64URL decoded Python code:
- Mask encoding and decodingThe Mask key is 84ded030The Mask-encoded data is:
385fb6fd742e2f42bbe7e6fd3ff7a8341ac13f99d46ccd8351567c07d220b4febbfaca2ef5cff9113469cfa9c494e5185094226e00c3dac61cf088255974ccd7426ccfc6d959185c9e46186b5587c4b42d630ce182c6643f6890b70505ce34da3e731122bbd47691fe8c096fe01505f16f028f2ad08d89ef8ae67c6c8844eca0The Mask-decoded data is:
bc8166cdf0f0ff723f3936cdbb2978049e1fefa950b21db3d588ac3756fe64ce3f241a1e71112921b0b71f99404a3528d44af25e841d0af6982e5815ddaa1ce7c6b21ff65d87c86c1a98c85bd1591484a9bddcd10618b40fec4e67358110e4eabaadc1123f0aa6a17a52d95f64cbd5c1ebdc5f1a545359df0e38ac5c0c9a3c90Using the Python code in Figure 18 to decode the Mask-encoded data, the decoded hex data length is 128 bytes. The 128 bytes are the encrypted metadata with an RSA algorithm that will be detailed in a forthcoming piece.
Mask-decoded Python code:
Cases in the Wild
The following sections show two different cases of Cobalt Strike payloads found in the wild used by malware. One uses Base64 and the other uses Base64URL encoding. Palo Alto Networks identified them using static and dynamic analysis under the Unit42.CobaltStrike tag in the AutoFocus system.
Base64
SHA256: 6b6413a059a9f12d849c007055685d981ddb0ff308d6e3c2638d197e6d3e8802
Base64URL Encoding
SHA256: f6e75c20ddcbe3bc09e1d803a8268a00bf5f7e66b7dbd221a36ed5ead079e093
Conclusion
Cobalt Strike is a potent post-exploitation adversary emulator. The five encoding algorithms detailed above are elaborate and are designed to evade security detections. A single security appliance is not equipped to prevent a Cobalt Strike attack. Only a combination of security solutions – firewalls, sandboxes, endpoints and software to integrate all these components – can help prevent this kind of attack.
Palo Alto Networks customers are protected from this kind of attack by the following:
- Next-Generation Firewalls (NGFWs) with Threat Prevention signatures 86445 and 86446 identify HTTP C2 requests with the Base64 metadata encoding in default profiles.
- WildFire, an NGFW security subscription, and Cortex XDR identify and block Cobalt Strike Beacon.
- AutoFocus users can track this activity using the CobaltStrike tag
Indicators of Compromise
CS Samples
- 6b6413a059a9f12d849c007055685d981ddb0ff308d6e3c2638d197e6d3e8802
- f6e75c20ddcbe3bc09e1d803a8268a00bf5f7e66b7dbd221a36ed5ead079e093
CS Beacon Samples
- /n9Rd
- SHA256 Hash:
- fc95e7f4c8ec810646c16c8b6075b0b9e2cc686153cdad46e82d6cca099b19e7
- SHA256 Hash:
- /flas
- SHA-256 Hash:
- 11b8beaa53353f5f52607e994849c3086733dfa01cc57fea2dae42eb7a6ee972
- SHA-256 Hash:
CS TeamServer IP addresses
- 80.255.3[.]109
- 143.244.178[.]247
Additional Resources
Cobalt Strike Training
Cobalt Strike Malleable C2 Profile
Cobalt Strike Analysis and Tutorial: How Malleable C2 Profiles Make Cobalt Strike Difficult to Detect