windows - 最小的 Windows (PE) 可执行文件是什么?

标签 windows winapi executable portability portable-executable

作为编写编译器的先驱,我正在尝试了解 Windows(32 位)可移植可执行文件格式。我特别希望看到一个基本的可执行文件示例,它除了正确加载、运行和退出外什么都不做。

我已经尝试编写和编译一个简单的 C 主函数,它只执行生成的 .exe 文件,大约 22KB 并且包含许多从 KERNEL32.DLL 导入的文件(可能被 LIBC 用来设置环境、堆等)。甚至 DOS header 也可能更小(它目前打印默认的“此程序无法在 DOS 模式下运行”)。

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

最佳答案

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

  • Smallest possible PE file: 97 bytes
  • Smallest possible PE file on Windows 2000: 133 bytes
  • Smallest PE file that downloads a file over WebDAV and executes it: 133 bytes

The files above are the smallest possible PE files due to requirements of the PE file format and cannot be improved further.

这个结果是通过一些聪明的 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;DR:1340 字节,使用 NASM

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


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

关于windows - 最小的 Windows (PE) 可执行文件是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/553029/

相关文章:

windows - 如何与 Windows 操作中心维护集成?

windows - 为什么我的 Qt 应用程序即使在非管理员访问权限下也会写入 protected 位置?

windows - 24 位 USB 采样率支持

c - 即使文件已经打开以进行独占访问,如何获取文件大小?

.net - 检测 Windows 机器是否正在运行病毒扫描程序?

C++ DrawText 和 TextOut 不显示任何内容

c# - Windows 10 支持的操作系统 GUID 是什么?

c# - 使用 C# Process 运行可执行程序

windows - 如何从命令行启动这个程序?