Month: April 2020

Reversing Ryuk: A Technical Analysis of Ryuk Ransomware

Reversing Ryuk: A Technical Analysis of Ryuk Ransomware

Ryuk has been in operation since mid-2018 and is still one of the key ransomware variants operating in 2020. The threat actors behind Ryuk have been known to target a wide range of industries, and they typically demand substantial ransom amounts.

Lately, given the ongoing COVID-19 situation, the actors behind Ryuk have been taking advantage of this and targeting the most vulnerable – hospitals and the health care industry. In light of this (and because I am personally interested in how Ryuk functions), here is a technical analysis of Ryuk’s key functionalities.

Note: The Ryuk sample I used for this analysis is:

feafc5f8e77a3982a47158384e20dffee4753c20

Carbon Copies

The first thing Ryuk does upon execution is the creation of two “hidden” executable files that are placed on the desktop or one of the user’s temporary directories, depending on where the Ryuk sample was executed from.

Ryuk hidden executables.
Ryuk hidden executables.

These executables are actually copies of the primary Ryuk executable, and seem to be used for a few different purposes – most notably persistence and spawning additional instances of itself for more threads and faster encryption of the filesystem.

Ryuk child processes.
Ryuk child processes (executables) running.

Ryuk is extremely fast in its encryption process. This is possible due to the way Ryuk behaves in regards to threads. The two executables and associated processes that were created, along with the process injection techniques I will outline below, all serve as hosts for multi-threaded encryption. More on this later.

Process Injection

After the creation of its child processes, Ryuk will attempt to inject itself into additional processes running on the victim’s system.

Ryuk utilizes the Windows functions CreateToolHelp32Snapshot, Process32First, and Process32Next in order to enumerate processes running on the victim’s system and search for a feasible target process for injection:

Ryuk enumerating system processes.
Ryuk enumerating system processes.

Ryuk is only able to inject code into processes that are running at the same (or lower) privilege level as the Ryuk sample itself. So if Ryuk is running as Administrator or System (hopefully not the case!) it will be able to inject into System-level processes.

An important note is that Ryuk will not inject into csrss.exe, explorer.exe, or lsass.exe. This safeguard is likely used to prevent system instability, but this is just an educated guess. (Please let me know if you have additional information about this.)

Ryuk process-injection safeguards.
Ryuk process-injection safeguards.

After enumeration and selection of a target process, Ryuk utilizes a typical process injection technique:

First, the OpenProcess and GetModuleHandleA functions are called in order to get a handle to the target process.

Ryuk getting a handle to the target process.
Ryuk getting a handle to the target process.

VirtualAllocEx is then called in order to allocate memory within the address space of the target process, followed by WriteProcessMemory, which is called in order to write code into this new memory space. Finally, CreateRemoteThread is called to create a new thread in the context of the victim process, which will subsequently execute the injected code.

Ryuk writing memory and creating a thread.
Ryuk writing memory and creating a thread.

This injection process can also be seen in an excerpt from API Monitor:

Ryuk process injection - API Monitor.
Ryuk process injection – API Monitor.

The injected code is actually just another copy of the original Ryuk process. (See my post on unpacking Ryuk if you are interested in learning one method of leveraging this process injection technique in order to unpack Ryuk.)

When I ran Ryuk in my Windows VM, code was injected into dwm.exe, taskhost.exe, and even the VirtualBox Tray process (VBoxTray.exe). Interestingly, two of these processes crashed a few minutes after injection, so it appears that Ryuk can cause some incidental system instability.

Ryuk code injection crashes VBoxTray.exe.
Ryuk code injection crashes VBoxTray.exe.

Command Execution

Ryuk leverages Windows command line tools for most of its supporting functionalities. Some of these commands can be seen in the below code:

Ryuk executing various command-line commands.
Ryuk executing various command-line commands.

During my analysis, the following command were run by Ryuk:

net.exe stop "audioendpointbuilder" /y

This command kills the “audio endpoint builder” Windows service, which causes audio to malfunction on the victim system. I am still unsure why Ryuk executes this command, and I have no good suggestions.. Other than perhaps to infuriate the end user.

net.exe stop "samss" /y

Stops the Security Accounts Manager. This technique may be used to prevent security alerts being triggered and sent to a SIEM.

cmd.exe /c "WMIC.exe shadowcopy delete" 

This command clears the Windows Volume Shadow Copies so that they cannot be used to recover files.

cmd.exe /c "vssadmin.exe Delete Shadows /all /quiet"

This command is used as another method of removing shadow copies of files.

