Какой минимально возможный исполняемый файл Windows (PE)? - PullRequest
26 голосов
/ 16 февраля 2009

В качестве предшественника написания компилятора я пытаюсь понять формат переносимого исполняемого файла Windows (32-разрядный). В частности, я хотел бы увидеть пример простого исполняемого файла, который ничего не делает, кроме правильной загрузки, запуска и выхода.

Я пытался написать и скомпилировать простую основную функцию C, которая ничего не делает, но в результате получается .exe размером ~ 22 КБ и содержит много импортов из KERNEL32.DLL (предположительно, используется LIBC для настройки среды, куч и т. Д.). Возможно, даже заголовок DOS может быть меньше (в настоящее время он печатает значение по умолчанию «Эта программа не может быть запущена в режиме DOS»).

Какова структура минимально возможного 32-разрядного исполняемого файла Windows?

Ответы [ 2 ]

4 голосов
/ 15 ноября 2017

Как указано в источнике ( Создание минимально возможного исполняемого файла PE ): 1

  • Наименьший возможный PE-файл: 97 байт
  • Наименьший возможный PE-файл в Windows 2000: 133 байта
  • Наименьший PE-файл, который загружает файл через WebDAV и выполняет его : 133 байта

Приведенные выше файлы являются наименьшими возможными файлами PE из-за требований формата файла PE и не могут быть улучшены в дальнейшем.

Этот результат был достигнут с помощью некоторых хитрых трюков с NASM, таких как удаление шага, связанного с C stdlib, и удаление ряда полей заголовков и каталогов данных.

Полный исходный код приведен ниже. По сути, это то же самое, что и статья со следующими модификациями:

  • Удаление пустых строк
  • sectalign метка переименована в sect_align. Со времени написания этого ассемблерного кода sectalign стало ключевым словом NASM. Переименуйте его, чтобы избежать предупреждений и ошибок.

Код выглядит следующим образом:

; tiny97.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
sect_align 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 sect_align ; 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, sect_align)+round(codesize,sect_align) ; SizeOfImage
    dd round(hdrsize, filealign)  ; SizeOfHeaders
    dd 0  ; CheckSum UNUSED
    db 2  ; Subsystem (Win32 GUI)

hdrsize equ $ - $$
filesize equ $ - $$

Чтобы встроить в исполняемый файл:

nasm -f bin tiny97.asm -o tiny97.exe

Об исполняемых файлах GNU / Linux ELF см. Статью "Учебное пособие по созданию действительно исполняемых ELF-файлов для Linux" . TL; DR : 1340 байт с использованием NASM

Примечание : Этот ответ является расширением комментария J ... от 3 декабря 16 в 17:31, чтобы сохранить информацию, найденную в ссылке (в случае, если она тоже идет мертв).


  1. Tiny PE ; Александр Сотиров; просмотрено 15/11/2017 @ 17:50 SAST
1 голос
/ 06 августа 2017

В Windows XP (x32) самый маленький исполняемый файл PE составляет 97 байт. В 32-битных версиях Vista и 7 самый маленький исполняемый файл PE составляет 252 байта. В 64-битных версиях Windows самый маленький 32-битный исполняемый файл имеет размер 268 байт. На этом форуме вы найдете бит-карту такого исполняемого файла.

Самый маленький исполняемый файл x64 PE составляет 268 байт. Можно даже выполнить каждый байт в исполняемом файле такого размера. Вы также можете найти ссылку на этот форум .

Код ниже представляет собой исполняемый файл x64 PE (он же PE32 +) размером 268 байт.

