Since I love to play with the WinAPI or debugging in general, I decided to write a small unpacker for the open source PE executable packer UPX today (Windows version).
In order to accomplish this, I proceeded as follow:
CreateProcessAPI all with
GetThreadContextAPI call in order to read value of
ReadProcessMemoryAPI call loop searching for the last
- Overwriting the
CCin order to set an
INT3breakpoint on the address.
DebugEventloop waiting for the breakpoint. Once reached, reset byte back to
EIPby one and jump to the address (
OEP) of the target.
After reaching the
OEP, I proceed as follows in order to dump the process:
- Read ImageBase, Base of code, ImageSize, ... from original PE headers
ReadProcessMemory(hProcess, header32.ImageBase, buffer, header32.SizeOfImage, bytes_read)
- Save buffer content to payload.bin, update the PE header of the file with new EntryPoint (
OEP) and set
RawDataSizeof each section to its corresponding
After creating the dump with fixed
OEP & RAW offsets/sizes for the sections, I fix the dump with ImpREC (right now manually, but I plan to use
ImpREC.dll or the ImpREC lite source in order to assemble everything in one tool at a later point).
The thing that confuses me though, is the fact, that the resulting binaries worked perfectly fine (exact match with the MUP) for one test case (a small hello world fasm application) and my dump file was exactly the same I had received through OllyDump, but when I tried to do the same unpacking with an UPX packed version of
putty.exe, my dumped memory varied from the one OllyDump had dumped starting at RAW offset
0x73970 (exact match before that address).
However - the file size is again the same one (and all bytes before that offset match), just after that certain address the bytes magically won't match anymore (they are still non-zero though).
I studied the source code in
OllyDump.c thoroughly regarding this difference, but as for now I didn't find my mistake... In some cases my dumps are equal to the ones generated by OllyDump and in some they aren't. Or is the mistake probably in my approach already?
Note: Source code omitted on purpose, since it's a few hundred lines long and super messy as for now. Can/will add further details if required or if I missed something, please just let me know in the comments.