cmd.exe /c "bcdedit /set {default} recoveryenabled No & bcdedit /set {default}"
cmd.exe /c "bootstatuspolicy ignoreallfailures"

These commands are used to disable Windows error recovery and associated boot options so it is more difficult to recover the system.

icacls "C:*" /grant Everyone:F /T /C /Q
icacls "D:*" /grant Everyone:F /T /C /Q
icacls "Z:*" /grant Everyone:F /T /C /Q

These commands attempt to assign the group Everyone full permissions to the C, D,and Z drives. This is used before the encryption process begins, to ensure Ryuk has permissions to modify files.

cmd.exe " /C REG ADD "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v "EV" /t REG_SZ /d "<path_to_Ryuk>"

This command is used to add Registry persistence. Essentially, this will ensure the Ryuk sample will run again upon system bootup. Ryuk will only encrypt files once, however. Speaking of that… on to encryption!

Encryption – A Multi-Threaded Operation

The file encryption process runs once the above command line commands have been executed. As previously mentioned, Ryuk encrypts the filesystem using multiple threads, spread amongst the primary Ryuk executable, the secondary executables, and the processes Ryuk was able to inject into. Ryuk creates a new thread for each file being encrypted:

Ryuk encryption threads.
Ryuk encryption threads.

Ryuk utilizes the functions FindFirstFileW and FindNextFileW in order to iterate through the files on the victim system. Once a file has been found, Ryuk will call CreateThread in order to start a new encryption thread.

It is notable how quickly Ryuk is able to enumerate the files on the victim system and encrypt them. In my initial tests (running on a virtual machine with 50+ GB hard drive) files were encrypted within a matter of 120 seconds or so, including files on network-attached drives.

Ryuk will also create a “readme” file (RyukReadme.htm) in every directory that contains encrypted files. This readme file instructs the victim to contact the email address mentioned for further instructions on how to pay the ransom:

Ryuk readme file.
Ryuk readme file.

I originally wanted to go a bit more in depth into how Ryuk encrypted files and the encryption algorithms used. However, after a bit of research and code review, I realized that Ryuk is not doing anything incredibly new or note-worthy in terms of the encryption process. According to this research, Ryuk is utilizing RSA-4096 and AES-256 encryption algorithms, which are extremely strong and, at this point in time, “unbreakable”. I put unbreakable in quotes because, technically, no encryption algorithms are completely unbreakable and all will eventually be broken 😉

Network Enumeration

Ryuk performs some rudimentary network enumeration in order to discover other network drives and adjacent systems to encrypt. In my tests, and according to the Ryuk code in the sample I analyzed, Ryuk is able to enumerate the network in a few different ways.

First, Ryuk obtains the ARP table from the victim machine (using the GetIpNetTable function) and attempts to ping those connected systems to see if they are online:

Ryuk pinging connected systems.
Ryuk pinging connected systems.

If these systems are “alive”, Ryuk will attempt to connect to and mount SMB shares on these systems:

Ryuk attempting to connect to SMB network shares.
Ryuk attempting to connect to SMB network shares.

Ryuk will then attempt to encrypt any file system it is able to, given the victim system has the correct permissions and network capabilities to mount these devices.

In addition, Ryuk grabs the network adapter IP addresses (using the GetAdapterAddresses function) from the victim system:and attempts to send WOL (Wake-On-LAN) packets to these systems in order to wake them up. Ryuk will only send WOL packets to addresses that start with 10, 172, or 192.

Ryuk Wake-on-LAN attempts.
Ryuk Wake-on-LAN attempts.

Defending Against Ryuk

Ryuk MITRE ATT&CK matrix.
Ryuk MITRE ATT&CK matrix.
  • Since Ryuk (and other modern ransomware) is incredibly efficient and will encrypt an entire filesystem and attached network drives very quickly (likely within minutes), it is best to detect Ryuk as early in the Kill Chain as possible, ideally in the Delivery phases and before Installation.
  • Ryuk is typically delivered via other malware and droppers, such as Trickbot, Dridex, and Cobalt Strike Beacons. Developing detections and mitigating controls against these malware variants in order to detect an infection before the deployment of Ryuk is optimal.
  • In the event that Ryuk is deployed and encryption occurs, a sound business continuity and backup plan will be very helpful. Ensure offline backups are kept available.
  • Consider very carefully before paying the ransom for the purchase of the Ryuk decryptor software. This decryptor software has been well-researched by several threat intelligence vendors, and is said to be very poorly programmed and tends to crash during the decryption process, or worse, permanently destroys encrypted files.

As always, thanks for reading! If you enjoyed this post, follow me on Twitter (@d4rksystem).

Unpacking Ryuk

Unpacking Ryuk

