Introducing x64dbg and Pizzacrypts Ransomware Unpacking


About x64dbg

x64dbg is a new Windows debugger entirely free and open-source. The project is hosted on GitHub : 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 : 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 : It contains both x64dbg and x32dbg.

Unpacking Pizzacrypts

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 :

MD5	00f57ac8b384f7d21eeade87446659fd
SHA1	ee0204b4cda5cee612b2f62345e0bab6b125c1c4

Malwr Analysis, VirusTotal Analysis

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 :

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 WriteProcessMemory() :

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

VirusTotal Analysis

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.

Anti-debug checks

First, some weird anti-debug behaviors : the payload compares the running processes with this list :


Then calls DbgPrint("fuck") when a name matches, despite being user-mode, and after each process name comparison. It also contains the following strings :


But will only check for vboxhook.dll and vboxmrxnp.dll, try to load them and call ExitProcess() if the loading was successful.

Strings obfuscation

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[0]
			str_clear = "\""
			for l in string:
				if l in subst:
					index = subst.find(l)
					str_clear += alph[index]
					str_clear += l
			line = str_clear + "\"\n"

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.