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

自刪除 DLL 技術打造零依賴安裝/解除安裝程式:Rundll32 + LZCopy 實戰

     編輯:關於VC++

想完全掌控安裝/解除安裝畫面、不依賴第三方安裝包工具?本文揭秘 自刪除 DLL + Rundll32 核心技術,實現可執行檔「自我銷毀」,並結合 Windows 內建 LZCopy 解壓縮 API,打造零運行時依賴、體積極小的安裝/解除安裝程式。關鍵技術點:rundll32.exe 呼叫慣例、DLL 入口點精簡、資源嵌入與重建、compress.exe/expand.exe 工具鏈。

核心難題:EXE 如何刪除自己?

執行中的 EXE 檔案被系統鎖定,無法直接 DeleteFile。常見替代方案(修改執行緒屬性、批次檔延遲刪除)平台相容性差、時序難控制。本文採用 自刪除 DLL 代理刪除 EXE,再自我銷毀 的創新路徑。

關鍵技術拆解

1. Rundll32.exe 呼叫慣例

系統內建 rundll32.exe 可直接載入 DLL 並呼叫導出函數:

rundll32.exe DllName,ExportedFuncName arguments

導出函數簽名**必須**為:

extern "C" __declspec(dllexport) void CALLBACK FuncName(
    HWND hwnd, HINSTANCE hInst, LPTSTR lpCmdLine, int nCmdShow);
  • lpCmdLine 接收命令列參數(此處傳遞待刪除 EXE 路徑)。
  • extern "C" 防止 C++ 名稱修飾,__declspec(dllexport) 導出。

2. 自刪除 DLL 實作

HMODULE g_hmodDLL;
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID) {
    if (reason == DLL_PROCESS_ATTACH) g_hmodDLL = hinst;
    return TRUE;
}

extern "C" __declspec(dllexport) void CALLBACK MagicDel(HWND, HINSTANCE, LPTSTR lpCmdLine, int) {
    Sleep(2000);                    // 等待呼叫端進程退出
    DeleteFile(lpCmdLine);          // 刪除目標 EXE
    // 以下組合語言實現:FreeLibrary → DeleteFile(self) → ExitProcess
    char self[MAX_PATH];
    GetModuleFileName(g_hmodDLL, self, MAX_PATH);
    __asm {
        lea eax, self
        push 0; push 0; push eax
        push ExitProcess; push g_hmodDLL
        push DeleteFile; push FreeLibrary
        ret
    }
}

精簡 DLL 體積關鍵(預設 40KB → 優化 3KB):

  1. 連結器 → 忽略所有預設庫:/NODEFAULTLIB
  2. 連結器 → 入口點:DllMain
  3. C/C++ → 程式碼生成 → 緩衝區安全檢查:否 (/GS-)(移除 __security_cookie 依賴)

3. EXE 端嵌入 DLL 資源並啟動

// 資源定義
#define RC_BINARYTYPE 256
#define ID_MAGICDEL_DLL 100
// .rc: ID_MAGICDEL_DLL RC_BINARYTYPE MagicDel.dll

void WriteResourceToFile(HINSTANCE hInst, int idRes, const char* filename) {
    HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(idRes), MAKEINTRESOURCE(RC_BINARYTYPE));
    HGLOBAL hg = LoadResource(hInst, hRes);
    void* pv = LockResource(hg);
    DWORD cb = SizeofResource(hInst, hRes);
    HANDLE hFile = CreateFile(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    DWORD wr; WriteFile(hFile, pv, cb, &wr, 0); CloseHandle(hFile);
}

void SelfDelete(HINSTANCE hInst) {
    WriteResourceToFile(hInst, ID_MAGICDEL_DLL, "magicdel.dll");
    // 組裝命令列
    char cmd[MAX_PATH*3];
    GetWindowsDirectory(cmd, MAX_PATH); lstrcat(cmd, "\\rundll32.exe");
    if (GetFileAttributes(cmd) == INVALID_FILE_ATTRIBUTES) {
        GetSystemDirectory(cmd, MAX_PATH); lstrcat(cmd, "\\rundll32.exe");
    }
    lstrcat(cmd, " magicdel.dll,_MagicDel@16 "); // 注意修飾名
    char self[MAX_PATH]; GetModuleFileName(hInst, self, MAX_PATH);
    lstrcat(cmd, self);
    // 啟動並立即退出
    STARTUPINFO si = {sizeof(si)}; si.dwFlags = STARTF_FORCEOFFFEEDBACK;
    PROCESS_INFORMATION pi;
    CreateProcess(0, cmd, 0, 0, FALSE, NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi);
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int) {
    SelfDelete(hInst);
}

安裝程式:資源嵌入 + LZCopy 解壓縮

  1. 編寫互動式 Setup.exe(授權協議、選項、複製檔案...)。
  2. 用 compress.exe (SDK 附帶) 壓縮:compress Setup.exe Setup.ex_。
  3. 將 Setup.ex_ 作為二進制資源嵌入安裝程式 Installer.exe。
  4. Installer.exe 啟動流程:
WriteResourceToFile(hInst, ID_COMPRESSED_SETUP, "AppSetup.ex_");
DecompressFile("AppSetup.ex_", "AppSetup.exe");  // LZCopy API
DeleteFile("AppSetup.ex_");
CreateProcess(0, "AppSetup.exe", ...);           // 啟動安裝精靈

DecompressFile 實作:

void DecompressFile(const char* src, const char* dst) {
    OFSTRUCT ofs = {sizeof(ofs)};
    int hSrc = LZOpenFile((char*)src, &ofs, OF_READ);
    int hDst = LZOpenFile((char*)dst, &ofs, OF_CREATE | OF_WRITE);
    LZCopy(hSrc, hDst);
    LZClose(hSrc); LZClose(hDst);
}
  • 專案需連結 lz32.lib (Platform SDK Lib 目錄)。
  • 同樣設定 /MT 靜態連結 CRT,達成零依賴。

解除安裝程式流程

  1. 啟動時自我複製到 %TEMP% 目錄(避免鎖定安裝目錄)。
  2. 刪除所有程式檔案、目錄、註冊表項、捷徑。
  3. 呼叫上述 SelfDelete 刪除自身副本。

工具鏈補充

  • compress.exe:ftp://ftp.microsoft.com/softlib/mslfiles/CP0982.EXE 解包後取得。
  • expand.exe:系統內建,命令列解壓縮 expand file.ex_ file.exe。

全平台 (Win9x/NT/2000/XP) 驗證通過。附件含完整安裝/解除安裝專案與 MagicDel.dll 原始碼。

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