2009-02-16 17 views
18

Jako prekursor pisania kompilatora staram się zrozumieć format Windows (32-bit) Portable Executable. W szczególności chciałbym zobaczyć przykład pliku wykonywalnego "bare-bones", który nie robi nic poza ładowaniem poprawnie, uruchamianiem i zamykaniem.Jaki jest najmniejszy możliwy plik wykonywalny systemu Windows (PE)?

Próbowałem napisać i skompilować prostą funkcję główną C, która nie robi nic poza wynikowym .exe jest ~ 22 KB i zawiera wiele importów z KERNEL32.DLL (prawdopodobnie używane przez LIBC do konfiguracji środowiska, stosów itp.). Nawet nagłówek DOS mógłby być prawdopodobnie mniejszy (obecnie wypisuje domyślne "Ten program nie może być uruchomiony w trybie DOS").

Jaką strukturę ma najmniejszy możliwy 32-bitowy plik wykonywalny systemu Windows?

+0

Poprzednia poprzednio głosowana odpowiedź to link tylko do martwego i złośliwego linku. Treść jest archiwizowana tutaj [Tiny PE] (http://archive.is/w01DO#selection-265.0-269.6) –

+0

@J ... Mam nadzieję, że nie przeszkadza ci to, że zacytuję ten link jako odpowiedź, unikaj ryzyka, że ​​stanie się on kolejnym martwym ogniwem. (jak na twój komentarz). –

+0

@AgiHammerthief - Jeśli chcesz, bądź moim gościem. Wielkim zajęciem jest prawidłowe oznaczanie wszystkiego. Należy również pamiętać: https://meta.stackoverflow.com/a/321326/327083 –

Odpowiedz

2

Jak cytowany ze źródła (Creating the smallest possible PE executable):

  • możliwe Najmniejszy plik PE: 97 bajtów
  • możliwe Najmniejszy plik PE w systemie Windows 2000: 133 bajtów
  • Najmniejszy plików PE, który pobiera plik ponad WebDAV i wykonuje go: 133 bajtów

Powyższe pliki są najmniejszymi możliwymi plikami PE ze względu na wymagania formatu pliku PE i nie można ich dalej ulepszać.

Ten wynik został osiągnięty za pomocą pewnych sprytnych sztuczek NASM, takich jak usunięcie kroku, który łączy się z C stdlib i usunięcie wielu pól nagłówka i katalogów danych.

pełny kod źródłowy (jak wydaje się w artykule, bez zmian, z wyjątkiem usuwania pustych wierszy) jest następujący:

; 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 $ - $$ 

dla plików wykonywalnych GNU/Linux ELF, zobacz artykuł "Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux". TL; DR: 1340 bajtów, przy użyciu NASM

Uwaga: Ta odpowiedź jest ekspansją J ... 's komentarz na Dec 3 '16 o 17:31, w celu zachowania informacji zawartych w link (w przypadku, który również nie działa).


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