簡體   English   中英

如何使用 MinGW 創建微型 PE (Win32) 可執行文件

[英]How to create tiny PE (Win32) executables using MinGW

我有以下 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. */
}

我使用 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

生成的 .exe 文件長 2048 字節。 如何使用 MinGW 使其更小,最好最多 1024 個字節,或者(甚至更好)最多 512 個字節?

我更喜歡不編寫匯編代碼的解決方案,但我也對匯編解決方案感興趣。

我試過-Wl,-N來減少節(段)的數量,但這會導致在 Wine 中運行 .exe 時出現段錯誤。

本文建議 480 字節是可能的。 它使用以下設置:

#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)

不幸的是,這些#pragma不適用於 MinGW GCC。 有等價物嗎?

這里,我能夠找到 GCC 標志-Wl,--section-alignment,16,--file-alignment,16將 .exe 大小降低到 752 字節。 .exe 似乎在 Wine 中工作。

通過修改鏈接器腳本,我能夠合並.data.rdata ,並減少到 736 字節。 除了上述那些之外,我還使用這些 GCC 標志: -Wl,--section-alignment,16,--file-alignment,16,-T,tinygccpe.scr

我仍在尋找等效於/MERGE的 MinGW 。

這個問題很相似,但它不會嘗試低於 9000 字節。

我也在尋找一個strip工具(MinGW 中的strip命令不會進一步減小 .exe 的大小),它可以刪除 DOS 存根(位於偏移量 0x40 和 0x80 之間,它包含This program cannot be run in DOS mode. ,我們可以節省 64 個字節)。 此代碼可以刪除它,但它也會破壞 .exe 中的所有絕對偏移量。 不幸的是,MinGW 中的鏈接器ld無法刪除 DOS 存根,它被硬編碼在文件bfd/peXXigen.c ,就在NT_SIGNATURE

是否可以從 .exe 中刪除更多的頭文件,即加載程序不使用的頭文件?

這個問題有大量的在線文獻,大約從 1995 年開始。

32 位和 64 位 Windows 的每個版本都有一套不同的規則,用於說明它們在 PE .exe 可執行文件中接受哪些標頭值。 例如,Windows 7 接受具有 0 節、節對齊 4、文件對齊 4 的 .exe 文件,而其他版本的 Windows(例如 Windows XP 和 2020 年的最新 Windows 10)拒絕這些文件。

不過,可以創建小於 2048 字節的有效 .exe 文件。 例子:

  • hh6d.golden.exe (584 字節)是可移植的:它適用於 Microsoft 發布的所有 Win32 實現,也適用於 Wine。 (在 Windows NT 3.1、Windows 95、Windows XP 和 Windows 10、Wine 1.6.2、Wine 5.0 上測試。)
  • hh2d.golden.exe (408 字節)適用於 Windows 95 及更高版本。 (在 Windows 95、Windows XP、Windows 7 和 Windows 10 上測試)。
  • hh1.golden.exe (268 字節)不適用於 Windows XP,適用於 Windows 7,不適用於 Windows 10。
  • pts-tinype 存儲庫中包含的匯編源代碼。

這就是為什么不太可能發布小於 584 字節的便攜式 Win32 PE .exe hello-world 的原因:

  • 程序代碼必須放在一個可執行的節中,並且最早的文件字節偏移量是512,因為SectionAlignment 必須至少為512,並且節不能從文件的開頭開始。
  • 最小 hello-world 打印機 i386 Win32 機器代碼大小為 36 字節。 (這不包括消息大小,因為消息可以存儲在頭中的前 512 個字節內。)
  • 對於 KERNEL32.DLL,IMAGE_IMPORT_DESCRIPTORS 的最小大小為 20 字節。 Windows 95 不允許在頭文件中這樣做,所以它必須放在文件字節偏移 512 之后。
  • IAT(導入地址表)的最小大小為 16 字節:GetStdHandle 4 字節,WriteFile 4 字節,ExitProcess 4 字節,列表結尾 4 字節。 由於加載器修改了這些地址,所以不能放到header(只讀)中,所以必須放到文件字節偏移512之后。
  • 如果我們把這些加起來,我們得到 512 + 36 + 20 + 16 = 584 個字節。

小於 268 字節的 .exe 文件僅適用於早於 Windows XP 的 Windows 版本,它們不適用於 64 位 Windows 系統。

相關文獻:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM