It’s been a long time since I’ve been thinking of writing some posts about packers/crypters/protectors. I’m not sure how many I’ll write; it will probably depend on the interest of the audience. What I do know, is that I’ll try and follow the blog’s philosophy so we’ll go bottom up, explaining the basic concepts or pointing out to the best references when I deem it appropriate.
Packers, Crypters, Protectors
The first time one tries to look into this topic, one comes across these different names for what at first glance seem to be pretty much the same. These terms are nowadays somewhat mixed, but I think the following definition won’t harm and might shed some light for the inexperienced:
- A Packer‘s main goal is to reduce the executable size using compression algorithms. (e.g. UPX)
- A Crypter‘s main goal is to encrypt the executable, hindering the disassembly process. (e.g. EasyCrypter)
- A Protector‘s main goal is to make more difficult the task of debugging an executable using anti debugging techniques. (e.g. Yoda’s Protector)
- An Hybrid combines two or more of the above characteristics (e.g. Crypter)
The categorization problem should be obvious now, since many existing tools combine more than one of the above attributes . The confusion as to why some people consider a pure packer to be a protection against reverse engineering may come from the fact that all of the above tools modify the Original Entry Point (OEP) of the executable and modify the Import Address Table (IAT) either compressing, encrypting or protecting it. For a better understanding of why this is a bother when reversing, it’s key to realize that one of the first steps when starting the reverse engineering process of a program is to locate the OEP as well as function calls and common API references. Since these tools compress or encrypt the executable code and the IAT, the reverse engineer cannot locate those APIs until the unpacking has taken place.
It should suffice to say that knowledge is always valuable, but for those of you wondering about the practicality of learning how to unpack a packed binary or how to create your own simple packer/crypter I’ll make a case. From a penetration tester perspective, knowing how to create your own packer/crypter may come in handy at situations where you need to bypass antivirus software in order to achieve code execution on your target. This has always been one of the main goals of crypters, and they’re heavily used by malware. From a reverse engineer perspective or binary auditor, you’ll come across many samples that are in fact packed. For the most common cases, there are automated tools that would be able to unpack the binary for you. Nevertheless, for new or unknown packers you’ll be on your own, and manually unpacking them will be the only way to go. If you’re a developer, you may want to know more about protectors/crypters in order to prevent unwanted eyes to pry on your application; many commercial applications make use of these kind of tools to keep the crackers at bay.
Introductory Example (Unpacking UPX)
Before giving a brief overview on theoretical concepts, I think I could show a manual (sort of) unpacking of the very well known UPX packer. The program we’re using for this example is Windows’ notepad.exe. First, we’ve downloaded UPX (from here) ,and we’ve packed notepad.exe
C:\Documents and Settings\adrian\Desktop\Unpacking\UPX\upx308w>upx.exe -o ..\notepad_UPX.exe ..\notepad.exe
That should have produced a file called notepad_UPX.exe which we’ll use for the demonstration. It might worth our while to stop now and try to identify any obvious differences between the original and the packed binaries.
Looks like UPX did a good job, it reduced the notepad.exe size from 69K to 48K by means of compression. Now let’s look at some PE tools to spot some other differences. First we’ll run RDG Packer Detector (download here) on both binaries, and the result is below:
As we can see RDG says that original notepad.exe has been developed with Microsoft Visual C++ 7.0 and that the packed version has been packed with UPX. This was the expected result, since UPX is a very notorious packer and it’s been around for a long time. Another thing we can observe is the section table; we’ll use PEiD for that (download here).
OK, so we have three sections (.text, .data, .rsrc) and everything looks normal. Besides that, we can see the entry point located at offset 0x73d9.
That’s some differences there. We still have three sections, but the names have changed from .text and .data to UPX0 and UPX1. That’s no putting too much effort into concealing the packer, not that it was UPX’s goal anyway. The Entry Point has changed as well, now it points to the start of the unpacking routine (within UPx1). It’s also interesting the fact that the Raw Size of UPX0 is exactly 0 bytes, ain’t that weird? That causes two sections to have the same Raw Offset (0x400). These kind of things are a strong indicator that the executable has been through some kind of manipulation.
So now, let’s go and try to unpack the notepad.exe file that we’ve packed with UPX before. First we open the executable in Immunity Debugger to see a common sign of packed executables.
OK, so now the EIP should be sitting on the first instruction of our program, that as we know now, it’s the first instruction of the unpacking routine. Many packers, including UPX, start saving the processor state (registers) with a PUSHAD instruction. These are the looks of that:
We’re gonna do some cheating for the sake of the explanation here. We’ll take a look at the OEP within the debugger at the moment, right after loading the executable. After the unpacking takes place, we know (for we have the original file to compare) that the execution will jump to 0x0100739D (the OEP). But before the unpacking takes place, this is what lies at that address:
That’s certainly not good code, more like a bunch of zeroes. Now the little trick for the simple UPX. Since the packer starts saving the registers as we saw above, we can expect these registers to be restored right before the execution of the original notepad code starts. Thus, we’ll set a breakpoint on those registers to figure out when are they restored. Remember that our goal is to figure out the OEP. We’ll do as follows:
- Single step over the PUSHAD instruction (hit F7)
- Right click on ESP and click “Follow in Dump”. You should be seeing the values of the registers in the dump window right now.
- Select the values of one of the saved registers in the dump window and set a hardware breakpoint, on access.
- Resume execution (hit F9).
If lucky, we should be stopping at the breakpoint we set in the previous step. A few instructions after where execution is stopped there should be a JMP, that will lead us to (oh surprise) the unpacked code of notepad.exe, and thus the OEP.
Single step from that JMP just once and you’ll land into the OEP at 0x0100739D (as we already knew). Don’t keep stepping for now. We’ll make use of OllyDumpEx (download here), a plugin for both Immunity Debugger and OllyDbg that dumps the process to disk. Now that the process is unpacked in memory, we can dump this to disk, creating an unpacked executable. That executable won’t run just like so, we’ll need to to a little bit of work on it, but for now, let’s dump it. The options you have to select on the OllyDumpEx window are displayed below.
Click on Dump and save it with the name of your choice (in my case notepad_UPX_dump.exe). At this point, if we try to run the dumped binary it will display an error message, in other words, it won’t run. As disappointing as that might be, it has a rational explanation, and that is because the IAT needs to be repaired. We’ll talk about the IAT and how to repair it manually coming up in future post entries. For now, it suffices to say that our dumped binary has no clue where to obtain the addresses of the API functions it requires to execute properly. Many times, there is no need to repair the IAT manually and we can rely on ImpREC tool (download here) to do that for us. What we’re doing now to fix the IAT is:
- Run the packed version of notepad (notepad_UPX.exe) and leave it there.
- Run ImportREC
- In the dropdown menu, locate your notepad_UPX.exe process.
- Then modify the OEP box at the bottom to point to the OEP we’ve previously found, without the base address (i.e. just the offset). In this case 0000739D.
- Click on “Get Imports”
The ImpREC window should look like the picture below.
Now hit on “Fix Dump”, select the previously dumped file (notepad_UPX_dump.exe) and click OK. That’s it, ImpREC should have fixed the IAT of our process and created a new file called “notepad_UPX_dump_.exe” (note trailing underscore). You can try and run it now, if you followed all the steps, the notepad window should open as expected. Finally we have an unpacked version of notepad that we can now reverse engineer at will.
We’ve seen a little bit about packers and we’ve shown a quick and very easy example on how to unpack UPX to whet the appetite. There are many more things to do with this, there are many more topics to cover as it gets more challenging and interesting at once. Hopefully we’ll cover more of that in subsequent entries, till then If you have any questions, please leave a comment. Take care!