Sei sulla pagina 1di 8

1

Decrease the size of your Windows C++ executable


Using Compiler and Linker settings





Author: Zer0Flag
Contact: zer0fl4g@gmail.com
Greetz: s0rb, Celt1c, EvilB4st4rd, aSh and Sy1ux
To the drunkennanomites team
And of course all Reverse Engineers and Programmers out there!


2

Content
1. Introduction ..................................................................................................................................... 3
2. Removing the C Runtime ................................................................................................................. 4
3. Manifest .......................................................................................................................................... 5
4. Relocation ........................................................................................................................................ 6
5. Section Merging............................................................................................................................... 7
6. Compiler Settings ............................................................................................................................ 7
7. Section Alignment ........................................................................................................................... 8
8. Final Words ...................................................................................................................................... 8




3

1. Introduction

These days its not anymore such important to decrease your binary sizes cause of growing HDDs and much
higher bandwidth in a normal household. Some may need this just for a personal challenge, for PE Protectors
or just because they dont like huge files.
At first I will show you how big the c runtime is and how we can remove it from our project. Then we will
remove Manifests and optimize the PE Header using Section merging, Alignment adaption and disabling
Relocations. In the final step we will use the compiler settings to optimize the last bytes out of our file. And at
the end I will show you an overview of what we did and how much it reduced the file size. This will cover only
what I did myself using Visual Studio and the built-in compiler (tested only with VS2010 but most things should
work with older versions or other compilers too). Recommended would be some basic knowledge about the PE
File format. Because I dont want to dig too deep into it since there are enough awesome tutorials about this
Topic.
I will create a little MessageBox C++ Project using Visual Studio. Here is the Code:
#include <Windows.h>

INT WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MessageBoxW(NULL,
L"MessageBox from small .exe",
L"Decrease this file!",
MB_OK);
return true;
}


Picture 1 : This should be the result of the compiled code. Way to huge just for a MessageBox right?

Dont forget to backup in case something went wrong.

Good Luck and Happy Learning


4

2. Removing the C Runtime

Click on Project <ProjectNameHere> -Settings in the Menu from Visual Studio and you should see the
window with the Settings we can use to optimize our file.
First we will look at the Code generation Tab in the Property window. Mainly interesting for us is the option
how we want to include our c runtime. We can choose between Multithreaded-DLL and Multithreaded.
The difference between this two options are that in the first the c runtime is used from a .dll which must be
present on the OS where you want to run your file. The second option links the c runtime into your project so
you have no additional dependencies through the c runtime. And the two debug versions are the same just
that they contain some debug information. Once we selected Multithreaded /MT and you recompile your
Project you will see that the size increased! But dont be scared, we will remove the c runtime in the next steps.
But now you can see how big the runtime is even if we have nearly no code in our project.
You should keep in mind that some basic functions you use may depend on the c runtime (like memset ,
memcpy , printf). So be careful when you want to strip off your c runtime and you use some of these functions.
Most of them can be replaced by small code snippets or you can link some customized crt lib with your project
which provides the basic functions and isnt that huge. For some of this crt functions exists also a WinApi
alternative (check this link).
The next Settings lead us to the Input Setting of the Linker. By default the entry point is not set to your main
function. First some functions of the c runtime are running e.g. to init and watch the stack. And then the
execution continues on your entry point. Since we will cut off the c runtime we need to set an entry point to
our WinMain function.

Picture 2 : going to remove the c runtime

We want to remove the c runtime so we select in the 2
nd
Option Yes /NODEFAULTLIB. Additional we could
now remove all other dependencies (except the kernel32.lib) and then load all other APIs using
GetModuleHandle or LoadLibrary and GetProcAddress. This would help to reduce the File size too if we have
linked too much libs with our file. But in this example I will remove all except the User32.dll which is needed
for our MessageBoxW API. Now you should get some error on compiling your project.
error LNK2001: Nicht aufgelstes externes Symbol "_WinMainCRTStartup"
This means that the compiler didnt find the _WinMainCRTStartup function and could not link it. But thats
normal since its the entry point from the c runtime which just got cut off. So we will set our new entry point
now.


