I’ve been experimenting with writing the smallest possible Portable Executable (PE) files in assembly on Windows 11 x64. My goal is to reduce the size as much as possible while keeping the executable functional.
I have two examples: one that works and one that doesn’t, despite my attempts to optimize it. I suspect the issue lies in how I’ve minimized the PE header, but my understanding of the PE format isn’t strong enough to pinpoint the problem.
Working example:
BITS 64
%define align(n,r) (((n+(r-1))/r)*r)
; DOS Header
dw 'MZ' ; file signature
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
times 4 dw 0
dw 0
dw 0
times 10 dw 0
dd pe_hdr
; PE Header
pe_hdr:
dw 'PE', 0 ; signature
dw 0x8664
dw 0
dd 0
dd 0
dd 0
dw opt_hdr_size
dw 0x22
opt_hdr:
dw 0x020b
db 0
db 0
dd 0
dd 0
dd 0
dd entry
dd 0
dq 0x000140000000
dd 0x10
dd 0x10
dw 0x06
dw 0
dw 0
dw 0
dw 0x06
dw 0
dd 0
dd file_size
dd 0
dd 0
dw 0x02
dw 0x8160
dq 0x100000
dq 0x1000
dq 0x100000
dq 0x1000
dd 0
dd 0
dd 0
dd 0
opt_hdr_size equ $-opt_hdr
section .text
entry:
db 0x90, 0x90 ;.. shellcode continues
file_size equ $
Broken Example:
BITS 64
;DOS Header:
dw 'MZ'
dw 0
pe_hdr:
dw 'PE'
dw 0
dw 0x8664
dw 0x01
dd 0
dd 0
dd 0
dw opt_hdr_size
dw 0x22
opt_hdr:
dw 0x020b
db "inkbox"
dd 0
dd 0
dd entry
dd 0
dd 0
dd 00
dd 4
dd 4
dw 0
dw 0
dw 0
dw 0
dw 0x06
dw 0
dd 0
dd file_size
dd 0
dd 0
dw 0x02
dw 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
dq 0
opt_hdr_size equ $-opt_hdr
entry:
db 0x90, 0x90 ;.. shellcode continues
file_size equ $-$$
1