[英]How to create tiny PE (Win32) executables using MinGW
I have the following C program:我有以下 C 程序:
#include <windows.h>
void __cdecl mainCRTStartup() {
DWORD bw;
HANDLE hfile = GetStdHandle(STD_OUTPUT_HANDLE);
WriteFile(hfile, "Hello, World!\r\n", 15, &bw, 0);
ExitProcess(0); /* Needed for successful (0) exit. */
}
I compile it with GCC 4.8.2, using the following command line:我使用 GCC 4.8.2 编译它,使用以下命令行:
i686-w64-mingw32-gcc -s -Os -fno-ident -fno-stack-protector -fomit-frame-pointer \
-fno-unwind-tables -fno-asynchronous-unwind-tables -falign-functions=1 \
-mpreferred-stack-boundary=2 -falign-jumps=1 -falign-loops=1 -mconsole \
-nostdlib -nodefaultlibs -nostartfiles -o h.exe h.c -lkernel32
The generated .exe file is 2048 bytes long.生成的 .exe 文件长 2048 字节。 How can I make it smaller using MinGW, preferably at most 1024 bytes, or (even better) at most 512 bytes?
如何使用 MinGW 使其更小,最好最多 1024 个字节,或者(甚至更好)最多 512 个字节?
I'd prefer a solution without writing assembly code, but I'm also interested in assembly solutions.我更喜欢不编写汇编代码的解决方案,但我也对汇编解决方案感兴趣。
I've tried -Wl,-N
to decrease the number of sections (segments), but that caused a segfault when running the .exe in Wine.我试过
-Wl,-N
来减少节(段)的数量,但这会导致在 Wine 中运行 .exe 时出现段错误。
This article suggests that 480 bytes is possible. 本文建议 480 字节是可能的。 It uses the following settings:
它使用以下设置:
#pragma comment(linker, "/FILEALIGN:16")
#pragma comment(linker, "/ALIGN:16")// Merge sections
#pragma comment(linker, "/MERGE:.rdata=.data")
#pragma comment(linker, "/MERGE:.text=.data")
#pragma comment(linker, "/MERGE:.reloc=.data")
#pragma optimize("gsy", on)
Unfortunately these #pragma
s don't work with MinGW GCC.不幸的是,这些
#pragma
不适用于 MinGW GCC。 Are there equivalents?有等价物吗?
In here I was able to find the GCC flags -Wl,--section-alignment,16,--file-alignment,16
which bring down the .exe size to 752 bytes.在这里,我能够找到 GCC 标志
-Wl,--section-alignment,16,--file-alignment,16
将 .exe 大小降低到 752 字节。 The .exe seems to work in Wine. .exe 似乎在 Wine 中工作。
By modifying the linker script I was able to merge .data
and .rdata
, and go down to 736 bytes.通过修改链接器脚本,我能够合并
.data
和.rdata
,并减少到 736 字节。 I'm using these GCC flags in addition to those above: -Wl,--section-alignment,16,--file-alignment,16,-T,tinygccpe.scr
.除了上述那些之外,我还使用这些 GCC 标志:
-Wl,--section-alignment,16,--file-alignment,16,-T,tinygccpe.scr
。
I'm still looking for the MinGW equivalent of /MERGE
.我仍在寻找等效于
/MERGE
的 MinGW 。
This question is similar, but it doesn't attempt to go below 9000 bytes. 这个问题很相似,但它不会尝试低于 9000 字节。
I'm also looking for a strip
tool (the strip
command in MinGW doesn't reduce the .exe size any further) which can remove the DOS stub (which is between offsets 0x40 and 0x80, it contains This program cannot be run in DOS mode.
, we could save 64 bytes).我也在寻找一个
strip
工具(MinGW 中的strip
命令不会进一步减小 .exe 的大小),它可以删除 DOS 存根(位于偏移量 0x40 和 0x80 之间,它包含This program cannot be run in DOS mode.
,我们可以节省 64 个字节)。 This code can remove it, but it also breaks all the absolute offsets in the .exe. 此代码可以删除它,但它也会破坏 .exe 中的所有绝对偏移量。 Unfortunately the linker
ld
in MinGW isn't able to remove the DOS stub, it's hardcoded in the file bfd/peXXigen.c
, just above the NT_SIGNATURE
.不幸的是,MinGW 中的链接器
ld
无法删除 DOS 存根,它被硬编码在文件bfd/peXXigen.c
,就在NT_SIGNATURE
。
Is it possible to strip more headers from the .exe, ie headers which the loader doesn't use?是否可以从 .exe 中删除更多的头文件,即加载程序不使用的头文件?
This question has extensive online literature, starting from about 1995.这个问题有大量的在线文献,大约从 1995 年开始。
Each version of 32-bit and 64-bit Windows has a different set of rules on what header values they accept in PE .exe executables. 32 位和 64 位 Windows 的每个版本都有一套不同的规则,用于说明它们在 PE .exe 可执行文件中接受哪些标头值。 For example, Windows 7 accepts .exe files with 0 sections, section alignment 4, file alignment 4, and other versions of Windows (eg Windows XP and the most recent Windows 10 in 2020) reject these files.
例如,Windows 7 接受具有 0 节、节对齐 4、文件对齐 4 的 .exe 文件,而其他版本的 Windows(例如 Windows XP 和 2020 年的最新 Windows 10)拒绝这些文件。
It's possible to create working .exe files smaller than 2048 bytes though.不过,可以创建小于 2048 字节的有效 .exe 文件。 Example:
例子:
Here is why it is unlikely that a portable Win32 PE .exe hello-world shorter than 584 bytes will be released:这就是为什么不太可能发布小于 584 字节的便携式 Win32 PE .exe hello-world 的原因:
The .exe files smaller than 268 bytes work only on Windows versions earlier than Windows XP, and they don't work on 64-bit Windows systems.小于 268 字节的 .exe 文件仅适用于早于 Windows XP 的 Windows 版本,它们不适用于 64 位 Windows 系统。
Related literature:相关文献:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.