//第一种
利用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;
}