CrossC2 Expanding Cobalt Strike Beacon to Cross-Platform Attacks – JPCERT/CC Eyes

Summarize this content to 600 words
From September to December 2024, JPCERT/CC has confirmed incidents involving CrossC2, the extension tool to create Cobalt Strike Beacon for Linux OS. The attacker employed CrossC2 as well as other tools such as PsExec, Plink, and Cobalt Strike in attempts to penetrate AD. Further investigation revealed that the attacker used custom malware (hereafter referred to as «ReadNimeLoader») as a loader for Cobalt Strike. Information submitted to VirusTotal suggests that this attack campaign may have been observed across multiple countries, not only in Japan.
This article explains CrossC2 and Cobalt Strike, the malware used in the campaign, as well as other tools employed by the attacker. A tool released by JPCERT/CC to support the analysis of CrossC2 is also introduced at the end.

CrossC2

CrossC2 is an unofficial Beacon and builder compatible with Cobalt Strike version 4.1 and above, developed in C language. It is designed to operate on Linux (x86, x64) and macOS (x86, x64, M1) architectures. While the builder is publicly available on GitHub(1), allowing users to create Beacons, the source code for both the builder and the Beacon are not released.

Upon execution, CrossC2 immediately forks itself, and the main processing is carried out in the child process. The C2 information is retrieved from the configuration, while the C2 server host and port number can also be obtained from the environment variables «CCHOST» and «CCPORT». Once executed, CrossC2 is capable of executing various Cobalt Strike commands after establishing communication with the Cobalt Strike TeamServer. However, the range of executable commands is limited compared to the full functionality of standard Cobalt Strike. The Beacon contains the following multiple anti-analysis features:

String encoding using single-byte XOR
Insertion of a large amount of junk code

Figure 1 shows a part of the inserted junk code. A significant amount of such code is embedded in key functions. However, the obfuscation can be easily removed by replacing the following byte sequence with NOP instruction.

8B 85 ?? ?? ?? ?? 2D ?? ?? ?? ?? 89 85 ?? ?? ?? ?? 0F 84 ?? ?? ?? ?? E9 00 00 00 00

Figure 1: A part of obfuscated code in CrossC2

The configuration data is stored at the end of the file. CrossC2 first retrieves its own file path using the readlink function and then fread its own code. It keeps searching for the string «HOOK» to locate the address of the configuration data. The structure of the configuration is as shown below. The encrypted configuration data can be decrypted using AES128-CBC(no padding). CrossC2 uses OpenSSL library functions to perform the decryption.

0x0: «HOOK» search tag
0x4: Size of the configuration data
0x8: Encrypted configuration data

CrossC2 can create Beacon using legitimate TeamServer extensions. By default, the generated Beacon is packed with UPX, but attempting to unpack it with UPX fails due to the configuration information at the end of the file. To unpack the Beacon successfully, the configuration block must first be removed. After unpacking using UPX, the configuration block needs to be reinserted at the end.

Cobalt Strike

Figure 2 illustrates the flow of Cobalt Strike execution. The process is initiated by a legitimate java.exe file, which is executed from a Task Scheduler job registered by the attacker. This java.exe loads jli.dll through DLL sideloading. The DLL file is ReadNimeLoader, which is written in Nim language. ReadNimeLoader reads a data file named readme.txt from the same directory, decrypts it, and executes its content in memory. This file contains OdinLdr(2), an open-source Shellcode-format loader, which decodes the embedded Cobalt Strike Beacon and executes it in memory. All related files, including ReadNimeLoader, were located under «C:\$recycle.bin\» on the affected system. In addition, some ReadNimeLoader samples were found to contain the following PDB path.

D:\BuildServer\bna-4\work-git\phoenix-repository\phoenix\Release\Battle.net Launcher.exe.pdb

Figure 2: Flow of Cobalt Strike execution

ReadNimeLoader

ReadNimeLoader incorporates the following four anti-analysis techniques:

Detect debugging by checking BeingDebugged value in PEB
Detect debugging by checking CONTEXT_DEBUG_REGISTER value
Measure the difference of elapsed time and proceed to debag checking when the value exceeds 0x512
Detect debugging by causing an exception and checking whether an exception handler is obtained

