看看这个,号称可以:
' UPDATED:
' - I now show you how to copy some data between your original process and your hijacked one.
' - How to delete your original program and keep running the code inside (the main point of this code)
' - How to display whole user interfaces and subclass them using your hijacked process (Only an API form for now...but I'll make it better)
' - How to inject in Explorer.exe
Introduction
SelfDelete() is a simple Win API function for creating a self-deleting executable. It works by invoking the command shell as a serialized process to delete the program file.
The Command Shell
The command shell program is defined by the environment variable "COMSPEC". This varies with the Windows OS: Win9x/ME use COMMAND.COM, while WinNT/2K/XP use CMD.EXE. The following string is passed to the command shell:
/c del Filename > nul
which translates to: "Run a single command to delete a file and redirect the output to nowhere." Filename is the full path and name of the file we want to delete. This name needs to be converted into its short 8.3 name to change any extended characters into OEM equivalents.
The command shell is started as an independent process by calling the ShellExecuteEx() function. Its process handle is defined by the SHELLEXECUTEINFO struct member "hProcess". NOTE: The "/c" switch is necessary for the command shell process to exit. Do not omit it from the parameters string.
Serializing Processes
Self-deletion presents us with a special problem: The main program must exit and close its opened file handle before the command shell deletes the file. To do this, we must serialize two independent, parallel processes—the current program process and the command shell process. This is done by manipulating CPU resource priorities to temporarily suppress the command shell process. As written, the code will allocate all CPU resources to the main program until it exits. This effectively blocks any command shell execution until the program has terminated.
CPU Allocation
Allocating the REALTIME_PRIORITY_CLASS and THREAD_PRIORITY_TIME_CRITICAL settings can interfere with driver functions and can cause Windows to "hang" if kept in a prolonged state. To avoid these problems, a self-deleting app must exit cleanly upon a boolean return of TRUE. Developers need to make sure all ancillary processes and threads have finished and all handles are closed before calling the function. SelfDelete() should only be called at a program's main exit:
INT APIENTRY WinMain(...)
{
...
// on program exit
// close all handles etc.
if(!SelfDelete())
{
// add error messaging
}
return 0; // WinMain exit
}
It may be desirable to use a lower CPU allocation, such as:
This allocation does not guarantee a complete cessation of the command shell process, but nevertheless works well.
Code Limitations
There is no error checking if the command shell cannot delete the file. Make sure the program file is not set with a "hidden," "system," or "read-only" attribute.
The explorer shell will always remove the program icon from view regardless of whether the command shell is able to actually delete the file. Pressing F5 will update the shell folder and correct any erroneous listings.
The command shell can only run a single command. Multiple commands such as to delete a file and remove its directory cannot be done without a script file.
Update
The code has been modified to work better on NT kernel computers with multiple processors. Windows allocates resources through a thread priority queue rather than by time-slicing CPU cycles. Two modifications have been made to the code:
The thread allocation to the program process has been increased prior to invoking the command shell process. This ensures the program process will always have priority in the resource queue. Threads created by the ShellExecuteEx function do not inherit the resource allocation of the calling process.
The NT kernel will transiently increase priority to whatever process is granted CPU resources. The SetProcessPriorityBoost function has been added to prevent this from happening to the command shell process.
////////////////////////////////////////////////////////
// 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;
}
从Tony和DM的对话中,我们不难看到其设计思想是
1,avoid any Shell API calls
2,totally elliminates any "race" between processes. You might push the COMSPEC process to an even lower priority with this line:
Since the COMSPEC process is started suspended, you could increase resource allocation to main program AFTER the CreateProcess call, and that way you don't have to re-normalize allocatons on an error condition.
Module name: DeleteMe.cpp
Written by: Jeffrey Richter
Description: Allows an EXEcutable file to delete itself
**************************************************/
#include
#include
#include
/////////////////////////////////////////////////
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
//***注意了***:
// Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE
HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL, OPEN_EXISTI
NG, 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());
// This original process can now terminate.
} else {
// Clone EXE: When original EXE terminates, delete it
HANDLE 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);
}