Arctic Wolf Labs has been tracking two recent intrusions where threat actors leveraged a new Go-based malware downloader we are calling “CherryLoader” that allowed them to swap exploits without recompiling code. The loader’s icon and name masqueraded as the legitimate CherryTree note taking application to trick the victims. In the intrusions we investigated, CherryLoader was used to drop one of two privilege escalation tools, PrintSpoofer or JuicyPotatoNG, which would then run a batch file to establish persistence on the victim device.
- Arctic Wolf has observed a new loader, dubbed “CherryLoader”, written in Go used in recent intrusions.
- The loader contains modularized features that allow the threat actor to swap exploits without recompiling code.
- CherryLoader drops two publicly available privilege escalation exploits.
- CherryLoader’s attack chain leverages process ghosting and allows threat actors to elevate privileges and establish persistence on victim machines.
Based on incident response data and additional analysis, the threat actors initially leveraged the IP address 141.11.187[.]70 to serve the victim CherryLoader and associated files. Two files were downloaded from that IP, a password protected rar file (Packed.rar) and an executable (main.exe) used to unpack Packed.rar.
The Packed.rar file contained a Golang binary (cherrytree.exe) along with three additional files, NuxtSharp.Data, Spof.Data, and Juicy.Data. Cherrytree.exe was stripped and had its import address table destroyed to hinder analysis efforts.
Using static analysis, a unique reference for the project was found, revealing the author’s original project name “XorRunPeGoler”.
After CherryLoader and its associated files were extracted from the .rar file, the threat actors invoked CherryLoader using the following command:
Cherrytree.exe 405060EEw@! NuxtSharp.Data Spof.Data
Upon execution, the binary checks the arguments passed to it and compares the first argument (password) against a hardcoded MD5 password hash. If the hashes match, the binary proceeds to the next step, if not, CherryLoader quits.
The binary then allocates memory to read and decrypt the file passed via the second argument (NuxtSharp.Data). The file is then decrypted with a simple XOR algorithm.
To start the XOR loop, CherryLoader copies the XOR key “Kry” and allocates memory for the decrypted data. It then iterates over the NuxtSharp.Data file byte by byte and XORs the bytes with a letter that corresponds to an index in [“K”, “r”, “y”]. The index is limited with a modulus of 3 to avoid out of bounds access.
Notably, the decryption algorithm does not rely on the entered password, therefore, it can be patched, rendering the password argument useless. The password check is likely in place to deter analysis of the file. A python script to demonstrate the decryption process can be found here.
After the XOR loop completes and the file (NuxtSharp.Data) has been decrypted in memory, GetProcAddress is used to dynamically locate CreateFileW which saves the decrypted file as File.log in the %TEMP% directory.
After saving File.log to disk, the sample will dynamically locate the CreateProcessW function to run cmd.exe which, in turn, will run File.log as its child process:
cmd.exe /c File.log Spof.Data 123 12.log
After running the cmd.exe process, it dynamically locates and calls DeleteFileW and RemoveDirectoryW to delete any evidence in the %TEMP% directory.
File.log (a.k.a NuxtSharp.Data)
File.log is a PE file written in C and appears to have symbols referring to an original project named NuxtSharp. File.log represents the next stage in the attack chain which begins by decrypting Spof.Data.
Decrypting the Spoofer
CherryLoader runs File.log as a process with three additional arguments. The main function of the File.log executable will facilitate the passing of arguments to a function that will later decrypt and load the binary from memory.
File.log starts by creating a file named 12.log (the last argument specified on the command line). File.log then opens the encrypted Spof.Data file (first argument) and reads the data into a buffer for decryption.
Spof.Data is encrypted using AES ECB (Rijndael); the key “123” was passed as the second argument in the initial command line.
Notably, one of the other files found with CherryLoader, Juicy.Data, used the same encryption algorithm and key. Arctic Wolf has created a Python script that will aid in decrypting both Spof.Data and Juicy.Data, the script can be found in the appendix here.
Evasion Attempt (Process Ghosting)
Once File.log has completed the decryption of Spof.Data, it attempts to create a new process named 12.log using a fileless technique known as Process ghosting. This technique is modular in design and will allow the threat actor to leverage other exploit code in place of Spof.Data. In this case, Juicy.Data which contains a different exploit, can be swapped in place without recompiling File.log.
The process ghosting technique starts by creating a file using the CreateFile API with the DELETE flag set as its dwDesiredAccess parameter.
Then, it uses NtSetInformationFile API to set the FileInformation parameter which points to a FILE_DISPOSITION_INFORMATION structure; this structure has single Boolean parameter, called DeleteFile which, when set, causes the operating system to delete the file when it is closed.
File.log then writes the decrypted binary into a newly created file using the WriteFile API and then it creates an image section using NtCreateSection:
Once the image section is created, it then uses CreateFileMappingA and MapViewOfFile to map the created file into memory.
After creating the file mapping, it closes the handles to the mapped files, resulting in the deletion of the previously created file.
File.log then creates a new process leveraging the previously mapped section.
Once the created process is complete, it then retrieves the environment variables using CreateEnvironmentBlock, and the RtlCreateProcessParameters functions to set the arguments and the environment of the newly created process.
Before creating a new thread of execution, File.log will allocate memory into the newly created process using VirutalAllocEx and calls the WriteProcessMemory and ReadProcessMemory functions to set the base address, process parameters, and environment data into the newly allocated memory.
Finally, it creates a new thread using a handle to the newly created process and the NtCreateThreadEx function to start the execution of the 12.log process.
After successful thread creation, it prints “Success – Threat ID” to the terminal with an ironic misspelling of the word “Threat” instead of Thread.
The newly created process 12.log (Spof.Data) is linked to a publicly available privilege escalation tool named PrintSpoofer that abuses the SeImpersonatePrivilege on Windows 10 and Server 2016/2019. The strings in the binary contained the name of the author for the PrintSpoofer tool.
Similarly, based on the file’s strings, Juicy.Data was another publicly available privilege escalation tool named JuicyPotatoNG.
The encrypted Spof.data and Juicy.data executables had three things in common:
- They were both publicly available privilege escalation tools
- Naming convention followed the original project name:
- Open source PrintSpoofer named Spof.data
- Open source JuicyPotatoNG named Juicy.data
- They both attempt to run user.bat after successfully escalating privileges.
After successfully escalating privileges, Spof.data and Juicy.data, will attempt to run a batch file script called user.bat. The batch file script is not obfuscated and will perform the following:
- First it creates an administrator account with a misspelled username Administrater and the password 102030TTYG@
- Whitelist the exe process in Microsoft Defender (Ngrok is a reverse proxy, which can be used to connect to an internal service that is not exposed externally or allowed through an external firewall)
- Sets an exclusion for .exe files in Windows defender
- Disable Microsoft defender AntiSpyware (Effectively disabling Windows Defender)
- Enable remote connections and add firewall rules to allow RDP connections on port 3389
- Restart the windows service termservice (remote desktop service)
The goal of this stage is to establish persistence on the victim’s machine.
CherryLoader is newly identified multi-stage downloader that leverages different encryption methods and other anti-analysis techniques in an attempt to detonate alternative, publicly available privilege escalation exploits without having to recompile any code.
Encryption methods include simple XOR as well as AES; Anti-analysis techniques includes a password provision and process ghosting; exploits in the package analyzed include PrintSpoofer and JuicyPotatoNG.
Arctic Wolf is committed to ending cyber risk and when active intrusions are identified we are quick to protect our customers. In response to the intrusion, Arctic Wolf has detections in place to alert upon malicious activity found by the CherryLoader and the accompanying modules.
Customers can further protect their systems by ensuring they have regularly patched their software, limited the ability to create or audit the creation of administrator accounts, audit firewall modifications, audit the disablement of Windows Defender, audit Remote Desktop services, and the use of reverse proxy tools like ngrok.
XOR Decryption Script for NuxtSharp.Data
The following Python script performs the same decryption function as Cherrytree.exe. It XORs each byte with one of the three characters in the [“K”, “r”, “y”] array:
from pathlib import Path key = "Kry" file = Path("NuxtSharp.Data") with file.open("rb") as enc_file: dec_file = Path("dec_NuxtSharp") file_content = enc_file.read() kry_index = 0 with dec_file.open('wb') as decrypted_file: for enc_byte in file_content: dec_byte = bytes([enc_byte ^ ord(key[kry_index])]) decrypted_file.write(dec_byte) kry_index = (kry_index + 1) %3
Another way to draw the same conclusion, is through data analysis of the file, as the XOR key would overwrite the null bytes with the corresponding letter as seen in the following figure:
AES Decryption Script for Spof.Data and Juicy.Data
The following Python script performs the same decryption function as File.log. It uses the AES ECB algorithm and the provided AES key to do so.
#command line to decrypt Spof.Data decrypt_file.py -f Spof.Data -k 123 #command line to decrypt Juicy.Data decrypt_file.py -f Juicy.Data -k 123
from Crypto.Cipher import AES from pathlib import Path import click @click.command() @click.option("-k", "--key", required=True, help="AES Key for ECB Decryption") @click.option("-f", "--file", required=True, help="File to decrypt") def decrypt(file, key, output): file = Path(file) if not file.exists(): print("[!] File does not exist.") output_file_name = "decrypted_" + file.name output_file = Path(output_file_name) key = bytes(key, 'utf-8').ljust(16, b'\0') ecb = AES.new(key , AES.MODE_ECB) with file.open('rb') as encrypted_file:
Indicators of Compromise (IOCs)
|IP used to download Packed.rar and main.exe
By Hady Azzam, Christopher Prest, and Steven Campbell
Hady Azzam | Senior Security Researcher
Hady is a Senior security researcher at Arctic Wolf Labs focusing on malware analysis and detection research, He has over six years of cumulative experience in reverse engineering and strong passion for novel security research.
Christopher Prest | Lead Security Researcher
Christopher is a lead security researcher and a 17 year veteran in Software and Application security development, coupled with 2 years of cutting edge detection engineering and security research. A seasoned expert, Christopher focuses on Malware analysis and reverse engineering to shape the future of cybersecurity.
Steven Campbell | Senior Threat Intelligence Researcher
Steven Campbell is a Senior Threat Intelligence Researcher at Arctic Wolf Labs and has more than eight years of experience in intelligence analysis and security research. He has a strong background in infrastructure analysis and adversary tradecraft.