crear - ¿Cuál es el ejecutable de Windows(PE) más pequeño posible?
crear winpe windows 10 (1)
Como precursor de escribir un compilador, intento comprender el formato ejecutable portátil de Windows (32 bits). En particular, me gustaría ver un ejemplo de un ejecutable escueto que no hace más que cargar correctamente, ejecutar y salir.
Intenté escribir y compilar una función principal C simple que no hace más que el .exe resultante es ~ 22KB y contiene muchas importaciones de KERNEL32.DLL (presumiblemente utilizado por LIBC para configurar el entorno, montones, etc.). Incluso el encabezado de DOS podría ser más pequeño (actualmente imprime el predeterminado ''Este programa no se puede ejecutar en modo DOS'').
¿Cuál es la estructura del ejecutable de Windows 32 bit más pequeño posible?
Según lo citado de la fuente ( Creando el ejecutable PE más pequeño posible ): 1
- El archivo PE más pequeño posible: 97 bytes
- El archivo PE más pequeño posible en Windows 2000: 133 bytes
- El archivo PE más pequeño que descarga un archivo sobre WebDAV y lo ejecuta: 133 bytes
Los archivos anteriores son los archivos PE más pequeños posibles debido a los requisitos del formato de archivo PE y no pueden mejorarse aún más.
Este resultado se logró con algunos trucos ingeniosos de NASM, como eliminar el paso que vincula a C stdlib
y eliminar varios campos de encabezado y directorios de datos.
El código fuente completo (tal como aparece en el artículo, sin modificaciones, excepto la eliminación de líneas en blanco) es el siguiente:
; tiny.asm, copyright Alexander Sotirov
BITS 32
;
; MZ header
; The only two fields that matter are e_magic and e_lfanew
mzhdr:
dw "MZ" ; e_magic
dw 0 ; e_cblp UNUSED
; PE signature
pesig:
dd "PE" ; e_cp, e_crlc UNUSED ; PE signature
; PE header
pehdr:
dw 0x014C ; e_cparhdr UNUSED ; Machine (Intel 386)
dw 1 ; e_minalloc UNUSED ; NumberOfSections
; dd 0xC3582A6A ; e_maxalloc, e_ss UNUSED ; TimeDateStamp UNUSED
; Entry point
start:
push byte 42
pop eax
ret
codesize equ $ - start
dd 0 ; e_sp, e_csum UNUSED ; PointerToSymbolTable UNUSED
dd 0 ; e_ip, e_cs UNUSED ; NumberOfSymbols UNUSED
dw sections-opthdr ; e_lsarlc UNUSED ; SizeOfOptionalHeader
dw 0x103 ; e_ovno UNUSED ; Characteristics
; PE optional header
; The debug directory size at offset 0x94 from here must be 0
filealign equ 4
sectalign equ 4 ; must be 4 because of e_lfanew
%define round(n, r) (((n+(r-1))/r)*r)
opthdr:
dw 0x10B ; e_res UNUSED ; Magic (PE32)
db 8 ; MajorLinkerVersion UNUSED
db 0 ; MinorLinkerVersion UNUSED
; PE code section
sections:
dd round(codesize, filealign) ; SizeOfCode UNUSED ; Name UNUSED
dd 0 ; e_oemid, e_oeminfo UNUSED ; SizeOfInitializedData UNUSED
dd codesize ; e_res2 UNUSED ; SizeOfUninitializedData UNUSED ; VirtualSize
dd start ; AddressOfEntryPoint ; VirtualAddress
dd codesize ; BaseOfCode UNUSED ; SizeOfRawData
dd start ; BaseOfData UNUSED ; PointerToRawData
dd 0x400000 ; ImageBase ; PointerToRelocations UNUSED
dd sectalign ; e_lfanew ; SectionAlignment ; PointerToLinenumbers UNUSED
dd filealign ; FileAlignment ; NumberOfRelocations, NumberOfLinenumbers UNUSED
dw 4 ; MajorOperatingSystemVersion UNUSED ; Characteristics UNUSED
dw 0 ; MinorOperatingSystemVersion UNUSED
dw 0 ; MajorImageVersion UNUSED
dw 0 ; MinorImageVersion UNUSED
dw 4 ; MajorSubsystemVersion
dw 0 ; MinorSubsystemVersion UNUSED
dd 0 ; Win32VersionValue UNUSED
dd round(hdrsize, sectalign)+round(codesize,sectalign) ; SizeOfImage
dd round(hdrsize, filealign) ; SizeOfHeaders
dd 0 ; CheckSum UNUSED
db 2 ; Subsystem (Win32 GUI)
hdrsize equ $ - $$
filesize equ $ - $$
Para ejecutables ELF de GNU / Linux, consulte el artículo "Tutorial de Whirlwind sobre la creación de ejecutables ELF realmente complejos para Linux" . TL; DR : 1340
bytes, utilizando NASM
Nota : Esta respuesta es una expansión del comentario de J ... el 3 de diciembre de 2016 a las 17:31, con el fin de preservar la información que se encuentra en el enlace (en caso de que también desaparezca).
- Tiny PE ; Alexander Sotirov; visto el 15/11/2017 a las 17:50 SAST