Kimsuky - Gomir Linux backdoor
Kimsuky, also known as Velvet Chollima, is a North Korean advanced persistent threat (APT) group primarily engaged in cyber-espionage. Since its emergence around 2012, Kimsuky has targeted entities across South Korea, Japan, the United States, and various European countries.
Kimsuky is notorious for its sophisticated social engineering techniques, frequently deploying spear-phishing campaigns to gain initial access.
The group is also adept at exploiting vulnerabilities in widely-used software, leveraging both zero-day exploits and known security flaws to infiltrate systems. Kimsuky’s operations are characterized by a blend of stealth and persistence, making it difficult for victims to detect and remove them from compromised networks.
Their activities align closely with the strategic interests of the North Korean regime, reflecting a broader agenda of gathering intelligence to support state objectives, circumvent international sanctions, and bolster national defense capabilities. Their actions have significant implications for global cybersecurity, highlighting the persistent and evolving nature of nation-state cyber threats.
Their latest attacks involves the exploitation of vulnerabilities in ScreenConnect software to deploy a new malware variant named ToddlerShark. This malware is designed for long-term espionage and intelligence gathering. Kimsuky has been leveraging two specific flaws, CVE-2024-1708 and CVE-2024-1709, which allow for authentication bypass and remote code execution.
Build information
SHA256 Hash: 30584f13c0a9d0c86562c803de350432d5a0607a06b24481ad4d92cdf7288213 (VirusTotal)
The backdoor is built using Golang 1.10 in ELF 32 format.
Program Flow
The flow of the sample starts off with installing a the malware for persistence and then periodically checking for new commands via the hardcoded command and control URL.
The sample will begin by calling syscall ‘202’ which resolves to the ‘getegid32()’ function. This function is responsible for getting the group identity. The sample is attempting to determine if the group ID is ‘0’ or ‘root’. If the process is running under group 0, the sample will attempt to install a new service under ‘systemd’ (see persistence below) . If the process is not under group 0, the sample will attempt to install a new service under ‘crontab’ (see persistence below).
Once persistence has taken place, the sample will then periodically call its command and control infrastructure to run commands or send results to the attacker.
Persistence
The persistence mechanism depends on the output from the syscall 202 or getegid32() call. The sample will install itself in either the crontab or the systemd service if the group ID of the process is running under root or not.
CronTab
The sample will attempt to install itself into the existing crontab. The sample will first get the existing cron entries by utilizing the ‘crontab -l’ command via the local shell. The output from the command will be copied into a new cron entry buffer. This buffer contains the new cron entry ‘@reboot <path to executable>’.
The new cron job will act as the persistence mechanism that will start/restart the process when the system is rebooted. The cron tab entry is stored in a file temporary called ‘cron.txt’, this file will be passed into as the first argument to the command ‘crontab’. Once the crontab is updated with the new entry, the ‘cron.txt’ is deleted.
Systemd service
The sample will obtain its currently running executable path and create a copy in ‘/var/log/syslogd’.
A new ‘systemd’ service is created in the directory ‘/etc/systemd/system/’. This file is named ‘syslogd.service’. This is used to confuse the system administrators into overlooking the service, which points to a fake ‘/var/log/syslogd’ which is the current running sample. This new service file will allow for Gomir to be executed upon restarting the system, and ensure that it is loaded after the ‘network’ target units. This means that the backdoor will have the ability to reach out of the already initialized network interfaces.
The ‘systemctl’ command is used to reload the systemd units (the new service file) and dependencies.
Lastly, the sample will remove itself from the filesystem and rely on the newly created systemd service file and the copy of the malware located in ‘/var/log/syslogd’.
Command and Control
The sample will make use of a hardcoded IP and URL via HTTP. The sample uses HTTP post requests to execute commands and send results to the C2 infrastructure. The C2 can be found in the sample at the address ‘0x0834F79F’ in the ‘.rodata’ section. The commands are made up of integer values indicating the type of command to execute. This is easily changed by the threat actor, and the payload format is structured as four bytes for the encryption key and variable length for the command.
Alienvault has a record for the hardcoded IP address 216.189.159[.]34. A verdict of malicious was tagged, along with a list of aliases, countries and campaigns the Kimsuky threat actor is part of.
Once the C2 is contacted, it will attempt to use base64 encoded payloads with a custom encryption algorithm via HTTP traffic. The commands downloaded have the first few bytes checked for the command type.
The sample supports a socks proxy, which will allow traffic through the backdoored victim on behalf of the C2 infrastructure.
Both the command shell and the codepage for output from the shell can be modified by the attacker. This allows the attacker to control the shell prior to executing commands and sending the results back to the infrastructure. The code page is especially important as it will ensure the character map used for the results is compatible with the infrastructures expectations. This leads me to believe that the infrastructure has some automated process to parse the command results.
The sample supports retrieving the shutdown command, retrieval of the current working directory of the process, modifying the working directory using ‘chdir’, executing commands via the configured shell (defaults to ‘/bin/sh’) and sleeping the connection to a desired time.
Commands to handle the location of the running executable via ‘/proc/self/exe’, size of directory and filesystem, system information discovery and creating a new TCP connection on a new port. All of these commands use existing Linux host binaries or the Golang runtime.
The filesystem size is done by first obtaining the size in raw bytes, then converting them to human readable values via the github project ‘go-humanize’ @ github.com/dustin/go-humanize
The system information is obtained by utilizing the ‘/proc/sys/kernel/hostname‘ and the username via syscall 199 or the ‘getuid32()’ function. This function returns the real ID of the user for the calling process.
For the CPU information the golang library ‘klauspost/cpuid’ was used this can be found @ github.com/klauspost/cpuid
For the System memory, the golang library 'pbnjay/memory’ was used this can be found @ ‘github.com/pbnjay/memory’. The raw sizes are converted using the go-humanize library.
Lastly the network interfaces are obtained using the Linux ‘route’ information.
Hibernating allows the sample to sleep the C2 connection until some specified time. This can be useful if the threat actor wanted to stay “silent” during peak activity hours of the victim. Once the timer is up, new commands will be automatically downloaded from the C2 infrastructure.
The sample has the ability to download or send files to the C2 infrastructure depending on the command. This is done via the golang file read, file write methods and the existing HTTP post requests to the C2 infrastructure.
YARA
rule GomirBackdoor {
meta:
description = "Rule to detect Gomir Backdoor"
author = "ShadowStackRe.com"
date = "2024-05-22"
Rule_Version = "v1"
malware_type = "backdoor"
malware_family = "gomir"
License = "MIT License, https://opensource.org/license/mit/"
Hash = "30584f13c0a9d0c86562c803de350432d5a0607a06b24481ad4d92cdf7288213"
strings:
$strCronText = "cron.txt"
$strHttpResPathMIR = "mir/"
$strSystemDSvc = "syslogd.service"
$strSocksList = "Socks list"
$strCmdPath = "CmdPath:"
$strCodePage = "Codepage:"
$strNextConnTime = "Next Connection Time:"
$strTCPOpenedIndicator = {
C7 44 24 29 5B 2B 5D 20
C7 44 24 2C 20 4F 70 65
C7 44 24 30 6E 65 64 2E
}
condition:
all of them and filesize < 6MB
}