In the previous post, we started to step through the Necurs sample using WinDbg. We also used IDA Pro to perform static analysis of the malware sample so we could get an idea of where to set breakpoints. However, while stepping through the code, we jumped to a location in WinDbg that was not disassembled by IDA Pro. When we looked a little closer, the hex values in the memory window in WinDbg did not match up with the hex values displayed in IDA Pro. It looked like the malware sample had “unpacked” itself, and we had jumped to a location that’s called the “original entry point”, or OEP. This post is going to describe how to patch the original executable with the unpacked code so we can continue to use IDA Pro to perform static analysis.
I’m going spend some time talking about the information in the PE header. Since discussing the PE header in detail is outside of the scope of this blog post, I’d highly recommend taking a look at an article in CodeBreakers Magazine called Portable Executable File Format – A Reverse Engineer View. The article was written in 2006, but is applicable to this sample. It is pretty lengthy, but is well written and very interesting. It’s also a lot easier to understand than the formal specification of the PE file format.
Section Header Analysis
Before getting started, recall that we are paused at offset 0x40614C in WinDbg. Take a snapshot of the Windows VM and call the snapshot OEP. Then restore the snapshot of the VM that was paused at the entry point of the program. Enter !dh 0x400000 in the WinDbg command window. This was the command that was used to display the entry point of the executable. This command will also display information about the different sections in the malware sample. The section we are interested in is section 1, the text section.
We know that the text section is loaded into memory at offset 0x401000. We also know that 0xF088 bytes of memory were allocated for this section. Finally, we know that the executable has been unpacked in the OEP snapshot. So if we can dump the contents of memory at this offset into a file and replace the text section of the original executable with the memory dump, we should have an unpacked executable that can be disassembled by IDA Pro. We will also have to patch the entry point of the program so that IDA Pro knows where to start disassembling the new executable.
To dump the memory, restore the OEP snapshot. Then in the WinDbg command window, use the following command to dump the memory:
.writemem c:\necurs.bin 0x401000 0x410087.
The command window should display that F088 bytes were written. We will use the necurs.bin file to patch the text section of the malware sample.
The entry point of the malware sample is stored at offset 0x118 in the original executable. This offset shows a value of 0xd460. However, the actual value of the entry point was 0x60D4. The entry point is stored in little endian format, so when we patch this value, we will need to convert the new entry point into little endian format as well. Recall that we jumped to 0x40614C after the executable was unpacked, so we’ll change the bytes at offset 0x118 from 0x60D4 to 0x4C61.
The python script shown below was used to patch the malware sample. The original malware sample was named necurs-packed.exe. The memory dump was named necurs.bin, and the patched malware sample was called necurs-unpacked.exe.
Some Things To Keep In Mind
It was relatively easy to patch the Necurs malware sample so we could analyze it in IDA Pro. However, there are packing algorithms that also compress the executable code. If this happens, the size of the unpacked section may be larger than the size of raw data in the executable file. If this is the case, the memory dump will not “fit” into the text section of the original executable. If this happens, it’s still possible to patch the executable, but it gets a little bit more complicated. Specifically, the file pointer to raw data field of any other sections would need to be patched to make room for the contents of the memory dump.
Also, even though we patched the entry point of the unpacked executable, the unpacked executable may not run in a debugger in the same way as the unpacked code. Any subroutines that were executed before the jump to the OEP may have written data to memory, and the new start routine may need to access this data. Remember that the main purpose of unpacking the executable in this way was to allow IDA Pro to properly disassemble the malware sample.
In the next blog post, I’ll talk about using scripting in IDA Pro as an alternative to patching the executable.