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;
}
| 偏移 | 內容 | 說明 |
|---|---|---|
| 24 | 0 | DeleteFile 返回地址(ExitProcess 參數) |
| 20 | 0 | ExitProcess 返回地址 |
| 16 | offset buf | DeleteFile 參數:檔案路徑 |
| 12 | ExitProcess 地址 | UnmapViewOfFile 返回地址 |
| 8 | module | UnmapViewOfFile 參數:基地址 |
| 4 | DeleteFile 地址 | UnmapViewOfFile 返回地址 |
| 0 | UnmapViewOfFile 地址 | ret 跳轉入口 |
執行鏈:
ret → UnmapViewOfFile(module):解除映像記憶體映射DeleteFile(buf):刪除磁碟檔案ExitProcess(0):終止進程(不返回)DeleteFile 不再因共享違規失敗// 標準「複製-啟動-刪除」模式(Jeffrey Richter)
// 1. 複製自身到暫存目錄
// 2. CreateFile(FILE_FLAG_DELETE_ON_CLOSE) 開啟副本
// 3. CreateProcess 啟動副本,傳遞原檔路徑與進程句柄
// 4. 原進程退出
// 5. 副本 WaitForSingleObject 等待原進程結束
// 6. DeleteFile 原檔
// 7. 副本退出,系統自動刪除副本(FILE_FLAG_DELETE_ON_CLOSE)
此標準方案不依賴未文檔化行為,相容性更好,是工程實踐的推薦選擇。