REDXOR MALWARE

Based on Tactics, Techniques, and Procedures (TTPs) the backdoor is believed to be developed by Chinese nation-state actors

The backdoor masquerades itself as polkit daemon. We named it RedXOR for its network data encoding scheme based on XOR. The malware was compiled on Red Hat Enterprise Linux

We provide recommendations for detecting and responding to this threat below

Intro
2020 set a record for new Linux malware families. New malware families targeting Linux systems are being discovered on a regular basis. Backdoors attributed to advanced threat actors are disclosed less frequently.

We have discovered an undocumented backdoor targeting Linux systems, masqueraded as polkit daemon. We named it RedXOR for its network data encoding scheme based on XOR.

Based on victimology, as well as similar components and Tactics, Techniques, and Procedures (TTPs), we believe RedXOR was developed by high profile Chinese threat actors. The samples, which have low detection rates in VirusTotal, were uploaded from Indonesia and Taiwan, countries known to be targeted by Chinese threat actors. The samples are compiled with a legacy GCC compiler on an old release of Red Hat Enterprise Linux, hinting that RedXOR is used in targeted attacks against legacy Linux systems.

During our investigation we experienced an “on and off” availability of the Command and Control (C2) server indicating that the operation is still active.

Connections to Chinese Threat Actors
We uncovered key similarities between RedXOR and previously reported malware associated with Winnti umbrella threat group. These malware are PWNLNX backdoor and XOR.DDOS and Groundhog, two botnets attributed to Winnti by BlackBerry.

The below samples can be used for reference:

PWNLNX – 4278ab79c34ea92788259fb43e535aa3
XOR.DDOS – d6a6dee6afa6879b729a0af3cde7ff33
Similarities between the samples:

Use of old open-source kernel rootkits: RedXOR uses an open-source LKM rootkit called “Adore-ng” to hide its process. Based on a FireEye report Winnti used this rootkit in their “ADORE.XSE” Linux backdoor. Embedding open-source LKM rootkits is a common Winnti technique. The group has been documented using Azazel and Suterusu.
The CheckLKM function name used by RedXOR has also been used in PWNLNX and XOR.DDOS.
Provides the operator with a pseudo-terminal: RedXOR uses Python pty shell by importing the python pty library. PWNLNX implements the pty shell function in c.

Figure 1: Python pty shell used in RedXOR

Encoding network with XOR: The backdoor encodes its network data with a scheme based on XOR. Encoding network data with XOR has been used in previous Winnti malware including PWNLNX.
Persistence service name: As part of its persistence methods, RedXOR attempts to create a service under rc.d. The developer added “S99” before the name of the service to lower its priority and make it run last on system initiation. This technique was used in XOR.DDOS and Groundhog samples where the malware developer added “S90” to the service name.
Main functions flow: PWNLX and RedXOR have a main function which is in charge of initialization. In both backdoors, the main function calls another function which is in charge of the main logic. The main logic function names are main_process in RedXOR and MainThread in PWLNX. Both main functions daemonize the process to detach from the terminal and run in the background.
XML for file listing: RedXOR’s directory function and PWNLNX’s getfiles function are both in charge of directory listing. Their code flow implementation is different, however, as both malware send the directory listing as an XML file to the C2 server. Figure 2 shows the XML structure used in PWNLNX and RedXOR. The file’s data used in both functions are: path, name, type, user, permission, size, time.


Figure 2: The XML structure used by PWNLNX’s getfiles function and RedXOR’s directory function

Legacy Red Hat compilers: RedXOR and PWNLNX were both compiled with a Red Hat 4.4.7 compiler. This compiler is the default GCC compiler on RHEL6.
Chown similarity: Both PWNLNX and RedXOR change the file’s user and group owner to a large ID. The same technique has been used by the XOR.DDoS malware as referenced in the analysis by MalwareMustDie.


Figure 3: Similarity between PWNLNX and RedXOR of the UID and GID used with “lchown” function call
Overall flow and functionalities: The overall code flow, behavior, and capabilities of RedXOR are very similar to PWNLNX. Both have file uploading and downloading functionalities together with a running shell. The network tunneling functionality in both families is called “PortMap”.
Unstripped ELF binaries: Malware developers will often tamper with a file’s symbols and/or sections, making it harder for researchers to analyze them. However, RedXOR and various Winnti malware, including PWNLNX and XOR.DDOS, are unstripped.
Technical Analysis
The samples are both unstripped 64-bit ELF files called po1kitd-update-k. Uploaded to VirusTotal from Taiwan and Indonesia, they are low detected at the time of this writing.

Figure 4: 2bd6e2f8c1a97347b1e499e29a1d9b7c in VirusTotal

