1. 程式人生 > >程式實現自我刪除的七種方法

程式實現自我刪除的七種方法

//第一種

利用CREATEFILE函式的FILE_FLAG_DELETE_ON_CLOSE,標誌位實現

#include <windows.h>
#include <tchar.h>

int CommitSuicide(char *szCmdLine)
{
	HANDLE hTemp;
	char szPath[MAX_PATH];
	char szTemp[MAX_PATH];

	static BYTE buf[1024];
	
	STARTUPINFO			si;
	PROCESS_INFORMATION pi;
	UINT ret;

	GetTempPath(MAX_PATH, szTemp);
	lstrcat(szTemp, "suicide.exe");

	GetModuleFileName(0, szPath, MAX_PATH);
	
	CopyFile(szPath, szTemp, FALSE);

	hTemp = CreateFile(szTemp, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, 0,
		OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);

	ZeroMemory(&si, sizeof(STARTUPINFO));
	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

	ZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);

	lstrcat(szTemp, " ");
	lstrcat(szTemp, szCmdLine);

	ret = CreateProcess(0, szTemp, 0, 0, FALSE, NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi);

	Sleep(100);
	CloseHandle(hTemp);

	return 0;
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, PSTR szCmdLine, int iCmdShow)
{
	char szPath[MAX_PATH];

	if(szCmdLine[0] == '\0')
	{
		HMODULE hModule = GetModuleHandle(0);

		GetModuleFileName(hModule, szPath, MAX_PATH);

		CommitSuicide(szPath);
		
		return 0;
	}

	else
	{

		Sleep(200);

		DeleteFile(szCmdLine);

		return 0;
	}
}	


第二種

//利用UnmapViewOfFile系列函式逆向刪除自身,一般僅限於低版本系統。

#include <windows.h>
#include <tchar.h>

int main(int argc, char *argv[])
{
    TCHAR	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;
}


第三種

//同第二種進行改進

#include <windows.h>

void DeleteMyself()
{
    char    buf[MAX_PATH];
    HMODULE module;
    
    module = GetModuleHandle(0);
    GetModuleFileName(module, buf, MAX_PATH);

    if(0x80000000 & GetVersion())
    {
        __asm 
        {
          lea     eax, buf
          push    0
          push    0
          push    eax
          push    ExitProcess
          push    module
          push    DeleteFile
          push    FreeLibrary
          ret
        }
    }

    else    
    {
        CloseHandle((HANDLE)4);

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

int main(int argc, char *argv[])
{
   DeleteMyself();
   return 0;
} 


第四種

//以臨時檔案開啟建立程序

#include <windows.h>
#include <tchar.h>

#pragma comment (linker, "/NODEFAULTLIB")

#ifndef _DEBUG
#pragma comment(linker,"/merge:.rdata=.data")
#pragma comment(linker,"/merge:.text=.data")
#pragma comment(linker,"/merge:.reloc=.data")
#pragma comment(linker,"/FILEALIGN:0x200")
#endif	// _DEBUG


TCHAR szAppName[]  = _T("delthis");
TCHAR szUsage[]    = _T("Usage:\r\n\r\nselfdel  [options]\r\n\r\nOptions:\r\n-u  (Uninstall)\r\n-pid Pid\r\n-exe Path");
TCHAR szError1[]   = _T("Failed to open process [%u]");
TCHAR szDeleting[] = _T("Deleting:\r\n\r\n%s");

int _tatoi(TCHAR *num)
{
	int   n = 0;
	TCHAR *nptr = num;
	
	while(*nptr && IsCharAlphaNumeric(*nptr) && !IsCharAlpha(*nptr))
		n = 10 * n + (*nptr++ - '0');

	return n;
}

void MyZeroMem(void *mem, DWORD bytes)
{
	BYTE *bptr = (BYTE *)mem;

	while(bytes--)
		*bptr++ = 0;
}

void CommitSuicide(void)
{
	HANDLE				hTemp;
	char				szPath[MAX_PATH];
	char				szTemp[MAX_PATH];
	char				szBig [MAX_PATH*2 + 100];

	STARTUPINFO			si;
	PROCESS_INFORMATION pi;
	
	UINT				ret;


	GetTempPath(MAX_PATH, szTemp);
	lstrcat(szTemp, "selfdel.exe");


	GetModuleFileName(0, szPath, MAX_PATH);
	

	CopyFile(szPath, szTemp, FALSE);

	hTemp = CreateFile(szTemp, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, 0,
		OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);


	MyZeroMem(&si, sizeof(STARTUPINFO));
	MyZeroMem(&pi, sizeof(PROCESS_INFORMATION));

	si.cb = sizeof(STARTUPINFO);

	wsprintf(szBig, "\"%s\" -pid %u -exe \"%s\"", 
		szTemp, 
		GetCurrentProcessId(),
		szPath);


	ret = CreateProcess(0, szBig, 0, 0, FALSE, NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi);
	Sleep(100);
	CloseHandle(hTemp);
}


//
void DeleteExe(DWORD dwPid, TCHAR *szPath)
{
	HANDLE hProcess;
	TCHAR  szErr[MAX_PATH+32];


	hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, dwPid);

	if(hProcess == 0)
	{
		wsprintf(szErr, szError1, dwPid);
		MessageBox(0, szErr, szAppName, MB_OK|MB_ICONINFORMATION);
		return;
	}


	WaitForSingleObject(hProcess, INFINITE);
	CloseHandle(hProcess);

	DeleteFile(szPath);
}

TCHAR * GetNextArg(TCHAR *szPtr, TCHAR *szOut)
{
	TCHAR *pOut = szOut;
	TCHAR ch = *szPtr++;

	if(ch == '\0')
		return 0;

	while(ch == ' ' || ch == '\t')
	{
		ch = *szPtr++;
	}

	if(ch == '\"')
	{
		ch = *szPtr++;
		
		while(ch && ch != '\"')
		{
			*szOut++ = ch;
			ch = *szPtr++;

		}

		*szOut = '\0';
		return szPtr;
	}

	while(ch && ch != ' ' && ch != '\t')
	{
		*szOut++ = ch;
		ch = *szPtr++;
	}

	*szOut = '\0';
	return szPtr;
}


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
{
	DWORD	dwProcessId;
	TCHAR  *ptr;
	TCHAR   buf[MAX_PATH];

	ptr = lpCmdLine;

	ptr = GetNextArg(ptr, buf);

	if(lstrcmpi(buf, "-u") == 0)
	{
		CommitSuicide();
		ExitProcess(0);
		return 0;
	}
	
	if(lstrcmpi(buf, "-pid") == 0)
	{
	
		ptr = GetNextArg(ptr, buf);

		dwProcessId = _tatoi(buf);


		ptr = GetNextArg(ptr, buf);

		if(lstrcmpi(buf, "-exe") == 0)
		{
			//exe-path specified - get the path
			ptr = GetNextArg(ptr, buf);
			DeleteExe(dwProcessId, buf);
			return 0;
		}
		else
		{
			return 1;
		}
	}
	else
	{
	
		return 1;
	}

	return 0;
}


int  WINAPI WinMainCRTStartup()
{
	UINT  ret;
	TCHAR *pszCmdLine;
	TCHAR temp[MAX_PATH];

	HINSTANCE hInst = GetModuleHandle(0);
	pszCmdLine = GetCommandLine();

	pszCmdLine = GetNextArg(pszCmdLine, temp);
	
	ret = WinMain(hInst, 0, pszCmdLine, SW_SHOWNORMAL);
	
	if(ret != 0)
	{
		MessageBox(0, szUsage, szAppName, MB_OK|MB_ICONINFORMATION);
	}

	ExitProcess(ret);
	return 0;
}



第五種

//利用系統環境變數實現

#include <windows.h>

BOOL SelfDelete()
{
  TCHAR szFile[MAX_PATH], szCmd[MAX_PATH];

  if((GetModuleFileName(0,szFile,MAX_PATH)!=0) &&
     (GetShortPathName(szFile,szFile,MAX_PATH)!=0))
  {
    lstrcpy(szCmd,"/c del ");
    lstrcat(szCmd,szFile);
    lstrcat(szCmd," >> NUL");

    if((GetEnvironmentVariable("ComSpec",szFile,MAX_PATH)!=0) &&
       ((INT)ShellExecute(0,0,szFile,szCmd,0,SW_HIDE)>32))
       return TRUE;
  }
  return FALSE;
}

int main()
{
	SelfDelete();
	return 0;
}


第六種

//注入別的程序代替實現

#include <windows.h>
#include <tchar.h>

#pragma pack(push, 1)

#define CODESIZE 0x200

typedef struct _SELFDEL
{
	struct _SELFDEL *Arg0;			

	BYTE	opCodes[CODESIZE];		

	HANDLE	hParent;				

	FARPROC	fnWaitForSingleObject;
	FARPROC	fnCloseHandle;
	FARPROC	fnDeleteFile;
	FARPROC	fnSleep;
	FARPROC	fnExitProcess;
	FARPROC fnRemoveDirectory;
	FARPROC fnGetLastError;

	BOOL	fRemDir;

	TCHAR	szFileName[MAX_PATH];	

} SELFDEL;

#pragma pack(pop)

#ifdef _DEBUG
#define FUNC_ADDR(func) (PVOID)(*(DWORD *)((BYTE *)func + 1) + (DWORD)((BYTE *)func + 5))
#else
#define FUNC_ADDR(func) func
#endif


static void remote_thread(SELFDEL *remote)
{

	remote->fnWaitForSingleObject(remote->hParent, INFINITE);
	remote->fnCloseHandle(remote->hParent);


	while(!remote->fnDeleteFile(remote->szFileName))
	{
		
		remote->fnSleep(1000);
	}
	remote->fnExitProcess(0);
}

	
BOOL SelfDelete(BOOL fRemoveDirectory)
{
	STARTUPINFO			si = { sizeof(si) };
	PROCESS_INFORMATION pi;

	CONTEXT				context;
	DWORD				oldProt;
	SELFDEL				local;
	DWORD				entrypoint;

	TCHAR				szExe[MAX_PATH] = _T("explorer.exe");


	if(CreateProcess(0, szExe, 0, 0, 0, CREATE_SUSPENDED|IDLE_PRIORITY_CLASS, 0, 0, &si, &pi))
	{
		local.fnWaitForSingleObject		= (FARPROC)WaitForSingleObject;
		local.fnCloseHandle				= (FARPROC)CloseHandle;
		local.fnDeleteFile				= (FARPROC)DeleteFile;
		local.fnSleep					= (FARPROC)Sleep;
		local.fnExitProcess				= (FARPROC)ExitProcess;
		local.fnRemoveDirectory			= (FARPROC)RemoveDirectory;
		local.fnGetLastError			= (FARPROC)GetLastError;

		local.fRemDir					= fRemoveDirectory;

		DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), 
			pi.hProcess, &local.hParent, 0, FALSE, 0);

		GetModuleFileName(0, local.szFileName, MAX_PATH);


		memcpy(local.opCodes, FUNC_ADDR(remote_thread), CODESIZE);

		context.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;
		GetThreadContext(pi.hThread, &context);

	
		entrypoint = (context.Esp - sizeof(SELFDEL)) & ~0x1F;
		
	
		local.Arg0 = (SELFDEL *)entrypoint;

		context.Esp = entrypoint - 4;	
		context.Eip = entrypoint + 4;	

		
		VirtualProtectEx(pi.hProcess,   (PVOID)entrypoint, sizeof(local), PAGE_EXECUTE_READWRITE, &oldProt);
		WriteProcessMemory(pi.hProcess, (PVOID)entrypoint, &local, sizeof(local), 0);

		FlushInstructionCache(pi.hProcess, (PVOID)entrypoint, sizeof(local));

		SetThreadContext(pi.hThread, &context);

	
		ResumeThread(pi.hThread);
		CloseHandle(pi.hThread);
		CloseHandle(pi.hProcess);

		return TRUE;
	}

	return FALSE;
}


int main(void)
{
	SelfDelete(TRUE);
	return 0;
}


第七種

//同第六種進行改進

#include <windows.h>
#include <tchar.h>

#define EXPLORER_PID 1444

typedef UINT  (WINAPI * WAIT_PROC)(HANDLE, DWORD);	
typedef BOOL  (WINAPI * CLOSE_PROC)(HANDLE);		
typedef BOOL  (WINAPI * DELETE_PROC)(LPCTSTR);		
typedef VOID  (WINAPI * EXIT_PROC)(DWORD);			

typedef struct
{
	WAIT_PROC	fnWaitForSingleObject;
	CLOSE_PROC	fnCloseHandle;
	DELETE_PROC	fnDeleteFile;
	EXIT_PROC	fnExitProcess;

	HANDLE		hProcess;
	TCHAR		szFileName[MAX_PATH];

} INJECT;

#pragma optimize("gsy", off)
#pragma check_stack(off)		

DWORD WINAPI RemoteThread(INJECT *remote)
{
	remote->fnWaitForSingleObject(remote->hProcess, INFINITE);
	remote->fnCloseHandle(remote->hProcess);
	remote->fnDeleteFile(remote->szFileName);
	remote->fnExitProcess(0);

	return 0;
}

#pragma check_stack

HANDLE GetRemoteProcess()
{
	STARTUPINFO			si = { sizeof(si) };
	PROCESS_INFORMATION pi;

	
	if(CreateProcess(0, "explorer.exe", 0, 0, FALSE, CREATE_SUSPENDED|CREATE_NO_WINDOW|IDLE_PRIORITY_CLASS,
                         0, 0, &si, &pi))
	{
		CloseHandle(pi.hThread);
		return pi.hProcess;
	}
	else
	{
		return 0;
	}
}

