Request a Demo Cybersecurity Assessment Latest Trellix Events Contact Us

Blogs

The latest cybersecurity trends, best practices, security vulnerabilities, and more

Kuiper Ransomware’s Evolution

The Golang-based Kuiper ransomware is presented as an opportunity for other criminals to make money by ransoming one or more targets. Additionally, RobinHood, the actor behind Kuiper, states that help with operations can be provided for a commission. A leak site, to double extort victims (once by ransoming their systems, and again by threatening to publish the stolen data if the ransom demand is not met) is in the works, but remains unfinished.

The ransomware advertisement sounds promising with regards to the technical capabilities, while in reality the actor seems to have bitten off more than they can chew. Reality caught up with the threat actor, as observed in a blog by Stairwell’s Silas Cutler, where they obtained a copy of the server the actor used, including the ransomware’s source code and decryption keys.

This blog will cover the sales post of the actor, an analysis of the ransomware for Windows, Linux, and MacOS targeting binaries, and a version comparison. The version comparison is included within the technical analysis. The analyzed files, their hashes, and the detection information are listed at the end of this blog.

The ransomware advertisement

The underground markets offer numerous opportunities for actors to select a ransomware family of their choice. Some actors only advertise once their first version is finished, whereas others release “beta” versions. These are generally not advertised as such and are often disguised with terms like “active development”. Do note that not all malware under active development is in a beta stage. The Kuiper ransomware is advertised by its developer RobinHood in a promising sales post on an underground forum as ready-to-use, but in reality the sales post is overhyped and bloated, including false promises.

The original underground sales post was made on the 22nd of September 2023. Within the advertisement, RobinHood lists the alleged capabilities of Kuiper. In comments on said thread, the actor provides information about updates to the malware, which shows the actor is actively working on the malware.

Figure 1 - The initial sales post for the Kuiper ransomware
Figure 1 - The initial sales post for the Kuiper ransomware

The malware is stated to use AES-CFB encryption with a random key and IV, along with several command-line interface arguments, more on these later on. Further claims are the generation of a unique key for each network, the ability to run without any dependencies, the exclusion of system critical folders on the victim’s machine(s), the self deletion of the ransomware post encryption, the stopping of processes and services to avoid interruption during the encryption process, the removal of shadow copies, the stopping of Defender, memory cleaning post encryption, and highly obfuscated polymorphic code along with anti-reversing and evasion techniques, all while being fully undetected by antivirus software.

The claims are meant to make the ransomware easy to use out-of-the-box for ransomware operators, requiring minimal changes in tooling, and allowing the actors to efficiently continue with their illicit operations. The excerpt below shows the exact phrasing the actor used in the original sales post.

Figure 2 - The AV/EDR evasion section of the original sales post
Figure 2 - The AV/EDR evasion section of the original sales post

By the 25th of September 2023, just three days after the initial advertisement announcing the ransomware was available for purchase, two updates had allegedly been made to the ransomware. These updates included changing the wallpaper of the victim’s machine to the Kuiper logo once encryption is finished and changing the encryption method to intermittently encrypt files when the size of said file is larger than 600 megabytes.

Figure 3 - The first update post to the Kuiper ransomware sales post
Figure 3 - The first update post to the Kuiper ransomware sales post

Two days after that, on the 27th of September 2023, yet another update was posted. The post claims the update speeds up the encryption of files overall, and states MacOS and FreeBSD versions of the ransomware would be available from then on. The ID was supposedly shortened and generated differently, where the ID is unique per private key. Lastly, generic comments were made about fixing bugs and optimising the source code.

Figure 4 - A more elaborate second update to the sales thread
Figure 4 - A more elaborate second update to the sales thread

On the 6th of October, a new post indicated the AES encryption algorithm would not be the only algorithm available for encryption and the ChaCha20 encryption algorithm was added. If selected, ChaCha20 would be used for files smaller than 600 megabytes whereas AES is supposedly used for files larger than 600 megabytes. And again, the post states that multiple fixes were applied without diving into any specifics.

Figure 5 - The introduction of the ChaCha20 encryption algorithm in the ransomware
Figure 5 - The introduction of the ChaCha20 encryption algorithm in the ransomware

The next update, posted on the 24th of October 2023, alleges that file shares can also be encrypted by detecting and mounting them. Furthermore, the percentage of a given file that is encrypted, is supposedly altered for different files and file sizes, without providing further context. The malware is, allegedly, undetected by antivirus software, and the malware has been improved more, yet again without any further details. The leak blog, to double extort victims, is “soon” to come.

Figure 6 - The share encryption and IP scan over the last octet is advertised in a new sales update
Figure 6 - The share encryption and IP scan over the last octet is advertised in a new sales update

Given the actor’s lack of operational security, the blog has been reported publicly late December 2023, as can be seen in the screenshot below. This information was shared by Foxwild_threatintel on social media.

Figure 7 - The Kuiper leak site, live but in development
Figure 7 - The Kuiper leak site, live but in development

The timestamps listed by the open directory date back to August 2023, although there is no proof for this to be correct.

Figure 8 - The open directory listing of the leak blog
Figure 8 - The open directory listing of the leak blog

Another update, on the 21st of November, states that the ransomware’s overall functionality got upgraded.

Figure 9 - A generic update message, showing the actor’s active development of the ransomware
Figure 9 - A generic update message, showing the actor’s active development of the ransomware

On the 4th of December, yet another update was posted. This update alleges the addition of a safe mode command-line interface argument, which will ensure to reboot the system into safe mode, prior to the encryption. Additionally, some housekeeping was allegedly done to further improve the ransomware, once more without specific comments.

Figure 10 - The safe mode reboot feature is added
Figure 10 - The safe mode reboot feature is added

The below image shows the actor’s activity with regards to updates on the sales post, and its subsequently claimed updates over time.

