作为编写编译器的先驱,我正在尝试了解 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 的评论的扩展,以保留在链接中找到的信息(以防万一死了)。
- Tiny PE ;亚历山大·索蒂罗夫;已查看 15/11/2017 @ 17:50 SAST
关于windows - 最小的 Windows (PE) 可执行文件是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/553029/