; PE64smallest.asm   Aug 19, 2018 (c) DrakoPensulo
; A smallest PE32+ executable (x64)
; 
; Features:
;  - Windows Vista/7/8/10 compatible
;  - Size: 268 bytes (an executable file on x64 Windows cannot be smaller)
;  - No sections
;  - No Data Directories (in particular no imports and no TLS callbacks)
;  - Exits with code 0x2a (this executable does nothing else than that)
;
;
; Compile using FASM (https://flatassembler.net)  command line: fasm.exe PE64smallest.asm

format binary as 'exe' 
use64 


EntryPoint:
db 'MZ'     ; DOS signature
dw 0faceh

dd 00004550h    ; Signature PE\0\0
dw 8664h    ; Machine
dw 0000h    ; NumberOfSections

dd 0facefaceh   ; TimeDateStamp

dd 0facefaceh   ; PointerToSymbolTable

dd 0facefaceh   ; NumberOfSymbols

dw 0        ; SizeOfOptionalHeader      ; must be multiple of 8 not too large 
dw 002fh    ; Characteristics       ; must be bit 1=1 bit 13=0

dw 020Bh    ; PE32+ Magic
db 0fah     ; MajorLinkerVersion
db 0fah     ; MinorLinkerVersion

dd 0facefaceh   ; SizeOfCode

dd 0facefaceh   ; SizeOfInitializedData

dd 0facefaceh   ; SizeOfUninitializedData

dd start    ; AddressOfEntryPoint       ; cannot be smaller than SizeOfHeaders

dd 0facefaceh   ; BaseOfCode

dq 0000000100000000h    ; ImageBase     ; must be multiple of 64k

dd 4        ; SectionAlignment and e_lfanew ; PE header offset in file

dd 4        ; FileAlignment

dw 0faceh   ; MajorOperatingSystemVersiom

dw 0faceh   ; MinorOperatingSystemVersion

dw 0faceh   ; MajorImageVersion

dw 0faceh   ; MinorImageVersion

dw 5        ; MajorSubsystemVersion     ; >3.1 or 4  
dw 0h       ; MinorSubsystemVersion

dd 0facefaceh   ; Win32VersionValue     

dd 0400h    ; SizeOfImage           ; MSB has to be small, must be >0200h

dd start    ; SizeOfHeaders         ; SizeOfHeaders has to be < SizeOfImage

dd 0facefaceh   ; CheckSum

dw 0002h    ; Subsystem 2-GUI 3-CUI
dw 0        ; DllCharacteristics

dd 000cefaceh
dd 0        ; SizeOfStackReserve  upper dword has to be 0, MSB of lower dword has to be small

dd 000cefaceh
dd 0        ; SizeOfStackCommit  upper dword has to be 0, MSB of lower dword has to be small

dd 000cefaceh
dd 0        ; SizeOfHeapReserve  upper dword has to be 0, MSB of lower dword has to be small

dd 000cefaceh
dd 0        ; SizeOfHeapCommit  upper dword has to be 0, MSB of lower dword has to be small

dd 0facefaceh   ; LoaderFlags

dd 0        ; NumberofRvaAndSizes   

dd 0facefaceh
dd 0facefaceh   ; Export Directory Address and Size

dd 0facefaceh
dd 0facefaceh   ; Import Directory Address and Size

dd 0facefaceh   
dd 0facefaceh   ; Resource Directory Address and Size

dd 0facefaceh
dd 0facefaceh   ; Exception Directory Address and Size

dd 0facefaceh
dd 0facefaceh   ; Security Directory Address and Size

dd 0facefaceh
dd 0facefaceh   ; Base Relocation Table Address and Size

    dd 0facefaceh
dd 0facefaceh   ; Debug Directory Address and Size

dd 0facefaceh   
dd 0facefaceh   ; Architecture Specific Data Address and Size

dd 0facefaceh
dd 0facefaceh   ; RVA of GlobalPtr Directory Address and Size

dd 0facefaceh
dd 0facefaceh   ; TLS Directory Address and Size

dd 0facefaceh
dd 0facefaceh   ; Load Configuration Directory Address and Size

dd 0facefaceh
dd 0facefaceh   ; Bound Import Directory Address and Size

dd 0facefaceh
dd 0facefaceh   ; Import Address Table Address and Size

dd 0facefaceh
dd 0facefaceh   ; Delay Load Import Descriptors Address and Size

dd 0facefaceh
dd 0facefaceh   ; COM runtime Descriptors Address and Size

dd 0facefaceh

start:
push 2ah
pop rax
ret     ; Reserved Descriptor

Кстати, в этой записи блога вы найдете небольшой (316 байт) исполняемый файл x32 с исходным кодом на ассемблере и множеством технических деталей.

...