Figure 11 - The advertisement post and updates to it, set on a timeline
Figure 11 - The advertisement post and updates to it, set on a timeline

Different versions

The Trellix Advanced Research Center analyzed different versions of the Kuiper ransomware and will detail them next. To avoid overcomplicating the comparison, the first version is used as a baseline, and dictates the order in which features are discussed. For each discussed feature, a comparison with the other versions is made. Over time, some features might be removed, while others might be added. These differences will be discussed in combined sections, based on the behaviour of the malware if it overlaps. If there’s no overlap, they will be discussed in separate sections.

Within this blog, the word “version” will refer to either A, B, or C, and defines a specific version of the malware. For each version, there are different “variants”, which refer to the target platform of said binary. Within some screenshots, one can see the naming scheme adhered for this blog, which separates the version and variant with a dot, such as “A.Windows” or “B.Linux”.

High-level overview

The ransomware’s overall behaviour is, compared to a generic piece of ransomware, fairly standard. The internal configuration is initialized, back-ups are removed, unwanted processes and services are terminated and stopped respectively, and the target is encrypted. Since this analysis covers multiple samples, multiple high-level overview flowcharts are used to display the inner workings. For all flowcharts, a dotted line is a conditional action, whereas the solid line defines an action which will happen. The first flowchart is of the Windows variant of version A.

Figure 12 - The ransomware’s flowchart for the Windows-targeting variant of version A
Figure 12 - The ransomware’s flowchart for the Windows-targeting variant of version A

Note that the third step, which terminates and stops unwanted processes and services respectively, is executed in two loops within the main function.

Figure 13 - The ransomware’s flowchart for the Windows-targeting variant of version B
Figure 13 - The ransomware’s flowchart for the Windows-targeting variant of version B

While the flowchart of the Windows variant of version B looks rather similar to the Windows variant of version A, there are quite a few differences. Most of those will be described in the next sections. Version B better uses the concurrency for which Golang is known. Further use of concurrency in contrast with the previous version will not be mentioned furthermore within this blog, but the change is noteworthy enough to warrant a general mention.

The dedicated function to disable Windows Defender has been removed. Additionally, the function to stop and terminate unwanted processes and services is now a separate function. Another major addition between version A and B, is the continuous loop to terminate specific processes, based on several process names.

The comparison of the flow graph of the main functions of the Windows variants of version A and B, shows how much the two functions are alike. The goal of this comparison is not to dive into the specifics of these graphs and their respective basic blocks, but rather to show how the malware’s internal structure remains similar over time. The image below shows version A on the left, and version B on the right. Note that the image’s instructions are not meant to be readable, as the focus should rather be on the shape of the basic blocks of the two functions.

Figure 14 - The comparison of the main functions of the Windows variants of version A (left) and B (right)
Figure 14 - The comparison of the main functions of the Windows variants of version A (left) and B (right)

The two loops on the left are responsible for the stopping and termination of unwanted processes and services. These loops are moved into a separate function, hence their absence on the right side.

In version C, the ransomware got an overhaul with more features, some of which changed the layout of the main function. The image below shows all three functions, A through C, from left to right.

Figure 15 - The comparison of the main functions of the Windows variants of version A (left), B (middle), and C (right)
Figure 15 - The comparison of the main functions of the Windows variants of version A (left), B (middle), and C (right)

The biggest part of the function’s layout is the same, barring the function calls to obtain the IP and find machines within the same last octet of the local IP with an open SMB connection, and the call to map all drives to the machine. Additionally, debug messages are only printed if the global debug variable is “true”. Below, the flowchart for the Windows variant of version C is given.

Figure 16 - The ransomware’s flowchart for the Windows-targeting variant of version C
Figure 16 - The ransomware’s flowchart for the Windows-targeting variant of version C

To avoid comparing samples which target a different platform, the next comparison will cover the Linux variants. Given that only one MacOS sample is included in this dataset, it will be compared and contrasted with the Linux variant of the same version, meaning C.MacOS and C.Linux will be compared to one another.

The first obtained Linux based sample is version B. As such, no comparison with the Linux variant of version A can be made. The capabilities of the ransomware is rather simplistic, compared to the Windows variant. It starts to recursively encrypt the targeted folder, cleans the keys from the memory, and optionally reboots the system. Essentially, it strips any Windows-specific functionality and relies purely on platform agnostic code.

Figure 17 - The ransomware’s flowchart for the Linux-targeting variant of version B
Figure 17 - The ransomware’s flowchart for the Linux-targeting variant of version B

Within version C, there’s no major difference, aside from some minutiae, which will be discussed in the relevant sections in this blog. Much like the lack of differences between the Linux variants of version B and C, the MacOS version differs very little from the aforementioned Linux versions. The flowchart below covers both the Linux and MacOS variants of version C.

Figure 18 - The ransomware’s flowchart for the Linux- and MacOS-targeting variants of version C
Figure 18 - The ransomware’s flowchart for the Linux- and MacOS-targeting variants of version C

Kuiper’s CLI-arguments

The ransomware uses an internal configuration to (not) carry out specific actions. Some of these settings can be set via the command-line interface (CLI), while others are hardcoded into the binary. Below, the arguments are given, along with a brief explanation with regards to their purpose.

