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

進程未結束即自我刪除:Windows 經典黑科技原理解析

     編輯:關於C++

Gary Nebbett(《Windows NT/2000 Native API Reference》作者)分享的一段極具技巧性的代碼:進程在自身映像檔案仍被系統鎖定的情況下,實現「自我刪除」。這不僅是技術好奇心的滿足,更深刻揭示了 Windows 執行檔映射、句柄管理與進程終止機制的底層邏輯。

核心代碼

int main(int argc, char *argv[]) {
    HMODULE module = GetModuleHandle(0);
    CHAR buf[MAX_PATH];
    GetModuleFileName(module, buf, sizeof buf);
    CloseHandle(HANDLE(4)); // 關閉映像區段句柄

    __asm {
        lea eax, buf
        push 0
        push 0
        push eax
        push ExitProcess
        push module
        push DeleteFile
        push UnmapViewOfFile
        ret
    }
    return 0;
}

堆疊佈局與執行流程

偏移內容說明
240DeleteFile 返回地址(ExitProcess 參數)
200ExitProcess 返回地址
16offset bufDeleteFile 參數:檔案路徑
12ExitProcess 地址UnmapViewOfFile 返回地址
8moduleUnmapViewOfFile 參數:基地址
4DeleteFile 地址UnmapViewOfFile 返回地址
0UnmapViewOfFile 地址ret 跳轉入口

執行鏈:

  1. ret → UnmapViewOfFile(module):解除映像記憶體映射
  2. 返回 → DeleteFile(buf):刪除磁碟檔案
  3. 返回 → ExitProcess(0):終止進程(不返回)

三大精妙關鍵點

1. CloseHandle(HANDLE(4)):破解檔案鎖定

  • 句柄 4 是系統硬編碼的執行檔映像區段句柄
  • 預設系統假設無人關閉此句柄,檔案持續被鎖定
  • 關閉後,DeleteFile 不再因共享違規失敗

2. UnmapViewOfFile:切斷記憶體映射依賴

  • 解除映像在記憶體中的映射
  • 後續代碼絕不能引用映像內任何代碼/數據(否則頁面錯誤)
  • 彙編鏈巧妙安排:Unmap 後僅執行 DeleteFile 與 ExitProcess,兩者均為系統 DLL 導出函數,不依賴映像內代碼

3. 時序反轉:進程存活而檔案已逝

  • Windows 保護映射到記憶體的映像檔不被刪除
  • 此技巧打破保護:先解除映射 → 再刪除檔案 → 最後退出進程
  • 結果:進程仍在運行,但磁碟上已無對應 EXE

實際應用場景與風險

  • 反安裝程式:安裝包執行後自我銷毀
  • 授權保護:試用版運行一次後銷毀
  • 惡意軟體特徵:殺毒軟體常作為可疑行為標記
  • 風險:依賴未文檔化行為(句柄 4)、x64 彙編不相容、現代 Windows 版本可能失效、觸發安全軟體攔截

現代替代方案

// 標準「複製-啟動-刪除」模式(Jeffrey Richter)
// 1. 複製自身到暫存目錄
// 2. CreateFile(FILE_FLAG_DELETE_ON_CLOSE) 開啟副本
// 3. CreateProcess 啟動副本,傳遞原檔路徑與進程句柄
// 4. 原進程退出
// 5. 副本 WaitForSingleObject 等待原進程結束
// 6. DeleteFile 原檔
// 7. 副本退出,系統自動刪除副本(FILE_FLAG_DELETE_ON_CLOSE)

此標準方案不依賴未文檔化行為,相容性更好,是工程實踐的推薦選擇。

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