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 : 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.
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 :
CRC32 DBB16EA4
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 :
- Spawning a new process in a suspended state using
CreateProcess()
with theCREATE_SUSPENDED (0x00000004)
flag - Unmapping the sections with
NtUnmapViewOfSection()
- Writing the payload inside the process with
WriteProcessMemory()
- Updating registers and resuming the process execution using
SetThreadContext()
andResumeThread()
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
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 :
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
Then calls 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.
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 :
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
amNFHufoTRn0P3vI8xBS4t6jM9CqXeibUDEpQ1ZGYywJzAg7sk2lc5WLOrKdhV
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]
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.