Argument
Introduced in version
Type
Default value
Purpose
--help
A
String
-
Display the help menu
--p
A
String
The root of the drive
The path to start the recursive file encryption in. When omitted, the root of the file system is used. On Windows, the drive letters A through Z are targeted when not specifying a path.
--note
A
Boolean (yes/no)
yes
Defines if the ransom note is to be left during the encryption process, or only once the encryption process is complete.
-reboot
A
Boolean (yes/no)
yes
When true, the malware forces the machine to reboot once the encryption has finished.
--rename
A
Boolean (yes/no)
yes
Ensures the encrypted files are renamed to include the ransom extension, either on a per encrypted file basis, or once the encryption has finished, for yes and no respectively.
--kill
A
Boolean (yes/no)
yes
Terminates specific processes to avoid interruption prior and during the encryption, when set to true.
--bm
A
Boolean (yes/no)
yes
Ensures big files are encrypted first when set to true.
--shared
C
String
auto or ip
The ransomware will find and mount remote shares.
--chacha
C
Boolean (yes/no)
yes
Use the ChaCha20 algorithm, rather than the default AES, to encrypt files whose size is no larger than 500 megabyte.
--safe
C
Boolean (yes/no)
yes
Reboot the system into safe mode, and start the encryption from there.
--spread
C
Boolean (yes/no)
yes
Spread from a domain controller to all connected hosts.

These settings are stored within global variables and are accessed during the ransomware’s execution. Samples where the debug setting isn’t enabled, can be patched to enable it. One can do so by finding the boolean’s value in the binary, after which it is set to “1”. The updated file will then print out the debug messages during runtime, as the patched variable is never written to during runtime, and is only read. This setting is enabled by default within all encountered samples.

Once the ransomware starts, it will print debug messages in the console. The screenshot below shows the first messages printed by the Windows variant of version B, where the specified starting path of the recursive encryption was “C:\Users”.

Figure 19 - The start of the execution log when the Kuiper ransomware version B (Windows targeting) starts
Figure 19 - The ransomware’s flowchart for the Linux- and MacOS-targeting variants of version C

Figure 20 - Logs from the ransomware during the encryption, stating which file it encrypted
Figure 20 - Logs from the ransomware during the encryption, stating which file it encrypted

The usage of the command-line argument “-safe” will trigger an immediate response while initializing the internal configuration. At first, a check is performed if the ransomware is running with administrative privileges. If this is not the case, these privileges will be requested, and the device will be rebooted into safe mode. If such privileges have already been granted, the system is rebooted into safe mode directly.

Figure 21 - The administrative privilege check within the “-safe” command-line interface argument’s handler
Figure 21 - The administrative privilege check within the “-safe” command-line interface argument’s handler

The check to verify if administrative privileges are granted works by attempting to read physical drive 0. This file can only be accessed by processes with administrative privileges, and an error will be thrown if a process attempts to read it without the required privileges. Based on the result of the attempted file read, a boolean is returned.

Figure 22 - The administrative check function
Figure 22 - The administrative check function

If no administrative privileges are granted, a PowerShell script is executed using “cmd.exe /c”. The PowerShell command restarts the ransomware with the required privileges. The comment, in purple, in the screenshot below, shows the full command.

Figure 23 - The command to obtain administrative privileges and start an instance of the ransomware to reboot the system into safe mode
Figure 23 - The command to obtain administrative privileges and start an instance of the ransomware to reboot the system into safe mode

Note that the normal execution continues once the sleep is over since this function returns, after which the configuration initialization function also returns and the execution resumes from there.

If the required privileges are available, the “main.RestartSafemode” function is called. At first, it will read itself and write the newly read data into “safemode.exe” within the public user profile’s home folder.

Figure 24 - A copy of the ransomware is created in the public profile’s home folder
Figure 24 - A copy of the ransomware is created in the public profile’s home folder

Next, it will create a file named “safemode.bat”, located in the same folder as “safemode.exe”. This batch file will add a registry key named “Shell” to execute the ransomware upon the system’s startup. If this key were to already exist, it is overwritten by this command. Once the batch file is written, it is executed, and after a one second sleep, it is removed. The system is then set to start into safe mode with network access upon the next boot sequences. Lastly, the system is rebooted, forcing the system into safe mode, where the ransomware is automatically started.

Figure 25 - The auto-start of the ransomware in safe mode, and the other required changes to reboot into safe mode
Figure 25 - The auto-start of the ransomware in safe mode, and the other required changes to reboot into safe mode

Backup deletion

The deletion of the backups is commonly observed in numerous ransomware families, and the main purpose is to ensure the backup restoration process is made as difficult as possible. This ought to swing the negotiation in the threat actor’s favour, since the victim can restore fewer (if any) files once the encryption process completes.

Versions A, B, and C all execute the command-line interface strings via a wrapper call, which executes “cmd.exe /c” on Windows and “/bin/bash -c” on Unix platforms, followed by a space and the command to execute. In the Windows variants of all versions, the window of the newly created process is hidden. Version A uses stack strings to build the command-line interface strings, whereas version B and C use hardcoded strings. The image below shows a stack string as Ghidra shows it initially.

Figure 26 - The stack string, as shown in Ghidra initially
Figure 26 - The stack string, as shown in Ghidra initially

With the help of my stack strings script, one can quickly find out the string’s content, as shown in the screenshot below, taken from Ghidra’s console output once the script finished.

Figure 27 - The stack string script’s output in Ghidra’s console
Figure 27 - The stack string script’s output in Ghidra’s console

Upon changing the type into “char[31]” (as it is 31 bytes in size) and renaming the resulting variable, the decompiler shows the string’s value character-by-character.

Figure 28 - The stack string once retyped and renamed, as shown in Ghidra’s decompiler
Figure 28 - The stack string once retyped and renamed, as shown in Ghidra’s decompiler

Noteworthy are the strings within version A, as they contain “cmd.exe /c” at the start (as seen in the image above), meaning that the execution chain contains two “cmd.exe” instances, prior to the execution of the actual command. From version B onwards, the “cmd.exe /c” has been removed from the command strings. The table below shows the executed commands for each version, where version B and C show possible additions in the newer versions. No commands were removed over time.

Backup deletion commands
Version A
Version B additions
Version C additions
for drives A through Z: vssadmin resize shadowstorage /for=[drive]: /on=C: /maxsize=401MB wevtutil cl system
-