5

To do this we go to the Advanced Tab of our Linker settings and place the name of our new entry point in the
entry point setting.


Picture 3 : Set our new Entry point
Now you should be able to recompile your project without any error (dont forget to keep User32.lib in the
dependencies until you dont want to load the API dynamically). If you look at the file size now you will see a
huge change! We are at 3072 Bytes now.

3. Manifest

The Manifest is generated by the Visual C++ compiler and is a XML file which usually gets placed into a resource
of your generated Project. It provides some information about dependencies, Version numbers etc. To disable
the manifest we go to the Manifestfile Tab in our Linker settings and set the first option to No.

Picture 4 : Disable the manifest generation
After we recompile our project without the manifest the file size decreased once more to just 2560 Bytes.



6


4. Relocation


Picture 5 : PE Sections of our File

The next Step we do is to look at our File trough a PE Editor. There we can see 3 Sections. The first .text is
used for our Code and there is also the API call located. The 2
nd
.rdata contains as the name says data like
vars or our MessageBoxW strings. And in the last Section, called .reloc, are the relocations stored.
Relocations are used to load a PE File at a random image base to a process. This means if we disable the
relocations in the linker we will cut off this section and we gain some bytes.
To disable random image base usage we just go to: Linker Advanced Random Base Address and disable
it.

Picture 6 : Disable Reloc

After a recompile we see again that our file size decreased to 2048 Bytes.




7

5. Section Merging

As we can see in Picture5 we had 3 Sections but we removed the .reloc section so there are still 2 Sections.
They are located at 0x1000 and 0x2000 but are holding just about 0xD2 Bytes. Seems a bit to huge for this
small amount of data right?


Picture 7 : Merge Sections

So the next step we do is to merge the 2 last sections. The Setting is hidden there: Linker Advanced
Merge Sections. The Syntax of the command is from=to means in our case .rdata=.text.
After this we recompile again and are now at 1024 Bytes.

6. Compiler Settings


Picture 8 : Optimizing Settings

Note: If we change the alignment first and then change these settings we will only be able to change the
alignment to 16.

The Compiler can optimize the generated code a little bit and so we may be able to decrease the file size a little
bit more. We set the first and fourth setting to optimize file size and disable all others (they can produce an
error since some use the c runtime).

After a recompile we are still at 1024 Bytes.



8

7. Section Alignment

Some Steps before we merged the two last Sections to one. But the Section Alignment causes that this section
is filled with 0x00 until it reaches the Alignment. To avoid this we will change the Section Alignment to a lower
value since this will remove unneeded data from our File.
Again this setting is hidden in the advanced Menu of our Linker.

Picture 9 : Section Alignment

The value we enter has to be a valid n potency of 2 and represents the bytes to which the section is filled up.
The lowest value which worked for me is 4. This value also depends on your project and it can be that you cant
use 4 on all of them. Then you need to find out whats the lowest number which works for you.
After a recompile we are at 696 Bytes now!

8. Final Words

So finally we reached our goal and decreased the file size a lot. We got from 7168 Bytes with
dependencies or 33280 Bytes without to 696 Bytes for a still working MessageBox (without any
dependencies). You should keep in mind that there are still ways to reduce the file size but to do this
we need to switch to assembly since C++ is limited there with the compiler / linker settings. Also this
Paper is not about how to strip down the PE Header. Its just an overview how you can reduce your
file size with the C++ compiler/linker.
I hope this short Paper helped you to learn something new. If you have improvement ideas or bug
reports then feel free to write me an E-Mail.
What did we do?

Current File Size!
Begin, no changes, default release build 7168 Bytes
Linking the C runtime instead of using it as a dll 33280 Bytes
Stripping the C runtime 3072 Bytes
Disable Manifest 2560 Bytes
Disable Relocations 2048 Bytes
Merging Sections 1024 Bytes
Optimizing Compiler Settings 1024 Bytes
New Section Alignment 696 Bytes

Potrebbero piacerti anche