I will show you how to unpack a Locky sample with OllyDbg. This packer is indeed an easy one. But you will see for yourself.
Download the sample from Hybrid-Analysis.
An alternative way of unpacking this sample is in this video on my channel:
The first thing I always do is a static check with a PE analysis tool like PortexAnalyzer. The image will look as follows and already tell us that the file is packed. Several sections of the file have a high entropy, including the .rdata section.
Packer identifies like DIE will not know what was used to pack it, because the packer is a custom one. This is often the case with malware samples.
This packer has the quirky characteristic to always add 32-bit Edition to the file version information whilst the other information changes:
language ID: 0x0409
code page: 0x04b0
FileDescription: Advanced Task Scheduler 32-bit Edition
InternalName: #dvenced Task Scheduler 32-bit Edition
LegalCopyright: Copyright © Southsoftware.com, 2002-2015
ProductName: Advanced Task Scheduler 32-bit Edition
The debug information has a strange, unknown type, hence Portex does not parse it any further:
Time Date Stamp: Thu Dec 09 05:07:00 CET 2083
Type: 4102553603 no description available
If you look into the binary (tip: search for 'RSDS' to find it with the hex editor) you will see that there is debug path that has been created or modified in a random fashion:
Whilst this does not help to unpack the file, it might help to recognize this custom packer in the future.
A check of the strings in the binary and the imports won't get us any further.
If you get this sample in a fresh state, you will easily see that this is Locky with dynamic analysis. But once the samples are older and can't find a working C&C, they won't encrypt anymore.
Now load the binary with OllyDbg. Don't forget to take a snapshot of your VM at this point. Simply step over with F8 while keeping your eyes open. If you happen to step over the following call you will see that the sample is doing a lot (reload the sample if that happens), so you should step into it instead (press f7).
The same happens at the following call, also step into:
Just keep on going like this, stepping over calls unless they start to do a lot, and keep your eyes open.
At address 0x402364 you might notice that the code writes to the .rdata section (0x417EE on that image). Indeed, if you put a breakpoint to the instruction and watch .rdata in the dump window while running to the breakpoint (F9), you will see how .rdata gets decrypted.
The jump to the .rdata section appears in 0x4020F0.
Note that push followed by ret equals a jump instruction. This ret instruction will jump to 0x41577A. Compare that with the PortexAnalyzer report or the Memory window in OllyDbg to verify that this virtual address is in the .rdata section.
Unfortunately we are not there yet. The decrypted code in the .rdata section is also a packer stub. Step through the code for a while. At some point you will see that the code collects addresses to common DLL functions with GetProcAddress. One of those is RtlDecompressBuffer, which is used by lots of packers to unpack their payload.
Break at address 0x415B37.
Right-click the value of EAX and click "Follow in Disassembler".
You will now see the code of the RtlDecompressBuffer function.
Break at the PUSH DWORD PTR [EBP + C] instruction:
Now right-click the EDI value and Follow in Dump
You will see an empty dump window
And after stepping over (F8) the file will unpack in memory.
The last thing to do is to open the Memory window and select the right memory area to dump the unpacked executable.
Choose the location to save the dump to and you are done. The result is an unpacked Locky as you can verify by checking the strings of the dump or looking at it with a hex editor.