i could have saved myself lots of time if i read some preliminaries regarding qnix’s qcrk1, especially if i’ve read this line, “Some of Modefieded UPX Uses” all the while, i was trying hard to rebuild the section headers and their corresponding section information. oh well, there’s an end to stupidity.
this isn’t really a solution to that crackme. it’s more of my encounter with the UPX implementation the author added to the crackme. i find that more interesting than the actual solving. my first time to handle a packed executable too. before anything else, a brief intro and acquainting to UPX was necessary.
UPX or “Ultimate Packer for eXecutables, by Markus Oberhumer & Laszlo Molnar is is a portable, extendable, high-performance executable packer for several different executable formats. It achieves an excellent compression ratio and offers *very* fast decompression.
i emerged UPX and experimented a bit, read the manual[3] and a wikipedia[2] entry about UPX[1].
now, the ptrace approach later on is a bit of an overkill and really not necessary as the author only modified a signature to disable “unpacking. how i discovered the rotten signature is another story. it was simply just a matter of studying some strace() logs of upx. and some brief analysis of packed executables against the corrupted signature from the crackme. (and some luck)
suffice to say, that normal UPX packed executables will have the signature UPX! at a relative offset. in the crackme’s case, the author replaced the signature with ZXC!
misha@heaven ~/git/reverse/needs_a_little_brain/qnix-qcrk1 $ hexdump -s 3362 -n 4 -C qcrk
00000d22 5a 58 43 21 |ZXC!|
i replaced those bytes with the correct signature UPX! and i was able to decompress/unpack the crackme via upx -d easily. boring. the only problem is, the author clearly stated in his rules about “no patching”. so another way was necessary. one that does not include modifying bytes in the binary.
quote from the UPX manual[3]:
A compressed executable consists of the UPX stub and an overlay
which contains the original program in a compressed form.
The UPX stub is a statically linked ELF executable and does
the following at program startup:
1) decompress the overlay to a temporary location in /tmp
2) open the temporary file for reading
3) try to delete the temporary file and start (execve)
the uncompressed program in /tmp using /proc/
/fd/X as
attained by step 2)
4) if that fails, fork off a subprocess to clean up and
start the program in /tmp in the meantime
The UPX stub is about 1700 bytes long, partly written in assembler
and only uses kernel syscalls. It is not linked against any libc.
i verified those steps thru strace() and it does actually makes a temporary image in /tmp (with a random filename) and executes the image from/proc. i didn’t reach number 4 though. my approach was to make a copy of the uncompressed file from “/proc” just before the call to execve() is made.
i named my program “dupx”. here goes nothing.
(more…)