Blogs
The latest cybersecurity trends, best practices, security vulnerabilities, and more
Kuiper Ransomware’s Evolution
By Max Kersten · January 17, 2024
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.
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.
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.
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.
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.
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.
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.
The timestamps listed by the open directory date back to August 2023, although there is no proof for this to be correct.
Another update, on the 21st of November, states that the ransomware’s overall functionality got upgraded.
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.
The below image shows the actor’s activity with regards to updates on the sales post, and its subsequently claimed updates over time.
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.
Note that the third step, which terminates and stops unwanted processes and services respectively, is executed in two loops within the main function.
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.
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.
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.
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.
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.
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.
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”.
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.
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.
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.
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.
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.
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.
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.
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.
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.
cmd.exe /c bcdedit /set {default} RecoveryEnabled No
cmd.exe /c vssadmin delete shadows /all /quiet
cmd.exe /c wbadmin delete catalog -quiet
cmd.exe /c wbadmin DELETE SYSTEMSTATEBACKUP
cmd.exe /c wbadmin DELETE SYSTEMSTATEBACKUP -deleteOldest
cmd.exe /c wevtutil cl application
cmd.exe /c wevtutil cl security
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.
(n=10, total=10)
(n=1, total=11)
(n=11, total=22)
Avast Antivirus!
iVPAgent
Ntrtscan
TMBMServer
Tmccst
Tmlisten
TMResponse
TmWSCSvc
Trend Micro Web Service Communicator
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.
(n=13, total=13)
(n=1, total=14)
(n=13, total=27)
avgsvc.exe
CETASvc.exe
iPVAgent.exe
KasperskyService.exe
McAfeeFramework.exe
NortonSecurity.exe
PccNTMon.exe
ResponseService.exe
SophosSAU.exe
SupportConnector.exe
tmwscsvc.exe
vastsvc.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.
iVPAgent
Ntrtscan
TMBMServer
Tmccsf
Tmlisten
TMResponse
TmWSCSvc
Trend Micro Web Service Communicator
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.
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.
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.
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.
DisableBehaviorMonitoring
DisableBlockAtFirstSeen
DisableIntrusionPrevention
DisableIOAVProtection
DisableRealtimeMonitoring
DisableRemovableDriveScanning
DisableScanningMapped
DisableScanningNetworkFiles
DisableScriptScanning
Taskkill loops (one per process) to terminate:
while($true){ Set-MpPreference -DisableRealtime- Attempts to bypasses sandbox environmentsMonitoring $true; taskkill /f /im tasklist.exe; taskkill /f /im taskmgr.exe; taskkill /f /im regedit.exe; taskkill /f /im ProcessHacker.exe; start-sleep 1 }
- 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.
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.
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.
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.
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.
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.
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.
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.
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.
The obtained locations are then mapped to a drive letter using “net use [drive] [location]”
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:
- Contact us as soon as possible to avoid damages and losses from your business.
- Send to us any encrypted file of your choice and your personal key.
- We will decrypt 1 file for test (maximum file size = 1 MB), its guaranteed that we can decrypt your files.
- Pay the amount required in order to restore your network back to normal.
- 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.
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.
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
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.
/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.
/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.
.bat
.bin
.blf
.cfg
.cmd
.com
.crlk
.dat
.desktop
.dll
.elf
.exe
.go
.html
.ini
.lnk
.msi
.so
.sys
.tmp
.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.
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.
.abu1
.acp
.adi
.avdx
.avhd
.backup
.bkz
.blend1
.doc
.docx
.dsb
.gho
.iso
.jpa
.mbk
.nba
.nvram
.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.
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.
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.
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.
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.
The decoded wallpaper, which is used by the ransomware, is shown below.
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.
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.
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.
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.
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.
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.
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
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
HXAV:
- Trojan.GenericKD.70673883
MVX:
- FE_Ransomware_Go_Kuiper_2
ENS:
- Ransom-Kuiper (ED) trojan
HXAV:
- Gen:Variant.Ransomware.Linux.Agent.1
MVX:
- FE_Ransomware_Go_Kuiper_2
ENS:
- Ransom-Kuiper (ED) trojan
HXAV:
- Gen:Variant.Ransomware.MAC.Agent.1
MVX:
- FE_Ransomware_Go_Kuiper_2
ENS:
- MacOS/Kuiper.a (ED) trojan
MITRE ATT&CK techniques
The techniques used within any of the discussed samples are listed below.
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
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
RECENT NEWS
-
Oct 3, 2024
Trellix CEO Rallies the Industry to Support CISO Role
-
Sep 10, 2024
Trellix Integrates Email Security with Data Loss Prevention
-
Aug 21, 2024
U.S. Department of Defense Chooses Trellix to Protect Millions of Email Systems from Zero-Day Threats
-
Aug 14, 2024
Magenta Buyer LLC Raises $400 Million of New Capital
-
Aug 1, 2024
Trellix Endpoint Security Stops 100% of Threats in Leading Industry Test
RECENT STORIES
The latest from our newsroom
Get the latest
We’re no strangers to cybersecurity. But we are a new company.
Stay up to date as we evolve.
Zero spam. Unsubscribe at any time.