To summarize the Windows variant of version A, the boot status policy is set to ignore all failures, which is the default setting. Additionally, recovery mode is disabled to avoid Windows’ automatic repair capability from starting. Next, all shadow copies are quietly deleted, along with the existing backup catalog, the system state backups, and the application and security logs.

From an attacker’s point of view, the removal of all these logs and files reduces the traces that can be found regarding the intrusion into the systems. While it is a telltale sign of an intrusion for the defending side when logs are cleared, the exact details of the intrusion are not available anymore. Additionally, the presence of ransomed files is enough on its own, making the argument of the telltale sign moot.

Process and service targeting

The ransomware will take precautions prior to encrypting files. It will terminate specific processes and stop targeted services to avoid any interruption during the ransomware’s main activity. In the two tables below, the targeted processes and services to be neutralized are listed. No removals were found in between the versions.

This activity is common for many ransomware families as it increases the chance of successfully encrypting the victim’s files. With regards to the blocklisted services, there is a minor increase in the number of blocklisted services between version A and B, with only a single addition. From B to C, the number of blocklisted services doubles, resulting in a total of 22.

Blocklisted services
Version A
(n=10, total=10)
Version B additions
(n=1, total=11)
Version C additions
(n=11, total=22)
AOTAgentSvc
Avast Antivirus!
iVPAgent
Ntrtscan
TMBMServer
Tmccst
Tmlisten
TMResponse
TmWSCSvc
Trend Micro Web Service Communicator
BackupExecAgentBrowser
Backup
GxBlr
GxCVD
GxVss
Memtas
Mepo
Msexchange
Sql
Svc$
Vss
Sophos

The blocklisted processes follow a similar pattern, where the number of processes starts at 13, version B adds one to the total, and version C nearly doubles the number of processes to 27, by adding 13.

Blocklisted processes
Version A
(n=13, total=13)
Version B additions
(n=1, total=14)
Version C additions
(n=13, total=27)
AOTAgent.exe
avgsvc.exe
CETASvc.exe
iPVAgent.exe
KasperskyService.exe
McAfeeFramework.exe
NortonSecurity.exe
PccNTMon.exe
ResponseService.exe
SophosSAU.exe
SupportConnector.exe
tmwscsvc.exe
vastsvc.exe
powerpnt.exe
calc.exe
Dbeng50.exe
Dbnmp.exe
Mydesktopqos.exe
notepad.exe
Ocomm.exe
Ocssd.exe
Oracle.exe
Sqbcoreservice.exe
Sql.exe
Steam.exe
Synctime.exe
Tbirdconfig.exe
Winword.exe

Based on a report regarding AvosLocker, published by Trend Micro on the second of May 2022, some of the blocklisted processes and services of version A seem to be copied. To be more specific, 9 services and 7 processes, as listed in the table below, overlap. There is no proof if this overlap is by chance, but given the number of items, it is not likely to be chance based. This does not imply any overlap between the two malware families or creators thereof. It is most likely a lack of creativity and effort of RobinHood, as the data is merely copied.

Overlap in blocklisted processes and services with Trend Micro’s AvosLocker report
Services
Processes
AOTAgentSvc
iVPAgent
Ntrtscan
TMBMServer
Tmccsf
Tmlisten
TMResponse
TmWSCSvc
Trend Micro Web Service Communicator
AOTAgent.exe
CETASvc.exe
iVPAgent.exe
PccNTMon.exe
ResponseService.exe
SupportConnector.exe
tmwscsvc.exe

Containment and environmental control

Once the attempt to disable the blocklisted process and services is complete, the ransomware moves on to disable Windows Defender. Different versions of Kuiper attempt to disable Defender in different ways.

The commands to disable Defender in Kuiper version A are hex encoded, only to be decoded during runtime. This is likely done to avoid matching literal strings within the binary with detection rules. The corresponding functions in version B and C contain base64 encoded PowerShell commands, rather than hex encoded strings.

Each command is structured in the same way, as all commands use the SetMpPreferences cmdlet: “powershell.exe -ep bypass -c Set-MpPreference -[setting] 1 -ErrorAction SilentlyContinue” The value of “[setting]” differs per command. Note that each command is present in full, there is no string replacement. The error action defines that any failed command is silently ignored. The command execution wrapper function executes the given command using “cmd.exe /c”, which is followed by a space and the given command.

Figure 29 - The encoded commands to disable Defender
Figure 29 - The encoded commands to disable Defender

Version B’s approach differs, as it creates several loops. One loop is used to continuously disable Defender’s real time monitoring capability, while the other loops are continuously terminate “taskkill.exe”, “tasklist.exe”, “taskmgr.exe”, “cmd.exe”, and “ps.exe”. There is a separate loop for each targeted process, as can be seen in the purple colour comment in the screenshot below.

Figure 30 - The continuous process termination loop in version B
Figure 30 - The continuous process termination loop in version B

In version C, the real time monitoring is still disabled, and several processes are targeted. Three changes can be observed: the processes have slightly changed, all code is now within the same single loop, and the loop now sleeps for a single second at the end of every iteration. The processes named “taskkill.exe”, “cmd.exe”, and “ps.exe” have been removed, while “regedit.exe” and “ProcessHacker.exe” have been added. The purple colored comment in the screenshot below shows the full command.

Figure 31 - The continuous process termination loop in version C
Figure 31 - The continuous process termination loop in version C

Version C has some additional features, similar to the features mentioned in this section: bypassing sandbox environments, and disabling Defender via a single function call. These two techniques are explained in detail below the table with all commands per version.

