Self-Deleting File - "Melting"

posted 13 Mar 2010, 14:33 by Delphi Basics   [ updated 18 Mar 2010, 23:31 ]
It may be necessary for an un-install program to remove an application, as well as itself in order to completely remove the application from disk. This [collection of] snippet[s] will enable an executable to delete itself from disk whilst running.

{
    Comspec Method
    Ported
: steve10120
    Compiled: Delphi 2007
    Website: hackhound.org
}
The Comspec method works under all 32bit versions of Windows (95,98,ME,NT,2000,XP), as long as the COMSPEC environment variable is defined. This is always defined (by default) to be the full path to the operating system's command interpreter. For Windows 95, this is "command.exe". For Windows NT, this is "cmd.exe".  The function will only work if the executable has exited, so it is important to call this function and then exit immediately. It works by spawning a copy of the system's command interpreter, and asking it to perform the following command:
del exepath >> NUL
This deletes the current executable, and pipes the output to NUL (no output). The shell process is created with a hidden window as well, so the whole process is invisible.  For more information, visit: http://www.catch22.net/tuts/selfdel
function ComSpecMelt():Boolean;
var
  szFile:  array[0..255] of Char;
  szCmd:   array[0..255] of Char;
begin
  Result := FALSE;
  if GetModuleFileName(0, szFile, 256) <> 0 then
  begin
    GetShortPathName(szFile, szFile, 256);
    lstrcpy(szCmd,'/c del ');
    lstrcat(szCmd, szFile);
    lstrcat(szCmd, ' >> NUL');
    if (GetEnvironmentVariable('ComSpec', szFile, 256) <> 0) and
       (ShellExecute(0, nil, szFile, szCmd, nil, SW_HIDE) > 32) then
      Result := TRUE;
  end;
end;

Self Deletion Unit coded by FoRSaKeN^
This unit uses code injection to delete itself.
unit DeleteUnit;

interface

uses Windows;
Procedure DeleteME(hProcess:Cardinal);


implementation


Procedure DeleteME(hProcess:Cardinal);
  Type
   TData   = Record
   _DeleteFileA : Pointer;
  _ExitThread  : Pointer;
  _Sleep       : Pointer;
   _szFile      : Pointer;
  end;

  procedure LoadProc(param: Pointer); stdcall;
  var
  Inject : TData;
  begin
  Inject := TData(param^);
    asm
      @del:
      push 1000
      call Inject._Sleep
      push Inject._szFile
      call Inject._DeleteFileA
      cmp  eax,0
      je   @del
      push 0
      call Inject._ExitThread
    end;
  end;

  Var
  Written,ThreadID      : Cardinal;
  Params,Proc           : Pointer;
   pData                 : TData;
  Handle                : hWnd;

begin
if hProcess = 0 then exit;
//------------------------------------------------------------------------------
pData._DeleteFileA   := GetProcAddress(GetModuleHandle(kernel32),'DeleteFileA');
pData._ExitThread    := GetProcAddress(GetModuleHandle(kernel32),'ExitThread' );
pData._Sleep         := GetProcAddress(GetModuleHandle(kernel32),'Sleep'      );
//------------------------------------------------------------------------------
pData._szFile := VirtualAllocEx(hProcess, nil, Length(ParamStr(0)) + 1, $3000, $40);
WriteProcessMemory(hProcess, pData._szFile, PChar(Paramstr(0)), Length(Paramstr(0)) + 1, Written);
//------------------------------------------------------------------------------
Params  := VirtualAllocEx(hProcess, nil, SizeOf(TData),$3000, $40);
WriteProcessMemory(hProcess, Params, @pData, SizeOf(TData), Written);
if Written<>SizeOf(TData) then exit;
//------------------------------------------------------------------------------
Proc    := VirtualAllocEx(hProcess, nil, 500, $3000, $40);
WriteProcessMemory(hProcess, Proc, @LoadProc, 500, Written);
if Written<>500 then exit;
//------------------------------------------------------------------------------
Handle := CreateRemoteThread(hProcess,nil,0, Proc, Params, 0, ThreadID);
if Handle = 0 then exit;
//------------------------------------------------------------------------------
end;

end.


In the near future, I will add more self-deletion / "melting" snippets.
Comments