Malware Installation
Upon execution RedXOR forks off a child process allowing the parent process to exit. The purpose is to detach the process from the shell. The new child determines if it has been executed as the root user or as another user on the system. It does this to create a hidden folder, called “.po1kitd.thumb”, inside the user’s home folder which is used to store files related to the malware. The malware creates a hidden file called “.po1kitd-2a4D53” inside the folder. The file is locked to the current running process, seen in Figure 5, essentially creating a mutex. If another instance of the malware is executed, it also tries to obtain the lock but ultimately fails. Upon this failure the process exits.

Figure 5: The malware creates a “mutex” file locking it to the process ID

After the malware creates the mutex, it installs itself on the infected machine. As shown in Figure 6, the malware looks up its current path and moves the binary to the created folder. It hides the file by naming it “.po1kitd-update-k”.

Figure 6: Malware moves the binary to the hidden folder “po1kitd.thumb” created earlier. It first tries to use the “rename” function provided by libc. If this fails, it executes an “mv” shell command via the “system” function

After installing the binary to the hidden folder, the malware sets up persistence via “init” scripts. The following files are created after executing the malware on boot:

/usr/syno/etc/rc.d/S99po1kitd-update.sh
/etc/init.d/po1kitd-update
/etc/rc2.d/S99po1kitd-update
The malware checks if the rootkit is active by creating a file and removing it. Then, the malware compares the “saved set-user-ID” of the process to the user ID. If they don’t match, the rootkit is enabled. If they match, it looks to see if the user ID is “10”. If this is the case, the rootkit is enabled. This logic is shown in Figure 7.

Figure 7: Logic used by RedXOR to check if the rootkit is enabled

The “CheckLKM” logic is almost identical to the “adore_init” function in the “adore-ng” rootkit. Afore-ng is a Chinese open-source LKM (Loadable Kernel Module) rootkit. This technique allows the malware to stay under the radar by hiding its processes. The code for the init function is shown in Figure 8.

Figure 8: Client authentication code for the adore-ng rootkit

Configuration
The malware stores the configuration encrypted within the binary. In addition to the Command and control (C2) IP address and port it can also be configured to use a proxy. The configuration includes a password, as can be seen in Figure 9. This password is used by the malware to authenticate to the C2 server.

Figure 9: Configuration options for the malware

The configuration values are decrypted by the “doXor” function. A pseudo-code representation of the function is shown in Figure 10. The decryption logic is a simple XOR against a byte key. The byte key is incremented by a constant for each item in the buffer. The only configuration value that is not encrypted is the server port. The port value is used to derive the key and the adder. The key is derived from bit shifting the port value eight steps to the right. The constant uses the port value.

Figure 10: Decryption logic of the configuration data. The data is XORed against a key byte that is incremented by a constant for each entry in the buffer

Communication with the C2
The malware communicates with the C2 server over a TCP socket. The traffic is made to look like HTTP traffic. Figure 11 shows a pseudo-code representation of the function used by the malware to prepare data that is to be sent to the C2 server. First, it fills the buffer with null bytes. The request body is XORed against a key. The malware uses the buffer length as the key. This value is also passed into the function as the “total_length” argument.

Figure 11: Function for preparing data to be sent to the C2 server

The same logic is used to decrypt the response body from the C2 server. From the response, the malware extracts “JSESSIONID”, “Content-Length”, “Total-Length” and the response body. The data is added to a struct with the following layout:

0x0 JSESSIONID as int

0x8 Content-Length as long

0x10 Total-Length as long

0x18 Response body

The content length is the length of the response body but also used as the key. The total length value is used as a constant which is added to the key in each iteration. The JSESSIONID value holds the command ID for the job the C2 wants the malware to perform.

Commands
The C2 server tells the malware to execute different commands via a command code that is returned in the “JSESSIONID” cookie. The codes are encoded as decimal integers. A full list of commands supported by the analyzed malware sample are shown in the table below. They can be grouped into command types. Commands in the 2000 range provide “filesystem” interaction, 3000 handle “shell” commands, and 4000 handle network tunneling.

Table 1: List of commands supported by the malware

Code

Command

0000

System information

0008

Update

0009

Uninstall

1000

Ping

1010

Install LKM

2049

List folder

2054

Upload file

2055

Open file

2056

Execute with system

2058

Remove file

2060

Remove folder

2061

Rename

2062

Create new folder

2066

Write content to file

3000

Start shell

3058

Exec shell command

3999

Close tty

4001

Portmap (Proxy)

4002

Kill portmap