A part of the decryption key required to decode OdinLdr is embedded within the functions for the abovementioned anti-analysis techniques. As a result, unless these functions are executed, the correct decryption key is not generated, and OdinLdr cannot be decrypted. In addition to these anti-analysis mechanisms, a large amount of junk code is also inserted. Figure 3 shows a part of the code.

Figure 3: A part of junk code

Strings used by ReadNimeLoader are encoded, and they are decoded using two distinct XOR-based decoding functions. Figure 4 shows a portion of each code.

Figure 4: Each decoding function

The encoded strings can be decoded using the Python script shown below. In earlier versions of ReadNimeLoader do not contain the decode02 function, indicating that it was added in a later version.

def BYTE1(in_data):
return (in_data >> 8) & 0xff

def BYTE2(in_data):
return (in_data >> 16) & 0xff

def BYTE3(in_data):
return (in_data >> 24) & 0xff

def decode02(enc_bytes, xor_key):
result = ()
for enc_byte in enc_bytes:
enc_byte ^= BYTE3(xor_key) & 0xEE ^ BYTE2(xor_key) & 0xEE ^ (xor_key ^ BYTE1(xor_key)) & 0xEE
result.append(i)
enc_byte += 1
return result

def decode01(enc_bytes, xor_key):
xor_table = ( 0, 8, 0x10, 0x18)
result = ()
for enc_byte in enc_bytes:
for j in range(4):
enc_byte ^= ((xor_key >> xor_table(j)) & 0xEE)
result.append(i)
return result

ReadNimeLoader uses AES256-ECB mode to decrypt the malware payload. The key is created by combining specific strings decoded by the aforementioned decoding functions, which is then converted into hexadecimal format, transformed to uppercase, and zero-padded. This decryption can be performed using the following Python script:

from Crypto.Cipher import AES
import binascii

def ZeroPadding(hexstr, num):
padding_num = num – len(hexstr)
if padding_num < 0:
return hexstr
return hexstr + b»\x00″ * padding_num

def decrypt(readme_data, key_string):
capitalized_key = binascii.hexlify(ascii_to_bytes(key_string)).upper()
key = ZeroPadding(capitalized_key, 32)
Cipher = AES.new(key, AES.MODE_ECB)
return Cipher.decrypt(readme_data)

OdinLdr

After execution, OdinLdr decrypts the internally encoded Cobalt Strike Beacon and runs it in memory. To avoid detection, the Beacon is periodically re-encrypted using a randomly generated XOR key and stored in newly allocated heap memory. It is a distinctive characteristic that there is the string «OdinLdr1337» at the beginning of the heap memory. Additionally, it has been confirmed that there are two types of Shellcode deployed by ReadNimeLoader: some samples execute the Cobalt Strike Beacon through OdinLdr, while others run the Beacon directly.
Appendix B outlines the relations between ReadNimeLoader versions and their corresponding decryption keys, the specific readme.txt files loaded, and the encoded malware payloads. A part of the Cobalt Strike configuration used is included in the appendix.

Tools used by the attacker

Among the tools used by the attacker, multiple ELF versions of SystemBC were identified. For more information on the differences from the Windows version of SystemBC, please refer to the report by ANY.RUN (3). Other confirmed tools include PsExec, commonly used for lateral movement; GetNPUsers (4), often leveraged in AS-REP Roasting attacks; Plink, an SSH client tool; and privilege escalation tools for Windows systems.

Attribution

Despite architectural differences, confirmed identical characteristics suggest that this attacker and the attack campaign have a potential connection to BlackBasta. More specifically, the domain confirmed to be used for the C2 in this campaign matches the one listed in Rapid7’s report on BlackBasta (5). Further similarities include the use of the files named jli.dll and readme.txt. Additionally, SystemBC was leveraged, and when attacking AD, AS-REP was also used.

Tools for analyzing CrossC2

As an analysis tools for CrossC2, a configuration parser is publicly available on JPCERT/CC’s GitHub.

GitHub: JPCERTCC/aa-tools/parse_crossc2beacon_config.py https://github.com/JPCERTCC/aa-tools/blob/master/parse_crossc2beacon_config.py

