← Retour à l'archive
·

Introducing x64dbg & 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

Analyse Malwr ↗, Analyse VirusTotal ↗

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 the CREATE_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() and ResumeThread()

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

Analyse VirusTotal ↗

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.