Methods to disable Windows Defender
Version A
Version B
Version C
DisableRealtimeMonitoring
Taskkill loops (one per process) to terminate:
- taskkill.exe
- tasklist.exe
- taskmgr.exe
- cmd.exe
- ps.exe
A single loop to kill several processes by name:
    while($true){
           Set-MpPreference -DisableRealtimeMonitoring
     $true;
           taskkill /f /im tasklist.exe;
           taskkill /f /im taskmgr.exe;
           taskkill /f /im regedit.exe;
    
           taskkill /f /im ProcessHacker.exe;
           start-sleep
     1
    }
- Attempts to bypasses sandbox environments
- Calls WDEnable to disable Defender

The sandbox bypass attempt reads “C:\Windows\system32\cmd.exe”. If this fails, the malware will shut down. The decompiled pseudo-C from Ghidra’s decompiler that is shared below, can easily be compared to Golang’s ReadFile example, where the returned error value is checked to be non-zero, meaning an error occurred.

Figure 32 - The sandbox bypass attempt within version C
Figure 32 - The sandbox bypass attempt within version C

Next, it attempts to disable Windows Defender by calling WDEnable. It will first load this DLL, to ensure it can be found, after which the function address is obtained. With the help of the obtained address, the function is called, passing “false” as the sole argument to the function.

Figure 33 - The call to WDEnable to attempt to disable Defender
Figure 33 - The call to WDEnable to attempt to disable Defender

Another sandbox bypass, per the malware author’s belief, is an empty loop which iterates 1000 times. The loop has no content, and is meant to consume CPU cycles. In practice, this ‘bypass’ achieves nothing. While the loop is within a function in the leaked source code, it is placed within the overarching bypass function by the compiler, as a function call to it would only increase overhead during runtime.

Figure 34 - All bypass methods, including the empty loop, in the Windows variant of version C
Figure 34 - All bypass methods, including the empty loop, in the Windows variant of version C

This loop is the only ‘bypass’ function which exists in the Linux and MacOS variants, as seen in the screenshot below. The purpose of this empty loop is taken from the leaked Kuiper source code, as no meaningful conclusion could be drawn from the empty loop within the decompiled code.

Note that the location of this loop within the Linux and MacOS variants is within the threaded main function. The compiler removed the function calls and simply in-lined this code to avoid overhead.

Figure 35 - The loop within the MacOS variant in version C
Figure 35 - The loop within the MacOS variant in version C

Worming around

The ransomware tries to spread itself throughout the network. In order to do this, it first obtains the IP address of the device it is currently running on. Next, it spreads the executable over the IPs within the range of the last octet of the local IP, and then mounts all shared folders and drives.

To get the local IP, there are two options, which depend on the command-line interface argument used. If the “auto” method is used, it uses “main.GetNetworkIp” to get the IP address. If this option is not used, “main.GetNetworkIpByIp” is used, and an IP address is provided via the command-line interface.

Figure 36 - The two methods to get the local IP and get the IP range to scan later on
Figure 36 - The two methods to get the local IP and get the IP range to scan later on

Within “main.GetNetworkIp” uses Golang’s net.Interfaces to obtain a list of interfaces on the machine. It checks if the name of each interface is not equal to “docker” or the loopback interfaces “lo” and “lo0”, and ignores interfaces with these names. This function then calls “main.GetNetworkIpByIp” in a loop, slowly incrementing the IP. This function returns a list of reachable IP addresses.

The purpose of “main.GetNetworkIpByIp” is to check if a SMB connection is possible on any device that is within the last octet of the local IP. Any IP where this is possible, is saved. This call originates either from else-body in the screenshot above, or the call within the aforementioned loop.

Figure 37 - The SMB check to a given IP, at port 445
Figure 37 - The SMB check to a given IP, at port 445

Once the IP addresses are iterated over, and the local address has been obtained, the malware starts to spread itself to all previously aggregated IPs where the SMB connection was possible. It does this by copying itself into the public user profile on the remote machine.

Figure 38 - A copy of the ransomware is made by reading the ransomware, and writing it to the public user’s home folder
Figure 38 - A copy of the ransomware is made by reading the ransomware, and writing it to the public user’s home folder

The excerpt above is part of “main.AutoCopy”, which is visible on line 29 in the screenshot below. The newly copied ransomware is then started using “wmic /node:[location] process call create” with a path to the ransomware, and command-line interface arguments to start it with. In this case, the ransomware runs with default settings, but will not reboot the machine once the encryption finishes.

Figure 39 - The ransomware is started using WMIC on the remote machine
Figure 39 - The ransomware is started using WMIC on the remote machine

Once it has copied itself to other machines, and started the processes on the remote machines, it moves on to mount shared folders on the machine it was already executing on. It obtains all shares using WMIC, and checks if there are more shares available than the default shares, which are blocklisted.

Figure 40 - The blocklisted network share names
Figure 40 - The blocklisted network share names

The obtained locations are then mapped to a drive letter using “net use [drive] [location]”

Figure 41 - The mounting of network locations using “net use”
Figure 41 - The mounting of network locations using “net use”

Ransom note

As is common with ransomware, a note with instructions on how to contact the actor is left in every folder. This way, the victim can discuss payment options via a channel of the actor’s choosing. The notes of Kuiper have not changed much throughout the different versions. In each version thus far, the notes are hex encoded, only to be decoded during runtime. The ransom note of version A is given below, without any changes to the text itself. Note that the “ID” at the end is replaced with the victim’s ID during runtime.

Your network has been compromised! All your important data has been encrypted!

There is  only one way to get your data back to normal:

  1. Contact us as soon as possible to avoid damages and losses from your business.
  2. Send to us any encrypted file of your choice and your personal key.
  3. We will decrypt 1 file for test (maximum file size = 1 MB), its guaranteed that we can decrypt your files.
  4. Pay the amount required in order to restore your network back to normal.
  5. We will then send you our software to decrypt and will guide you through the whole restoration of your network.

We prefer Monero (XMR) - FIXED PRICE

We accept Bitcoin (BTC) - 20% extra of total payment!

=========================================================================================

