首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 極致壓縮 EXE/DLL 體積技巧大全:從 1.5KB 到 992 字節

     編輯:VC 教學

核心原理:拒絕 C Runtime Library (CRT)

預設連結會引入龐大的 CRT 啟動代碼與函數庫。透過 /NODEFAULTLIB 排除所有預設庫,改用 Windows API 直接替代 CRT 函數,並合併區段、對齊到 16 位元組,可將簡單程式壓縮至 1.5KB 以下。

一、普通 EXE 壓縮實戰

1. 連結器設定 (專案屬性 → Link → Command Line)

/NODEFAULTLIB
/ENTRY:WinMain
/FILEALIGN:16
/ALIGN:16
/OPT:REF
/OPT:ICF
/OPT:NOWIN98
/MERGE:.rdata=.data
/MERGE:.text=.data
/MERGE:.reloc=.data

2. 程式碼中對應指令

#ifndef _DEBUG
#pragma comment(linker, "/NODEFAULTLIB")
#pragma comment(linker, "/ENTRY:WinMain")
#pragma comment(linker, "/FILEALIGN:16")
#pragma comment(linker, "/ALIGN:16")
#pragma comment(linker, "/OPT:REF")
#pragma comment(linker, "/OPT:ICF")
#pragma comment(linker, "/OPT:NOWIN98")
#pragma comment(linker, "/MERGE:.rdata=.data")
#pragma comment(linker, "/MERGE:.text=.data")
#pragma comment(linker, "/MERGE:.reloc=.data")
#endif

3. CRT 函數 → Win32 API 對照表

CRT 函數Win32 API 替代
malloc/freeHeapAlloc/HeapFree
strcpy/strcat/strlenlstrcpy/lstrcat/lstrlen
strcmp/strcmpilstrcmp/lstrcmpi
memcpy/memset/memmoveCopyMemory/FillMemory/MoveMemory
sprintf/vsprintfwsprintf/wvsprintf
toupper/tolowerCharUpper/CharLower
isalpha/isdigit 等IsCharAlpha/IsCharAlphaNumeric 等

4. 最小化範例 (約 1,488 字節)

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
    MessageBox(NULL, L"Hello, Tiny World!", L"1.5KB EXE", MB_OK);
    return 0;
}

二、若必須用部分 CRT:LIBCTINY.LIB

Microsoft 提供的精簡 CRT,僅含常用函數,體積極小。

三、普通 DLL 壓縮 (992 字節)

DLL 入口點 DllMainCRTStartup 也需 CRT,同樣用 LIBCTINY 解決。

#ifndef _DEBUG
#pragma comment(linker, "/DEFAULTLIB:kernel32.lib")
#pragma comment(linker, "/DEFAULTLIB:LIBCTINY.LIB")
#pragma comment(linker, "/NODEFAULTLIB:libc.lib")
#pragma comment(linker, "/NODEFAULTLIB:libcmt.lib")
#pragma comment(linker, "/FILEALIGN:16")
#pragma comment(linker, "/ALIGN:16")
#pragma comment(linker, "/OPT:NOWIN98")
#pragma comment(linker, "/MERGE:.rdata=.data")
#pragma comment(linker, "/MERGE:.text=.data")
#pragma comment(linker, "/MERGE:.reloc=.data")
#endif

BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return TRUE; }

extern "C" __declspec(dllexport) BOOL __stdcall ExpHook() {
    return FALSE; // 僅導出一個測試函數
}

四、複雜專案 (MFC/ATL/COM) 壓縮策略

關鍵點:

  • MFC 專案務必「靜態連結 MFC」而非共用 DLL,否則壓縮殼無法處理 MFC DLL 相依
  • ATL 專案定義 _ATL_MIN_CRT 可大幅減少 CRT 依賴
  • 壓縮殼選擇:UPX (開源免費)、ASPACK (商業、壓縮率更高)、PECompact
  • 壓縮後需測試:DEP/ASLR 相容性、防毒軟體誤報、啟動速度

五、避坑檢查清單

  1. 確認 /SUBSYSTEM:WINDOWS (GUI) 或 CONSOLE (CLI)
  2. 若使用 TLS/靜態物件建構子,/ENTRY 需指向 CRT 啟動函數,不可直接用 WinMain
  3. 合併區段可能導致資料執行保護 (DEP) 問題,測試環境需含 DEP 啟用機器
  4. 除錯版 (_DEBUG) 切勿套用上述設定,保留完整 CRT 便於除錯
  5. 數位簽章需在壓縮後進行,否則簽章失效

總結

極致壓縮適合:啟動器、安裝程式、Shellcode、嵌入式載入器、體積敏感的下載元件。一般業務邏輯 DLL/EXE 不建議 犧牲可維護性與除錯便利性換取體積。科學選型:簡單工具 → 移除 CRT + 合併區段;複雜模組 → 靜態連結 + UPX 壓縮殼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類型基礎大小壓縮手段預期大小
MFC 靜態連結~300KBUPX/ASPACK 壓縮殼~150KB (50%)
ATL 靜態連結~80KBUPX + 移除 CRT20-40KB
COM 元件視介面數ATL + 壓縮殼20-40KB