flat assembler
Message board for the users of flat assembler.

Index > Windows > Raw PE format again

Author
Thread Post new topic Reply to topic
Grom PE



Joined: 13 Mar 2008
Posts: 114
Location: i@grompe.org.ru
Grom PE 21 Apr 2008, 11:56
Well, I was exploring unused values in PE header and tried to create working executable with minimal header, without breaking any comatibility.

The purpose of this is not only writing smallest possible executables, as previous researches on this topic, but providing flexibility with PE format.

Known and satisfied constraints are:
- DOS stub is valid and shows "Need Win32", without using additional space;
- Section alignment >= 1000h and file alignment >= 200h, to be runable on Win9x;
- kernel32.dll present in import table, to be runable on Win2k;
- Size of optional header = 0E0h, to be runnable on Win7;

For now, PE format is created by hands, using format binary as 'exe'.
This has quite a few drawbacks - you can't include resources easily, relocation can't be generated automatically, and more.

When using format PE, I tried to use "load" and "store" directives to modify PE header, but it's considered out of address space. Modifying FASM source didn't lead to any good results...

For more info, look at comments in code below.

Code:
format binary as 'exe'
; Raw PE format with tiny header and dos stub
; v0.30
; for flat assembler by Grom PE

macro zeroalign value { rb (value-1)-($+value-1) mod value }

  use16

IMAGE_BASE equ 400000h

dw 'MZ'                           ; === MZ header ===
dw       200h                     ; Bytes on last page
dw         1h                     ; Pages in file
dw         0h                     ; Relocations count
dw         1h                     ; Paragraphs in header
db 0,'G'                          ; Minimum memory (Note: I think it's not
                                  ;                 dangerous to have min>max,
                                  ;                 the stub runs perfectly on
                                  ;                 DOSBox and DOS 7.10)
dd 'PE'       ; === PE header === ; Maximum memory + SS
  org 100h
dw       14Ch ; Machine           ; SP
dw         1h ; Count of sections ; Checksum
dw       13Ch ; \ Timestamp       ; IP
dw     0FFF0h ; /                 ; CS
dw        78h ; \ <UNUSED>        ; Relocations table address
dw ?          ; /                 ; <UNUSED>
dd ?          ; <UNUSED>          ; <UNUSED>
                                  ; === End of MZ header ===
dw       0E0h ; Size of optional header
dw       10Fh ; Characteristics
dw       10Bh ; Magic optional header
  _dos_msg db 'Need Win32.',0Dh,0Ah,'$' ; Unused fields  - part of DOS stub
dd      1000h ; Entry point
dd ?          ; <UNUSED>
dd        0Ch ; Pointer to PE header
dd IMAGE_BASE ; Image base
dd      1000h ; Section alignment
dd       200h ; File alignment
  mov dx,_dos_msg ; Unused fields - part of DOS stub
  mov ah,9h
  int 21h
  db 0E9h ; Caution: uses next two bytes - jmp+4 --.
dd         4h ; Subsystem version                  |
dw ?          ; <UNUSED>                           |
  int 20h ; Unused bytes - end of DOS stub      <-- 
dd      2000h ; Size of image
dd       200h ; Size of header
dd ?          ; <UNUSED> (Checksum)
dw         2h ; Subsystem
dw         0h ; DLL flags
dd      1000h ; Stack allocation
dd      1000h ; Stack commit
dd     10000h ; Heap allocation
dd         0h ; Heap commit
dd ?          ; <UNUSED?> (Loader flag)
dd        0Ah ; Number of directories
              ; === End of PE header ===

; === Constants used for directories ===

IMPORT_START equ _import_start - IMAGE_BASE
IMPORT_SIZE equ _import_end - _import_start

                       ; === Directories ===
dd        0h,       0h ; Export RVA and Size
dd IMPORT_START, IMPORT_SIZE ; Import
dd        0h,       0h ; Resource

dd        0h,       0h ; Exception
dd        0h,       0h ; Security
dd        0h,       0h ; Reloc
dd        0h,       0h ; Debug
dd        0h,       0h ; Description
dd        0h,       0h ; MIPSGP
dd        0h,       0h ; TLSVA
                       ; === End of directories ===

rb 30h ; <UNUSED>
; There is still space for some nice DOS stub

; === Constants used for sections ===

SECTION1_SIZE equ _section1_end - _section1_start

              ; === Sections ===
dq 'SECTION1' ; 1 Name
dd       400h ;   Virtual size
dd      1000h ;   RVA
dd SECTION1_SIZE ;   Physical size
dd       200h ;   Physical offset
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd 0E0000060h ;   Flags
dq ''         ; 2 Name
dd         0h ;   Virtual size
dd         0h ;   RVA
dd         0h ;   Physical size
dd         0h ;   Physical offset
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd 000000000h ;   Flags
dq ''         ; 3 Name
dd         0h ;   Virtual size
dd         0h ;   RVA
dd         0h ;   Physical size
dd         0h ;   Physical offset
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd 000000000h ;   Flags
dq ''         ; 4 Name
dd         0h ;   Virtual size
dd         0h ;   RVA
dd         0h ;   Physical size
dd         0h ;   Physical offset
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd 000000000h ;   Flags
dq ''         ; 5 Name
dd         0h ;   Virtual size
dd         0h ;   RVA
dd         0h ;   Physical size
dd         0h ;   Physical offset
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd 000000000h ;   Flags
dq ''         ; 6 Name
dd         0h ;   Virtual size
dd         0h ;   RVA
dd         0h ;   Physical size
dd         0h ;   Physical offset
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd ?          ;   <UNUSED>
dd 000000000h ;   Flags
              ; === End of sections ===
; "6 sections should be enough for everyone!"

