I've got a mystery file to analyze. On the surface, it is just a non-threatening windows executable file. It's name is malware.exe
Running it seemingly does nothing, except open a blank console window for a few seconds, which indicates at least something is happening. As is common with malware, I assume that this sample is packed. However, it's best to make sure, and also to know what packer was used. To do this, we open it up with DIE and view the file entropy:
The part to look at here is the very high (~8) entropy for the majority of the file. Entropy is simply a measure of the "randomness" of data within a file. It can range from 0 to 8. A score of 8 would mean complete randomness, which is common in encryption (ideally). A typical file would fluctuate like this:
Now that we know it's packed, we should also find out which packer was used. There are many ways to find this, but the easiest is to look at the sections headers in the first entropy picture. We see that there exists a header of the name UPX2
. UPX is one of the most common packers available. It is used for many legitimate applications, but low-grade malware also uses it because it is free and easy to use.
Packers are used to reduce the size of executable files. Essentially, when a program wants to reduce its size, it will compress the entire file, then attach a small program to the start address of itself which will decompress it at runtime. It's like zipping a file to send it over the internet, and also sending a copy of 7zip with it for the user to unpack the contents. This is the reason that packed applications often have very high and stable entropy. The contents are encrypted.
Looking at the packed code would be useless, so we need to unpack it before we do anything else. There are a few ways to unpack malware, but I am going to manually unpack this one for the purpose of having a cooler blog post. I start by attaching my debugger, x32dbg
to the program. The debugger automatically pauses.
The first thing we do is run the program up until the entry point, then pause again.
Now that we are paused, we begin looking for the end of the unpacker portion of the code within the binary. In this instance, it was near the end of the code-- One final jmp
instruction before the space is filled with zeroing operations.
The final jump before the zeroing operations indicates that the program has been unpacked, and is now going to jump to execution of the unpacked data. So, after pausing before the jump, we step one instruction forward and pause again. This will take us to, hopefully, the start of the "real" program.
We can use a plugin called Scylla
to carve out the new unpacked program. We use the IAT Autosearch and Get Imports functions to build the import tables for us, then dump the program to desktop.
We've now got a dump of the unpacked program, so let's verify that we did it properly by checking the entropy again.
So we've verified that we successfully unpacked the malware. The next step would be to analyze its activities and make a report.