CrossC2 can generate binaries for macOS, not only for Linux, and this parser is designed to support macOS binaries as well. Figure 5 shows a sample output from running the configuration parser.

Figure 5: Sample output of the configuration parser

In Closing

While there are numerous incidents involving Cobalt Strike, this article focused on the particular case in which CrossC2, a tool that extends Cobalt Strike Beacon functionality to multiple platforms, was used in attacks, compromising Linux servers within an internal network. Many Linux servers do not have EDR or similar systems installed, making them potential entry points for further compromise, and thus more attention is required. We hope the information provided in this article will be useful to you in incident response and malware analysis. For details on confirmed C2 servers and malware hash values, please refer to the Appendix.

Yuma Masubuchi (Translated by Takumi Nakano)

References

(1) CrossC2
https://github.com/gloxec/CrossC2

(2) OdinLdr
https://github.com/emdnaia/OdinLdr

(3) ANY.RUNA new SystemBC RAT is targeting Linux-based platforms
https://x.com/anyrun_app/status/1884207667058463188

(4) GetNPUsers.py
https://github.com/fortra/impacket/blob/master/examples/GetNPUsers.py

(5) Rapid7BlackSuit Continues Social Engineering Attacks in Wake of Black Basta’s Internal Conflict
https://www.rapid7.com/blog/post/2025/06/10/blacksuit-continues-social-engineering-attacks-in-wake-of-black-bastas-internal-conflict/

Appendix A: Example of CrossC2 configuration

C2: 162.33.179(.)247:8443
PUBLICKEY:
—–BEGIN PUBLIC KEY—–
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaW
34Iv7znqVuomjiJn4Yr1ck9YSWylfAoiy20DnR0ab
CoHtdPK3L05CgOjnLGSfM5Vji0IRd8xtCGpU699Jt
FCa/Jg7zmuejilkKTFpMB36+49UQtaYp4KjFuImRC
z72NdzszsLzHDlVWAPmn5CSTfsTIzceomQfmCDY//
IygzQIDAQAB
—–END PUBLIC KEY—–

Appendix B: The relations between ReadNimeLoader and malware payloads

Table 1: The relations between ReadNimeLoader and malware payloads

ReadNimeLoader Hash(SHA256)
Version
Key
readme.txt Hash(SHA256)
Encoded Malware

56b941f6dcb769ae6d6995412559012abab830f05d5d8acf2648f7fa48c20833
New
toupper(to_hex(«mfzuyqroasv»)) + zero padding
6246fb5c8b714707ac49ade53e6fe5017d96442db393b1c0ba964698ae24245d
OdinLdr + CobaltStrike

dfe79b9c57cfb9fc10597b43af1c0a798991b6ceeec2af9b1e0ed46e6a8661c8
New
toupper(to_hex(«vbewtdsmmswfweoz»))
acdf2a87ed03f2c6fe1d9899e8a74e8b56f7b77bb8aed5adf2cc374ee5465168
OdinLdr + CobaltStrike

3f96b6589996e57abc1c4d9b732528d2d11dea5c814f8241170c14ca2cd0281d
New
toupper(to_hex(«lgehaoevolq»)) + zero padding
6b80d602472c76b1d0f05bcce62e0a34de758232d9d570ba61b540784c663c01
CobaltStrike

0ab709728666f8759ad8db574d4009cf74ebce36ef2572ef52b058997a9b2a25
New
toupper(to_hex(«ffjazoinsmsiywwt»))
3079a29575a0adff91f04c5493a7f3e1c89795e3a90cf842650cd8bd45c4e1bc
CobaltStrike

ecca3194613b0bab02059c3544fdc90f6d4af5a4c06518c853517eb1d81b9735
Old
toupper(to_hex(«bcstctskmngpjjax»))
Unknown
Unknown

ad90a4490d82c7bd300fdbbdca0336e5ad2219d63ea0f08cebc33050d65b7ef2
Old
toupper(to_hex(«lklzndaawijhd»)) + zero padding
70b3b8e07752c1f3d4a462b2ab47ca3d9fb5094131971067230031b8b2cd84f2
CobaltStrike

