什么是最小的 Windows (PE) 可执行文件? [英] What is the smallest possible Windows (PE) executable?

查看:22
本文介绍了什么是最小的 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 主函数,它除了生成的 .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?

推荐答案

引自来源 (Creating最小的 PE 可执行文件):1

  • 可能的最小 PE 文件:97 字节
  • Windows 2000 上可能的最小 PE 文件:133 字节
  • 通过 WebDAV 下载文件的最小 PE 文件和执行它: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 to sect_align. Since the time this assembly code was written sectalign 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 创建真正小巧的 ELF 可执行文件的旋风教程".TL;DR:1340 字节,使用 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... 在 2016 年 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).

  1. 微型 PE;亚历山大·索蒂罗夫;2017 年 15 月 11 日下午 17:50 观看
  1. Tiny PE; Alexander Sotirov; viewed 15/11/2017 @ 17:50 SAST

这篇关于什么是最小的 Windows (PE) 可执行文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