大家都知道,一般的程序運行的時候,可執行文件本身是被操作系統保護的,不能用改寫的方式訪問,更別提在本身還在運行的時侯刪除自己了。
網上流傳了一些刪除自己的代碼,但基本上是在win9x的系統下才可行,2000/XP下這樣的代碼基本沒有,因爲window2000/XP對這方面進行修補。所以甚至有人放言,2000/XP(Ring3下)下不可能刪除自己(當然不是採取批處理,也不是機器重啓後刪除的辦法),真的是這樣嗎?沒有任何辦法嗎?筆者經過一段時間的研究,終於獲得瞭解決,方法是來自Windows編程的經典之作《Windows核心編程》的啓發。
實現代碼難度不大,研習過《Windows核心編程》的讀者均可理解。基本方法是採用創建遠程線程的方法實現。首先爲explorer.exe創建遠程線程,來執行DeleteFile函數,程序自己立即退出,這時可執行文件已經不被操作系統保護,聯繫方式:[email protected]
本程序全部源代碼如下:(win9x下無效,xp上運行成功)
// EXIT.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
//獲取explorer.exe進程的ID
DWORD GetWinProcessID()
{
HANDLE hProcessSnap=NULL;
PROCESSENTRY32 pe32={0};
hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hProcessSnap==INVALID_HANDLE_VALUE) return 0;
pe32.dwSize=sizeof(PROCESSENTRY32);
if(Process32First(hProcessSnap,&pe32))
{
MODULEENTRY32 me32={0};
do
{
if(strcmp(pe32.szExeFile,"explorer.exe")==0)
{
CloseHandle(hProcessSnap);
return pe32.th32ProcessID;
}
}
while(Process32Next(hProcessSnap,&pe32));
}
CloseHandle(hProcessSnap);
return 0;
}
//刪除文件
//dwProcessId --- 創建遠程線程的目標進程ID
//filename --- 要刪除文件的完整文件名
void DeleteSelf(DWORD dwProcessId,char *filename)
{
HANDLE hProcess=NULL,hThread=NULL;
char *add=NULL;//爲目標進程分配的地址
hProcess=OpenProcess(
PROCESS_QUERY_INFORMATION |
PROCESS_CREATE_THREAD | // 爲 CreateRemoteThread
PROCESS_VM_OPERATION | // 爲 VirtualAllocEx/VirtualFreeEx
PROCESS_VM_WRITE , // 爲 WriteProcessMemory
FALSE,dwProcessId);//打開進程
int strnum=strlen(filename)+1;//文件名長度
add=(char *)VirtualAllocEx(hProcess,NULL,strnum,MEM_COMMIT,PAGE_READWRITE);//爲將要寫入的文件名分配空間
WriteProcessMemory(hProcess,add,(PVOID)filename,strnum,NULL);//將文件名寫入目標進程的地址空間
PTHREAD_START_ROUTINE pfnThreadRtn=(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")),"DeleteFileA");//獲得DeleteFileA函數的地址
hThread=CreateRemoteThread(hProcess,NULL,0,pfnThreadRtn,add,0,NULL);//爲目標創建遠程線程
exit(0);//進程強制結束(既然已經結束,當然也無法釋放空間、關閉句柄了)
}
int main(int argc, char* argv[])
{
DWORD WinID=GetWinProcessID();
char filename[256];
GetModuleFileName(NULL,filename,256);//獲取本可執行文件名
DeleteSelf(WinID,filename);
return 0;
}