rb 0ch

  use32

  org IMAGE_BASE+1000h
_section1_start:

  push 0 _test _looknice 0
  call [MessageBoxA]
  push 0
  call [ExitProcess]
  ; plain "ret" could be used here, but we have to import at least one function
  ; from kernel32 to be runable under Win2000. So let's use it.

_test db "Test",0
_looknice: db "Do I look small and nice?",0

zeroalign 4
_import_start:
dd 0,0,0,_kernel32_dll - IMAGE_BASE,_kernel32_import - IMAGE_BASE
dd 0,0,0,_user32_dll   - IMAGE_BASE,_user32_import   - IMAGE_BASE
dd 0,0,0,0,0
_kernel32_import:
label ExitProcess dword
dd _ExitProcess - IMAGE_BASE
dd 0
_user32_import:
label MessageBoxA dword
dd _MessageBoxA - IMAGE_BASE
dd 0
_kernel32_dll: db "kernel32.dll",0
_user32_dll: db "user32.dll",0
_ExitProcess:
db 0,0,"ExitProcess",0
_MessageBoxA:
db 0,0,"MessageBoxA",0
zeroalign 4
_import_end:

_section1_end:

; Raw resources would be an very inconvenient
; trouble, so I'm searching for workaround...
    


Please test this example on any available to you Win32 PE EXE loaders and tell me if it runs ok.

At the moment, tested and runs on Windows 98SE, Windows XP SP2, HX DOS Extender.
[11 Jan 2014] Updated to run on Windows 7 64-bit.


Last edited by Grom PE on 11 Jan 2014, 08:40; edited 1 time in total
Post 21 Apr 2008, 11:56
View user's profile Send private message Visit poster's website Reply with quote
AlexP



Joined: 14 Nov 2007
Posts: 561
Location: Out the window. Yes, that one.
AlexP 21 Apr 2008, 13:49
Unfortunately, I'm not at home right now. When I do I will test it out, nice work
Post 21 Apr 2008, 13:49
View user's profile Send private message Visit poster's website Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo 23 Apr 2008, 20:18
Works fine on Vista Home Premium w/ SP1. (I can attach a screenshot if you want.)
Post 23 Apr 2008, 20:18
View user's profile Send private message Visit poster's website Reply with quote
ic2



Joined: 19 Jan 2008
Posts: 75
ic2 23 Apr 2008, 23:42
Looks very small and nice. Smile

It works on XP Professional Service Pack 2. AntiVir set High and said "There is no problem".

Do you plan to include resource


Great work!!!

Just checked on both Win95 and Win98... Fired right up with no problem.
...
Post 23 Apr 2008, 23:42
View user's profile Send private message Reply with quote
Grom PE



Joined: 13 Mar 2008
Posts: 114
Location: i@grompe.org.ru
Grom PE 24 Apr 2008, 08:36
Thanks for testing!
I'm thinking if adding resources is possible and won't be too slow using macros and reading .res format...

rugxulo, no, I don't need a screenshot, why? =)
Post 24 Apr 2008, 08:36
View user's profile Send private message Visit poster's website Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo 03 May 2008, 07:35
Grom PE wrote:

rugxulo, no, I don't need a screenshot, why? =)


Because Vista is such an oddball, so I wasn't sure if you'd believe me saying that it (gasp) works! Wink


Description: partial screenshot from Vista Home Premium
Filesize: 53.05 KB
Viewed: 11745 Time(s)

grompe.jpg


Post 03 May 2008, 07:35
View user's profile Send private message Visit poster's website Reply with quote
Grom PE



Joined: 13 Mar 2008
Posts: 114
Location: i@grompe.org.ru
Grom PE 11 Jan 2014, 08:42
Hi, just updating this to make it run on Windows 7 64-bit. Better late than never!

Windows 7 doesn't like "Size of optional header" value to be anything other than 0E0h.

Correction: "Size of optional header" must be multiple of 8.


Last edited by Grom PE on 08 May 2016, 02:19; edited 1 time in total
Post 11 Jan 2014, 08:42
View user's profile Send private message Visit poster's website Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 794
Location: Adelaide
sinsi 11 Jan 2014, 08:47
700 bytes, works in Win8.1 Pro 64-bit Cool

edit: 6 years!
Post 11 Jan 2014, 08:47
View user's profile Send private message Reply with quote
upsurt



Joined: 14 Jan 2014
Posts: 51
upsurt 14 Jan 2014, 20:55
WOW! Fantastic! Realy like the idea Smile
There is a lot I can learn from that source.
Post 14 Jan 2014, 20:55
View user's profile Send private message Reply with quote
MUFOS



Joined: 17 Apr 2016
Posts: 47
MUFOS 16 Jun 2016, 17:09
I am sorry to revive this thread (if people mind such in the FASM world).
I am wondering how I can make it work with ONE section only and remove the DOS_STUB (I have read that one only needs the DOS_SIGNATURE & the pointer to the PE_HEADER). I am still learning about the PE format, so some advice would be great!
Post 16 Jun 2016, 17:09
View user's profile Send private message Reply with quote
Mikl___



Joined: 30 Dec 2014
Posts: 138
Location: Russian Federation, Irkutsk
Mikl___ 17 Jun 2016, 00:01
Hi, MUFOS!
See Tiny PE in win64 a working PE64 with import, size of exe-file is 268 bytes or Examples for Win64 Iczelion tutorial
Post 17 Jun 2016, 00:01
View user's profile Send private message Visit poster's website Reply with quote
patulinu



Joined: 21 Jun 2016
Posts: 15
patulinu 22 Jun 2016, 03:17
Great stuff! Thanks for sharing.
Screenshot of running on Windows 7 (32-bit):


Image[/img]
Post 22 Jun 2016, 03:17
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.