Contents
- Introduction
- The investigation begins
- First version of GoRed and other malicious tools we found
- Relation to ExCobalt
- GoRed analysis
- Versions we found
- Internal packages
- 1. Start of execution
- 2. Gaining persistence in the system
- 3. Initializing beacon mode
- 4. Establishing an initial connection
- 5. Listen and execute mode
- 6. Communications in beacon mode
- Configurations
- Communication protocols
- Background commands
- Issued commands
- Conclusion
- IOCs
- MITRE TTPs
- Verdicts by Positive Technologies products
Introduction
While responding to an incident at one of our clients, the PT ESC CSIRT team discovered a previously unknown backdoor written in Go, which we attributed to a cybercrime gang dubbed ExCobalt.
ExCobalt focuses on cyberespionage and includes several members active since at least 2016 and presumably once part of the notorious Cobalt gang. Cobalt attacked financial institutions to steal funds. One of Cobalt's hallmarks was the use of the CobInt tool, something ExCobalt began to use in 2022.
Over the past year, the PT ESC has recorded attacks linked to ExCobalt and investigated related incidents at Russian organizations in the following sectors:
- Metallurgy
- Telecommunications
- Mining
- Information technology
- Government
- Software development
This article discusses ExCobalt's new tool, GoRed, how it evolved, and some of the tactics, techniques, and procedures that the group has used in its attacks.
The investigation begins
While investigating an incident recorded in March 2024 on one of our client's Linux hosts, we discovered a file named scrond, compressed with UPX (Ultimate Packer for eXecutables).
The data in an unpacked sample, written in Go, included package paths containing the substring "red.team/go-red/". This fact suggests that this sample is a proprietary tool called GoRed.
After investigating the site, we were unable to find any significant links to malicious activity. Therefore, we can assume that the red.team domain found in the GoRed strings is a local repository with penetration testing tools.bsp;longer actively used by its creators. All the information dates back to 2019, and the design is typical of many similar sites.
![Internal packages](/upload/corporate/ww-en/pt-esc/406364/111.png)
As for the GoRed backdoor, the following key features can be identified:
- Operators can connect to the backdoor and execute commands, similar to other C2 frameworks like Cobalt Strike or Sliver.
- GoRed uses the RPC protocol to communicate with its C2 server.
- Operators use DNS/ICMP tunneling, WSS, and QUIC to communicate with GoRed.
- GoRed can obtain credentials from compromised systems.
- It collects various types of information from compromised systems: details of active processes, host names, lists of network interfaces, file system structures, and so on.
- Operators use a variety of commands to conduct reconnaissance on the victim's network.
- GoRed serializes, encrypts, archives, and sends data it collects to a special server dedicated to storing compromised data.
For a complete technical description of GoRed, see the further section "GoRed analysis".
First version of GoRed and other malicious tools we found
As we analyzed GoRed, we found that we had already come across several versions of the backdoor while responding to incidents at several of our clients earlier. For example, in July 2023, as we were investigating an incident at a certain company, we discovered several different tools inside the attackers' directories due to an error they had made, one of tools being the original version of GoRed.
Similarly, in an October 2023 incident, we found further tools inside public directories on the attackers' network. A short name and description of each tool we found during the investigations are presented in the table below.
2586 | CVE-2022-2586: a Linux kernel vulnerability associated with pointer abuse in the io_uring function. This was used by the threat actor to escalate privileges and execute arbitrary code in the vulnerable system | |
3156.zip | CVE-2021-3156: a sudo vulnerability known as Baron Samedit. This allows a local user to execute arbitrary code with root privileges, bypassing standard security controls | |
4034 | Pwnkit is a local privilege escalation exploit for CVE-2021-4034. This is a vulnerability in the pkexec utility. It allows local users to escalate their privileges to root, which can lead to complete compromise of the system | |
traceme | Local privilege escalation exploit for CVE-2019-13272. This is a vulnerability in the Linux kernel, in the ptrace component. It allows users with CAP_SYS_PTRACE privileges to escalate their privileges to root to execute arbitrary code in the system | |
bitrix.zip | This is an archive with vote_agent.php and html_editor_action.php files, containing RCE exploits for Bitrix. It was distributed via Telegram channels in June 2022, and also mentioned in connection with the May 2023 mass defacement of Russian websites (https://habr.com/ru/companies/ruvds/articles/739898/) | |
col | First version of the GoRed backdoor: 0.0.1 | |
fs | fscan (https://github.com/shadow1ng/fscan/) | |
get_wp-commentin.txt | Obfuscated PHP file | |
run | FreeBSD file. Runs the specified executable file as root, same as the command sudo exec < specified file> | |
set | FreeBSD file. Sets root as file owner and grants rwx (read, write, execute) permissions to it, same as the commands chown < file> 0; chmof < file> 777 | |
install | Installs a malicious module for Apache 2.4 | |
install[drop] | Contains a dropper with a UPX-compressed binary file that is written to /usr/local/games/w. The file’s privileges are then changed: chown root:root; chmod 4755 | |
install[drop][upx] /usr/local/games/w | Tries to run the following command as root: (setuid(0); setgid(0); /bin/sh -c...)) |
|
k | Contains the following set of basic network utilities and replaces the process name with [kthr]: | |
curl | Stripped down version of curl | |
socksd | Proxy (socks4/5 with user+pass support) | |
shell | Bind shell | |
host | Resolves a host’s name via the 8.8.8.8 DNS server | |
hash | MD5/SHA-1/SHA-256 | |
gz | Inflate/deflate functionality | |
netcat | - | |
kit | Shell script to install kitsune. The MEGATSUNE variable was used instead of KITSUNE. amd64.rpm-bin.link and pkg.dpkg-source.info were used as the C2s | |
lock.zip | Part of the locker wiper ransomware repository with a read.me file in Russian inside | |
locker | Locker from lock.zip without the configuration files | |
m | Mettle (https://github.com/rapid7/mettle) | |
rev | Bind shell, shares code with shell from k, renames process to [kr] | |
sf | Binary for BSD | |
spark | Spark RAT | |
w.txt | PHP web shell: WSO (https://github.com/ndbrain/WSO) |
|
wef | Variant of reverse SSH client (https://github.com/NHAS/reverse_ssh) | |
y.txt | PHP shell: p0wny-shell | |
knife/k | We found this file several months after the above-mentioned k, also in a public directory but in a different domain. It was also named k, and the functionality is similar, which suggests that this is simply the next version. This is a tool to control a compromised Linux server. It has extensive functionality; commands to execute are specified in the command line: | |
sync | No handler. Causes segfault if run | |
curl < url> | Loads content from specified URL | |
socksd | Starts a SOCKS server | |
netcat | No handler. Causes segfault if run | |
host < host> | Tries to resolve the host’s name via the 8.8.8.8:53 DNS server | |
hash < filename> | Calculates the file’s hash (MD5, SHA-1, SHA-256 are available) | |
gz < filename> | Compresses the file | |
shell < options> < IP address:port> | Remote shell. The command can be run with the following possible options: -l (listen to the specified address) or -c (connect to the specified address) |
In addition to the tools obtained from the threat actors' server directories, ExCobalt used the following tools:
- Mimikatz
- ProcDump
- SMBExec
- Metasploit
- rsocx
Modified versions of standard utilities
Besides the above tools found in public directories, we came across modified versions of standard Linux utilities in several incidents, something we first saw in November 2023.
The modification of utilities serves two purposes:
1. Modified ps and htop hide an active core process of the gsocket module and related processes in terminal output.
Let's take ps as an example.
The simple_readproc function was modified.
The original code looks as follows:
![Original ps code](/upload/corporate/ww-en/pt-esc/406364/2.png)
The following code was added:
![Code added to ps](/upload/corporate/ww-en/pt-esc/406364/3.png)
The is_target_proc function checks for every process whether its name is equal to any of the hardcoded names of malicious processes:
![The check inside is_target_proc](/upload/corporate/ww-en/pt-esc/406364/4.png)
If the check returns true, the process will be hidden in the terminal output. Here's the list of the names of malicious processes hidden this way:
![Names of malicious processes](/upload/corporate/ww-en/pt-esc/406364/5.png)
2. Modified ss and netstat hide the active network connection of the core module of gsocket in terminal output.
Let's take netstat as an example.
The first code modification was made in the main function.
The original code looks as follows:
![Original code of the main function of netstat](/upload/corporate/ww-en/pt-esc/406364/6.png)
First, code was added to copy all C2s from the data section to a global structure:
![Copying the C2s to a global structure](/upload/corporate/ww-en/pt-esc/406364/7.png)
Second modification was in the tcp_do_one function, starting here:
![Original code of the tcp_do_one function of netstat](/upload/corporate/ww-en/pt-esc/406364/8.png)
Checks for the name of the malicious process and malicious connection were added to the code. If the check returns true, the process with one of the hardcoded names or network connections will be hidden:
![Checking for the name of the malicious process and malicious connection](/upload/corporate/ww-en/pt-esc/406364/9.png)
Relation to ExCobalt
In November 2023, we discussed ExCobalt's attacks on Russian companies.
In that report, we mentioned the domain lib.rpm-bin.link, where upon directory enumeration we found many of the tools described above—including col, the first version of GoRed.
Also, in a March 2024 incident, we observed infected hosts that contacted the threat actor's servers: get.rpm-bin.link and leo.rpm-bin.link. Additionally, GoRed used a static_TransportConfig structure with the following C2s:
- leo.rpm-bin.link
- sula.rpm-bin.link
- lib.rest
- rosm.pro
In May 2023, Bi.Zone researchers released an analysis of attacks by Sneaking Leprechaun, whose tools showed some overlap with the above-mentioned files found inside the public directories.
Furthermore, our colleagues at Rostelecom-Solar in May 2024 released a report on the Shedding Zmiy activity cluster, which also correlated with ExCobalt. Case 7 in this report described the same attack and a GoRed stealer sample with a C2 at pkg.collect.net.in. This sample was designated as Bulldog Backdoor in the report.
GoRed analysis
Before we proceed to analyzing the current version of GoRed, we will provide a retrospective analysis of its evolution.
Versions we found
All the versions we found are shown in the table below.
Version | Description |
---|---|
0.0.1 |
|
0.0.9 |
|
0.0.9 |
|
0.0.13 |
|
0.0.23-10-g4528ef3 |
|
0.1.3-4-g68c293d | This version is mentioned only in the Solar report; we have not come across it. |
0.1.3-62-g4843e53 |
|
0.1.4 | No changes found from previous version. |
This article examines the current version, 0.1.4.
Internal packages
First, we will describe the structure of the internal packages and their purpose to give you an understanding of GoRed functionality. In the backdoor's data, we have found the following package paths containing the substring "red.team/go-red/":
Package | Purpose |
---|---|
red.team/go-red/config/ | Retrieval of the internal and transport configurations |
red.team/go-red/bb/ | Processing of an operator's commands |
red.team/go-red/birdwatch/ | Monitoring of the file system |
red.team/go-red/gecko/ | Protocol for communication between GoRed and its C2 |
red.team/go-red/backend/ | Connecting to a data exfiltration server |
red.team/go-red/collector/ | Collecting system information |
red.team/go-red/util/ | Various auxiliary utilities |
red.team/go-red/packer/ | Data packing |
red.team/go-red/proxy/ | Proxy mode operation |
red.team/go-red/revshell/ | Reverse shell mode operation |
red.team/go-red/dns/ | DNS tunneling implementation |
red.team/go-red/icmptunnel/ | ICMP tunneling implementation |
Let's now proceed to analysis proper. Here's a simplified diagram of the control flow to give you an understanding of how it works.
![Diagram of the control flow](/upload/corporate/ww-en/pt-esc/406364/control_flow_en.png)
1. Start of execution
The control flow relies on the command line interface (CLI). However, before passing control to the CLI, the backdoor initializes a number of commands, which are described below.
- service command
- gecko subcommand
![Initializing the command and subcommand](/upload/corporate/ww-en/pt-esc/406364/11.png)
The service command, intended for gaining persistence in the system, is initialized first. The GoRed CLI command structure looks as follows:
struct cli_Command { string Name; _slice_string Aliases; string Usage; string UsageText; string Description; string ArgsUsage; string Category; PTR_cli_BashCompleteFunc BashComplete; PTR_cli_BeforeFunc Before; PTR_cli_AfterFunc After; PTR_cli_ActionFunc Action; PTR_cli_OnUsageErrorFunc OnUsageError; _slice__ptr_cli_Command Subcommands; _slice_cli_Flag Flags; cli_FlagCategories flagCategories; bool SkipFlagParsing; bool HideHelp; bool HideHelpCommand; bool Hidden; bool UseShortOptionHandling; string HelpName; _slice_string commandNamePath; string CustomHelpTemplate; cli_CommandCategories categories; bool isRoot; cli_separatorSpec separator; };
In terms of command identification, the most helpful fields in this structure are the following:
- Name: command name
- Usage: command description
- Action: function called when the command is executed
- Subcommands: subcommands for the current command
Next, the structure of the CLI itself is initialized into the variable app.
![Initializing the app structure for the CLI](/upload/corporate/ww-en/pt-esc/406364/12.png)
The app structure looks as follows:
struct cli_App { string Name; string HelpName; string Usage; string UsageText; string ArgsUsage; string Version; string Description; string DefaultCommand; _slice__ptr_cli_Command Commands; _slice_cli_Flag Flags; bool EnableBashCompletion; bool HideHelp; bool HideHelpCommand; bool HideVersion; cli_CommandCategories categories; cli_FlagCategories flagCategories; PTR_cli_BashCompleteFunc BashComplete; PTR_cli_BeforeFunc Before; PTR_cli_AfterFunc After; PTR_cli_ActionFunc Action; PTR_cli_CommandNotFoundFunc CommandNotFound; PTR_cli_OnUsageErrorFunc OnUsageError; PTR_cli_InvalidFlagAccessFunc InvalidFlagAccessHandler; time_Time Compiled; _slice__ptr_cli_Author Authors; string Copyright; io_Reader Reader; io_Writer Writer; io_Writer ErrWriter; PTR_cli_ExitErrHandlerFunc ExitErrHandler; map_string_interface_ Metadata; PTR_func_map_string_string ExtraInfo; string CustomAppHelpTemplate; string SliceFlagSeparator; bool DisableSliceFlagSeparator; bool UseShortOptionHandling; bool Suggest; bool AllowExtFlags; bool SkipFlagParsing; bool didSetup; cli_separatorSpec separator; _ptr_cli_Command rootCommand; };
Here, too, the most informative fields for identifying commands are as follows:
- Name: current command name
- Action: function called
- Commands: subcommands for the current command
The Commands field for the app structure is also initialized.
![Initializing the CLI context structure](/upload/corporate/ww-en/pt-esc/406364/13.png)
Next, the Logging field is retrieved from the embedded_Config structure described in the section below. After this, the control flow moves to the CLI.
![Transferring control to the CLI](/upload/corporate/ww-en/pt-esc/406364/14.png)
2. Gaining persistence in the system
The first command to be executed is service. It achieves persistence in the system. It can be executed with the following options:
Option | Purpose |
---|---|
no-service | Simply proceeds to executing CLI commands |
uninstall | Removes the service |
restart | Restarts the service |
If there are no options from the table above, it gains persistence as a service with the name it received as an argument. To maintain presence in the compromised system, it creates environment variables whose names begin with "BB", for example:
- BB_WS
- BB_QUIC
- BB_ICMP
- BB_DNS
- BB_START_DELAY
3. Initializing beacon mode
The control flow is then transferred to the gecko command. This command is the entry point for GoRed to run in beacon mode.
![Execution options for the gecko command](/upload/corporate/ww-en/pt-esc/406364/15.png)
It can be executed with the following options:
Option | Purpose |
---|---|
wss | Use the corresponding protocol for communication between the operator and GoRed |
quic | |
icmp | |
dns | |
background | Run the command in the background |
start-delay | Add delay in communications with the C2 |
Depending on the protocol received as an option, the command fetches the C2 from the transport configuration whose structure is described in the section below. It then begins initializing the beacon functionality.
![Initializing the beacon functionality](/upload/corporate/ww-en/pt-esc/406364/16.png)
To identify the victim, the malware first generates an ID, which is an MD5 hash of the computer's MAC addresses and name, similarly to the case described in our Hellhounds: Operation Lahat article. The resulting hash sum is added to a field in the client structure, which stores all data required for communication with the C2.
![Obtaining a victim ID](/upload/corporate/ww-en/pt-esc/406364/17.png)
4. Establishing an initial connection
After GoRed is initialized, it needs to connect to its C2. The number of connection attempts is defined in the backoff package.
![Setting the number of C2 connection attempts](/upload/corporate/ww-en/pt-esc/406364/18.png)
The execution flow calls the function that registers the beacon functionality, after which the CLI commands are initialized.
![Starting beacon functionality](/upload/corporate/ww-en/pt-esc/406364/19.png)
Registration uses the RPC protocol. Data in the model_Beacon structure is sent to the server, and data in the model_Auth structure is used for authentication with the server.
struct model_RegisterBeaconRequest { model_Beacon Beacon; model_Auth Auth; }; struct model_Beacon { string ID; string Hostname; string ClientIPs; _slice_string Tags; string OS; string Username; }; struct model_Auth { string Token; uuid_UUID ClientID; string Transport; };
The fields in these structures have the following purposes:
Field | Purpose | |
---|---|---|
Beacon | The structure containing victim information | |
Field | Purpose | |
ID | Victim's ID | |
Hostname | Victim's hostname | |
ClientIPs | Victim's IP addresses | |
Tags | Victim's tag | |
OS | Victim's operating system | |
Username | Victim's username | |
Auth | The structure containing authentication data | |
Field | Purpose | |
Token | Authentication token | |
ClientID | Client ID | |
Transport | Protocol being used |
After registering, GoRed runs the birdwatch command to monitor the file system.
![Running birdwatch in the background](/upload/corporate/ww-en/pt-esc/406364/20.png)
The execution flow then sets a GoRed beacon mode heartbeat period (for signaling to C2).
![Setting a heartbeat period](/upload/corporate/ww-en/pt-esc/406364/21.png)
The execution flow then runs a command to monitor the password file stored in /etc/shadow/.
![Running creds-watcher in the background](/upload/corporate/ww-en/pt-esc/406364/22.png)
Finally, the execution flow initializes all available commands and goes into heartbeat mode.
![Entering heartbeat mode](/upload/corporate/ww-en/pt-esc/406364/23.png)
5. Entering listen and execute mode
At the final stage of initialization, GoRed starts listening for the operator's commands that it previously initialized. It can execute both system and built-in commands. Commands can be set to run in the background.
![Function to set a command to run in the background](/upload/corporate/ww-en/pt-esc/406364/24.png)
6. Communications in beacon mode
GoRed uses the RPC protocol to communicate with its C2 in beacon mode.
![RPC functionality](/upload/corporate/ww-en/pt-esc/406364/25.png)
It registers a custom codec to communicate via RPC.
![Custom RPC codec functionality](/upload/corporate/ww-en/pt-esc/406364/26.png)
The registered codec serializes data with CBOR and encrypts with AES-256-GCM (Secret field in embedded_Config) when sending, and does the reverse when receiving.
![Function that transforms data for exfiltration](/upload/corporate/ww-en/pt-esc/406364/27.png)
Configurations
GoRed contains two configuration blocks: built-in and transport.
Built-in configuration
This is the configuration of GoRed itself. It is encoded in Base64 and serialized with msgpack.
![Built-in configuration](/upload/corporate/ww-en/pt-esc/406364/28.png)
For versions 0.0.23-10-g4528ef3 through 0.1.4, the structure of the built-in configuration is as follows:
struct embedded_Config { string Logging; string Token; uuid_UUID UserID; uuid_UUID ClientID; string ClientKey; string Version; _slice_string Tags; _slice_string Args; string Secret; _ptr_url_URL BackendAddress; _ptr_url_URL ProxyAddress; };
The purposes of the built-in configuration fields are as follows:
Field | Purpose |
---|---|
Logging | Logging and log format:
|
Token | Generated JWT for RPC |
UserID | UUID for the payload field in the JWT (when using RPC) |
ClientID | Unique identifier for the exfiltrated data of the victim |
ClientKey | HS256 key needed to generate the JWT when exfiltrating data |
Version | GoRed version |
Tags | Victim's tag |
Args | GoRed arguments |
Secret | AES-256-GCM key for encrypting or decrypting the data transmitted or received via RPC |
BackendAddress | Address of a dedicated server for data exfiltration |
ProxyAddress | List of proxy addresses for data exfiltration |
Configuration structure for versions 0.0.9 through 0.0.13.
struct embedded_Config { bool Debug; string Token; uuid_UUID ClientID; string ClientKey; string Version; _slice_string Tags; string Secret; string BasicAuthLogin; string BasicAuthPass; _ptr_url_URL BackendAddress; _ptr_url_URL ProxyAddress; };
The fields in this version of the built-in configuration have the following purposes:
Field | Purpose |
---|---|
Debug | Logging and log format:
|
BasicAuthLogin | Login for authentication when using the curl command |
BasicAuthPass | Password for authentication when using the curl command |
Built-in configuration for version 0.0.1.
struct embedded_Config { bool Debug; uuid_UUID ClientID; string ClientKey; string Version; _ptr_url_URL BackendAddress; };
Golang script for getting built-in configuration fields:
package main import ( "encoding/base64" "fmt" "net/url" "github.com/google/uuid" "github.com/vmihailenco/msgpack/v5" ) type embedded_Config struct { Logging string Token string UserID uuid.UUID ClientID uuid.UUID ClientKey string Version string Tags []string Args []string Secret string BackendAddress* url.URL ProxyAddress* url.URL } const config = `...` func main() { var item map[string]any data, _ : = base64.StdEncoding.DecodeString(config) err : = msgpack.Unmarshal(data, &item) if err != nil{ panic(err) } fmt.Print("Logging: ") fmt.Println(item["Logging"]) fmt.Print("Token: ") fmt.Println(item["Token"]) fmt.Print("UserID: ") fmt.Println(uuid.UUID(item["UserID"].([]byte))) fmt.Print("ClientID: ") fmt.Println(uuid.UUID(item["ClientID"].([]byte))) fmt.Print("ClientKey: ") fmt.Println(item["ClientKey"]) fmt.Print("Version: ") fmt.Println(item["Version"]) fmt.Print("Tags: ") fmt.Println(item["Tags"]) fmt.Print("Args: ") fmt.Println(item["Args"]) fmt.Print("Secret: ") fmt.Println(item["Secret"]) fmt.Print("BackendAddress: ") fmt.Println(string(item["BackendAddress"].([]byte))) fmt.Print("ProxyAddress: ") fmt.Println(item["ProxyAddress"]) }
Python script for getting built-in configuration fields:
import msgpack import base64 s = base64.b64decode('...') config = msgpack.unpackb(s, raw = False) print(config)
Transport configuration
The transport configuration looks as follows:
![Transport configuration](/upload/corporate/ww-en/pt-esc/406364/29.png)
It has the following structure:
struct static_TransportConfig { static_Transport Revsh; static_Transport RPC; static_Transport Proxy; }; struct static_Transport { _ptr_static_Address WS; _ptr_static_Address QUIC; _ptr_static_Address ICMP; _ptr_static_Address DNS; _ptr_static_Address TCP; }; struct static_Address { string Domain; string BackupIP; signed __int64 Port; string Proto; };
The fields of the static_TransportConfig structure have the following purposes:
Field | Purpose |
---|---|
Revsh | Reverse shell connection addresses for an operator |
RPC | Addresses for GoRed beacon mode RPC heartbeats |
Proxy | Addresses for running GoRed in proxy mode |
The fields of the static_Address structure have the following purposes:
Field | Purpose |
---|---|
Domain | Domain to connect to |
BackupIP | IP to connect to if the domain cannot be resolved |
Port | Connection port |
Proto | Connection protocol |
Communication protocols
GoRed has several protocols for communicating with the operator.
Protocol | Implementation |
---|---|
ws | Implements WebSocket connection |
quic | Implements QUIC connection |
icmp | Implements ICMP tunneling |
dns | Implements DNS tunneling |
DNS
DNS tunneling in GoRed can use Base64 or Base32. This option is selected during compilation.
![Using Base32 for traffic tunneling](/upload/corporate/ww-en/pt-esc/406364/30.png)
An example of a domain used in an attack is 8E1A4QB4OGA66RPJCHL72DJGCKRMIOR8CDN3EDJBDOOAEQ3FEDQ5UQB4OGA66RP.JCHL6EDJGCKRMIOR8CDN3EDJBDLJG.rosm[.]pro.
Background commands
Background commands run continuously; some of them can be added to the background or removed, depending on the conditions in the table below.
Command | Description |
---|---|
birdwatch | Watches for new files inside directories. Runs in the background by default.
|
creds-watcher | Watches for passwords. Runs in the background by default. |
revsh-host | Enables reverse shell mode. Runs in the background upon execution.
|
rev-proxy | Enables reverse proxy mode via SOCKS5. Runs in the background upon execution. |
rev-fwd | Enables reverse port forwarding mode. Runs in the background upon execution. |
Connecting in rev-proxy and rev-fwd mode
Before starting to act as a server, GoRed needs to initialize an embedded X.509 certificate, similarly to the case described in our Hellhounds: Operation Lahat. Part 2 article.
![Retrieving the certificate and host information](/upload/corporate/ww-en/pt-esc/406364/31.png)
The backdoor also needs to collect information about the victim's host by executing the CollectHostInfo function shown above. This produces the structure presented below, except for the Addr field.
struct proto_HostInfo { string Addr; string OS; string Username; string Hostname; _slice_string IPs; };
The fields in the structure have the following purposes:
Field | Purpose |
---|---|
Addr | Address to connect to, passed to the command as a parameter |
OS | Victim's operating system |
Username | Victim's username |
Hostname | Victim's hostname |
IPs | Victim's IP addresses |
A structure to identify GoRed as a server is initialized as follows:
![Initializing the structure](/upload/corporate/ww-en/pt-esc/406364/32.png)
The initialized structure looks as follows:
struct proto_BinInfo { uuid_UUID ClientID; string Token; _slice_string Tags; };
The fields in the structure have the following purposes:
Field | Purpose |
---|---|
ClientID | Identifies the victim |
Token | Generated JWT for RPC |
Tags | Victim's tag |
Having received the proto_HostInfo and proto_BinInfo structures, GoRed uses their fields in a handshake message that it sends to the C2 at the address it gets from the transport configuration. The handshake message structure looks as follows:
struct proto_MsgGreeting { proto_ConnectionMode Mode; string MachineID; proto_BinInfo BinInfo; _ptr_proto_HostInfo HostInfo; };
The fields in the structure have the following purposes:
Field | Purpose |
---|---|
Mode | The following modes are supported:
|
MachineID | Victim's computer ID |
BinInfo | Structure containing the GoRed configuration information |
HostInfo | Structure containing victim information |
The handshake sequence used to register GoRed as a server looks as follows:
![Communications with the C2](/upload/corporate/ww-en/pt-esc/406364/33.png)
In response to the handshake message, the server sends a message with the following structure:
struct proto_MsgGreetingResponse { string Greeting; _ptr_proto_BinInfo BinInfo; _ptr_proto_HostInfo HostInfo; };
If the Greeting field contains the string "welcome", the connection is considered successful, and GoRed starts running in server mode; if not, the connection cannot be established.
Issued commands
The operator uses the following commands to communicate with GoRed:
Command | Description |
---|---|
upload | Exfiltrates files. Takes a file path as the argument |
download | Downloads files onto the infected computer. Takes a file path as the argument |
bg-list | Displays a list of internal background commands |
bg-stop | Cancels an internal background command. Takes a command ID as an argument. Can be used to stop all background commands |
stealth | Automatically sets the heartbeat frequency within a larger range for greater stealth.
|
emit-period | Gets or sets a heartbeat frequency manually |
conn-providers | Gets the communication protocols available in the current version of GoRed |
info | Gets victim information:
|
collect | Collects and exfiltrates system information. See the section below for more details |
bb-update | Updates GoRed. Sends a GET request to the URL passed as the argument and restarts GoRed with the restart argument |
bb-ps | Gets the status of the process passed as the argument |
bb-cat | Reads the file passed as the argument |
bb-find | Searches for files passed as the argument |
bb-ls | Displays the contents of the directory passed as the argument |
bb-mkdir | Creates the directory passed as the argument |
bb-pwd | Returns the full path of the current directory |
bb-rm | Deletes the file passed as the argument |
bb-wc | Collects information about the file passed as the argument:
|
bb-nmap | Scans the network. Takes a host IP as the argument |
bb-ping | Pings an external host. Takes an IP as the argument |
bb-wget | Gets files via HTTP. Takes two arguments: the source URL and the output filename specified after the —output option |
bb-curl | Similar to curl, but with limited functionality |
collect
Since this command collects system information and data for subsequent exfiltration, we decided to describe it in more detail:
Option | Purpose |
---|---|
local-archive | Selects a compression algorithm: tar or gzip |
skip-trees | Skips collecting file system structure information |
skip-files | Skips collecting files |
exec-timeout | Sets a time period for collecting files |
Collected information
An example of the code used to collect information is shown below.
![Example of the code used to collect information](/upload/corporate/ww-en/pt-esc/406364/34.png)
A complete list of collected information is provided in the table below.
File | Contents |
---|---|
processes.json | List of processes |
envvars.json | List of environment variables |
host.json | Information about the processor, RAM, installed OS, user name, group name |
network_interfaces.json | List of network interfaces |
netstats.json | List of active network connections |
*.txt | Files that will be collected depending on the values of the fields in the model_CollectionConfig structure |
hardware.json | Hardware information |
trees.json | File system structure |
Exfiltration
Before the data is sent, it is serialized with msgpack and encrypted with AES-256-GCM (Secret field in embedded_Config).
![Example of collected data preparation](/upload/corporate/ww-en/pt-esc/406364/35.png)
Next, after archiving the data, the backdoor sends it with a POST request to a URL generated by appending "/api/collection-result" to the BackendAddress field in embedded_Config.
![Data exfiltration](/upload/corporate/ww-en/pt-esc/406364/36.png)
It is also possible to update the model_CollectionConfig structure by sending a GET request to a URL generated by appending "/api/config" to the BackendAddress field in embedded_Config.
\![Configuration update](/upload/corporate/ww-en/pt-esc/406364/37.png)
The model_CollectionConfig structure is a configuration for the collect command and has the following fields:
struct model_CollectionConfig { _slice__slice_string Commands; _slice_string Files; _slice_string TreePaths; };
The fields in the structure have the following purposes:
Field | Purpose |
---|---|
Commands | bb_files_* command |
Files | Files |
TreePaths | Paths |
Conclusion
ExCobalt continues to demonstrate a high level of activity and determination in attacking Russian companies, constantly adding new tools to its arsenal and improving its techniques. Not only is it developing new attack methods, but it's also actively improving its existing tools, such as the GoRed backdoor.
ExCobalt is apparently aiming for more sophisticated and productive methods of hacking and cyberespionage, seeing how GoRed has been acquiring new capabilities and features. These include expanded functionality for collecting victim data and increased secrecy both inside the infected system and in communications with C2 servers.
In addition, ExCobalt demonstrates flexibility and versatility by supplementing its toolset with modified standard utilities, which help the group to easily bypass security controls and adapt to changes in protection methods. The use of modified utilities is a sign that the members of the group have an in-depth understanding of the weaknesses of companies they attack, while leveraging vulnerabilities helps them to pursue sophisticated attacks on their targets.
Overall, the evolution of ExCobalt and its toolset, including GoRed and the modified utilities, highlights the need for organizations and cybersecurity professionals to continuously improve detection and protection techniques to combat this group as well as other similar cyberthreats.
Authors:
Vladislav Lunin, Senior Information Security Threat Researcher, PT ESC
Alexander Badayev, Information Security Threat Researcher, PT ESC
IOCs
File indicators
File | MD5 | SHA-1 | SHA-256 |
---|---|---|---|
GoRed |
|||
col | 6ea3feb1888ce02e3d0d2857b5ef71c4 | c5540ec2ec79a21f07b0d793cc36b024a0db64cc | 67b7a8fad28dcc40c0889e5c4e40aef9348441c64bba74bd6db885d88ce6d246 |
coll.exe | 64db61efc8acf370b91110b6f93d4dce | a81373d92d798418109552fb91d4c407d4c37a89 | f43c99ef85166774ed47cad96c70b8273aa82c313e55bb08d9c74e2b3f59b000 |
63f6de3c86de55172b147b947f29c808.virus | 63f6de3c86de55172b147b947f29c808 | 5a504869350a4bdbcda22b09dbe7b05a7551a860 | f91c9fd27bf0e3a7e82998721946ee70735ec46ee672ca80e3062aa2d5195447 |
c.upx | d3cd9d9bad6450e8fd4fd2e972639c69 | a190448a0c01a6e58610de27d022ccba0e755f79 | be246cdf932aa5b1c2ada0d74c8d1eca4028538b28fb61d7a8d930b4266fd55c |
cad5cb82baccd1f28e381e5c924f204a.virus | cad5cb82baccd1f28e381e5c924f204a | 81861a853216f78219dd8cb0b4717d5d63260e7d | ec36fcd64432843292d16f601a758ba4091ada906c5c4c4e540e326676911141 |
bb.exe | 6f6e7fe49a8d5696f389e202d3b8c7e2 | 1d784e6c7d12fb7730895f21e4bfd3cde4b3900f | 41d35016c78f86eee8972808c7de8c200ff24625639adff5b9d0ab8773fff6b4 |
coll.exe | b5dc9a67f76fa18784b51fd3c5b9607c | de243b57b087f5d1cde50db1949aa3744f1f6b5e | aca34d7c3832879f6f7ebe8f7c59160896909574c94d1d12d7c71b6f7918bc50 |
revsh.exe | caf68b393d56548074b9434564cb0625 | 680cb0a25e4a5148f5a1f7d3b75fad4fd345cdb0 | 8d055f3ad4d01f601df24a7c20ded981005adef7e6d26750415d1f95a471c2e3 |
- | b747c05888caf380edf6b2baab142272 | ef50067027e27bea188023fa6a8ce9054c7d4ce9 | 17e57c5e71b99a386b18728eac4a27e83415756071c9e85859940da41e94976b |
dttcodexgigas.4f6164321d10c7a54a54398ccc7b11c1e7390e38 | 0385b0f83dbfc99c243ff066e3fe3cb2 | 4f6164321d10c7a54a54398ccc7b11c1e7390e38 | 32d76f2fe1188a131cb3219356639e83c60d47a703e40b8801a364d98e37128f |
7dc1e49f1664af70d85d31af70f29071 | 7dc1e49f1664af70d85d31af70f29071 | 1981f9a1d885c0ccb2d1f5910765a52d1989bc37 | f3bb44d52e43477ce43c91eb8d9830e356fc105b96377edd6b190fcccda61e2f |
Scada.Connect.Win.ConnectionImpl.dll | fc3b7f47958f6c1c6a93a2f2f970734c | 8030f2430234426ab3bdc8cdd995be7c4805d7d2 | ab801eaa9ad11199e1382a124d6024f9551a5a33ca1b9e5cafc0098621abb91f |
- | - | - | e2b2ebe1b82d1c122dc2750f318f2484fe5361fcd964bfdcdcae631cf32f8d37 |
srond | c02bee46d6a7a46f54e6abe003fec897 | 58d03630792f287184177660d9fd846fbde5416c | 4561a38ff34cc71cc73d54e2adfbd378f58d54596b012ff1841fdd7fc42063c3 |
scrond | ad5c0363e7e28c69007f891fbc3dd030 | 3dd9bd38a8f8166b1af25cb523a9a6f25b1791df | f56b7fbc5dda7e46aff1b7753a1edb1f6fad5c8953dd3dbff30b3d8675b1dbd3 |
Utilities we found during our research |
|||
/dev/shm/.gs-0/gsn | b3a07b9f99f8d36bda871b63d55afb01 | 7e3d46ce5aa7345d8b84e6145323366122bd21f4 | 9bad8f88be8f143e37616556b9331af69a806281019b8a336ee6e14cd04b3c0e |
check.zip | c1f3f6efb9ef18268eb3b841065e6554 | ca9a2e18119ac348962e2112c6681268e1df73d1 | 5a3a44d5482bb9b632d0a9da47e5ae7d27cd397ca08d764bdf1ed636565ef5e7 |
gsn_x86_64-alpine.tar.gz | e210c26d26a1395d9bc1de21fe1b2975 | 4ba1ae554f2cfeeccf250ba5a258a4ffb8651c66 | 8c545687a21481969ea4299e997cfc527a16503d042c2116801ee08f14ec6595 |
xlswifi | 376531d8a3a19016aa64d80dec23d980 | 0f621d371782f8e610c630f942a8951878e90bfe | f6e8220dbf407300fbc78d823004de5d0c4d2816218b8e2b5f8993e97f1e6a32 |
xlswired | fcc1ad58da960c5780a66fcc24c6c2fa | 928e4e776e82645fe14a53e2ad62b5cb75b98b53 | 017e03f9185e24c30de6b94bd6a36d48788d0b72134235e3f3dd1322dca426c9 |
3156.zip | 489fbca25049e5fab9dca10541e33214 | 91eeab83ddcd82a77804f2e5572d849dc846b225 | 9ec7495bb6d3a7d3bfd5d5ae9e704d0f42f3136166652a5576f15d0379126d75 |
4034 | a5fa43f822b6dd88298371232d49c597 | 1aa5b4deae98f707b0a529d97fd8e7f2372c549e | 7d2ae888fd06b811f6ba880c1fec3f37d49d50e0716de1b28f978240abe7795e |
bitrix.zip | d08bef69aee69d91b8cd0315175f665c | ada92c3a38e227aa8d42b4886e036caddba2cf84 | 0ac2f15f3a36e67b8e03f69685193480edf3e3b10fc69ccbec76d3d5878c708c |
fs | 89ae36448f1922870f1a09c29f17c775 | 3b1329e81739b1ea6acbb4ec4dff11f02ff42570 | f34bd1d485de437fe18360d1e850c3fd64415e49d691e610711d8d232071a0b1 |
get_wp-commentin.txt | 46eb5fa7c75cc29d89f3e48be26bbd46 | 36ef757aa3eedc3ec22bb56d60931c88cc62770e | c287956c4eb683e1ee62bc9ddb739d3d1c9c5dad7a73be3977bc53468665c7f7 |
install | 848faa5839487c4331cb2a1146811f23 | f67dbe68fc11139b719fec11784247c5f6e7ea93 | 37affeab7fb06a052413e9cc9272ea9cb2fd160fd204b506620d4303b06298c4 |
k | 0cda2ee10f5b8e9a241ef3e7e352752d | 6ffe11b31443bd9cef4928aa3f29b11d0e47ccec | 6262558adf132ae3c67d6f241c7abd62f987ce2881d459a66332234971e49e95 |
kit | 2cad1092a2828a33df2156a3a97d7cf1 | 27dd8d144d0ac3af9f4ad3df8a060d86166ae7a5 | c738d594d09c651109c4422acbecad23a461bab6cd4eafc41546f036816533a0 |
lock.zip | a2ff5b0bc0782560090574c992ccf995 | 97a3ead87af829f77dacfa23ab2786b21b427332 | c0cd580d83f4171b34b956d0c29dbc8fcafba8889594d85d471c14d7cf33be79 |
locker | d3064fe5d8a402b26099fcdbaeaedef1 | f07e31056001ccc26be75772c9a2f3972cd8d96a | 22ab2abda59edc1b6ba733fc140ab0c6b0c503b726a377a2e2ee6e6c95644aae |
m | fbb3f02b37b10bde868fed9d7b750fd8 | 7c27d25dbc01958724fd55f0fadf966e892d181e | 211a73ab3fb49957277a2efb50ad3140673b65df577961a58c3c9c90791e961e |
rev | 9b6122f1b4f6513c22b50ef05e881f38 | 6559a9eda3b8164e0c8926b4b71780f7744c4cb7 | 1b96adc3c129e7e41f7c67f0d56dc05d6cdee31f69ff85f27e6a90270cfefdcf |
sf | bc421b337fc639749528f2e756239269 | d75faee2f8ec90a69354a2c033f20e18e5ed0589 | bc159721bbe192f9c5cd24d3e9356a28f5b0c6b182de9fecf0b0ac28035f566a |
spark | 76cc921e5b26a0720db213479bff1ea2 | f640f70d1b65b0bfc8bcbf5261f3cdc85cfe7a21 | 1807c7a44da958f15e4dcb77cab78e92eeb96b3ace91d6923c2022d646d5593c |
w.txt | 3500760bc3e69102e01d256637f5f4a8 | 6ff2821bef28476341b75b67d9c9f2d66d4b6cfe | a5e61987676b7aed2c6d6d32c657f9351c2daa7c36365db20713dd42a03b1504 |
wef | b7735e157273a013f26515f0c969b093 | 5e79fffbbafddeb2d85c8fe835b07eeda08cc319 | 86bd9caab7526f2cd7e468d692ee2bac571465d25eb0619a10b0b46ae9a5b8e2 |
y.txt | 166a248f264fbf11998c86e8b384e47a | 9de84bd7118dee80f5b309ddbc46dc31283cbb0e | 91136b3145a52b66a3f5edd7d8a8d06698666300f24861074df1308491f50ba5 |
Modified legitimate utilities |
|||
ps | 4a04baf3c65581bcd14fbaf58aa6860b | 352a62abc61c93fdb08f6f4201326f147cb819ca | 895988088f25c89295f1a17f222a4553eafb2137b115f2ad4a0a25d273eb6521 |
netstat | 83b8aa078be2a0a5ca0ebf1968989a4b | a16120cca64e0c9a73f02975691e4675bb4c44a4 | a6dfef8616959969c06b65685e39929630f2819e6d5920498cdb1e89185ab7cd |
ps | b7db832b2598c83b7b077ce603a3ff73 | 1af6946263f4f548ffcf510c9f68378a4d7e0895 | 20927a1fc3441668264673d77c81652818a630f3b2055545b0e0938c523827c3 |
ss | 415d091f42fc62e8dfb6f8bb5ce641c5 | ad6653a7ee1bcb9590f5da12cf46d856135bbb71 | a9b1a99729860c004fbef463958871956cbb3c8e365383042978c260012055bd |
htop | eda9ca5f9405b5e2d004a4ba5c0dcd16 | 1fc930a59587fd9faf7536add47d92de0cecea53 | a9b1a99729860c004fbef463958871956cbb3c8e365383042978c260012055bd |
netstat | eda9ca5f9405b5e2d004a4ba5c0dcd16 | 1d4c0b3c74ddacf7459743cc60dd2a819c0c7e27 | 7e8bde3e34fbf9b99b7915e12de42f6b806153e44b6aaf68b172db50e18e3b9e |
ps | d215a54c581ab62079389c852d9ef84f | 7e0a4c53bf3dfcb08993231539986a220a6803fd | ac0906ff674c555e102f076100d0c12ea4a4aa7d74cc15f67c4038a84100f4cf |
ss | ffc418b222c08f3071ff53cde4acb22e | 2683dcce7fc3886f8305030b128103bd82cea528 | 8fe0ba1cb68225ab9a2cb11c1419f52adb03898c5f11d2221ba9765843443d24 |
Network indicators
pkg.collect.net.in |
leo.rpm-bin.link |
lib.rest |
45.146.7.26 |
rosm.pro |
193.37.71.75 |
sula.rpm-bin.link |
45.146.7.16 |
get.upd-rkn.net |
rls.upd-rkn.net |
94.131.113.95 |
mtp.upd-rk.net |
get.upd-rk.net |
src.setup.mom |
45.147.200.165 |
wired.setup.mom |
188.127.225.231 |
get.rpm-bin.link |
75.119.130.76 |
135.125.107.221 |
45.87.247.239 |
ci.upd-rkn.net |
base.upd-rkn.net |
mtp.upd-rkn.net |
bot.upd-rkn.net |
narwhal.rpm-bin.link |
unicorn.rpm-bin.link |
ci.rpm-bin.link |
ops.rpm-bin.link |
lib.rpm-bin.link |
rhl.rpm-bin.link |
source.rpm-bin.link |
chifa.rpm-bin.link |
amd64.rpm-bin.link |
get.setup.mom |
trust.setup.mom |
File signatures
rule PTESC_apt_linux_UA_Excobalt__RiskTool__PsPatched{ strings: $s = "For more details see ps(1)." $readproc_patched = {48 8B BB A8 02 00 00 48 ?? ?? 74 0DE8 ?? ?? ?? ?? 85 ?? 0F 85 81 05 00 00 48 8B BB 28 03 00 00 48 ?? ?? 74 0D E8 ?? ?? ?? ?? 85 C0 0F 85 68 05 00 00 41 8B 54 24 50 48 89 D8 85 D2 74 13 83 7B 04 02 0F 84 52 05 00 00 83 ?? ?? 0F 84 49 05 00 00} condition: ( uint32be ( 0 ) == 0x7f454c46 ) and ( all of them ) } rule PTESC_apt_linux_UA_Excobalt__RiskTool__NetstatPatched{ strings: $s = "usage: netstat [-vWeenNcCF] [] -r" $main_patched = {48 8D 05 ?? ?? ?? ?? 4A 8B ?? ?? 0F B6 [1-2] 8D 50 ?? 80 FA ?? 76 ?? 84 C0 74 ?? 66 0F EF C0 31 F6} condition: ( uint32be ( 0 ) == 0x7f454c46 ) and ( all of them ) } rule PTESC_apt_linux_UA_Excobalt__RiskTool__SsPatched{ strings: $s = "Usage: ss [ OPTIONS ]" $main_patched = {48 63 FD 48 8D 05 ?? ?? ?? ?? 4C 89 EE 83 C5 ?? 48 C1 E7 ?? BA ?? ?? ?? ?? 48 01 C7 E8 ?? ?? ?? ?? 83 FB ?? 0F 9E C0 83 FD ?? 0F 9E C2 48 83 C3 ?? 20 D0 0F 85 ?? ?? ?? ??} condition: ( uint32be ( 0 ) == 0x7f454c46 ) and ( all of them ) } rule PTESC_apt_linux_UA_Excobalt__RiskTool__HtopPatched{ strings: $s = "/.htoprc" $readproc_patched = {48 89 DF E8 ?? ?? ?? ?? 48 8B 7B ?? 48 85 FF 74 ?? E8 ?? ?? ?? ?? 85 C0 75 ?? 48 8B 7B ?? 48 85 FF 74 ?? E8 ?? ?? ?? ?? 85 C0 75 ??} condition: ( uint32be ( 0 ) == 0x7f454c46 ) and ( all of them ) } rule PTESC_apt_multi_UA_Excobalt__Backdoor__GoRed__Obf{ strings: $s1 = ").Parse" ascii nocase $s2 = ").MarshalBinary" ascii nocase $s3 = ").UnmarshalBinary" ascii nocase $s4 = ").Request" ascii nocase $s5 = ").Connect" ascii nocase $s6 = ").MarshalJSON" ascii nocase $s7 = ").Hash" ascii nocase $s8 = ").Add" ascii nocase $s9 = ").Close" ascii nocase $s10 = "JWT" ascii nocase $s11 = "config" ascii nocase $s12 = "GET" ascii nocase $s13 = "POST" ascii nocase $s14 = "a5674391" ascii nocase $c1 = {0F B6 54 0C ? ? 0F B6 74 0C ? ? 29 D6 40 88 74 0C ? ? 48 FF ? ? 48 83 F9 ? ? 7C ? ? } $c2 = {0F B6 54 04 ? ? 0F B6 74 04 ? ? 31 D6 40 88 74 04 ? ? 48 FF ? ? 66 0F 1F 44 00 ? ? 48 83 F8 ? ? 7C ? ? } $c3 = {0F B6 54 0C ? ? 0F B6 74 0C ? ? 01 F2 88 54 0C ? ? 48 FF ? ? 48 83 F9 ? ? 7C ? ? } condition: ((uint32be(0) == 0x7f454c46) or (uint16be(0) == 0x4d5a)) and (all of them) } rule PTESC_apt_multi_UA_Excobalt__Backdoor__GoRed{ strings: $s1 = "embedded.GetConfig" ascii nocase $s2 = "common.runInBackground" ascii nocase $s3 = "common.run" ascii nocase $s4 = "common.RunCommand" ascii nocase $s5 = "revsh" ascii nocase $s6 = "dns" ascii nocase $s7 = "ws" ascii nocase $s8 = "dump" ascii nocase $s9 = "shell" ascii nocase $s10 = "files" ascii nocase condition : ((uint32be(0) == 0x7f454c46) or (uint16be(0) == 0x4d5a)) and (all of them) }
MITRE TTPs
ID | Name | Description |
---|---|---|
Reconnaissance |
||
T1595.002 | Active Scanning: Vulnerability Scanning | ExCobalt used tools such as fscan to scan the system for vulnerabilities |
Resource Development |
||
T1583.001 | Acquire Infrastructure: Domains | ExCobalt registered domains and used these in its attacks |
T1583.002 | Acquire Infrastructure: DNS Server | ExCobalt used purchased DNS servers for tunneling |
T1587.003 | Develop Capabilities: Digital Certificates | ExCobalt created self-signed digital certificates for mutual TLS authentication for its GoRed backdoor |
Initial Access |
||
T1199 | Trusted Relationship | ExCobalt infiltrated an infrastructure and further developed the attack by taking advantage of a previously compromised contractor |
T1195.001 | Supply Chain Compromise: Compromise Software Dependencies and Development Tools | ExCobalt infected a component used to build the target company's legitimate software |
Execution |
||
T1059.003 | Command and Scripting Interpreter: Windows Command Shell | ExCobalt used the Spark RAT, which leveraged cmd.exe for command execution |
T1059.004 | Command and Scripting Interpreter: Unix Shell | ExCobalt used shell scripts, such as an sh script to install kitsune |
T1059.006 | Command and Scripting Interpreter: Python | ExCobalt used Python scripts for C2 communications |
T1106 | Native API | ExCobalt used the GoRed backdoor, which leveraged built-in Windows/Linux API calls to execute system commands |
Persistence |
||
T1053.003 | Scheduled Task/Job: Cron | ExCobalt used the GoRed backdoor, which leveraged cron to gain persistence in the system |
T1505.003 | Server Software Component: Web Shell | ExCobalt used various web shells to gain persistence |
T1136.001 | Create Account: Local Account | ExCobalt created accounts in compromised systems |
Privilege Escalation |
||
T1068 | Exploitation for Privilege Escalation | In its attacks, ExCobalt exploited the following vulnerabilities: CVE-2022-2586, CVE-2021-3156, CVE-2021-4034, CVE-2019-13272, CVE-2022-27228, CVE-2021-44228, CVE-2021-40438, CVE-2023-3519, BDU:2023-05857, and CVE-2019-12725 |
Defense Evasion |
||
T1140 | Deobfuscate/Decode Files or Information | ExCobalt used various tools to deobfuscate and decode files, including the Spark RAT, which relied on a custom XOR algorithm to decrypt the payload |
T1027.002 | Obfuscated Files or Information: Software Packing | ExCobalt used the Spark RAT packaged with Enigma Protector to conceal its contents |
T1027 | Obfuscated Files or Information | ExCobalt used the GoRed backdoor whose earlier versions were obfuscated with garble |
T1601.001 | Modify System Image: Patch System Image | ExCobalt used modified ps, netstat, ss, and htop utilities that hid gsocket network connections by removing them from the list of returned connections |
T1070.004 | Indicator Removal: File Deletion | ExCobalt removed files from the file system using the rm command |
Credential Access |
||
T1003.008 | OS Credential Dumping: /etc/passwd and /etc/shadow | ExCobalt used the GoRed backdoor to obtain passwords from /etc/shadow |
T1003.001 | OS Credential Dumping: LSASS Memory | ExCobalt used tools for dumping the system process lsass.exe |
Discovery |
||
T1082 | System Information Discovery | ExCobalt used various tools to obtain a system's host name, keyboard layout, and language information |
T1614.001 | System Location Discovery: System Language Discovery | ExCobalt used various tools to obtain system language information |
T1033 | System Owner/User Discovery | ExCobalt used various tools to obtain information about users |
T1087.001 | Account Discovery: Local Account | ExCobalt used the GoRed backdoor to receive information about the victim's account |
T1083 | File and Directory Discovery | ExCobalt used various tools, including the GoRed backdoor, to scan the file system |
T1046 | Network Service Discovery | ExCobalt used the GoRed backdoor to scan the gomap package, an nmap-like Go module |
T1057 | Process Discovery | ExCobalt used various tools, including the GoRed backdoor, to obtain information about active processes |
Lateral Movement |
||
T1021.004 | Remote Services: SSH | ExCobalt navigated the network via SSH, installing gsocket in the process |
T1021.002 | Remote Services: SMB/Windows Admin Shares | ExCobalt used the SMBExec utility |
T1021.001 | Remote Services: Remote Desktop Protocol | ExCobalt used RDP to connect |
T1563.001 | Remote Service Session Hijacking: SSH Hijacking | ExCobalt intercepted the contents of outgoing SSH sessions |
Collection |
||
T1560.001 | Archive Collected Data: Archive via Utility | ExCobalt used the knife utility to archive files using the gz < filename> command |
T1560.002 | Archive Collected Data: Archive via Library | ExCobalt used the GoRed backdoor to archive data for exfiltration via the gzip and tar Go packages |
T1074 | Data Staged | ExCobalt used the GoRed backdoor to store collected data in an archive before exfiltrating |
Command And Control |
||
T1071.001 | Application Layer Protocol: Web Protocols | ExCobalt used the Spark RAT, which relied on HTTP POST requests to communicate with its C2 server to get commands, and GoRed, which leveraged WS for C2 communications |
T1132.001 | Data Encoding: Standard Encoding | ExCobalt used various tools, including the Spark RAT, to encrypt messages sent to the C2 server in Base64 |
T1071.004 | Application Layer Protocol: DNS | ExCobalt used the GoRed backdoor, which leveraged DNS tunneling for C2 communications |
T1572 | Protocol Tunneling | ExCobalt used the GoRed backdoor, which utilized DNS and ICMP protocol tunneling |
T1132.002 | Data Encoding: Non-Standard Encoding | ExCobalt used the GoRed backdoor, which leveraged Base32 to tunnel DNS traffic |
T1573.001 | Encrypted Channel: Symmetric Cryptography | ExCobalt used the GoRed backdoor, which leveraged AES-256-GCM to encrypt exfiltrated data |
T1090.001 | Proxy: Internal Proxy | ExCobalt used the GoRed backdoor, which could act as a proxy server |
T1095 | Non-Application Layer Protocol | ExCobalt used the GoRed backdoor, which leveraged RPC, QUIC, and ICMP tunneling to communicate with its C2 server |
Exfiltration |
||
T1041 | Exfiltration Over C2 Channel | ExCobalt used various tools, including the Spark RAT, to transmit data over the C2 channel |
T1048.001 | Exfiltration Over Alternative Protocol: Exfiltration Over Symmetric Encrypted Non-C2 Protocol | ExCobalt used the GoRed backdoor, which leveraged HTTPS to exfiltrate data encrypted by AES-256-GCM |
T1020 | Automated Exfiltration | ExCobalt used the GoRed backdoor to automatically exfiltrate data to the threat actor's domain |
T1567 | Exfiltration Over Web Service | ExCobalt used the GoRed backdoor to exfiltrate data to the threat actor's server. The server acted as an exfiltration mechanism rather than a C2 server |
Impact |
||
T1485 | Data Destruction | ExCobalt used the locker wiper ransomware to encrypt the system |
T1486 | Data Encrypted for Impact |
Verdicts by Positive Technologies products
PT Sandbox
apt_multi_UA_Excobalt__Backdoor__GoRed |
apt_multi_UA_Excobalt__Backdoor__GoRed__Obf |
apt_linux_UA_Excobalt__RiskTool__PsPatched |
apt_linux_UA_Excobalt__RiskTool__NetstatPatched |
apt_linux_UA_Excobalt__RiskTool__HtopPatched |
apt_linux_UA_Ruh8__Dropper__kit |
tool_multi_ZZ_WebShell__Backdoor__Generic__PHP |
tool_multi_ZZ_WebShell__Backdoor__PHP__Obfuscated |
tool_multi_ZZ_Gsocket__NetTool |
MaxPatrol SIEM
Unix_Boot_Modify (mod probe) |
Unix_System_Information_Discovery |
Unix_Connect_from_Suspicious_Dir |
Unix_Suspicious_Command |
PT NAD
BACKDOOR [PTsecurity] GoRed Request sid: 10011377 |
BACKDOOR [PTsecurity] GoRed Exfiltration sid: 10011378 |
ATTACK AD [PTsecurity] Anonymous SMB connect to IPC share sid: 10005876, 10005877 |
TOOLS [PTsecurity] .gs.thc.org domain resolve. Probably activity gsocket sid: 10009306 |
TOOLS [PTsecurity] gsocket server activity sid: 10009305 |
SUSPICIOUS [PTsecurity] Suspicious communication using UA go-external-ip & External IP Check sid: 10011380 |
POLICY [PTsecurity] HTTP Host header RFC2616 violation sid: 10011339 |
POLICY [PTsecurity] Unsuccessful SMB Port Scan External Network sid: 10001310, 10003655 |