Packing is a very common technique used by malware for obfuscation. The most popular and well-known packer is called UPX (Ultimate Packer for Executables). By packing malware binary files, the data stored within the file becomes unreadable, and thus will need to be unpacked in order to become readable again. However, some developers have begun to employ anti-packing techniques to stop the malware becoming unpacked for analysis.
Let’s begin by examining a binary packed with UPX. UPX is a free portable program. Once you have downloaded UPX and opened the binary in Command Prompt, then you should see a main screen like below:
I would suggest placing upx and the binary you wish to compress in the same directory. The binary file which I’m using is the latest version of Firefox, which surprisingly isn’t packed with UPX, therefore I’ve packed it with UPX.
Multi-Layer Packing is a popular technique employed by malware developers to prevent unpacking from lesser skilled security analysts. The general process is to pack the malware with a common packer like UPX and then pack the same binary again but with a custom packer. These custom packers are unknown, and therefore unpacking programs won’t be able to unpack them. These requires the malware to be unpacked manually. Furthermore, most static analysis programs like PEStudio will consider UPX packing as suspicious because of it’s large use.
UPX will compress the sections stored within the Section Table of the PE file, these sections are sorted by their RVAs (Relative Virtual Addresses). We can investigate these sections with CFF Explorer. You’ll notice that the section header names have been changed to UPX 0 and UPX 1 respectively. The .rsrc section is left unpacked.
The section table is an array of structures called IMAGE_NT_HEADERS, this structure provided information about the corresponding section such as location and length. UPX 0 is an empty section containing only the process address space, it acts as a area where the decompressed code can be placed. UPX 1 is entrypoint section, it contains the decompression code which loads the original unpacked code into memory. UPX 2 is where the compressed version of the IAT, this is later reconstructed by the loader.
A packer will compress the sections as described, and add a small loader to the PE in a new code section. The loader within this newly code section (.text) will decompress the binary into memory, load the OEP (Original Entry Point) and resolve the IAT.
With malware, you’ll most likely find file and process functions within the IAT which allow the malware to drop additional files, copy itself into important Windows directories or start further malicious processes.
- SizeOfImage –
A method which is used to unpack code is by using memory dumping of the process address space. This commonly completed by using programs like LordPE. However, malware developers have managed to overcome this by changing the value of the SizeOfImage variable stored within the PEB. This achieved by getting the address of the PEB, finding the _PEB_LDR_DATA structure, and finding the doubly linked list called InLoadOrderModuleList, storing the address of the linked list inside a register and adjusting the size of list with a mov instruction.
This prevents debuggers to be attached to the process and prevents memory dumpers from working correctly.
- Removal of the Section Header –
The removal of the Section Header will prevent programs from gathering information about the image from the sections, and therefore will prevent dumping of the image address space.
- Nanomites and Self-Debugging (see Armadillo)
Armadillo is a anti-cracking software, it has been used to prevent anti-dumping and thus anti-packing of binary files. Armadillo uses self-debugging to prevent another debugger from being attached to the parent process. It relies on the simple fact that only one process can be debugged at one time in User-Mode. Self-Debugging works by creating a process, and that same process then attaches to itself by acting as a debugger. To overcome this implementation used by Armadillo, the DebugPort field can be set to 0.
Most Anti-Debugging techniques will work with anti-packing, these includes removal of the Imports section, thread hiding, uses debugger checking APIs and checking heap flags.
A Study of the Packer Problem and Its Solutions (Guo, Ferrie and Chiueh) – Symantec Research
Anti-Unpacker Tricks (Ferrie) – Microsoft Research
Armadillo 4.20 Removing the armour: a naked animal (AndreaGeddon)