Wednesday, January 4, 2012

Self-Deleting Executable

I wrote a program the other day.  When you run it, it deletes itself.  Yay, but not as easy to accomplish as you might like.  So, with that in mind I’m going to give you all the source code to such a marvel.  It only works on Windows because it utilizes Window’s libraries.

 

   1:  /*
   2:   * This program produces an executable file that, when run, deletes itself from the hard disc.
   3:   * Author: SevenBits
   4:   */
   5:  #define WIN32_LEAN_AND_MEAN
   6:   
   7:  #include <windows.h>
   8:  #include <tchar.h>
   9:   
  10:  int CommitSuicide(char *szCmdLine)
  11:  {
  12:      //Define variables.
  13:      HANDLE hTemp;
  14:      char szPath[MAX_PATH];
  15:      char szTemp[MAX_PATH];
  16:   
  17:      static BYTE buf[1024];
  18:      
  19:      STARTUPINFO si;
  20:      PROCESS_INFORMATION pi;
  21:      UINT ret;
  22:   
  23:      //Open a temporary file.  Copy ourselves into that file.
  24:      GetTempPath(MAX_PATH, szTemp);
  25:      lstrcat(szTemp, "suicide.exe");
  26:   
  27:      GetModuleFileName(0, szPath, MAX_PATH);
  28:      
  29:      CopyFile(szPath, szTemp, FALSE);
  30:   
  31:      hTemp = CreateFile(szTemp, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, 0,
  32:          OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
  33:   
  34:      //Create a process using the temporary executable. This will cause
  35:      //the file's handle count to increase, so we can close it.
  36:      ZeroMemory(&si, sizeof(STARTUPINFO));
  37:      ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
  38:   
  39:      ZeroMemory(&si, sizeof(STARTUPINFO));
  40:      si.cb = sizeof(STARTUPINFO);
  41:   
  42:      lstrcat(szTemp, " ");
  43:      lstrcat(szTemp, szCmdLine);
  44:   
  45:      ret = CreateProcess(0, szTemp, 0, 0, FALSE, NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi);
  46:   
  47:      //Close our handle to the new process. Because the process is
  48:      //memory-mapped, there will still be a handle held by the OS, so
  49:      //it won't get deleted. Give the other process a chance to run..
  50:      Sleep(100);
  51:      CloseHandle(hTemp);
  52:   
  53:      return 0;
  54:  }
  55:   
  56:  //Don't start the file in main() but here, as this program can avoid the overhead of a main() function.
  57:  int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, PSTR szCmdLine, int iCmdShow)
  58:  {
  59:      char szPath[MAX_PATH];
  60:   
  61:      //
  62:      //    Parse the command line:
  63:      //    Normally, we should not be run with any parameters.
  64:      //    We re-spawn ourselves with the current module's path.
  65:      //
  66:      if(szCmdLine[0] == '\0')
  67:      {
  68:          // Spawn a duplicate process, and tell it to delete us.
  69:          HMODULE hModule = GetModuleHandle(0);
  70:   
  71:          GetModuleFileName(hModule, szPath, MAX_PATH);
  72:   
  73:          CommitSuicide(szPath);
  74:          
  75:          // Exit normally
  76:          return 0;
  77:      }
  78:      //    This is where we pick up execution second time we run,
  79:      //  When a filename has been specified on the command line
  80:      else
  81:      {
  82:          // Give the calling process time to exit...
  83:          Sleep(200);
  84:   
  85:          // Delete the file specified on command line.
  86:          DeleteFile(szCmdLine);
  87:   
  88:          // Exit normally. When we close, this executable will be automatically deleted.
  89:          return 0;
  90:      }
  91:  }    



Innovative? No.  Something new? No. But it’s a lot harder to do for beginners than one might think.  Feel free to use this code for whatever you desire.

No comments: