大家都知道,一般的程序运行的时候,可执行文件本身是被操作系统保护的,不能用改写的方式访问,更别提在本身还在运行的时侯删除自己了。
网上流传了一些删除自己的代码,但基本上是在win9x的系统下才可行,2000/XP下这样的代码基本没有,因为window2000/XP对这方面进行修补。所以甚至有人放言,2000/XP(Ring3下)下不可能删除自己(当然不是采取批处理,也不是机器重启后删除的办法),真的是这样吗?没有任何办法吗?笔者经过一段时间的研究,终于获得了解决,方法是来自Windows编程的经典之作《Windows核心编程》的启发。
实现代码难度不大,研习过《Windows核心编程》的读者均可理解。基本方法是采用创建远程线程的方法实现。首先为explorer.exe创建远程线程,来执行DeleteFile函数,程序自己立即退出,这时可执行文件已经不被操作系统保护,联系方式:yinwei_88@sina.com
本程序全部源代码如下:(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;
}