// sde : Self deleting executable // OS : Works on NT and 2000 // Author : Gary Nebbett // STL, London Road, Harlow, Essex CM17 9NA, UK // Voice +44-279-29531 // Email [email protected] | PSI%234237100122::GRN // Reference : Deleting the Executable File of // the Running Process Gary Nebbett [email protected] // Windows Developer Magazine // http://www.windevnet.com/documents/s=7257/wdj0109g/0109g.htm // selfdel.cpp // ------------------ ------------------- ---------------- // | | | Virtual Address | | File Control | // | Process Object |------>| Descriptor | | Block | // | | | (VAD) | | (FCB) | // ------------------ ------------------- ---------------- // : | ^ // handle : to | ptr reference | ptr // v v | // ------------------ ------------------- --------------- // | | | Image Section | | | // | Section Object | | Control Area | | File Object | // | | | | | | // ------------------ ------------------- --------------- // | ^ ^ | // | ptr | ptr | ptr | ptr // v | | | // ------------------ | | ------------- | // | | | | | Section | | // | Segment |<----------- ---| Object |<--- // | | | pointers | // ------------------ ------------- // DeleteFile() fails when used on it's own (running) executable // because there is a reference from the File Object to the File // Control Block that is incompatible with the deletion of the file. // The reference to the File Control Block persists until we eliminate: // - The section object from which the process was created. // - The VAD (Virtual Address descriptor recording that the file is // mapped into the virtual address space. //#in clude windows.h int main ( int argc, char * argv[]) { char buf[MAX_PATH]; HMODULE module; // Remove the Process object's handle to the Section object. // Empirical observations indicate that the value of the handle // is always four, the lowest valid handle value. // The handle is the only reference to the section object, // and when the reference count goes to zero the section // object is deleted. CloseHandle( (HANDLE) 4 ); // Get module handle to the running executable. // We will need this as an argument to UnmapViewOfFile() module = GetModuleHandle(0); // Get module name of the running executable // We will need this as an argument to ExitProcess() GetModuleFileName(module, buf, MAX_PATH); // Generate stack. // The return address specifies the address to which control will be transferred on exit from a function. // -------------------------------------------------------------------------------- // ExitProcess()'s argument 1 : (UINT uExitCode) // stack frame return address : transfer control on exit to 0 (Kernel32) // -------------------------------------------------------------------------------- // DeleteFile()'s argument 1 : (LPCTSTR lpFileName) // stack frame return address : transfer control on exit to ExitProcess() // -------------------------------------------------------------------------------- // UnmapViewOfFile()'s argument 1 : (HMODULE hModule) // stack frame return address : transfer control on exit to DeleteFile() // -------------------------------------------------------------------------------- __asm { push 0 ; ExitProcess() argument (UINT uExitCode) push ; ExitProcess() return address : transfer control to kernel32() ; ExitProcess() stack frame lea eax, buf ; forward pass setup. push eax ; DeleteFile() argument (LPCTSTR lpFileName) push ExitProcess ; DeleteFile() return address : transfer control to ExitProcess() ; DeleteFile() stack frame push module ; UnmapViewOfFile() argument (HMODULE hModule) push DeleteFile ; UnmapViewOfFile() return address : transfer control to DeleteFile() push UnmapViewOfFile ; UnMapViewOfFile() stack frame ret ; Start unwinding the stack. } return 0; }
// OS : Works on NT and 2000
// Author : Gary Nebbett
// STL, London Road, Harlow, Essex CM17 9NA, UK
// Voice +44-279-29531
// Email [email protected] | PSI%234237100122::GRN
// Reference : Deleting the Executable File of
// the Running Process Gary Nebbett [email protected]
// Windows Developer Magazine
// http://www.windevnet.com/documents/s=7257/wdj0109g/0109g.htm
// selfdel.cpp
// ------------------ ------------------- ----------------
// | | | Virtual Address | | File Control |
// | Process Object |------>| Descriptor | | Block |
// | | | (VAD) | | (FCB) |
// ------------------ ------------------- ----------------
// : | ^
// handle : to | ptr reference | ptr
// v v |
// ------------------ ------------------- ---------------
// | | | Image Section | | |
// | Section Object | | Control Area | | File Object |
// | | | | | |
// ------------------ ------------------- ---------------
// | ^ ^ |
// | ptr | ptr | ptr | ptr
// v | | |
// ------------------ | | ------------- |
// | | | | | Section | |
// | Segment |<----------- ---| Object |<---
// | | | pointers |
// ------------------ -------------
// DeleteFile() fails when used on it's own (running) executable
// because there is a reference from the File Object to the File
// Control Block that is incompatible with the deletion of the file.
// The reference to the File Control Block persists until we eliminate:
// - The section object from which the process was created.
// - The VAD (Virtual Address descriptor recording that the file is
// mapped into the virtual address space.
//#in clude windows.h
int main ( int argc, char * argv[]) {
char buf[MAX_PATH];
HMODULE module;
// Remove the Process object's handle to the Section object.
// Empirical observations indicate that the value of the handle
// is always four, the lowest valid handle value.
// The handle is the only reference to the section object,
// and when the reference count goes to zero the section
// object is deleted.
CloseHandle( (HANDLE) 4 );
// Get module handle to the running executable.
// We will need this as an argument to UnmapViewOfFile()
module = GetModuleHandle(0);
// Get module name of the running executable
// We will need this as an argument to ExitProcess()
GetModuleFileName(module, buf, MAX_PATH);
// Generate stack.
// The return address specifies the address to which control will be transferred on exit from a function.
// --------------------------------------------------------------------------------
// ExitProcess()'s argument 1 : (UINT uExitCode)
// stack frame return address : transfer control on exit to 0 (Kernel32)
// --------------------------------------------------------------------------------
// DeleteFile()'s argument 1 : (LPCTSTR lpFileName)
// stack frame return address : transfer control on exit to ExitProcess()
// --------------------------------------------------------------------------------
// UnmapViewOfFile()'s argument 1 : (HMODULE hModule)
// stack frame return address : transfer control on exit to DeleteFile()
// --------------------------------------------------------------------------------
__asm {
push 0 ; ExitProcess() argument (UINT uExitCode)
push ; ExitProcess() return address : transfer control to kernel32()
; ExitProcess() stack frame
lea eax, buf ; forward pass setup.
push eax ; DeleteFile() argument (LPCTSTR lpFileName)
push ExitProcess ; DeleteFile() return address : transfer control to ExitProcess()
; DeleteFile() stack frame
push module ; UnmapViewOfFile() argument (HMODULE hModule)
push DeleteFile ; UnmapViewOfFile() return address : transfer control to DeleteFile()
push UnmapViewOfFile ; UnMapViewOfFile() stack frame
ret ; Start unwinding the stack.
}
return 0;
}