Code Crunching – Tiny PE (challenge) [update #2: now with 304 bytes!]
[ Update: tiny PE is now at 384 bytes. The follow-up post and one of the techniques used to achieve this can be found here.
Update #2: tiny PE is now at 304 bytes:
Or shall I dare saying the Tiniest?
It all began a few days ago, a few friends challenged me to write a smaller PE executable than theirs.
It might sound fairly easy at first, but it’s not, and there is merely one simple goal:
Grab a file from the Internet and execute it.
With the following rules:
1) Only Imports section is allowed for kernel32.dll to get LoadLibraryA and GetProcAddress.
2) All strings must not be viewable (except rule 1), so we xor…
After working dozens of hours I came up with something extremely crazy, 411 bytes.
Most of the debuggers will hate this file and it has anti-disassemblers effect. I couldn’t check it on many systems, just my WinXP and it works nicely.
Here’s the hex:
If any of you have ever tried to do this before, the common mistake is that the minimum .exe file size you can get is 0×200 bytes. Since the File Alignment has to be at least 0×200. The OS Loader gracfully ignores it, luckily
The code itself is really efficient, though it may still be possible to shave a few more bytes off. In my opinion that extra work on it is not worth it under the 80/20 rule.
To achieve this, lots of tricks were needed. To name a few, I used:
1) All (well almost) sizes fields of DataDirectory (to place my code).
2) Unused fields in the Section structure (to store a string).
3) Unused fields in the Import Module Descriptor (to store another string).
4) The fact that the OS Loader will zero the caves (from end of my code to segment alignment).
And many other things! I even tried to change the size of the optional header, though one might say it was a pointless effort…
What I did
I went through three main stages while working on this:
First was to crunch the PE itself, proceed to write some code and then seriously mix these two methods.
I had to see how the OS Loader works, because before all this work, it didn’t want to load my file. Thanks to WinDbg it was easier to do so. The funny thing is that most of the file (35%) are zero bytes, the rest are the strings and then the code itself which is sparsely located all over the file.
The file can be found here:
Hint: xor the file with 0xAA to see its resources.
Tools I used for this research: my very own diStorm64, WinDbg, OllyDbg, IDA Pro, Yasm, RTA, Python, LordPE, PE Tools and as you can see Hexplorer.
It almost looks like I was in the middle of a war between all these tools
BTW – The file will download a stub (showing a message box) from my site and launch it.
An older very crazy code crunching challenge I did was this:
What do you think, how can we make it smaller?
I am going to work on this some more later in the week. My target is reaching less than 400 bytes, but maybe someone else will get there first?
Lame tricks such as using a shorter URL or msiexec should not be used.