Author Topic: Looking for the smallest possible .EXE  (Read 563 times)

aw27

  • Member
  • ****
  • Posts: 709
Looking for the smallest possible .EXE
« on: October 06, 2017, 05:20:57 AM »
 :biggrin:

I have been able to see 32-bit .exes with around 100 bytes, however they don't launch on a 64-bit operating system.

This is as small as I could go for a 32-bit .exe on 64-bit OS - 515 bytes (I could reduce it to 513 bytes leaving only the ret).

It was based on a sample in the Jwasm\Uasm Samples directory:

Code: [Select]

;--- assemble: UASM -bin -Fo tiny.exe tiny.ASM

    .386
    option casemap:none

    include winnt.inc   ;Use the simplified winnt.inc from Sample folder of UASM.

IMAGEBASE equ 400000h

PEHDR segment dword FLAT
    ORG IMAGEBASE
start_header label near

;--- simplified DOS "MZ" header
IMAGE_DOS_HEADER <"ZM", 0, 0, 0,0,0,0,0,0,0,0,0,0,0,<0>,0,0,<0>,IMAGEREL PEHdr>

;--- define the Win32 "PE" header
PEHdr label byte
    db "PE",0,0
    IMAGE_FILE_HEADER <IMAGE_FILE_MACHINE_I386, num_sections, 0, 0, 0, sizeof IMAGE_OPTIONAL_HEADER32,\
        IMAGE_FILE_RELOCS_STRIPPED or IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LOCAL_SYMS_STRIPPED>

    IMAGE_OPTIONAL_HEADER32 { 10Bh, ;magic
        6,0,                        ;linker major, minor
        0,0,0,              ;sizeof code, initialized data, uninitialized data
        IMAGEREL main,    ;entry point
        0, 0,  ;baseof code, data
        400000h,    ;imagebase
        1000h,200h,   ;section alignment, file alignment
        5,0,          ;OS major, minor
        0,0,          ;Image major, minor
        5,0,          ;Subsys major, minor
        0,            ;win32 version
        2000h,        ;sizeof image
        1000h,        ;sizeof header
        0,            ;checksum
        IMAGE_SUBSYSTEM_WINDOWS_CUI,
        0,            ;dll characteristics
        100000h,1000h,;stack res,com
        100000h,1000h,;heap res, com
        0,            ;loader flags
        16,           ;number of directories
  16 dup (<0,0>)}
;--- define the section table

sectiontable label byte
    IMAGE_SECTION_HEADER <".text", <sizeof_text>, IMAGEREL start_text, sizeof_text,\
        200h, 0, 0, 0, 0, 060000020h >
num_sections equ ( $ -  sectiontable ) / sizeof IMAGE_SECTION_HEADER

    ORG IMAGEBASE+200h   ;forces physical size of header to 200h and sets VA to 400200h

PEHDR ends


_TEXT segment dword public FLAT 'CODE'
ORG 0E00h   ; change pc to RVA 1000h, section alignment and file alignment are different
start_text label near

;--- entry
main proc c
xor eax, eax
ret
main endp

sizeof_text equ $ - start_text

_TEXT ends

    END

Note: Most of the PE fields are not used at all by the launcher, so you may be surprised to find them zeroed here.

aw27

  • Member
  • ****
  • Posts: 709
Re: Looking for the smallest possible .EXE
« Reply #1 on: October 06, 2017, 06:12:25 PM »
I attach a 32-bit .exe with 358 bytes, but it will only run on a 32-bit Operating System.
This is probably as short as we can go without using the ultra "dirty" tricks elaborated here:
http://www.phreedom.org/research/tinype/

In the attachment I include a batch file to confirm that the .Exe actually works (it should echo the returned value which in this case is 33).


jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 4813
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Looking for the smallest possible .EXE
« Reply #3 on: October 06, 2017, 08:05:38 PM »
 :biggrin:

You guys must be bored.  :P
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

aw27

  • Member
  • ****
  • Posts: 709