99d6b73b1a9e66d7f6dcb3244ea0783b60776efd223d95c4f95e31fde434e258
Old
toupper(to_hex(«ifovxtgokm|yzjwz»))
Unknown
Unknown

Appendix C: Example of Cobalt Strike configuration

BeaconType – HTTPS
Port – 443
SleepTime – 30000
MaxGetSize – 2097328
Jitter – 40
MaxDNS – Not Found
PublicKey_MD5 – d67a7903c6777d64b69845b6fcd5db65
C2Server – 64.95.10(.)209,/Collector/2.0/settings/,179.60.149(.)209,/Collector/2.0/settings/,64.52.80(.)62,/Collector/2.0/settings/
UserAgent – Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Teams/1.4.00.2879 Chrome/80.0.3987.165 Electron/8.5.1 Safari/537.36
HttpPostUri – /MkuiIJzM2IZs
Malleable_C2_Instructions – Remove 46 bytes from the end
Remove 130 bytes from the beginning
NetBIOS decode ‘a’
HttpGet_Metadata – ConstHeaders
Accept: json
Host: westeurope-teams.azureedge.net
Referer: https://teams.microsoft.com/_
x-ms-session-id: f73c3186-057a-d996-3b63-b6e5de6ef20c
x-ms-client-type: desktop
x-mx-client-version: 27/1.0.0.2021020410
Accept-Encoding: gzip, deflate, br
Origin: https://teams.microsoft.com
ConstParams
qsp=true
client-id=NO_AUTH
sdk-version=ACT-Web-JS-2.5.0&
Metadata
base64url
parameter «events»
HttpPost_Metadata – ConstHeaders
Connection: Keep-Alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
SessionId
base64url
parameter «id»
Output
base64url
print
PipeName – Not Found
DNS_Idle – Not Found
DNS_Sleep – Not Found
SSH_Host – Not Found
SSH_Port – Not Found
SSH_Username – Not Found
SSH_Password_Plaintext – Not Found
SSH_Password_Pubkey – Not Found
SSH_Banner –
HttpGet_Verb – GET
HttpPost_Verb – POST
HttpPostChunk – 0
Spawnto_x86 – %windir%\syswow64\powercfg.exe
Spawnto_x64 – %windir%\sysnative\powercfg.exe
CryptoScheme – 0
Proxy_Config – Not Found
Proxy_User – Not Found
Proxy_Password – Not Found
Proxy_Behavior – Use IE settings
Watermark_Hash – NtZOV6JzDr9QkEnX6bobPg==
Watermark – 987654321
bStageCleanup – True
bCFGCaution – True
KillDate – 0
bProcInject_StartRWX – True
bProcInject_UseRWX – False
bProcInject_MinAllocSize – 8096
ProcInject_PrependAppend_x86 – Empty
ProcInject_PrependAppend_x64 – Empty
ProcInject_Execute – ntdll.dll:RtlUserThreadStart
NtQueueApcThread-s
SetThreadContext
CreateRemoteThread
kernel32.dll:LoadLibraryA
RtlCreateUserThread
ProcInject_AllocationMethod – VirtualAllocEx
bUsesCookies – False
HostHeader –
headersToRemove – Not Found
DNS_Beaconing – Not Found
DNS_get_TypeA – Not Found
DNS_get_TypeAAAA – Not Found
DNS_get_TypeTXT – Not Found
DNS_put_metadata – Not Found
DNS_put_output – Not Found
DNS_resolver – Not Found
DNS_strategy – round-robin
DNS_strategy_rotate_seconds – -1
DNS_strategy_fail_x – -1
DNS_strategy_fail_seconds – -1
Retry_Max_Attempts – 0
Retry_Increase_Attempts – 0
Retry_Duration – 0

Appendix D: Network

64.52.80(.)62:443
64.95.10(.)209:443
67.217.228(.)55:443
137.184.155(.)92:443
159.65.241(.)37:443
162.33.179(.)247:8443
165.227.113(.)183:443
179.60.149(.)209:443
192.241.190(.)181:443
api.glazeceramics(.)com:443
doc.docu-duplicator(.)com:53
doc2.docu-duplicator(.)com:53
comdoc1.docu-duplicator(.)com:53

