EXE程序的自刪除實現

程序的自刪除已經不是什麼新鮮的話題了,它廣泛運用於***病毒中。試想想,當你的程序還在運行中(通常是完成了駐留、感染模塊),它就自動地把自己從磁盤中刪掉,這樣一來,就做到了神不知鬼不覺,呵呵,是不是很cool呢?

 

自刪除(Self Deleting)最早的方法是由 Gary Nebbett 大蝦寫的,太經典了,不能不提。程序如下:

#include "windows.h"

int main(int argc, char *argv[])
{
char buf[MAX_PATH];
HMODULE module;

module = GetModuleHandle(0);
GetModuleFileName(module, buf, MAX_PATH);
CloseHandle((HANDLE)4);

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

return 0;
}

試試編譯它,運行。怎麼樣?從你的眼皮底下消失了吧?是不是很神奇?

Gary Nebbett 鑽了系統的一個漏洞,他的程序是關閉了 exe 文件的 IMAGE(硬編碼爲4),然後用 UnmapViewOfFile 解除了 exe 文件在內存中的映象,接着通過堆棧傳遞當前程序的 Handle 給 DeleteFile() ,實現了程序的自刪除。

Gary Nebbett 果然不愧爲 WIN 系統下頂尖的底層高手。那麼是否還有其他的方法實現程序的自刪除呢?答案是肯定的。

在 Win9x/ME 下,還可以利用 WININIT.INI 的一些特性。在 WININIT.INI 文件裏面有一個節 [Rename] ,只要在裏面寫入要 “Nul=要刪除的文件”,那麼下次系統重新啓動的時候,該文件就會被自動刪除了。以下是一個例子:

[Rename]
NUL=c:\SelfDelete.exe

利用這個特性,我們就可以在程序中對這個 ini 文件進行操作。值得注意的是,當需要自刪除的文件多於一個的時候,就不能使用 WritePrivateProfileString 來實現,因爲這個 API 會阻止多於一個“NUL=”這樣的入口在同一個節裏面出現,所以最好還是自己手動實現。

第三種方法是利用批處理文件。先讓我們做一個試驗:

創建一個 a.bat ,給它寫入以下內容:

del %0.bat

現在運行它吧,屏幕一閃而過,最後留下一串字符:“The batch file cannot be found”。這時候它已經從你的硬盤中消失了。

這說明,批處理文件是可以刪除自己的,於是我們可以把這個小技巧運用在自己的程序當中:

:Repeat
del "C:\MYDIR\SelfDelete.exe"
if exist "SelfDelete.exe" goto Repeat
rmdir "C:\MYDIR"
del "\DelUS.bat"

它會重複不斷地搜索是否有 SelfDelete.exe 這個文件,直到刪除了它爲止;當刪除完畢後,這個批處理文件就會把自己刪除。
(注:本方法可以支持所有的 Windows 版本,即 Win9x/Me/NT/2000/XP)

用批處理文件的方法有一個缺陷,就是會突然彈出一個 DOS 窗,冷不防的嚇人一跳,不過據我所知這是目前唯一可以在 WinXP 下起作用的方法。當然,最理想的方法是用 Gary Nebbett 的那種,不過它的缺陷是沒法在 WinXP 下起作用。

