【问题标题】:What is the smallest possible Windows (PE) executable?什么是最小的 Windows (PE) 可执行文件?
【发布时间】:2010-10-07 20:54:16
【问题描述】:

作为编写编译器的前奏,我试图了解 Windows(32 位)可移植可执行文件格式。特别是我想看一个简单的可执行文件的例子,它除了正确加载、运行和退出之外什么都不做。

我尝试编写和编译一个简单的 C 主函数,它除了生成的 .exe 约为 22KB 并包含许多来自 KERNEL32.DLL 的导入(可能被 LIBC 用于设置环境、堆等)。甚至 DOS 标头也可能更小(它当前打印默认的“此程序无法在 DOS 模式下运行”)。

最小的 Windows 32 位可执行文件的结构是什么?

【问题讨论】:

  • 这里之前投票最多的答案是仅链接到现在已死的恶意链接。内容存档在这里Tiny PE
  • @J... 我希望您不介意我引用该链接文章作为答案,以避免它也成为另一个死链接的风险。 (根据您的评论)。
  • @AgiHammerthief - 如果你愿意,请成为我的客人。正确地标记整个事情是一项艰巨的工作。也请务必关注:meta.stackoverflow.com/a/321326/327083

标签: windows winapi executable portability portable-executable


【解决方案1】:

在 Windows XP (x32) 上,最小的 PE 可执行文件是 97 字节。 在 32 位版本的 Vista 和 7 上,最小的 PE 可执行文件是 252 字节。 在 64 位版本的 Windows 上,最小的 32 位可执行文件是 268 字节。在this forum 上,您可以找到此类可执行文件的位图。

最小的 x64 PE 可执行文件是 268 字节。甚至可以执行这种大小的可执行文件中的每个字节。您也可以在 this forum 上找到链接。

下面的代码是一个大小为 268 字节的 x64 PE(又名 PE32+)可执行文件。

; 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

顺便说一句,在blog entry 上,您会发现一个小型(316 字节)x32 可执行文件,其中包含汇编源代码和许多技术细节。

【讨论】:

    【解决方案2】:

    引自来源 (Creating the smallest possible PE executable):1

    • 最小的 PE 文件:97 字节
    • Windows 2000 上最小的 PE 文件:133 字节
    • 通过 WebDAV 下载文件并执行的最小 PE 文件: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 可执行文件,请参阅文章 "Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux"TL;DR1340 字节,使用 NASM

    注意:此答案是对 J... 在 2016 年 12 月 3 日 17:31 发表的评论的扩展,以保留链接中的信息(以防万一死了)。


    1. Tiny PE;亚历山大·索蒂罗夫;已于 2017 年 15 月 11 日 @ 17:50 SAST 查看

    【讨论】:

      猜你喜欢
      • 2011-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-17
      • 1970-01-01
      • 2010-10-01
      • 2010-11-18
      相关资源
      最近更新 更多