- Identifying a packed executable
- Locating the OEP (Original Entry Point) of the unpacked executable
- Dumping the unpacked executable from memory
- Fixing the import table
- IDA Pro
- OllyDbg (with OllyDump plugin)
- VMWare Virtual Machine (with Windows 7 Installed)
- calc.exe packed with UPX 3.08
This post aims to illustrate the general tasks involved when unpacking windows executable files. In this illustration, an executable (calc.exe) is packed using UPX 3.08.
Identifying a Packed Executable (Manually)
Take a look at the structure of the executable (using LordPE).
- there are custom sections added, and some of the existing sections (.text and .data) are not visible.
|calc.exe before packing.|
|calc.exe after packing.|
- the entry point address of the executable now lies outside of the code area address space and the section UPX0 has abnormal RSize and VSize.
|before packing, the EntryPoint address lies within the .text address space.|
|After packing, the EntryPoint lies within the address space of the custom section UPX1. Also note the abnormal RSize (Raw Size) of zero and VSize (Virtual Size) of non-zero for the section UPX0.|
Take a look at the Executable in IDA Pro
- there is only one start function and a few imports.
- only a small amount of code is recognizable by IDA's automatic analysis features.
Identifying a Packed Executable (Automatically)
- Automated tools such as PEiD are able to identify if an executable is packed, and possibly even identify the type of packer used.
- Once the unpacking stub has completed unpacking the packed executable, it has to transfer execution to it. This transfer involves somehow setting the address of EIP to the address of the original entry point (OEP) of the unpacked executable.
- There isn't a fixed strategy that is guaranteed to find the OEP for all packers, but generally the concepts still apply.
Locating the OEP
- A jmp instruction is the most popular way for the unpacking stub to transfer execution to the unpacked executable's OEP. This is typically referred to as the "tail jump".
- Logically, since the original executable is located in an address space outside of the unpacker stub's address space, and in it's packed state, the executable's code cannot be analyzed, the "tail jump" could be analyzed in IDA as a jmp to an address space that cannot be traced/analyzed.
- Of course this method of locating the OEP isn't full proof, and there could be many of such jumps in the unpacker stub's code, but it provides a good indicator for analysis of the binary and potentially the OEP.
|Note the tail jump to 0x01012475 shortly after the popad instruction. Also notice the code following the tail jump are all zeros.|
Dumping the Executable
- When execution is transferred to the unpacked executable, dump the process and save it as an executable on the file system using the OllyDump plugin and do not close the debugger.
|EIP is at 0x01012475 and execution has been transferred to the unpacked executable.|
|Dump the executable using the OllyDump plugin, check that the OEP is correct and that the "Rebuild Import" check box is unchecked. The tool Import Reconstructor will be used to rebuild the imports.|
Fixing the Import Tables (Automatically)
- Select the executable that is currently being debugged in OllyDbg. Set the OEP, click the "IAT AutoSearch" button, click the "Get Imports" button and finally click the "FixDump" button. After clicking the "FixDump" button, select the executable dumped using OllyDump.
Its Done! But Note the Differences
- The section names remain as they were when the executable was packed.
- In the process of fixing the import table, Import Reconstructor added a new section, ".mackt".
- The file size is larger than the original executable because the unpacking stub code is still there and there is an added section ".mackt".