什么是最小的Windows(PE)可执行文件?
作为编写编译器的前提,我试图了解Windows(32位)可移植可执行文件格式.特别是,我想看一个简单的可执行文件示例,该示例除了正确加载,运行和退出外不执行任何操作.
As a precursor to writing a compiler I'm trying to understand the Windows (32-bit) Portable Executable format. In particular I'd like to see an example of a bare-bones executable which does nothing except load correctly, run and exit.
我尝试编写和编译一个简单的C main函数,该函数什么也不做,但是生成的.exe约为22KB,包含许多从KERNEL32.DLL导入的文件(可能是LIBC用来设置环境,堆等).甚至DOS标头也可能较小(它当前会打印默认的此程序无法在DOS模式下运行").
I've tried writing and compiling a simple C main function which does nothing but the resulting .exe is ~22KB and contains many imports from KERNEL32.DLL (presumably used by LIBC to set up environment, heaps etc.). Even the DOS Header could probably be smaller (it currently prints the default 'This program cannot be run in DOS mode').
最小的Windows 32位可执行文件的结构是什么?
What is the structure of the smallest possible Windows 32-bit executable?
引用来源(创建最小的PE可执行文件): 1
- 最小可能的PE文件:97个字节
- 在Windows 2000上最小可能的PE文件:133个字节
- 最小的PE文件,该文件通过WebDAV和执行它:133个字节
由于PE文件格式的要求,上述文件是可能的最小PE文件,无法进一步改进.
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
的步骤,并删除了许多标头字段和数据目录.
This result was achieved with some clever NASM tricks, such as removing the step that links to C stdlib
and removing a number of header fields and data directories.
完整的源代码如下.实际上与经过以下修改的文章相同:
The full source code is below. It is effectively the same as the article with these modification:
- 删除空白行
-
sectalign
标签已重命名为sect_align
.从编写此汇编代码的时间起,sectalign
成为NASM关键字.重命名它以避免警告和错误.
- Removal of blank lines
-
sectalign
label renamed tosect_align
. Since the time this assembly code was writtensectalign
became a NASM keyword. Rename it to avoid warnings and errors.
代码如下:
; 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 $ - $$
要构建为可执行文件,请使用:
To build into an executable use:
nasm -f bin tiny97.asm -o tiny97.exe
有关GNU/Linux ELF可执行文件,请参见文章关于为Linux创建真正的Teenf ELF可执行文件的旋风教程" . TL; DR :使用NASM
For GNU/Linux ELF executables, See the article "Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux". TL;DR: 1340
bytes, using NASM
注意:该答案是J ...在16年12月3日17:31时的评论的扩展,目的是保留链接中找到的信息(以防万一)死了.)
Note: This answer is an expansion of J...'s comment on Dec 3 '16 at 17:31, in order to preserve the information found in the link (in case that too goes dead).
- 小PE ;亚历山大·索提洛夫(Alexander Sotirov)查看15/11/2017 @ 17:50 SAST
- Tiny PE; Alexander Sotirov; viewed 15/11/2017 @ 17:50 SAST