WARNING!

Do not rename encrypted data.

Do not try to decrypt using third party software, it may cause permanent data loss not being able to recover.

=========================================================================================


Contact information:

 

In order to contact us, download with the following software: https://qtox.github.io or https://tox.chat/download.html

Then just add us in TOX: D27A7B3711CD1442A8FAC19BB5780FF291101F6286A62AD21E5F7F08BD5F5F1B9803AAC6ECF9

 

If there is any problems setting up TOX then just write to us at the following mail, it will only apply for problems setting up TOX and contacting us through TOX:

 

kuipersupport@onionmail.org

 

====================================================================================== ======================================

 

Your personal id: ID


Within version B, the email address is removed from the note, along with the accompanying message. The excerpt is given in the table below.

If there is any problems setting up TOX then just write to us at the following mail, it will only apply for problems setting up TOX and contacting us through TOX:

 

kuipersupport@onionmail.org

In version C, the email address is added again, without the accompanying message regarding the potential troubles one might have with TOX. The added text is given below.

OR

 

Through email: kuipersupport@onionmail.org

The victim ID in version A is generated during runtime and contains the used key and IV, in an encrypted form, along with an MD-5 hash of the public key. The data is split with colons, and the complete string starts with “RSA=”. The complete string is hex encoded and replaces the “ID” in the ransom note. This results in a rather long victim ID. It does, however, contain all the information the threat actor needs to obtain the used key and IV, which allows files to be decrypted.

Within version C, the format changes with the introduction of ChaCha20 as an option to encrypt large files with. The ID is still hex encoded, and still starts with “RSA=” prior to encoding. It now contains 32 characters, a colon, four digits, and a boolean. The data within the ID is similar, but now also contains the ChaCha20 key and IV, along with the AES key and IV. This data is gzip compressed. The boolean defines if ChaCha20 was used at all.

File encryption

The file encryption is done asynchronously using channels which allows Goroutines to communicate during their execution. There are channels for normal files, big files, and semaphores. The latter one isn’t used much, and will be excluded from the analysis.

The ransomware will recursively encrypt the targeted path, which depends on the provided or lacking command-line argument. The name of each folder the recursive algorithm enters, is checked against a list of blocked names, as given below.

Excluded folders on Windows
Version A
Version B additions
Version C additions
App Data
AppData
BOOTNXT
DumpStack.log.tmp
Program Files (x86)
ProgramData
Recovery
SysWOW64
System Volume Information
System32
Temp
Windows
appdata
desktop.ini
ntuser.dat
pagefile.sys
perflogs
swapfile.sys
thumbs
$Recycle.Bin
boot
Default
efi
Open
Public
sources
sources64
support
upgrade

On Linux, excluded folders are included from version B onwards, even though they do not appear in the specific version C build. The leaked source code does include the information. As such, it is likely a mistake from the actor when building version C. The excluded folders are listed in the table below.

/bin
/boot
/dev
/etc
/initrd
/lib
/lib64
/libx32
/opt
/proc
/root
/run
/sbin
/srv
/sys
/tmp
/usr/
/var

The MacOS variant also excludes specific folders, although it is unclear when this was introduced, as the only available sample for this platform is version C. The excluded folders are listed below.

/Applications
/bin
/cores
/dev
/etc
/home
/Library
/net
/private
/sbin
/System
/tmp
/usr
/var

Each detected file is then evaluated based on its extension. If the extension is not blocklisted, it is encrypted. The blocklisted extensions are found in the table below. The list of extensions seem to have been ‘inspired’ by AvosLocker, as seen in a report from Zscaler.
Excluded extensions
Version A
Version B additions
Version C additions
.bak
.bat
.bin
.blf
.cfg
.cmd
.com
.crlk
.dat
.desktop
.dll
.elf
.exe
.go
.html
.ini
.lnk
.msi
.so
.sys
.tmp
.rtf
.386
.cert
.DATA
.inf
.key
.LOG
.LOG1
.LOG2
.man
.private_key
.regtrans-ms
.search-ms
.ttf

If large files are to be encrypted differently, i.e. using ChaCha20 or AES, a different percentage of the file is encrypted. Additionally, the extension of any big file is checked once more. If it is equal to “.sql”, “.txt”, “.db”, or “.json”, it is encrypted as if it is a normal sized file, regardless of the actual size of the file.

Figure 42 - The check for extensions to avoid partially encrypting specific files
Figure 42 - The check for extensions to avoid partially encrypting specific files

If the file is considered big, the extension is checked once more. If the extension matches any of the extensions given in the list below, it is encrypted in fast mode, meaning only a quarter of the file is encrypted.

.abk
.abu1
.acp
.adi
.avdx
.avhd
.backup
.bkz
.blend1
.doc
.docx
.dsb
.gho
.iso
.jpa
.mbk
.nba
.nvram
.pdf
.pvm
.qbmb
.qcow2
.raw
.scripa
.sis
.spg
.subvol
.vbox-prev
.vdi
.vhd
.vhdx
.vmcx
.vmdk
.vmem
.vmrs
.vmsd
.vmsn
.vmx
.vsv
.wx
.xlsx
.zip

Depending on the command-line interface flag, files will be renamed with the appended “.kuiper” extension during or post encryption.

Once the encryption is complete, the ransomware has several actions to perform. It will clean the memory keys. The boolean which is checked, is set to “true” by default, and is not altered during runtime. If the reboot function is called, the ransomware’s execution stops there. If not, the execution continues as is described in the next section.

Figure 43 - Post encryption actions
Figure 43 - Post encryption actions

The clean memory key function is simple, yet effective. It will, as can be seen in the screenshot below, loop 100 times, where each iteration regenerates new keys and IVs for the AES and ChaCha20 encryption eight times. As such, this method overwrites the memory space where the original keys and IVs were 800 times, rendering any memory dump past this point useless.

