2009-02-16 13 views
18

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.¿Cuál es el ejecutable de Windows (PE) más pequeño posible?

He intentado escribir y compilar una función C simple que no hace nada más que el .exe resultante es ~ 22KB y contiene muchas importaciones desde 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?

+0

La respuesta que anteriormente se votó con mayor frecuencia aquí fue solo un vínculo a un vínculo ahora inactivo y malicioso. El contenido está archivado aquí [Tiny PE] (http://archive.is/w01DO#selection-265.0-269.6) –

+0

@J ... Espero que no te importe que cite ese artículo vinculado como una respuesta, para evite el riesgo de que también se convierta en otro enlace muerto. (según su comentario). –

+0

@AgiHammerthief - Si quieres, sé mi invitado. Es un gran trabajo marcar todo el asunto correctamente. También asegúrese de seguir: https://meta.stackoverflow.com/a/321326/327083 –

Respuesta

2

Como se citó de origen (Creating the smallest possible PE executable):

  • más pequeño del archivo PE posible: 97 bytes
  • más pequeño del archivo PE posible en Windows 2000: 133 bytes
  • archivo PE más pequeño que descarga un archivo a través 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 un número de campos de encabezado y directorios de datos.

El código fuente completo (tal como aparece en el artículo, sin modificación alguna, salvo 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 GNU/Linux ELF, consulte el artículo "Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux". TL; DR: 1340 bytes, utilizando NASM

Nota: Esta respuesta es una expansión de J ... 's comentario el 3 de diciembre '16 a las 17:31, con el fin de preservar la información que se encuentra en el enlace (en caso de que también se muera).


  1. Tiny PE; Alexander Sotirov; visto 15/11/2017 @ 17:50 SAST
Cuestiones relacionadas