不連結任何 CRT/Lib,直接呼叫 Native API (ntdll.dll)、kernel32.dll 匯出函數,產生極小執行檔 (原文測試 VC2003 約 1KB,VC6 類似)。
MyEntryPoint (非 main/WinMain),避免 CRT 啟動代碼。PEB (Process Environment Block) 走訪 Ldr 模組列表,找 kernel32.dll 基址,解析匯出表取得 LoadLibrary/GetProcAddress,再載入其他 DLL 取函數。strcpy/malloc,自行實作或用 RtlMoveMemory (ntdll)。#pragma pack(8))typedef struct _PEB_LDR_DATA {
ULONG Length; BOOLEAN Initialized; PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA;
typedef struct _LDR_MODULE {
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage;
UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName;
// ... 其餘欄位
} LDR_MODULE;
#define WIN32_LEAN_AND_MEAN
#include // 僅用型別定義,不連結.lib
#pragma comment(linker, "/ENTRY:MyEntryPoint /SUBSYSTEM:WINDOWS /MERGE:.rdata=.text /SECTION:.text,EWR")
// 手動實作 strlen, strcmp, 字串轉數字等...
// 走訪 PEB 取得 kernel32 基址 -> 解析匯出表 -> 取得 LoadLibraryA -> 載入 user32.dll -> 取得 MessageBoxA
void MyEntryPoint() {
// 1. 從 FS:[0x30] (TEB) 取得 PEB
// 2. PEB->Ldr->InLoadOrderModuleList 走訪找 kernel32.dll
// 3. 解析 PE 匯出表找 LoadLibraryA, GetProcAddress
// 4. LoadLibraryA("user32.dll") -> GetProcAddress("MessageBoxA")
// 5. 呼叫 MessageBoxA(NULL, "Hello", "Tiny", MB_OK);
// 6. 取得 ExitProcess 並呼叫退出
}
/ENTRY:MyEntryPoint 指定進入點。/SUBSYSTEM:WINDOWS 或 CONSOLE。/MERGE:.rdata=.text 合併區段減少對齊浪費。/SECTION:.text,EWR 設定區段屬性 (可執行/可寫/可讀)。/OPT:REF /OPT:ICF 移除未參考代碼/合併相同函數。代碼片段截斷於 _RTL_USER_PROCESS_PARAMETERS 結構定義中,完整實作需補齊 PEB 走訪、PE 匯出表解析、字串比對 (Unicode/ANSI) 等數百行組合邏輯。