Figure 44 - The method to clean the keys and IVs by overwriting the in-memory data 800 times
Figure 44 - The method to clean the keys and IVs by overwriting the in-memory data 800 times

Leaving a mark and cleaning up

Once the machine is encrypted, the ransomware has a few more tricks up its sleeve. The tricks themselves depend on the malware’s version. All versions remove the backups on the machine once more, avoiding any trace of the execution, other than the altered files on the disk. The function used to delete the backups is the same as the one that is used prior.

Version B, and no other version, signals that it will stop the service and process blocklist loop, but the function is empty, as can be seen below. In the screenshot, the listing with the disassembled code is visible on the left hand side, whereas the decompiled pseudo-C code shown on the right. Both views indicate no presence of other code, and there is no code related to this function above or below the given function in the listing.

Figure 45 - An empty function, showing the developmental stage the ransomware is in
Figure 45 - An empty function, showing the developmental stage the ransomware is in

Version C has some additional features, which consist of a change in the desktop’s wallpaper, and the removal of the binary itself. This can be observed in the “main.main” function, which is Golang’s equivalent of C’s “main”. The waitgroup is used to wait until the clear signal is given, while the “ThreadedMain” function executes in a separate thread in the background. The threaded main function contains all other code. Version B’s main function only serves to start the threaded main function, and contains no further logic. Once the threaded main function finishes, the functions to change the wallpaper and to remove the current ransomware sample from the disk are called sequentially.

Figure 46 - The main function of the Windows variant of version C
Figure 46 - The main function of the Windows variant of version C

To change the wallpaper, two steps are required to be taken. The image needs to be available for the operating system, and it needs to set the new image as the wallpaper. In version C of this ransomware, the wallpaper is hex encoded. During runtime, it is decoded, after which it is set as the new wallpaper.

Figure 47 - The function which decodes and sets the desktop wallpaper
Figure 47 - The function which decodes and sets the desktop wallpaper

The decoded wallpaper, which is used by the ransomware, is shown below.

Figure 48 - The decoded wallpaper within the ransomware executable
Figure 48 - The decoded wallpaper within the ransomware executable

The function to set the new wallpaper comes from user32.dll, and is named SystemParametersInfoW. While one can do multiple things with this function, one of its use cases is to change the wallpaper. The function arguments, as seen in the purple coloured comments in the screenshot from Ghidra’s decompiler, specify the action type, the path to the wallpaper, and value which decides if and how the user profile is to be updated. Using “SPIF_SENDCHANGE”, the user profile is updated directly, and the WM_SETTINGCHANGE message is directly broadcast to all top-level windows, to take immediate effect.

Figure 49 - The function call to SystemParametersInfoW to change the wallpaper to the given image
Figure 49 - The function call to SystemParametersInfoW to change the wallpaper to the given image

Once the function to change the wallpaper returns, the ransomware removes itself from the disk. It does this by creating a small batch file, named “setup.bat”. The content of this file can be seen on line 30 through 35 in the screenshot below.

Figure 50 - The self-remove function which uses a batch script to do so
Figure 50 - The self-remove function which uses a batch script to do so

The batch file hides itself, and starts a loop which deletes the newly created wallpaper image, the ransomware’s executable, after which it sleeps for one second, before attempting to execute the two deletion commands again.

The autoremove function is present within the Linux and MacOS variants, but contains no code, as can be seen below.

Figure 51 - The lack of a self-remove function in a non-Windows variant of version C
Figure 51 - The lack of a self-remove function in a non-Windows variant of version C

Broken promises

Looking back on most of the sales posts while knowing all of the above, it is obvious that some of the claims are blatantly misleading and incorrect. The original sales post makes several claims about the binary’s output. It suggests the code is “highly obfuscated”, “polymorphic”, and contains “anti-reverse methods”. The excerpt from the original sales post is given below.

Figure 52 - The AV/EDR evasion ‘promise’ in the original sales post
Figure 52 - The AV/EDR evasion ‘promise’ in the original sales post

None of the obtained binaries contain any form of obfuscation. The screenshots within this blog serve as evidence thereof. Variables are renamed and retyped to improve the decompiler output, but this is merely the byproduct of analysing compiled code, not the result of any action the actor took.

The “polymorphic code” is a laughable claim. While there are indeed changes per version of the code, they aren’t “polymorphic” by any definition. The naming scheme of functions is used to randomise some function names. In some cases, the entire function name is randomised, whereas in some cases only a part of the function name is randomised. The below screenshot shows the randomised names for “main.generateKeyAndIV” on the left side, and the partially random name “main.Config”. Even though the screenshot only uses Windows variants, this pattern occurs in all variants in all versions.

Figure 53 - Fully randomised function names on the left, and partially random names on the right
Figure 53 - Fully randomised function names on the left, and partially random names on the right

The final debunked claim regarding “anti-reverse methods” is easy to refute: there is no such code within any of the versions of the ransomware.

Conclusion

Malware changes over time as it evolves due to different wants and needs, and to stay ahead of the competition. While the Kuiper ransomware got many updates over time, not all of which are verifiable, it shows the financial incentive actors have when it comes to ransomware operations.

The quality of the ransomware’s codebase, based on observations when reversing the binaries and by reading the leaked source code, show a fundamental lack of understanding programming concepts by the actor, along with shoddy coding skills. The concurrency focused nature of Golang benefits the threat actor here, avoiding race conditions and other common problems when dealing with multiple threads, which would have otherwise been a (near) certainty. This aspect is one of the reasons as to why Golang’s increased popularity comes as no surprise.

Another factor that the Kuiper ransomware leverages, which is also a reason for Golang’s increased popularity, are the language’s cross-platform capabilities to create builds for a variety of platforms. This flexibility allows attackers to adapt their code with little effort, especially since the majority of the code base (i.e. encryption related activity) is pure Golang and requires no rewriting for a different platform. While the variants for the lesser used platforms do not contain as many features as the Windows-targeting flagship version, it still impacts a victim by ransoming a given device.