(注:Gary Nebbett 的方法,hume已經給出了例子,所以我就不重複了,請到他的網站 http://humeasm.yeah.net 下載。)


以上的方法都是前輩高人的研究總結,可不是我原創的,不過最後我給出一個 Win32ASM 例子,演示一下用批處理文件刪除程序自身的方法。


;******************************************************
;程序名稱:程序自刪除示例,適用於Win9x/WinMe/Win2000/WinXP
;作者:羅聰
;日期:2002-10-23
;出處:http://www.luocong.com(老羅的繽紛天地)
;注意事項:如欲轉載,請保持本程序的完整,並註明:
;轉載自“老羅的繽紛天地”(http://www.luocong.com)
;******************************************************

.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\shell32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\shell32.lib

DeleteExecutableBF PROTO

.code
main:
invoke DeleteExecutableBF
invoke ExitProcess, NULL

;********************************************
; 模塊功能:用批處理文件刪除自身
; 入口參數:無
; 出口參數:無
;********************************************
DeleteExecutableBF proc
LOCAL hFile :DWORD
LOCAL len :DWORD
LOCAL hHeap :DWORD
LOCAL pszUnsetupPathname :DWORD
LOCAL pszUnsetupPath :DWORD
LOCAL pszBatFilePathname :DWORD
LOCAL pBatFile :DWORD

jmp nextcode

szBatFileName BYTE "DelUS.bat", 0
szOpen BYTE "open", 0
szBKSlash BYTE "\", 0
L1 BYTE ":Repeat", 13, 10, 0
L2A BYTE "del """, 0
L2B BYTE """", 0
L3A BYTE 13, 10, "if exist """, 0
L3B BYTE """ goto Repeat", 13, 10, 0
L4 BYTE "rmdir """, 0
L5 BYTE """",13, 10, "del """, 0
L6 BYTE """",13, 10, 0

nextcode:
; 爲字符串分配堆:
invoke GetProcessHeap
mov hHeap, eax
invoke HeapAlloc, hHeap, NULL, 4 * MAX_PATH + 1000
mov pszUnsetupPath, eax
add eax, MAX_PATH
mov pszUnsetupPath, eax
add eax, MAX_PATH
mov pszUnsetupPathname, eax
add eax, MAX_PATH
mov pszBatFilePathname, eax
add eax, MAX_PATH
mov pBatFile, eax

; 創建一個批處理文件,用於刪除我們的exe文件。當exe文件被刪除後,這個批處理文件會自動刪除自己,以及它所在的目錄。

; 得到 temp 目錄的路徑:
invoke GetTempPath, MAX_PATH, pszBatFilePathname

invoke lstrcat, pszBatFilePathname, addr szBatFileName
invoke CreateFile, pszBatFilePathname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, NULL
mov hFile, eax
.if (hFile != INVALID_HANDLE_VALUE)

; 得到我們的 exe 文件的全路徑(包括文件名):
invoke GetModuleFileName, NULL, pszUnsetupPathname, MAX_PATH

; 得到我們的 exe 文件的路徑(不包括文件名):
invoke lstrcpy, pszUnsetupPath, pszUnsetupPathname

; 找到路徑最後的 ’\’ 並把它改成0
mov edx, pszUnsetupPath
mov ecx, edx
.repeat
mov al, byte ptr [edx]
.if al == 92 ; "\"
mov ecx, edx
.endif
inc edx
.until al == 0
mov byte ptr [ecx+1], 0

; Bat 文件的內容:
; :Repeat
; del "C:\Win95ADG\DelSelf.exe"
; if exist "DelSelf.exe" goto Repeat
; rmdir "C:\Win95ADG"
; del "c:\%temppath%\DelUS.bat"
invoke lstrcat, pBatFile, addr L1
invoke lstrcat, pBatFile, addr L2A
invoke lstrcat, pBatFile, pszUnsetupPathname
invoke lstrcat, pBatFile, addr L2B
invoke lstrcat, pBatFile, addr L3A
invoke lstrcat, pBatFile, pszUnsetupPathname
invoke lstrcat, pBatFile, addr L3B
invoke lstrcat, pBatFile, addr L4
invoke lstrcat, pBatFile, pszUnsetupPath
invoke lstrcat, pBatFile, addr L5
invoke lstrcat, pBatFile, pszBatFilePathname
invoke lstrcat, pBatFile, addr L6

; 創建 bat 文件:
invoke lstrlen, pBatFile
mov len, eax
invoke WriteFile, hFile, pBatFile, len, addr len, NULL
invoke CloseHandle, hFile

; 現在在後臺執行我們的 bat 文件:
invoke ShellExecute, NULL, addr szOpen, pszBatFilePathname, NULL, NULL, SW_HIDE

.endif

; 釋放堆:
invoke HeapFree, hHeap, NULL, pszUnsetupPath
return:
; 結束啦!
ret

DeleteExecutableBF endp

end main
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章