• ### Announcements

#### Archived

This topic is now archived and is closed to further replies.

# Smallest .exe possible...

## Recommended Posts

There is an article on HUGI diskmag 21 [http://www.hugi.scene.org/hugiidh.htm] that explains methods to make a smaller windows executable. Some of the optimisations are OS version specific though. Does anyone know of any other tricks? Regards, R

##### Share on other sites
did you mean issue #27, with darkblade? if so, there is a second aritlce in the series at ukscene.org.
there are other methods to reduce the exe size, by changing the size of the alignments, but you then loose win98 portability, and, since in that article he demonstrates how to compress the exe header the size difference is typically only a few bytes : basically not worth it.
if you want to give it a shot, set align and filealign to 16 each.

if you want to make a really small exe, use assembly. there are examples floating around.

##### Share on other sites
http://www.coldcity.com/code_tinyexes.asp

This even works in vc7.1

..Then, after compilation, you could use UPX on the executable to make it even smaller.

http://upx.sourceforge.net/

[edited by - shrt on January 7, 2004 1:34:44 AM]

##### Share on other sites
Thanks!

I compressed one of my programs with UPX. It was 86Kb, and it is now 36Kb!

I have tried it on my W2K install, and it works no problems... if anyone has a W9X or XP install that is unbreakable...?

SendToSync homepage

R

[edited by - reaction on January 7, 2004 2:44:56 AM]

##### Share on other sites
Actually the alignment tweak won''t remove compatibility with Windows 98. The tweak controls the section alignment; under Windows 98 it is optimal to align sections on a 4k boundary to improve load time but this obviously results in larger executables. If you don''t do this (specify /opt:nowin98 in VS or change Properties->Linker->Optimisation->Optimise for Windows98) then it''ll just load a little slower under Win98.

cheers
sam

##### Share on other sites
I wrote a tutorial a while back.. maybe it can help.
http://dr-code.com/modules/Top/Tutorial_C+/rse.html

##### Share on other sites
Thanks Eddycharly,

Those ''#pragma'' statements will be in my next source.

How bad would the performance penalty be for something like a game?

R

##### Share on other sites
I don''t think you''ll notice a change..
Maybe it will be a bit slower to start, but once it''s started, it should run at the same speed than an uncompressed exe.

##### Share on other sites
Would DWORD (32 bit) alignment be affected at all?

quote:

In fact, you cannot reduce them more than the size of the biggest structure used in your program.

If a structure is aligned in the .exe in a particular way, are all structures created in the memory heap by the .exe aligned the same way, or are they re-aligned (DWORD) for efficiency there?

R

(That is the best article I have read on the subject BTW)

[edited by - reaction on January 7, 2004 7:18:07 AM]

##### Share on other sites
Eddycharly: nice article, thanks! I was on a similar 'squeeze the hell out of my first demo' trip a while back That's an interesting idea with RLE for the header. My approach was to interleave the headers, and fit as much data in there as possible; apack would hopefully compress the remaining zeros effectively. I'll have to try your scheme (when I have time ).

You can save quite a bit in the dropper (52 -> 27!) - here's mine:
; exe dropper; Jan Wassenberg 2003; free mem	mov		ah, 0x49	int		0x21; fopen	mov		ah, 0x3c	pop		cx				; cx = 0 (attrib)	mov		dx, 0x100+exe			; filename == "MZ."	int		0x21; fwrite	xchg		ax, bx	mov		ah, 0x40	dec		cx				; 64 kb	int		0x21; fclose	mov		ah, 0x3e	int		0x21; exec	mov		ax, 0x4b00	int		0x21exe:incbin "w.exe"

(Note: the filename seems to require a '.').

		db	'MZ'				; e_magic		db	'.',0				;   dropped file name		dd	'PE'				; Signature		dw	0x014c				; Machine = x86		dw	1				; NumberOfSections		dd	0,0,0		dw	0x0070				; SizeOfOptionalHeader		dw	0x010f				; Characteristics = 32 bit exe		dw	0x010b				; Magic		db	'glu32.dll',0			;   Name (RVA 30)		dd	0		dd	rva(start)			; AddressOfEntryPoint		dd	0,0		dd	0x400000			; ImageBase		dd	4				; SectionAlignment, e_lfanew		dd	4				; FileAlignment		dd	0,0		dw	4				; MajorSubsystemVersion		db	'EDIT',0			;   wnd class name (RVA 78)		db	0		dd	0x10000				; SizeOfImage (virtual)		dd	0xa4				; SizeOfHeaders		dd	0		dw	2				; Subsystem = WIN32_GUI		dw	0		dd	0x400000			; SizeOfStackReserve		dd	0x400000			; SizeOfStackCommit		dd	30				;   Name (RVA 108)		dd	rva(imp_tbl)			;   FirstThunk		dd	0		dd	2				; NumberOfRvaAndSizes (# data dirs)		dd	0				; Export VirtualAddress		dd	0				; Export Size, End Import		dd	96				; Import VirtualAddress		dd	40				; Import Size		dd	0,0		dd	0				; VirtualSize		dd	0				; VirtualAddress		dd	0x10000				; SizeOfRawData				FIXME?		dd	0				; PointerToRawData

(Notes: I just saw it won't run on 9x at all - section alignment is set to 4. Total size = 160 bytes, including embedded import table; there's plenty of room for more data, but I didn't have any)

Another worthwhile thing to squeeze is OpenGL imports in the exe.
Specify the ordinals of functions you need (unfortunately, some idiot at MS removed the DllInitialize function in opengl32.dll for WinXP, so the ordinals are decreased by one. *sigh*); the ORD macro builds a table of deltas to the next value (1 byte). If there's a large gap, specify a dummy value to bridge it.
ORD glBegin, 12
ORD glClear, 18
...

now the import code:
; import gl functions	mov		esi, ord_tbl	mov		edi, ogl_funcs	push		byte num_ords	pop		ebp	xor		ebx, ebx			; (xchg eax, ebx if eax == 0)?.1:	xor		eax, eax	lodsb						; delta to next ordinal	add		ebx, eax			; ebx = current ordinal	push		ebx	push		opengl32	call		GetProcAddress	stosd	dec		ebp	jnz		.1

ogl_funcs is our import table, so to speak. call glClear translates to call [ebp-4] - 3 bytes! (Note: ebp points to my BSS; the table comes before it).

Great fun

[edited by - Jan Wassenberg on January 7, 2004 7:20:29 AM]

##### Share on other sites
I just rebuilt SendToSync...

With...

// /Og (global optimizations), /Os (favor small code), /Oy (no frame pointers)#pragma optimize("gsy",on)// Make section alignment really small#pragma comment(linker, "/FILEALIGN:16")#pragma comment(linker, "/ALIGN:16")// Merge sections#pragma comment(linker, "/MERGE:.rdata=.data")#pragma comment(linker, "/MERGE:.reloc=.data")#pragma comment(linker, "/MERGE:.text=.data")

... saved ~7Kb (86 - 79).

With 'Project Settings->C/C++->Code Generation->Use Runtime Library->Multithreaded DLL' ... saved 32Kb (86 - 34).

With...

'Project Settings->C/C++->Code Generation->Struct Member Alignment->1 byte'

... the same, 34Kb (Also, I couldn't get the /ALIGN: value lower than 16).

With upx124w... it wouldn't pack as...

                     Ultimate Packer for eXecutables         Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002UPX 1.24w        Markus F.X.J. Oberhumer & Laszlo Molnar         Nov 7th 2002        File size         Ratio      Format      Name   --------------------   ------   -----------   -----------upx: SendToSync.exe: CantPackException: filealign < 0x200 is not yet supportedPacked 1 file: 0 ok, 1 error.

...

R

[edited by - reaction on January 7, 2004 7:42:57 AM]

##### Share on other sites
Thanks for the input Jan Wassenberg. That''s nice to have a bit of feedback.
I don''t have the time to look at that right now, but i''ll do it asap and update the article.

##### Share on other sites
WARNING!

Be aware that messing with file and section alignments can produce unusable applications.

My .exe has...

quote:

section alignment 00000010h
file alignment 00000010h

... and it will not work on Windows 98!

The W98 error message is...

quote:

... file is improperly linked with section alignment less than 0x1000. Fix the error, and then link again.

quote:

Windows cannot run this program because it is in an invalid format.

... From the help files of ''PE Explorer'' [http://www.heaventools.com]...

quote:

Section Alignment
Alignment (in bytes) of sections in RAM when loaded into memory. Must greater or equal to File Alignment. Default is the page size for the architecture.

File Alignment
Alignment factor (in bytes) used to align the raw data of sections in the image file. The value should be a power of 2 between 512 and 64K inclusive. The default is 512. If the SectionAlignment is less than the architecture’s page size than this must match the SectionAlignment.

.. so be careful.

Also, does anyone know of an application that can realign these sections to make a .exe reusable again (I have tried UPX and WWPack32 (NEOLITE appears to have been discontinued, or renamed at least)), neither worked.

I tried WINALIGN.EXE and WALIGN.EXE; no luck.

R

##### Share on other sites
... I tried both UPX 1.24w and 1.29w BETA.

R

##### Share on other sites
Just to say ty to shrt for the plug to http://www.coldcity.com/code_tinyexes.asp

www.coldcity.com
code, pics, life

##### Share on other sites
quote:

quote:

Section Alignment
Alignment (in bytes) of sections in RAM when loaded into memory. Must greater or equal to File Alignment. Default is the page size for the architecture.

File Alignment
Alignment factor (in bytes) used to align the raw data of sections in the image file. The value should be a power of 2 between 512 and 64K inclusive. The default is 512. If the SectionAlignment is less than the architecture’s page size then this must match the SectionAlignment.

Also, please be aware that the 'page size' for the 'Intel 386' (i386 - 32 bit processor) is 4096 bytes.

So if the 'section alignment' is < 4096 bytes, any 'file alignment' should be the same value.

quote:

// Make alignments safe for i386 architecture...

R

[edited by - reaction on February 13, 2004 8:17:40 AM]

##### Share on other sites
BTW, has anyone got a copy of SendToSync 4.7 @ 86kb... my HDD has failed, my webhosts have lost my backups, and I have no other backups to work off at the moment?

R

##### Share on other sites
I have also tried ASPACK, which is apparently the best packer available (a windows GUI for UPX I think, maybe).

R

##### Share on other sites
I have it on _good_ authority now that it is _not possible_ to re-align a mal-aligned executable or binary; at least, not with present technologies.

R

[edited by - reaction on February 13, 2004 10:44:26 AM]

##### Share on other sites
Here''s an interesting read on making a really teensy ELF executable.. Probably not of much value to you, but it''s kinda nifty. http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

##### Share on other sites
quote:
Original post by Eddycharly
I wrote a tutorial a while back.. maybe it can help.
http://dr-code.com/modules/Top/Tutorial_C+/rse.html

Was anyone able to get the realign working? When I set the alignments to 16 the compiler complaints that it''s a bad alignment factor.

Is this trick only applicable to MSVC++ compilers because I''m using Borland''s free compiler. I also can''t locate any switch that''ll allow me to merge the different sections of my executable.

Thanks

--{You fight like a dairy farmer!}

##### Share on other sites
reaction: what''s that, reverse psychology? Who says it''s not possible? And what future technology would be necessary? (I''ll assume file=mem alignment) The problem is basically inserting padding into the executable. Either the EXE must contain relocation information (this is rare nowadays though), or you have to scan through, and fix up all absolute and relative references. That means jump instructions, and all addresses. This shouldn''t be a problem, because if you don''t have relocation information, the OS assumes the load address, and so can you. It''s always been 0x400000 on 32 bit Windows, except on some earlier NT versions, IIRC.
Then again, why should anyone go to the trouble to write such a tool? You can just re-link your executable with a different alignment much more easily.

Greatwolf: those are options for Microsoft''s linker. I doubt you could use that in the place of the Borland tool, because the compiler emits OMF IIRC, while VC does COFF.

##### Share on other sites
Jan,

Thanks for replying, it gives me an opportunity to say that...

1. I will not name names, you'll just have belive that it was a good source.

[DANGROUS APPLICATION WARNING!]

2. MS WALIGN.EXE and WINALIGN.EXE are supposed to re-align (re-compile) executables to the 4KB alignment. They cannot re-align my mal-aligned application.

WINALIGN is quite difficult to get working, the only way I could find that worked, to scan all executables in a single directory, was to create a file called...

c:\windows\system\WinAlx.ini

... that contains _nothing_ (empty), in the same folder as the winalign executable. Then start a command prompt and type...

path c:\windows;c:\windows\command;c:\windows\system [RETURN]
winalign c:\the_folder_with_exe_to_realign_in -x -t[RETURN]

... the '-x' excludes nothing, and all the .exes are realigned, if possible. The '-t' logs activity to the same folder as 'winalign.exe' resides to a file called 'WinAlign Report.txt'

WARNING! - the program _may_ be dangerous, so please only work on _backups_ of executables.

There is a flag to restore. '-r', but that is obviously a last resort.

There are some other flags, but I have not used or tested them (-n and -g, I think). '-i' is supposed to 'include' the listed items, but I couldn't get that to work.

'Winalign.exe' itself is used by Windows and Windows Defrag to saccelerate application startup. It does this, I think, by pre-aligning the application so that it can be loaded directly into memory, without any conversion or realignment of any sort.

BTW, I managed to 'Winalign.exe' my entire harddrive, Windows 98 First Edition install, and _I think_ it is OK (I had two recoverable GPFs, in a VXD, but I was running my mainboard monitor at the time, and I think that that (the monitor), could be the reason).

There are a few more caveats to using winalign.exe and walign.exe, such as the presence of certain registry keys (walign, I think, looks for an office 97 install, for instance).

Also, the first time I try to winalign my malaligned app, it reports success, although the windows 'alignment <0x200' serror is still produced when I try to run it (the mal-aligned app). If I re-run winalign over the app again, winalign reports error [-5], and I don't know what that means(and the mal-aligned app windows error still occurs).

Please only work off backups for this though, I have only used the program once, and that was yesterday evening.

So, you could be right Jan, it may be possible, but the MS app won't do it (it does do something, it just doesn't work )...

R

###### optionalreaction.net

[edited by - reaction on February 14, 2004 3:32:47 PM]

##### Share on other sites
Would a disassembler work on a mal-aligned exe? As long as it doesn''t use special tricks (such as changing executable memory at runtime, or conditional jumps to the data segment that will never be executed), a good disassembler should be able to get code that will recompile to the same thing. If that works, all you''d need to do is change the alignment and reassemble, right?

##### Share on other sites
quote:

Would a disassembler work on a mal-aligned exe?

I expect so, disasembler''s are hacker tools though, and I wouldn''t even like to *search* for them. In this case though, it might be useful :|

R

• ### Forum Statistics

• Total Topics
627722
• Total Posts
2978804

• 10
• 9
• 21
• 14
• 12