APT37 - RokRat
Meet APT37 Group
APT37, also known as ScarCruft, Reaper, and Red Eyes, is a North Korean state-sponsored hacking group that has been active since 2012. Originally, its operations focused on public and private sectors within South Korea, though in 2017, it extended its targets to include Japan, Vietnam, the Middle East, and industries such as healthcare and manufacturing. By 2023, APT37 had shifted to phishing campaigns targeting users on both Windows and Android platforms.
The group is known for leveraging various attack vectors, including malicious LNK files spread via group chat platforms to infect victims.
Technical in Points
-
Infection Vector: The attack begins with phishing emails containing ZIP attachments that hide malicious LNK files, masquerading as documents related to North Korean affairs or trade agreements. When executed, the LNK file starts a multi-stage attack using batch scripts and PowerShell, finally having RokRat as the final payload.
-
Host Profiling: RokRat collects detailed system information, including the OS version, computer name, logged-in user, and executable path. It also retrieves hardware details, tracks system uptime, enumerates running processes and captures screenshots. This data is then exfiltrated to the Command-and-Control (C2) server.
-
C2 Communication: RokRat abuses cloud services like pCloud, Yandex, and Dropbox as its Command-and-Control (C2) channels, using their APIs to send, download, and delete files. It also embeds OAuth tokens within its code to facilitate seamless communication with these services.
-
Command Execution: RokRAT can execute commands on the infected system, allowing attackers to perform a wide range of activities, such as data exfiltration, system reconnaissance, and process termination. It can execute remote commands via cmd.exe, collect and upload files, scan system drives, delete specific files, and retrieve additional payloads from Command-and-Control (C2).
Infection Flow
The infection starts with phishing emails that look critical, as attackers use real information from websites to make them seem more believable. These emails contain ZIP files with malicious LNK files disguised as documents. When executed, it launches the next stage of the attack.
Stage 1 - LNK file
The code embedded within the .lnk
file executes commands that invoke PowerShell.
First, it checks if it’s running from System32 or Program Files. If so, it moves to the %temp%
directory. It then uses a simple trick to read itself by searching for .lnk
files with a size of 0x0DD4B11F
bytes.
Once found, it extracts multiple payloads from the .lnk
file and saves them in the %temp%
directory.
The extracted files are:
- At offset 0x111E, extracts 0xAD36 bytes and saves it as
.hwpx
, which is executed immediately. - At offset 0xBE54, extracts 0xD9190 bytes and saves it as
caption.dat
. - At offset 0xE4FE4, extracts 0x0636 bytes and saves it as
elephant.dat
. - At offset 0xE561A, extracts 0x0147 bytes and saves it as
sharkeba.bat
, which is then executed.
To automate the extraction process, I wrote a quick script.
import os
import sys
def extract_embedded_files(lnk_path, output_dir):
try:
if not os.path.exists(output_dir):
os.makedirs(output_dir)
with open(lnk_path, 'rb') as lnk_file:
lnk_file.seek(0x0000111E)
hwpx_data = lnk_file.read(0x0000AD36)
hwpx_path = os.path.join(output_dir, "extracted.hwpx")
with open(hwpx_path, 'wb') as f:
f.write(hwpx_data)
print(f"HWPX file extracted")
lnk_file.seek(0x0000BE54)
exe_data = lnk_file.read(0x000D9190)
exe_path = os.path.join(output_dir, "caption.dat")
with open(exe_path, 'wb') as f:
f.write(exe_data)
print(f"Caption.dat extracted")
lnk_file.seek(0x000E4FE4)
string_data = lnk_file.read(0x00000636)
string_path = os.path.join(output_dir, "elephant.dat")
with open(string_path, 'wb') as f:
f.write(string_data)
print(f"Elephant.dat extracted")
lnk_file.seek(0x000E561A)
bat_data = lnk_file.read(0x00000147)
bat_path = os.path.join(output_dir, "sharke.bat")
with open(bat_path, 'wb') as f:
f.write(bat_data)
print(f"Batch file extracted")
except :
print(f"Error occured ")
def main():
lnk_path = ''
output_dir = ''
extract_embedded_files(lnk_path, output_dir)
if __name__ == "__main__":
main()
Finally, it deletes the original .lnk
file to cover its tracks.
Stage 2 - The dropped files
HWPX document
This is a decoy document to make victims think they have opened a normal file while the real attack runs in the background. It appears to be a public service record form, commonly used in South Korea for official recommendations and recognitions.
shark.bat
Started by analyzing shark.bat
, which is extracted and executed. This batch script launches PowerShell in a minimized, hidden window. It then reads elephant.dat
from the %temp%
directory, loads it into memory, and executes it using Invoke-Command
.
elephant.dat
Despite its name, this is another PowerShell script designed to load and execute a payload in memory. It reads an encrypted file caption.dat (the fourth extracted file) from the %temp%
directory and decrypts it using a single-byte XOR key ‘d’ to obtain executable content.
Once decrypted, the script loads the necessary functions from kernel32.dll
to execute the payload in memory. It allocates memory and creates a thread to run the decrypted payload.
Stage 3 - shellcode
The decrypted shellcode decrypts the PE file from the hardcoded encrypted data.
The shellcode reads data from memory at offset 0x58B, where the first byte is the XOR key, the next four bytes give the encrypted data length, and the rest is the encrypted PE file. It decrypts the PE by XORing each byte with the key, loads it into memory, resolves imports and executes.
we can dump that decrypted PE file using this IDApython script .
def save_to_file(file_path, data):
with open(file_path, 'wb') as file:
file.write(data)
addr = 0x58B
xor_key = idc.get_bytes(addr, 1)
data_size = idc.get_wide_dword(addr + 1) # read 4-byte data size
enc_data = idc.get_bytes(addr + 5, data_size) # get encrypted data
dec_data = bytes(b ^ xor_key for b in enc_data)
save_to_file('dump_file.bin', dec_data)
Final payload - RokRat
The final payload is RokRat, a remote access Trojan (RAT) primarily used by the APT37 threat group. This sample was compiled in October 2024 and was previously seen in another attack in December 2024.
Anti analysis
Encrypted strings
Rokrat uses two custom string decryption techniques to hide its strings.
One technique involves storing strings as stack strings, encrypted using a simple subtraction-based transformation using the first character as a key, which is subtracted from each subsequent character along with a fixed value (2048).
Another method encrypts strings by using the first byte as a key. Each character is processed two bytes at a time, with the key subtracted from each to get the original text.
Here is the full decrypted string list :
Expand to see more
IsWow64Process
C:\Program Files\VMware\VMware Tools\vmtoolsd.exe
HARDWARE\DESCRIPTION\System
• SystemBiosVersion • "del \"%appdata%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*.VBS\" \"%appdata%\\*.CMD\" \"%appdata%\\*.BAT\" \"%appdata%\\*01\" \"%appdata%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*.lnk\" \"%allusersprofile%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*.lnk\" /F /Q"
• "del \"%appdata%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*.VBS\" \"%appdata%\\*.CMD\" \"%appdata%\\*.BAT\" \"%appdata%\\*01\" /F /Q"
• "tasklist>>\"%temp%\\r.txt\" & echo == Startup ==>>\"%temp%\\r.txt\" & dir /a \"%appdata%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\">>\"%temp%\\r.txt\" & dir /a \"%allusersprofile%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\">>\"%temp%\\r.txt\" & echo == Info ==>>\"%temp%\\r.txt\" & systeminfo>>\"%temp%\\r.txt\" & echo == Route ==>>\"%temp%\\r.txt\" & route print>>\"%temp%\\r.txt\" & echo == Ip ==>>\"%temp%\\r.txt\" & ipconfig /all>>\"%temp%\\r.txt\" & echo == arp ==>>\"%temp%\\r.txt"
• echo OK >> "%temp%\r.txt"
• echo BD >> "%temp%\r.txt"
• %spid:%d,name:%s,path:%s%s
• "SYSTEM\\CurrentControlSet\\Services\\mssmbios\\Data"
Anti-vm
Rokrat detects the existence of VMware Tools through vmtoolsd.exe. It first checks whether the executable exists in its default installation path and then retrieves its version details. If the file is found and its metadata is successfully extracted, it is assumed to be running inside a VMware virtual machine.
Detect sandbox
The function creates and then deletes a random file in C:\Windows, a common technique in malware and sandbox detection to test file system write permissions or introduce execution delays .
Also, Rokrat checks for a debugger using IsDebuggerPresent.
Gather host info
RokRat gathers detailed information about the compromised system. It first retrieves the system version and determines whether the process is running under WOW64
.
Also, it collects system-related details such as the computer name, the logged-in username, and the full path of the executable.
It retrieves extra system details from the registry and determines the system’s uptime in milliseconds, excluding sleep time.
It also extracts system details from the registry, including the SystemBiosVersion.
Process Enumeration
RokRat gathers details about running processes, including their Process ID (PID), executable name, and file path. The information is formatted as "%spid:%d,name:%s,path:%s%s"
, stored and prepared for exfiltration.
Capture a screenshot.
RokRat captures a screenshot, processes the image (converting it to JPEG), and prepares it for exfiltration.
C2 Communications
RokRat abuses legitimate cloud services such as pCloud, Yandex, and Dropbox as command and control (C2) channels. By using these platforms’ APIs, RokRat can seamlessly exfiltrate stolen data, download additional payloads, and execute commands, all while mixing into normal network traffic. Also, it features a test mode that lets it run on the local machine.
Operation | Cloud Provider | API |
---|---|---|
Upload File | Dropbox | https://content.dropboxapi.com/2/files/upload |
Yandex Disk | https://cloud-api.yandex.net/v1/disk/resources/upload?path=%s&overwrite=%s |
|
pCloud | https://api.pcloud.com/uploadfile?path=%s&filename=%s&nopartial=1 |
|
Download File | Dropbox | https://content.dropboxapi.com/2/files/download |
Yandex Disk | https://cloud-api.yandex.net/v1/disk/resources/download?path=%s |
|
pCloud | https://api.pcloud.com/getfilelink?path=%s&forcedownload=1&skipfilename=1 |
|
List Folder | Dropbox | https://api.dropboxapi.com/2/files/list_folder |
Yandex Disk | https://cloud-api.yandex.net/v1/disk/resources?path=%s&limit=500 |
|
pCloud | https://api.pcloud.com/listfolder?path=%s |
|
Delete File | Dropbox | https://api.dropboxapi.com/2/files/delete |
Yandex Disk | https://cloud-api.yandex.net/v1/disk/resources?path=%s&permanently=%s |
|
pCloud | https://api.pcloud.com/deletefile?path=%s |
It also contains OAuth tokens within its code to enable communication with these cloud services.
Mainly using pCloud for its Command-and-Control (C2) operations. It authenticates with pCloud via an HTTP request that contains a hardcoded OAuth token: JINs7ZDb7OvfloXrYZt8wH7kZ7LjAjGKBckj4kTgWSBiDSVWF1fKX
It also hides its HTTP traffic by spoofing its User-Agent string, making it appear as a legitimate Googlebot request:
Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
RokRat uses a combination of XOR obfuscation and RSA encryption before exfiltrating data. It first uses XOR encryption using randomly generated keys to obfuscate the data, making it less recognizable. Then, it encrypts the obfuscated data using RSA, ensuring that only the attacker, who owns the private key, can decrypt it.
Commands
RokRat retrieves encrypted commands from its Command-and-Control (C2) server, using AES-CBC mode for encryption. It then decrypts the commands locally and executes them on the system.
command ‘0’
This command sets the sent data flag to 0 (false), meaning that data collection should stop.
Command - ‘i’
This command sets the sent data flag to 1 (true), meaning that the collected information is ready to be sent to the command and control (C2) server.
Command - ‘j’ or ‘b’
This creates a termination process, forcing the malware to stop running and exit.
Command - ‘d’
This command performs a deletion operation to remove different script and shortcut files from the Windows Startup folder and the AppData directory. It targets .VBS
(VBScript), .CMD
, .BAT
(batch scripts), .LNK
(shortcuts), and any additional files created during execution.
del "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\*.VBS"
"%appdata%\*.CMD"
"%appdata%\*.BAT"
"%appdata%\*01"
"%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\*.lnk"
"%allusersprofile%\Microsoft\Windows\Start Menu\Programs\Startup\*.lnk" /F /Q
Once the deletion is complete, the command starts a termination process to shut down the RAT.
Command - ‘f’
This command is similar to the previous one, but it does not target .lnk (shortcut) files.
del \"%appdata%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\*.VBS\"\
"%appdata%\\*.CMD\" \
"%appdata%\\*.BAT\" \
"%appdata%\\*01\" /F /Q"
Once the deletion is complete, the command also starts a termination process to shut down the RAT.
Command - ‘g’
This command simply resets the memory and erases it, making it ready for another operation.
Command - ‘h’
This command scans all logical drives, including fixed, removable, and network drives, listing their contents recursively and saving the results in a temporary file. The file is then uploaded to the command and control (C2) server before being deleted to remove any traces.
Command - ‘e’
This command executes a received instruction from the C2 server via cmd.exe, allowing remote execution of system commands.
Command - ‘c’
This command receives a path from the C2 server and checks whether it’s a file or a directory. If the path is a directory, the function reads its files, processes them, encrypts their contents, and then uploads them to the C2 cloud server.
If the path is a file, a filtering is applied based on file extensions. When the filter is set to “Normal,” it specifically targets document-related file types such as .XLS
, .DOC
, .PPT
, .TXT
, .M4A
, .AMR
, .PDF
, and .HWP
. However, if the filter is set to “All,” it collects and uploads files of any type.
Commands [1-9]
These commands download a payload and execute it:
Download (Commands 1, 2, 5, 6):
These commands fetch secondary payloads dynamically from attacker-specified URLs. The process involves opening an HTTP connection to the URL and downloading the data without any additional decryption.
Download (Commands 3, 4, 7, 8, 9):
These commands download a payload from C2 cloud services. Once downloaded, the payload is decrypted, and its integrity is verified through checks.
Execution (Commands 1, 2, 3, 4):
In this case, the code checks if the download is successful. If it is, the code creates a new thread to execute the payload. If the execution is successful, it writes “OK” to a temporary text file (%temp%\r.txt)
. If the execution fails, it writes “BD” to the same file.
Additionally, a batch script is executed to gather system information, including :
- A list of running processes
- Startup items
- System configuration
- Routing details
This information is saved into the same temporary text file (r.txt), encrypted, and then exfiltrated to the C2 server. After exfiltration, the file is deleted .
Execution (Commands 5, 6, 7, 8, 9):
In this case, it also checks if the download is successful. If it is, it constructs a file path. Then, it creates a temporary file named KB400928_doc.exe
, writes the extracted data to it, and executes the file using ShellExecuteA
.
YARA Rule
rule detct_RokRat
{
meta:
description = "Detects Rokrat payload using some of the hardcoded strings "
author = "Mohamed Ezzat (@ZW01f)"
hash1 = "09a4adef9a7374616851e5e2a7d9539e1b9808e153538af94ad1d6d73a3a1232"
hash2 = "94159655fa0bfb1eff092835d8922d3e18ca5c73884fd0d8b78f42c8511047b6"
strings:
// apis used
$s0 = "https://api.pcloud.com/deletefile?path=%s" wide
$s1 = "https://api.dropboxapi.com/2/files/list_folder" wide
$s3 = "https://cloud-api.yandex.net/v1/disk/resources/upload?path=%s&overwrite=%s" wide
$s4 = "https://cloud-api.yandex.net/v1/disk/resources?path=%s&limit=500" wide
$s5 = "https://cloud-api.yandex.net/v1/disk/resources?path=%s&permanently=%s" wide
// file it use for download payloads .
$s6 = "KB400928_doc.exe"
$s7 = "%04d%02d%02d %02d%02d%02d" wide
condition:
uint16(0) == 0x5A4D and all of ($s*)
}
IoCs
Stage | Hash |
---|---|
Zip file | cfc814a16547dd4e92607bd42d2722cc567492e88d2830d7d28a0cc20bf3950c |
Lnk file | 7df7ad7b88887a06b559cd453e7b65230d0cccff1a403328a521d8753000c6c9 |
hwpx document | 9d96e4816a59475768d461a71cecf20fd99215ce289ecae8c865cf45feeb8802 |
shark.bat | 5306582c8a24508b594fed478d5abaa5544389c86ba507d8ebf98c5c7edde451 |
elephant.dat | 2b6928101efa6ededc7da18e7894866710c10794b8cbaf43b48c721e9731c41a |
caption.dat | 6d790df4a2c81e104db10f5e47eb663ca520a456b1305e74f18b2f20758ea4e1 |
shellcode - stage 3 | 1c4cd06ebece62c796ea517bf26cc869fa71213d17e30feb0f91c8a4cfa7ef1b |
RokRat - final payload | 09a4adef9a7374616851e5e2a7d9539e1b9808e153538af94ad1d6d73a3a1232 |