System Information
When the malware first contacts the C2 server it sends a password encoded in the request body. The C2 server responds with the command code 0 to collect system information. The data collected about the system by the malware is listed in the table below. The data is serialized into a URL query-like string, encrypted and then sent as the request body.
Table 2: Data collected by the malware and sent back to the C2 server

URL key

Description

Comment

hostip

IP

Hardcoded to 127.0.0.1

softtype

Hardcoded to “Linux”

pscaddr

MAC address

hostname

Machine name

hosttar

Username

Possibly “host target”

hostos

Distribution

Extracted from /etc/issue or /etc/redhat-release

hostcpu

Clock speed

/proc/cpuinfo

hostmem

Amount of memory

/proc/meminfo

hostpack

Hardcoded to “Linux”

lkmtag

Is rootkit enabled

kernel

Kernel version

Extracted from uname

Figure 12 shows the communication between RedXOR and the C2. The malware sends the password “pd=admin” and C2 responds with “all right” (JSESSIONID=0000). Next, the malware sends the system information and the C2 replies with the ping command (JSESSIONID=1000).

Figure 12: RedXOR communication with C2

Update Functionality
The malware can be updated by the threat actor. This is performed by sending command code 8 to the malware. When the malware receives this code the following actions are taken:

The malware opens the mutex file for writing.
It sends a request with the command code 8 and an empty request body to the C2 server.
The response body from the server is written to the mutex file. The response body is not encrypted.
The lock is released on the mutex file.
The malware executes “chmod” to set the execution flag on the file via the libc system function.
The malware sleeps and tries to obtain the lock on the file again when it wakes up. If it fails, it assumes the update was successful, closes the connection to the C2 server and exits.
Shell Functionality
The malware has the ability to provide its operator with a “tty” shell. If a shell is requested via the command code 3000, the malware creates a new thread executing “/bin/sh”. In the new spawned shell, the malware executes python -c “import pty;pty.spawn(‘/bin/sh’)” to get a pseudo-terminal (pty) interface. Any shell commands sent to the malware with the command code of 3058 are executed in the pty and the response is returned to the operator.

Network Tunneling
Network tunneling is enabled by sending the command code 4001 to the malware. As part of the request, a “configuration” is sent as part of the response body. The configuration consists of three items separated by a “#” character. The items are: a port to bind to, the IP to connect to, and a port to connect to. The malware uses a modified version of the open-source project Rinetd for the tunneling logic. Rinetd is designed to use a configuration file stored on the machine. To get around this, the malware author has modified the function that parses the configuration in order to directly take the required values normally found in the configuration file.

Detection & Response

Detect if a Machine in Your Network Has Been Compromised
Use a Cloud Workload Protection Platform like Intezer Protect to gain full runtime visibility over the code in your Linux-based systems and get alerted on any malicious or unauthorized code or commands.

Try our free community edition

Figure 13 emphasizes an Intezer Protect alert on a compromised machine. The alert provides additional context about the malicious code including threat classification (RedXOR), binary’s path on the disk, process tree, command, and hash.

Figure 13: Intezer Protect alerts on RedXOR

We also recommend using the IOCs section below to ensure that the RedXOR process and the files it creates do not exist on your system.

Intezer Protect defends all types of compute resources—including VMs, containers and Kubernetes—against the latest Linux threats in runtime. Try our free community edition

Response
If you are a victim of this operation, take the following steps:

Kill the process and delete all files related to the malware.

Make sure your machine is clean and running only trusted code using a Cloud Workload Protection Platform like Intezer Protect.
Wrap Up
Linux systems are under constant attack given that Linux runs on most of the public cloud workload. A survey conducted by Sophos found that 70% of organizations using the public cloud to host data or workloads experienced a security incident in the past year.

Along with botnets and cryptominers, the Linux threat landscape is also home to sophisticated threats like RedXOR developed by nation-state actors.

RedXOR samples are indexed in Intezer Analyze so that you can detect any suspicious file that shares code with this malware. pasted image 0 6
Figure 14: RedXOR sample in Intezer Analyze

IoCs
RedXOR
0a76c55fa88d4c134012a5136c09fb938b4be88a382f88bf2804043253b0559f

0423258b94e8a9af58ad63ea493818618de2d8c60cf75ec7980edcaa34dcc919

Network
update[.]cloudjscdn[.]com

158[.]247[.]208[.]230

34[.]92[.]228[].216

Process name
po1kitd-update-k

File and directories created on disk
.po1kitd-update-k

.po1kitd.thumb

.po1kitd-2a4D53

.po1kitd-k3i86dfv

.po1kitd-nrkSh7d6

.po1kitd-2sAq14

.2sAq14

.2a4D53

po1kitd.ko

po1kitd-update.desktop

S99po1kitd-update.sh