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).
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:
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.
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:
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:
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:
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).