c++ deleting current program

Started by
24 comments, last by Tayron 14 years, 7 months ago
Quote:Original post by Dizzy_exe
3. Inject yourself into another process and delete your program form there (complicated and dangerous)


The following works on NT based os (e.g. xp etc.) Not my code, found via quick google. Batch file would still be easier and less hassle

#include <windows.h>typedef UINT  (WINAPI *WAIT_PROC)(HANDLE, DWORD); // WaitForSingleObjecttypedef BOOL  (WINAPI *CLOSE_PROC)(HANDLE);       // CloseHandletypedef BOOL  (WINAPI *DELETE_PROC)(LPCTSTR);     // DeleteFiletypedef VOID  (WINAPI *EXIT_PROC)(DWORD);         // ExitProcesstypedef DWORD (WINAPI *REMOTETHREAD)(LPVOID);     // Our remote codetypedef struct{   WAIT_PROC   fnWaitForSingleObject;   CLOSE_PROC  fnCloseHandle;   DELETE_PROC fnDeleteFile;   EXIT_PROC   fnExitProcess;   HANDLE      hProcess;   TCHAR       szFileName[MAX_PATH];} INJECT;#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_stackPVOID GetFunctionAddr(PVOID func){   #ifdef _DEBUG       // get address of function from the JMP <relative> instruction       DWORD *offset = (BYTE *)func + 1;       return (PVOID)(*offset + (BYTE *)func + 5);   #else       return func;   #endif}BOOL SelfDelete(){   // Get process handle of the currently running as explorer   HANDLE hRemoteProcess = NULL;   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, &#960;)){       CloseHandle(pi.hThread);       hRemoteProcess = pi.hProcess;   }   if(hRemoteProcess == NULL) return FALSE;      // Allocate memory in remote process   BYTE *code = (BYTE *)VirtualAllocEx(hRemoteProcess, 0, sizeof(INJECT) + 128, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);   if(code == NULL){ CloseHandle(hRemoteProcess); return FALSE; };   // Setup remote structure   INJECT *remote = (INJECT *)(code + 128);   HMODULE hKernel32 = GetModuleHandle("kernel32.dll");   INJECT local;   local.fnWaitForSingleObject =   (WAIT_PROC)GetProcAddress(hKernel32, "WaitForSingleObject");   local.fnCloseHandle         =  (CLOSE_PROC)GetProcAddress(hKernel32, "CloseHandle");   local.fnExitProcess         =   (EXIT_PROC)GetProcAddress(hKernel32, "ExitProcess");   local.fnDeleteFile          = (DELETE_PROC)GetProcAddress(hKernel32, "DeleteFileA");   // Duplicate our own process handle for remote process to wait on   HANDLE hCurProc = GetCurrentProcess();   DuplicateHandle(hCurProc, hCurProc, hRemoteProcess, &local.hProcess, 0, FALSE, DUPLICATE_SAME_ACCESS);   // Find name of current executable   GetModuleFileName(NULL, local.szFileName, MAX_PATH);   // Write in code to execute, and the remote structure   WriteProcessMemory(hRemoteProcess, code,   GetFunctionAddr(RemoteThread), 128, 0);   WriteProcessMemory(hRemoteProcess, remote, &local, sizeof(local), 0);   // Execute the code in remote process   DWORD  dwThreadId = 0;   HANDLE hThread = CreateRemoteThread(hRemoteProcess, NULL, 0, (REMOTETHREAD)code, remote, 0, &dwThreadId);   if(hThread != 0) CloseHandle(hThread);   return TRUE;}
Advertisement
If you're not afraid of some inline assembly, here's an explanation I wrote up for one approach to the task. No need for batch files or remote threads. Not the cleanest approach either, but it works on NT too. The assembly uses AT&T syntax, specific to lcc-win32, so you might have to rejigger the assembly to intel syntax, but it's mostly pushes so that shouldn't be difficult.

#include <windows.h>int main(void){    // get the address that this module is mapped too    HINSTANCE hModule = GetModuleHandle(NULL);    // get the name of this module for passing to DeleteFileA    char buf[MAX_PATH];    GetModuleFileNameA(hModule, buf, sizeof(buf));    // provide an exit code for ExitProcess    UINT uExitCode = 0;    // get the direct addresses of the functions that go on the stack    HINSTANCE hKernel32 = GetModuleHandle("KERNEL32");    DWORD pExitProcess = (DWORD)GetProcAddress(hKernel32,"ExitProcess");    DWORD pDeleteFileA = (DWORD)GetProcAddress(hKernel32,"DeleteFileA");    // for this function the IAT address is ok    DWORD pUnmapViewOfFile = (DWORD)UnmapViewOfFile;    // handle to the file mapping object for this program    HANDLE hFileMapping = (HANDLE)(0x00000004);    // close the handle to the file mapping object for this program    CloseHandle(hFileMapping);    _asm("leal %buf, %eax");	        // load the address of the file name buffer into eax    _asm("pushl %uExitCode");            // push the parameter for ExitProces onto the stack    _asm("pushl $0x0");                 // return address for ExitProcess    _asm("pushl %eax");                 // eax provides address to parameter for DeleteFileA    _asm("pushl %pExitProcess");        // push direct address of ExitProcess onto the stack    _asm("pushl %hModule");             // push the parameter to UnmapViewOfFile onto the stack    _asm("pushl %pDeleteFileA");        // push direct address of DeleteFileA onto the stack    _asm("pushl %pUnmapViewOfFile");    // push IAT address of UnmapViewOfFile onto the stack    _asm("ret");                        // pop the stack fomenting the cascade of function calls    return 0;}
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Quote:Original post by LessBread
If you're not afraid of some inline assembly, here's an explanation I wrote up for one approach to the task. No need for batch files or remote threads. Not the cleanest approach either, but it works on NT too. The assembly uses AT&T syntax, specific to lcc-win32, so you might have to rejigger the assembly to intel syntax, but it's mostly pushes so that shouldn't be difficult.

*** Source Snippet Removed ***


This website provides a summary of all the methods discussed so far, as well as intel syntax for the method you just mentioned.

http://www.catch22.net/tuts/selfdel

However, it doesn't work anymore:

Quote:It works because under NT and 2000 the OS keeps a usermode HANDLE reference to the memory-mapped file which backs the executable image on disk. This HANDLE always has a value of "4" under these OSs.

Unfortunately this gem only works under NT/2000, not XP or .NET Server. This is because these OSs no longer maintain a usermode HANDLE to the executable's memory-mapped file - this section object is only accessible in kernel using a pointer reference. So although this technique is incredibly slick (it is the only true self-deleting method) it is no longer as-is.
That's too bad. I've exchanged emails with the guy who maintains catch22 so I trust that his account is accurate.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Quote:Original post by LessBread
That's too bad. I've exchanged emails with the guy who maintains catch22 so I trust that his account is accurate.


By the way, in that article, the last (and supposedly best) method that he proposes which works in XP...does not work in Vista (and the debug version results in a runtime crash). Possibly due to UIPI. Also note it must be compiled as C.
hmm...dunno...seems there are lots of ways, but some only work on some systems and some on other systems...I guess I'll stick to .bat 'till I figure out a better way...
here's my .bat code:
taskkill /F /pid *process id (got by calling GetCurrentProcessId())*ECHO Y | DEL *path to .exe*DEL %0

the .bat also closes the process for me...it works ok, and I it works on vista/7 too, right?

This topic is closed to new replies.

Advertisement