deleteme.cpp module name: deleteme.cpp written by: jeffrey richterdescription: allows an executable file to delete itself********************************************************************/ #include <windows.h>#include <stdlib.h>#include <tchar.h> ///////////////////////////////////////////////////////////////////// int winapi winmain(hinstance h, hinstance b, lpstr psz, int n) { // is this the original exe or the clone exe?// if the command-line 1 argument, this is the original exe// if the command-line >1 argument, this is the clone exe if (__argc == 1) { // original exe: spawn clone exe to delete this exe// copy this executable image into the user's temp directory tchar szpathorig[_max_path], szpathclone[_max_path];getmodulefilename(null, szpathorig, _max_path);gettemppath(_max_path, szpathclone);gettempfilename(szpathclone, __text("del"), 0, szpathclone); copyfile(szpathorig, szpathclone, false); //***注意了***: // open the clone exe using file_flag_delete_on_closehandle hfile = createfile(szpathclone, 0, file_share_read, null, open_existing, file_flag_delete_on_close, null); // spawn the clone exe passing it our exe's process handle// and the full path name to the original exe file.tchar szcmdline[512];handle hprocessorig = openprocess(synchronize, true, getcurrentprocessid());wsprintf(szcmdline, __text("%s %d \"%s\""), szpathclone, hprocessorig, szpathorig);startupinfo si;zeromemory(&si, sizeof(si));si.cb = sizeof(si);process_information pi;createprocess(null, szcmdline, null, null, true, 0, null, null, &si, &pi);closehandle(hprocessorig);closehandle(hfile); // this original process can now terminate.} else { // clone exe: when original exe terminates, delete ithandle hprocessorig = (handle) _ttoi(__targv[1]);waitforsingleobject(hprocessorig, infinite);closehandle(hprocessorig);deletefile(__targv[2]);// insert code here to remove the subdirectory too (if desired). // the system will delete the clone exe automatically // because it was opened with file_flag_delete_on_close}return(0);}
RENCE的作者.乃NT系统一等一的高手.下面就分析一些他的这段代码.
这段代码在PROCESS没有结束前就将启动PROCESS的EXE文件删除了.
int main(int argc, char *argv[])
{
HMODULE module = GetModuleHandle(0);
CHAR 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
}
return 0;
}
现在,我们先看一下堆栈中的东西
偏移 内容
24 0
20 0
16 offset buf
12 address of ExitProcess
8 module
4 address of DeleteFile
0 address of UnmapViewOfFile
调用RET返回到了UnmapViewOfFile,也就是栈里的偏移0所指的地方.当进入UnmapViewOf
File的流程时,栈里见到的是返回地址DeleteFile和HMODUL module.也就是说调用完毕后
返回到了DeleteFile的入口地址.当返回到DeleteFile时,看到了ExitProcess的地址,也
就是返回地址.和参数EAX,而EAX则是buffer.buffer存的是EXE的文件名.由GetModuleFi
leName(module, buf, sizeof buf)返回得到.执行了DeleteFile后,就返回到了ExitPro
cess的函数入口.并且参数为0而返回地址也是0.0是个非法地址.如果返回到地址0则会出
错.而调用ExitProcess则应该不会返回.
这段代码的精妙之处在于:
1.如果有文件的HANDLE打开,文件删除就会失败,所以,CloseHandle(HANDLE(4));是十分
巧妙的一手.HANDLE4是OS的硬编码,对应于EXE的IMAGE.在缺省情况下,OS假定没有任何调
用会关闭IMAGE SECTION的HANDLE,而现在,该HANDLE被关闭了.删除文件就解除了文件对
应的一个句柄.
2.由于UnmapViewOfFile解除了另外一个对应IMAGE的HANDLE,而且解除了IMAGE在内存的
映射.所以,后面的任何代码都不可以引用IMAGE映射地址内的任何代码.否则就OS会报错
.而现在的代码在UnmapViewOfFile后则刚好没有引用到任何IMAGE内的代码.
3.在ExitProcess之前,EXE文件就被删除了.也就是说,进程尚在,而主线程所在的EXE文件
已经没了.(WINNT/9X都保护这些被映射到内存的WIN32 IMAGE不被删除.)
del c:\a.exe
copy c:\b.exe c:\a.exe然后在程序a.exe的InitInstance()开始处用ShellExecute()执行这个批处理,结果是这样:有时候可以del,有时候会出现无法访问,但第二个语句可以成功执行。
如果去掉第一个语句,只执行copy那句,就无法成功执行,怎么回事??
CHAR 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
}
module name: deleteme.cpp
written by: jeffrey richterdescription: allows an executable file to delete itself********************************************************************/
#include <windows.h>#include <stdlib.h>#include <tchar.h>
/////////////////////////////////////////////////////////////////////
int winapi winmain(hinstance h, hinstance b, lpstr psz, int n) {
// is this the original exe or the clone exe?// if the command-line 1 argument, this is the original exe// if the command-line >1 argument, this is the clone exe
if (__argc == 1) {
// original exe: spawn clone exe to delete this exe// copy this executable image into the user's temp directory
tchar szpathorig[_max_path], szpathclone[_max_path];getmodulefilename(null, szpathorig, _max_path);gettemppath(_max_path, szpathclone);gettempfilename(szpathclone, __text("del"), 0, szpathclone); copyfile(szpathorig, szpathclone, false);
//***注意了***: // open the clone exe using file_flag_delete_on_closehandle hfile = createfile(szpathclone, 0, file_share_read, null, open_existing, file_flag_delete_on_close, null);
// spawn the clone exe passing it our exe's process handle// and the full path name to the original exe file.tchar szcmdline[512];handle hprocessorig = openprocess(synchronize, true, getcurrentprocessid());wsprintf(szcmdline, __text("%s %d \"%s\""), szpathclone, hprocessorig, szpathorig);startupinfo si;zeromemory(&si, sizeof(si));si.cb = sizeof(si);process_information pi;createprocess(null, szcmdline, null, null, true, 0, null, null, &si, &pi);closehandle(hprocessorig);closehandle(hfile);
// this original process can now terminate.} else {
// clone exe: when original exe terminates, delete ithandle hprocessorig = (handle) _ttoi(__targv[1]);waitforsingleobject(hprocessorig, infinite);closehandle(hprocessorig);deletefile(__targv[2]);// insert code here to remove the subdirectory too (if desired).
// the system will delete the clone exe automatically // because it was opened with file_flag_delete_on_close}return(0);}
98下好像完全不行。
HMODULE module = GetModuleHandle(0);
CHAR 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
}