Re: Looking for the smallest possible .EXE
« Reply #4 on: October 06, 2017, 09:03:28 PM »
Eight bytes should be enough to print "hello world" ;)
Yes, I miss as well those days where .com were not top level domains.  :(

Quote
You guys must be bored.  :P
sights.  :(

jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic
Re: Looking for the smallest possible .EXE
« Reply #5 on: October 06, 2017, 09:27:55 PM »
You guys must be bored.  :P

And proudly so :bgrin:

Siekmanski

  • Member
  • *****
  • Posts: 1094
Re: Looking for the smallest possible .EXE
« Reply #6 on: October 06, 2017, 11:13:23 PM »
Cool topic.

aw27, thanks for the link to phreedom.org.
One thing on my To-Do list is to create an executable file Compressor/Packer/Cruncher.
You triggered me to finally start studying this topic.

aw27

  • Member
  • ****
  • Posts: 709
Re: Looking for the smallest possible .EXE
« Reply #7 on: October 06, 2017, 11:43:30 PM »
Since I was at it I decided to use some of the "dirty" tricks from phreedom.org and I reduced the file size to 130 bytes! It was tested in Windows XP 32-bits and worked.
Basically the dirty tricks consist in moving structures to the middle of unused (by the loader) structure parts.
I did not try the last part, where phreedom.org states that we could save a further 26 bytes by using the zeros of the page after the end of the file because according to him it was not working for Windows 2000, so I did not expect miracles for XP.
Also I did not move the executable code to the middle of a structure because the benefit would not be important, only 3 bytes less.

Quote
One thing on my To-Do list is to create an executable file Compressor/Packer/Cruncher.
Excellent idea, Siekmanski!  :t

aw27

  • Member
  • ****
  • Posts: 709
Re: Looking for the smallest possible .EXE
« Reply #8 on: October 07, 2017, 02:37:42 AM »
Now working on 64-bit.  :bgrin:
Smallest file without stripping anything will be 520 bytes.

Code: [Select]
;--- assemble: UASM64 -bin -Fo tiny64.exe tiny64.ASM

.x64
option casemap:none

include winnt64.inc   ; Modification for 64-bit of winnt.inc from Sample folder of UASM.

IMAGEBASE equ 140000000h

PEHDR segment dword FLAT

;--- define the DOS "MZ" header

    ORG IMAGEBASE

    IMAGE_DOS_HEADER <"ZM", 80h, 1, 0,4,0,-1,0,200h,0,0,0,0,0,<0>,0,0,<0>,IMAGEREL PEHdr>

;--- define the "PE" header

PEHdr label byte
    db "PE",0,0
    IMAGE_FILE_HEADER <IMAGE_FILE_MACHINE_AMD64, num_sections, 0, 0, 0, sizeof IMAGE_OPTIONAL_HEADER64,\
        IMAGE_FILE_RELOCS_STRIPPED or IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_LARGE_ADDRESS_AWARE or IMAGE_FILE_LOCAL_SYMS_STRIPPED>

    IMAGE_OPTIONAL_HEADER64 { 20Bh, ;magic for PE+ 64-bit
        0Eh,0Ah,                          ;linker major, minor
        1000h,1000h,0,                 ;sizeof code, initialized data, uninitialized data
        IMAGEREL main,    ;entry point
        IMAGEREL start_text,  ;baseof code
        IMAGEBASE,    ;imagebase
        1000h,200h,    ;section alignment, file alignment
        6,0,          ;OS major, minor
        0,0,          ;Image major, minor
        6,0,          ;Subsys major, minor
        0,                    ;win32 version
        2000h,        ;sizeof image
        1000h,        ;sizeof header
        0,            ;checksum
        IMAGE_SUBSYSTEM_WINDOWS_CUI,
        0,            ;dll characteristics
        100000h,1000h, ;stack res,com
        100000h,1000h, ;heap res, com
        0,            ;loader flags
        16,            ;number of directories
        16 dup (<0,0>)}

;--- define the section table

sectiontable label byte
    IMAGE_SECTION_HEADER <".text", <sizeof_text>, IMAGEREL start_text, sizeof_text,\
        200h, 0, 0, 0, 0, 060000020h >
num_sections equ ( $ -  sectiontable ) / sizeof IMAGE_SECTION_HEADER

    ORG IMAGEBASE+200h   ;forces physical size of header to 200h and sets VA to IMAGEBASE + 200h

PEHDR ends

_TEXT segment dword public FLAT 'CODE'
ORG 0E00h   ; change pc to RVA 1000h section alignment and file alignment are different
start_text label near

main proc
mov rax,33
ret
main endp

sizeof_text equ $ - start_text

_TEXT ends



aw27

  • Member
  • ****
  • Posts: 709
Re: Looking for the smallest possible .EXE
« Reply #9 on: October 07, 2017, 04:37:03 AM »
This is the final and tiniest x64 file I was able to obtain that runs without crashing and without under the table tricks. Size=376 bytes.
And this ends my quest for the smallest .exes  possible :dazzled:


Siekmanski

  • Member
  • *****
  • Posts: 1094
Re: Looking for the smallest possible .EXE
« Reply #10 on: October 13, 2017, 08:08:28 AM »
Hi all,

The aw27 32 bit examples did not run on my 64 bit Windows 8.1 machine.
I'm new to this topic, but did a lot of reading and testing the last few days.
The smallest 32 bit example that runs now on my Windows 8.1 is 268 bytes.
The code size is only 128 bytes. ( padded with zeros to 268 bytes )

You can run the RUN.bat to execute the small exe to get the result, it should be: 55
If it runs on Windows XP <-> Windows 10, I could use this as a template for an executable packer/cruncher.

Would you guys be so nice and test if it runs on other Windows versions?  :t

Included the source ( fully commented ) for the PE32 writer, which creates the executable file.

Marinus

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 4813
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Looking for the smallest possible .EXE
« Reply #11 on: October 13, 2017, 08:40:59 AM »
Result on Win 10 64.

Executing Small_PE32.exe

Result is: 55

Press any key to continue . . .
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic
Re: Looking for the smallest possible .EXE
« Reply #12 on: October 13, 2017, 12:28:03 PM »
Same on Win7-64, but it fails with a c5 exception in my XP VM.

felipe

  • Member
  • ***
  • Posts: 282
  • I love assembly language programming.
Re: Looking for the smallest possible .EXE
« Reply #13 on: October 13, 2017, 12:40:12 PM »
All good here in windows 8.1 64 bits
 :icon14:
Felipe.

aw27

  • Member
  • ****
  • Posts: 709
Re: Looking for the smallest possible .EXE
« Reply #14 on: October 13, 2017, 04:35:57 PM »
The first of my samples, with 515 bytes was tested and run on Windows 10 64-bit.
The others failed on 64-bit OS, as I mentioned.

I will check the  Siekmanski work.