In an earlier post, I wrote a technical analysis of the Ryuk ransomware and its behaviors. This post is a follow-up to that, for whoever is interested in learning one method of unpacking a Ryuk sample.

As explained in my previous post, Ryuk will typically try to inject itself into several processes running on the victim system. It does this be leveraging a common injection technique using OpenProcess, VirtualAllocEx, WriteProcessMemory, and finally, CreateRemoteThread .

Ryuk can be extracted from memory by running it in a debugger (x64dbg is my choice for this) and setting a breakpoint on CreateRemoteThread (this can be done with the command setBPX CreateRemoteThread in x64dbg).

Breakpoint hit on CreateRemoteThread.
Breakpoint hit on CreateRemoteThread.

Once the breakpoint is hit and program execution is paused, we can expect to see a handle to a process (the process in which Ryuk wishes to inject code into) by inspecting the call stack window. In my case, the handle is 0x148, located in rcx:

Call stack for CreateRemoteThread.
Call stack for CreateRemoteThread.

Next, we need to cross-reference this handle with its process name in order to find out the target process. We could use x64dbg for this, but I will use ProcessHacker because I feel it is a bit easier to use in this case. To do this, simply launch ProcessHacker, right-click the running Ryuk process, select Properties, and then the Handles tab.

We can see below that the handle (0x148) is associated with the taskhost.exe process. It looks like Ryuk injected code into taskhost.exe and is now attempting to run this code. Note: This process may be different for you! Ryuk often injects into dwm.exe, virtual machine processes, and others.

Handle to taskhost.exe in Ryuk process.
Handle to taskhost.exe in Ryuk process.

Now we must inspect this taskhost.exe process and try to find the location where Ryuk injected code. We can do this with ProcessHacker or any number of memory inspection tools. I have chosen instead to attach the process again to x64dbg and inspect the memory there. This is just a matter of personal preference, however.

What we are looking for in the taskhost.exe process address space is a suspicious memory region where Ryuk’s code has likely been injected. This can be accomplished using the Memory tab in x64dbg (or the Memory tab in ProcessHacker, if you choose to do it with this tool). In x64dbg, underneath the taskhost.exe memory region, we can see a memory region has been created with ERW (Execute-Read-Write) permissions, which is suspicious. The memory region has a significant size (163 kb), which is definitely enough space to store an executable:

Injected executable in taskhost.exe.
Injected executable in taskhost.exe.

This is likely our injected code. We can dump this memory region from x64dbg (or from ProcessHacker) by right-clicking the memory region and selecting the Dump or Save option.

Now you should be able to inspect this file in a PE viewer, or a disassembler (such as IDA), and should be able to see readable strings:

Ryuk strings - before unpacking executable.
Ryuk strings – before unpacking executable.
Ryuk strings - after unpacking executable.
Ryuk strings – after unpacking executable.

After dumping the memory region, if we try to start analyzing this file in a disassembler (such as IDA), we would see that this file is not a valid PE file, or is otherwise corrupted. To fix this, you can the use PE_Unmapper tool. This tool will “unmap” the executable from memory and fix up our dumped executable, including rebuilding the Import Address Table. Note: Other tools may work for this as well, including Scylla or OllyDump, but I found that PE_Unmapper worked the best for my case.

With PE_Unmapper, we can unmap this dumped executable using the following command syntax:

pe_unmapper.exe [mem_dump_input] [mem_address_base] [output_file]

In my case, the command would be:

pe_unmapper.exe ryuk_dump.mem 0x13F630000 ryuk_fixed.exe

You should now have imports listed in a PE viewer tool or in a disassembler. One important thing to note is that Ryuk dynamically builds a second imports table using the GetProcAddress function. This means that there are actually more imports than what is listed in the Imports section of any PE viewer tool. Because of this, you will likely experience issues analyzing this file in a disassembler.

These functions seem to be labeled as cs:qword_<address>. To fix this issue, you will have to manually rename these functions, like so:

Ryuk imports table - before fixing.
Ryuk imports table – before fixing.
Ryuk imports table - after fixing.
Ryuk imports table – after fixing.

You could probably script this part as well, if you felt motivated enough. If you do, please share it with me 😉

Here is the sha256 hash of the sample I used in my analysis:

feafc5f8e77a3982a47158384e20dffee4753c20

This sample can be found on VirusTotal. If you don’t have access to VirusTotal, just Google the hash and you may be able to find it elsewhere online. Otherwise, any new-ish Ryuk sample will likely work for this analysis.

Well, that’s about it. As always, thanks for reading! If you enjoyed this post, follow me on Twitter (@d4rksystem).