APT37 - RokRat

13 minute read

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.

API Response Process

Figure(1): Infection Flow Diagram

Stage 1 - LNK file

The code embedded within the .lnk file executes commands that invoke PowerShell.

API Response Process

Figure(2): LECmd output

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

API Response Process

Figure(3): The HWPX document on VT


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.

API Response Process

Figure(4): content of HWPX document

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.

API Response Process

Figure(5): The used script

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.

API Response Process

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.

API Response Process

Stage 3 - shellcode

The decrypted shellcode decrypts the PE file from the hardcoded encrypted data.

API Response Process

Figure(6): The decrypted shellcode.


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.

API Response Process

Figure(7): The structure of the encrypted data


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.

API Response Process

Figure(8): Rokrat on VT.


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.

API Response Process

Figure(9): Encrypted algorithms used.


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.

API Response Process

Figure(10): Anti vm used.

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 .

API Response Process

Figure(11): Detect sandbox.


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.

API Response Process

Figure(12): Gathered Information.


It also extracts system details from the registry, including the SystemBiosVersion.

API Response Process

Figure(13): Get hardware Info from registry.

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.

API Response Process

Figure(14): Process Enumeration function.

Capture a screenshot.

RokRat captures a screenshot, processes the image (converting it to JPEG), and prepares it for exfiltration.

API Response Process

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)

API Response Process

Figure(15): Example of Http request .


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.

API Response Process

Figure(16): function scans all logical drives.


Command - ‘e’

This command executes a received instruction from the C2 server via cmd.exe, allowing remote execution of system commands.

API Response Process

Figure(17): Command e.


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.

API Response Process

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.

API Response Process

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.

API Response Process

Figure(18): Download file from internet.


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.

API Response Process

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 .

API Response Process

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

References