Introducing x64dbg and Pizzacrypts Ransomware Unpacking
x64dbg is a new Windows debugger entirely free and open-source. The project is hosted on GitHub : https://github.com/x64dbg/x64dbg. I learnt about x64dbg thanks to the Nuit du Hack 2k16 convention where the developer and founder, Duncan OGILVIE (@mrexodia) gave a talk about it. You can find the slides and a video of his presentation on this page : https://github.com/x64dbg/x64dbg/wiki/Contributing. The project was started in 2013 and has been under active development ever since.
I decided to give x64dbg a shot, and I'm loving it. The interface is very intuitive, clear and customizable.
There is a plugin support system with already a dozen of interesting plugins, ScyllaHide being one of them. There is also a lot of very useful commands that you can quickly type in the command line at the bottom.
You can download the latest build here : https://sourceforge.net/projects/x64dbg/files/snapshots/. It contains both x64dbg and x32dbg.
Pizzacrypts is another recent ransomware installed via a RunPE dropper. Since we're seeing more and more of those, it is always interesting to do some reversing and see how it works.
Hashes of the dropper posted on KernelMode :
CRC32 DBB16EA4 MD5 00f57ac8b384f7d21eeade87446659fd SHA1 ee0204b4cda5cee612b2f62345e0bab6b125c1c4
The packer uses the RunPE technique. It is pretty basic, but also very common nowadays so it can still be interesting to have a look at it. The RunPE method consists in these steps :
- Spawning a new process in a suspended state using
- Unmapping the sections with
- Writing the payload inside the process with
- Updating registers and resuming the process execution using
By putting a breakpoint on
CreateProcessW(), we can look at the stack and see the that the dropper creates a new process of itself in a suspended state :
1: [esp+4] 00000000 2: [esp+8] 00173C64 L"\"C:\\Pizzacrypts.exe\"" 3: [esp+C] 00000000 4: [esp+10] 00000000 5: [esp+14] 00000000 6: [esp+18] 00000004 (CREATE_SUSPENDED) 7: [esp+1C] 00000000 8: [esp+20] 00000000 9: [esp+24] 00173C20 10: [esp+28] 001744B0 "VBoxService.exe"
You can see the process with Process Explorer :
Then, the dropper performs the unmapping :
Now that the sections have been unmapped, the dropper will allocate new chunks of memory with
VirtualAllocEx() and then start writing the payload. Here is the prototype of
BOOL WINAPI WriteProcessMemory( _In_ HANDLE hProcess, _In_ LPVOID lpBaseAddress, _In_ LPCVOID lpBuffer, _In_ SIZE_T nSize, _Out_ SIZE_T *lpNumberOfBytesWritten );
If we put a breakpoint on the first
WriteProcessMemory(), we can get the content of the lpBuffer parameter to find where the payload is being copied from in memory.
Then, we look at the Memory Map tab and search for this address to see its size, 0x0F00 (you can also figure it out using the PE header). We can now dump the payload in a file using the following x64dbg command (the file will be saved in the x32dbg folder) :
savedata pizzacrypts.bin, 01D00000, F000
The last step is to unpack with UPX to get the final payload. Hashes of the unpacked payload :
CRC32 870F97BF MD5 7bab4f58fc896266f42b90280421bc0e SHA1 a97f1a307aa0cf01cd4d656e3eee5b08f4faedb6
The method we used will work with most RunPE droppers.
Quick analysis of the Pizzacrypts payload
Pizzacrypts isn't really worth a thorough analysis, I'll only talk about a few interesting things.
First, some weird anti-debug behaviors : the payload compares the running processes with this list :
ollydbg.exe idag.exe idag64.exe idaw.exe idaw64.exe scylla.exe scylla_x64.exe scylla_x86.exe protection_id.exe x64_dbg.exe windbg.exe reshacker.exe ImportREC.exe IMMUNITYDEBUGGER.EXE
DbgPrint("fuck") when a name matches, despite being user-mode, and after each process name comparison. It also contains the following strings :
sbiedll.dll dbghelp.dll api_log.dll dir_watch.dll pstorec.dll vmcheck.dll wpespy.dll vboxhook.dll vboxmrxnp.dll
But will only check for vboxhook.dll and vboxmrxnp.dll, try to load them and call
ExitProcess() if the loading was successful.
If you search for all the text strings in the payload module, you can see they are obfuscated :
Address Disassembly String 00400499 mov edx,pizzacrypts_unpacked.401784 "QiJGi1LW.e11" 004004AD mov edx,pizzacrypts_unpacked.401794 "N1YzioCGe1i" 004004C7 mov edx,pizzacrypts_unpacked.4017A0 "NJiCAiuE1ia" 004004E1 mov edx,pizzacrypts_unpacked.4017AC "Fi1iAiuE1ia" ...
We can recognize some patterns such as '.e11' (that should be '.dll') everywhere so we can assume the obfuscation is pretty weak. Setting memory breakpoints on strings, we end up in the deobfuscation routine, at 0x004041CC. Looking at the code, this routine is a simple substitution cipher using the following alphabet :
You can get the clear strings by dumping the referenced strings from the payload module and running this python script :
import re alph = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" subst = "amNFHufoTRn0P3vI8xBS4t6jM9CqXeibUDEpQ1ZGYywJzAg7sk2lc5WLOrKdhV" f_w = open("pizzacrypts_clear.txt", "w") with open("pizzacrypts_strings.txt") as f: for line in f: s = re.findall(r'\"(.+?)\"', line) if s: string = s str_clear = "\"" for l in string: if l in subst: index = subst.find(l) str_clear += alph[index] else: str_clear += l line = str_clear + "\"\n" f_w.write(line) f_w.close()
Subtle UAC trigger
The payload tries to force users to re-execute itself with admin rights by calling and looping on the following command :
"C:\Windows\SysWOW64\wberm\WMIC.exe" process call create "C:\pizzacrypts_unpacked.exe"
This command is used to trigger the UAC via WMIC.exe, which is a Microsoft Windows file, to make it look like a trusted Windows program is trying to gain admin rights.
You can only see the trickery if you click on 'Show details' :
Rest is standard ransomware stuff.