Analysed samples

The analysed samples are listed below, in chronological order of their creation. Version A has been posted online by PCrisk’s Tomas Meskauskas on social media. The listed samples for version B and C have been obtained differently. All samples were analysed with the help of the Golang analysis scripts for Ghidra, which are freely available on Trellix’ GitHub.

Version A – Windows
MD-5
84820f3eb491a2fde1f52435cd29646c
SHA-1
8c6e135495fcf8898de62e6793e3cd06d3025461
SHA-256
df430ab9f5084a3e62a6c97c6c6279f2461618f038832305057c51b441c648d9
Detection names

EX/NX:
    - Ransomware.Win32.Kuiper.FEC3
    - Suspicious Process Disk Tampering Activity
    - Suspicious Ransom File Deletion
    - Suspicious Ransomware Activity

HXAV:
    - Trojan.GenericKD.69117908

ENS:
    - Ransomware-HPV!84820F3EB491

Source code date
26-08-2023

Version B – Windows
MD-5
0608c64c57dcc09246be00f0b2767e6e
SHA-1
02642663BFC7BE0C06051F4B01C9861102C71850
SHA-256
0162641163a30a2edff787eeecc733ab1de46f03e213743dc768d39eb3075985
Detection names

EX/NX:
    - Ransomware.Win.Generic.MVX
    - Malicious Trojan Indicator
    - Malicious Ransomware Indicator
    - Suspicious Process Disk Tampering Activity
    - Suspicious File Stealing Activity
    - Suspicious Ransomware Activity

HXAV:
    - Gen:Variant.Jaik.173826

ENS:
    - Ransomware-HPV!0608C64C57DC trojan

Source code date
19-09-2023

Version C – Windows
MD-5
193964c937493b979b1e9649a83ff000
SHA-1
d85a46b51b7cf9fe24783508e0739ccee3cf5874
SHA-256
d6c1d2e77ce21d5a026e7abf99c9fffe55d87b282f460dc737da231211a12a0d
Detection names

HXAV:
    - Trojan.GenericKD.70673883

MVX:
    - FE_Ransomware_Go_Kuiper_2

ENS:
    - Ransom-Kuiper (ED) trojan

Source code date
20-11-2023

Version C – Linux
MD-5
56cabcf95add39a6feb09391ccc40dcd
SHA-1
84c8921f18a6d7861e842e4edb9c0c96142b5f75
SHA-256
4e153342189a55ffed34a91f2a3f4440af1acbf7dc58135a165a06b4e657556a
Detection names

HXAV:
    - Gen:Variant.Ransomware.Linux.Agent.1

MVX:
    - FE_Ransomware_Go_Kuiper_2

ENS:
    - Ransom-Kuiper (ED) trojan

Source code date
20-11-2023

Version C – MacOS
MD-5
0bfe64b866911620f273a1d306984d29
SHA-1
4371132451177999fde66054fc84382a94f606c0
SHA-256
c66590a2ffbe53667be147c4e74e626764aff9eb31017dd8b8f161279fd0f4f6
Detection names

HXAV:
    - Gen:Variant.Ransomware.MAC.Agent.1

MVX:
    - FE_Ransomware_Go_Kuiper_2

ENS:
    - MacOS/Kuiper.a (ED) trojan

Source code date
20-11-2023

MITRE ATT&CK techniques

The techniques used within any of the discussed samples are listed below.

Technique
Description

Remote Services: SMB/Windows Admin Shares

Example command:
    - “wmic /node: process call create”

Process Discovery
    - Uses “taskkill” to loop and terminate targeted processes

Command and Scripting Interpreter: PowerShell

Example command:
    - Starts with “powershell.exe -ep bypass -w hidden -enc” followed by a space and the encoded command

Command and Scripting Interpreter: Windows Command Shell

Example command:
    - Starts with “cmd.exe /c” followed by a space and the command to execute (i.e. “shutdown /r /t 8”)

Command and Scripting Interpreter: Unix Shell

Example command:
    - Starts with “/bin/bash -c” followed by a space and the command to execute (i.e. “reboot”)

Active Scanning: Scanning IP Blocks

Iterates over the last octet of the current IP to see if the SMB share is open and writable, allowing the malware to spread itself

Gather Victim Network Information: IP Addresses

Gets the current IP address from the list of network interfaces from the machine, using a minor blocklist to avoid selecting the wrong address

Native API

Example command:
    - WDEnable

Data Encrypted for Impact

Service Stop

Example command:
    - “net stop” followed by the service name

Inhibit System Recovery

Example commands:
    - bcdedit /set {default} BootStatusPolicy IgnoreAllFailures
    - bcdedit /set {default} RecoveryEnabled No
    - vssadmin delete shadows /all /quiet
    - wbadmin delete catalog -quiet
    - wbadmin DELETE SYSTEMSTATEBACKUP
    - wbadmin DELETE SYSTEMSTATEBACKUP -deleteOldest
    - wevtutil cl application
    - wevtutil cl security

Virtualization/Sandbox Evasion

Tries to bypass using:
    - Iterating over an empty loop
    - Trying to read “C:\Windows\System32\cmd.exe”

System Shutdown/Reboot

Example commands:
    - reboot
    - shutdown /r /t 8

Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder

Example command:
    - reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersionWinlogon" /t REG_SZ /v Shell /d "C:\Users\Public\safemode.exe" /f

This document and the information contained herein describes computer security research for educational purposes only and the convenience of Trellix customers.

Get the latest

We’re no strangers to cybersecurity. But we are a new company.
Stay up to date as we evolve.

Please enter a valid email address.

Zero spam. Unsubscribe at any time.