PVOID GetFunctionAddr(PVOID func)
{
#ifdef _DEBUG


	DWORD *offset = (BYTE *)func + 1;
	return (PVOID)(*offset + (BYTE *)func + 5);

#else

	return func;

#endif
}

BOOL SelfDelete()
{
	INJECT local, *remote;
	BYTE   *code;
	HMODULE hKernel32;
	HANDLE  hRemoteProcess;
	HANDLE  hCurProc;

	DWORD	dwThreadId;
	HANDLE	hThread = 0;

	char ach[80];

	hRemoteProcess = GetRemoteProcess();

	if(hRemoteProcess == 0)
		return FALSE;
	

	code = VirtualAllocEx(hRemoteProcess, 0, sizeof(INJECT) + 128, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	if(code == 0)
	{
		CloseHandle(hRemoteProcess);
		return FALSE;
	}

	hKernel32 = GetModuleHandle(_T("kernel32.dll"));

	remote = (INJECT *)(code + 128);

	local.fnWaitForSingleObject  = (WAIT_PROC)GetProcAddress(hKernel32,  "WaitForSingleObject");
	local.fnCloseHandle		     = (CLOSE_PROC)GetProcAddress(hKernel32, "CloseHandle");
	local.fnExitProcess			 = (EXIT_PROC)GetProcAddress(hKernel32, "ExitProcess");

#ifdef UNICODE
	local.fnDeleteFile			  = (DELETE_PROC)GetProcAddress(hKernel32, "DeleteFileW");
#else
	local.fnDeleteFile			  = (DELETE_PROC)GetProcAddress(hKernel32, "DeleteFileA");
#endif


	hCurProc = GetCurrentProcess();
	DuplicateHandle(hCurProc, hCurProc, hRemoteProcess, &local.hProcess, 0, FALSE, DUPLICATE_SAME_ACCESS);

	GetModuleFileName(NULL, local.szFileName, MAX_PATH);


	WriteProcessMemory(hRemoteProcess, code,    GetFunctionAddr(RemoteThread), 128, 0);
	WriteProcessMemory(hRemoteProcess, remote, &local, sizeof(local), 0);

	wsprintf(ach, "%x %x\n", code, remote);
	OutputDebugString(ach);


	hThread = CreateRemoteThread(hRemoteProcess, 0, 0, code, remote, 0, &dwThreadId);

	if(hThread != 0)
	{
		CloseHandle(hThread);
	}
	
	return TRUE;
}

int main(void)
{
	SelfDelete();

	return 0;
}