Appendix E: Malware

Table 2: List of malware and tools

Malware
Filename
Hash(SHA256)

java(Legitimate)
java.exe
16b1819186f0803b9408d9a448a176142f8271a4bc0b42cdb78eb4489bce16fe

ReadNimeLoader
jli.dll
56b941f6dcb769ae6d6995412559012abab830f05d5d8acf2648f7fa48c20833

ReadNimeLoader
jli.dll
dfe79b9c57cfb9fc10597b43af1c0a798991b6ceeec2af9b1e0ed46e6a8661c8

ReadNimeLoader
jli.dll
3f96b6589996e57abc1c4d9b732528d2d11dea5c814f8241170c14ca2cd0281d

ReadNimeLoader
jli.dll
0ab709728666f8759ad8db574d4009cf74ebce36ef2572ef52b058997a9b2a25

ReadNimeLoader
jli.dll
ecca3194613b0bab02059c3544fdc90f6d4af5a4c06518c853517eb1d81b9735

ReadNimeLoader
jli.dll
ad90a4490d82c7bd300fdbbdca0336e5ad2219d63ea0f08cebc33050d65b7ef2

ReadNimeLoader
jli.dll
99d6b73b1a9e66d7f6dcb3244ea0783b60776efd223d95c4f95e31fde434e258

Cobalt Strike
readme.txt
6246fb5c8b714707ac49ade53e6fe5017d96442db393b1c0ba964698ae24245d

Cobalt Strike
readme.txt
acdf2a87ed03f2c6fe1d9899e8a74e8b56f7b77bb8aed5adf2cc374ee5465168

Cobalt Strike
readme.txt
6b80d602472c76b1d0f05bcce62e0a34de758232d9d570ba61b540784c663c01

Cobalt Strike
readme.txt
3079a29575a0adff91f04c5493a7f3e1c89795e3a90cf842650cd8bd45c4e1bc

Cobalt Strike
readme.txt
70b3b8e07752c1f3d4a462b2ab47ca3d9fb5094131971067230031b8b2cd84f2

CrossC2
gds
28d668f3e1026a56d55bc5d6e36fad71622c1ab20ace52d3ab12738f9f8c6589

CrossC2
gss
9e8c550545aea5212c687e15399344df8a2c89f8359b90d8054f233a757346e7

ELF-SystemBC
monitor
74a33138ce1e57564baa4ea4db4a882d6bf51081b79a167a6cb2bf9130ddad7f

ELF-SystemBC
monitor
7ccff87db7b4e6bc8c5a7e570f83e26ccb6f3a8f72388210af466048d3793b00

GetNPUsers
GetNPUsers_windows.exe
e0e827198a70eef6c697559660106cfab7229483b0cd7f0c7abd384a3d2ee504

Tools related to privilege escalation
wermgr.exe
f79e047ae4834e6a9234ca1635f18b074a870b366fe4368c10c2ddc56dfbb1bc

Tools related to privilege escalation
wermgr.exe
ac02aee660d44a8bfbc69e9c46cf402fd41e99915e13d0de3977e662ef13b2ca

Plink v0.81
conhost.exe
2e338a447b4ceaa00b99d742194d174243ca82830a03149028f9713d71fe9aab

PsExec v2.43
PsExec.exe
078163d5c16f64caa5a14784323fd51451b8c831c73396b967b4e35e6879937b

cab-related tool
hhupd.exe
d74eac55eeaa3138bc1e723c56013bb1af7709f0a77308bfbf268d4e32b37243

Enlace de la fuente, haz clic para tener más información

Artículos y alertas de seguridad

Consultar más contenidos y alertas

Alertas y noticias de seguridad de la información

Contacta

Contacta con nosotros para obtener soluciones integrales en IT y seguridad de la información

Estamos encantados de responder cualquier pregunta que puedas tener, y ayudarte a determinar cuáles de nuestros servicios se adaptan mejor a tus necesidades.

Nuestros beneficios:
¿Qué sucede a continuación?
1

Programamos una llamada según tu conveniencia.

2

Realizamos una reunión de descubrimiento y consultoría.

3

Preparamos una propuesta.

Agenda una consulta gratuita