文件自删除的几种实现方式
1. 文件自拷贝删除
1.1 实现原理
此种方式将文件自身拷贝一份到临时目录,再传递特定的参数启动拷贝后的程序。拷贝后的程序在启动后会通过不断等待之前的程序退出,退出之后再去删除之前的文件。而其本身因为是在临时目录中,所以会被系统清理软件给删除掉。
1.2 实现流程
流程如下所示:
1.3 优缺点
1. 优点:
ü 实现简单
ü 可靠删除
2. 缺点
² 删除过程设计文件拷贝
如果文件自身比较大,则拷贝过程会很长
² 文件删除过程中,用户有明显的感受
文件删除等待过程中,鼠标有后天运行的“转圈”标志
² 删除程序驻留在temp目录下,留下删除痕迹
2. 经典删除方法
2.1 实现原理
在可执行文件运行的最后关闭可执行文件的句柄,并且取消文件在内存中的映射,然后删除目标程序并退出。
2.2 实现方法
实现的代码如下所示:
HMODULE module = GetModuleHandle(0); TCHAR buf[MAX_PATH]; GetModuleFileName(module, buf, sizeof buf); CloseHandle(HANDLE(4)); __asm { lea eax, buf push 0 push 0 push eax push ExitProcess push module push DeleteFile push UnmapViewOfFile ret } |
首先获取程序的模块句柄和文件路径。
然后通过CloseHandle(4)以硬编码的方式强制关闭程序文件的句柄。Handle4是OS对程序的IMAGE句柄的硬编码,关闭之后就解除了内核对与此文件的一个引用。
之后将将要执行的代码压入到线程栈中(因为执行UnmapViewOfFile之后,可执行程序的代码段将不可访问)
先看下执行到ret时堆栈中的东西:
偏移量 | 内容 |
24 | 0 |
20 | 0 |
16 | offset of filepath |
12 | address of ExitProcess |
8 | module of image |
4 | address of DeleteFile |
0 | address of UnmapViewOfFile |
调用ret后,eip指向栈顶的第一个元素,即UnmapViewOfFile,其解除了另外一个对程序文件的引用,其返回地址是DeleteFile所在的地址,如图所示:
同理,DeleteFile执行之后的返回地址是ExitProcess用以结束当前进程。
可惜的是,在XP及其以上的系统中调用DeleteFile方法会失败,报访问拒绝的错误。
2.3 优缺点
优点
ü 实现直观、高效
ü 没有任何副作用
缺点
² 使用受限:只能在XP以前的平台上使用
3. 外部命令删除
3.1 实现原理
在主进程退出之前,启动CMD执行一系列耗时指令,在执行过程中,主进程退出,CMD执行的最后一条指令是删除目标程序,由于此时主进程已经退出,所以可以顺利删除目标程序。
3.2 实现方法
实现方法如下所示:
DWORD WINAPI ThreadSelfDeleteProc(LPVOID lpParam) { HMODULE module = GetModuleHandle(0); TCHAR buf[MAX_PATH]; TCHAR COMMAMD[512]; GetModuleFileName(module, buf, sizeof(buf)); wsprintf(COMMAMD,L"@ping 127.0.0.1 -n 1 >NUL&&@del \"%s\" /f /q",buf); _wsystem(COMMAMD); return 0; }
void DeleteAppSelf() { DWORD dwThreadID; CreateThread(NULL, NULL, ThreadSelfDeleteProc, NULL, 0, &dwThreadID); Sleep(10); ExitProcess(NULL); } |
在程序运行到最后时调用DeleteAppSelf,此方法创建一个线程去启动CMD命令去执行一系列的耗时指令,通过Sleep方法,确保刚启动的线程有足够的时间去创建CMD进程。并且在CMD进程执行耗时指令的过程中,必须要确保主进程已经退出。之后CMD进程执行最后一条命令去删除目标程序。
3.3 优缺点
优点:
ü 可支持不同的平台
ü 用户不会有明显的感知
缺点:
² 由于起依赖于进程调度之间的时间差,在极端情况下有可能会失效
4. 进程优先级调度
4.1 实现原理
其实现也是采用执行外部命令来删除目标程序,但是在创建CMD进程之前,首先提高自身的优先级,使得创建CMD进程后自身程序继续执行,然后降低已创建CMD进程的优先级并禁止系统动态提升此进程的优先级,确保自己退出之后,CMD进程能够继续执行。
4.2 实现方法
其实现过程如下所示:
BOOL SelfDelete() { SHELLEXECUTEINFO sei;
TCHAR szModule [MAX_PATH], szComspec[MAX_PATH], szParams [MAX_PATH];
// get file path names: if((GetModuleFileName(0,szModule,MAX_PATH)!=0) && //(GetShortPathName(szModule,szModule,MAX_PATH)!=0) && (GetEnvironmentVariable(L"COMSPEC",szComspec,MAX_PATH)!=0)) {
// set command shell parameters lstrcpy(szParams,L"/c del "); lstrcat(szParams, szModule); lstrcat(szParams, L" > nul");
// set struct members sei.cbSize = sizeof(sei); sei.hwnd = 0; sei.lpVerb = L"Open"; sei.lpFile = szComspec; sei.lpParameters = szParams; sei.lpDirectory = 0; sei.nShow = SW_HIDE; sei.fMask = SEE_MASK_NOCLOSEPROCESS;
MessageBox(0,szParams,0,0); // increase resource allocation to program SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS); SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);
// invoke command shell if(ShellExecuteEx(&sei)) { // suppress command shell process until program exits SetPriorityClass(sei.hProcess,IDLE_PRIORITY_CLASS); SetProcessPriorityBoost(sei.hProcess,TRUE);
// notify explorer shell of deletion SHChangeNotify(SHCNE_DELETE,SHCNF_PATH,szModule,0); return TRUE; } else // if error, normalize allocation { SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); } } return FALSE; } |
4.3 优缺点
优点:
ü 可支持不同的平台
ü 用户不会有明显的感知
ü 可靠性较高
缺点:
² 依赖于进程和线程的优先级调度
5. 添加开机计划任务
5.1 实现原理
通过设置一个开机计划任务,在用户下次开机时删除目标程序。
5.2 实现方法
略
5.3 优缺点
优点:
ü 可支持不同的平台
ü 用户不会有明显的感知
ü 可靠性高
缺点:
² 不能实时删除目标文件