Самоудаление *.exe

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by [53x]Shadow, 1 Jul 2007.

  1. [53x]Shadow

    [53x]Shadow Leaders of Antichat

    Joined:
    25 Jan 2007
    Messages:
    284
    Likes Received:
    597
    Reputations:
    514
    Может такая тема уже была, но ничего на ачате не нашел.
    Имхо вопрос самоудаления исполняемых файлов в Винде достаточно интересен. Сам всю жизнь юзал достаточно простые способы с батником и MoveFileEx, и через реестр.
    Но покопавшись в поиске нашел еще несколько способов, опишу здесь все. Сразу хочу отметить, что весь материал взят из статьи Ex`a с www.progz.ru
    Так же хотелось бы в этой теме увидеть и другие варианты/способы о которых знаете ВЫ.
    И так:

    Системный реестр

    Code:
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx
    
    Записи в этом разделе указывают на имена файлов, которые должны выполниться один раз во время загрузки системы. Для удаления программы, нужно всего лишь добавить запись с именем файла, который удалит ее или командой del "имя файла".

    MoveFileEx

    Code:
    BOOL MoveFileEx(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, DWORD dwFlags);
    
    Эта функция перемещает файл в новое место. Если вы передадите NULL в качестве второго параметра, то файл не будет перемещен, а фактически будет удален. Если указать флаг MOVEFILE_DELAY_UNTIL_REBOOT в dwFlags, то Windows удалить или переместит файл при перезагрузке. У этого метода есть несколько недостатков. Первый: вы не можете удалить каталог, в котором находиться исполняемый файл. Второй: Файл будет удален только после перезагрузки системы. Третий недостаток, в том, что функция MoveFileEx не поддерживается в Windows 9x/ME.

    Wininit.ini

    Code:
    [Rename]
    NUL=c:\dir\myapp.exe
    c:\dir\new.exe=c:\dir\old.exe
    
    В Windows 9x/ME при каждой загрузке системы выполняется приложение wininit.exe. Это приложение ищет на диске файл wininit.ini, если файл существует, то ищется секция [Rename]. Каждая строка в этой секции указывает на файл который должен быть переименован или удален. Этот метод похож на MoveFileEx, описанный выше. Имя файла с лева от знака “=” указывает на новый путь к файлу, название справа указывает на текущий путь. Если в качестве нового имени файла указан NUL, wininit.exe удалит его.

    Batch File
    Этот метод работает во всех версиях Windows. Он основан на том, что bat файлы способны удалять сами себя. Что бы проверить данный метод создайте небольшой bat файл (назовите его test.bat) содержащий единственную команду:

    Code:
    del test.bat
    После запуска, bat файл удалит себя и выйдет с сообщением об ошибке “the batch file cannot be found”, это всего лишь сообщение и его можно спокойно игнорировать. Для самоудаления программа должна создать и выполнить bat файл (назовем его delus.bat) со следующим содержанием:

    Code:
    :Repeat
    del "C:\MYDIR\MYPROG.EXE"
    if exist "MYPROG.EXE" goto Repeat
    rmdir "C:\MYDIR"
    del "\delus.bat"
    
    После запуска bat файл будет пытаться удалить указанную программу и после успешного удаления уничтожит себя.

    COMSPEC

    Code:
    BOOL SelfDelete()
    {
      TCHAR szFile[MAX_PATH], szCmd[MAX_PATH];
    
      if((GetModuleFileName(0,szFile,MAX_PATH)!=0) &&
       (GetShortPathName(szFile,szFile,MAX_PATH)!=0))
      {
        lstrcpy(szCmd,"/c del ");
        lstrcat(szCmd,szFile);
        lstrcat(szCmd," >> NUL");
    
      if((GetEnvironmentVariable("ComSpec",szFile,MAX_PATH)!=0) &&
       ((INT)ShellExecute(0,0,szFile,szCmd,0,SW_HIDE)>32))
      return TRUE;
    }
    
      return FALSE;
    }
    
    Этот способ похож на способ Batch File, но немного аккуратнее в реализации и работает под всеми 32-разрядными версиями Windows, где определена переменная среда COMSPEC. Она всегда определена по умолчанию и содержит полный путь к командному интерпретатору (для Windows 9x – это “command.exe”, для Windows NT – “cmd.exe”). Функция будет работать, только если программа не запущена, так что важно после запуска функции немедленно выйти из программы. Это функция порождает копию программного интерпретатора и выполняет следующий код:

    Code:
    del <путь к программе> >> NUL
    
    Этот код удаляет текущую программу и направляет вывод к NUL. Shell process создается со скрытым окном и поэтому весь процесс удаления незаметен.

    FILE_FLAG_DELETE_ON_CLOSE

    Функция CreateFile принимает несколько флагов, указывающих, как файл должен быть создан или открыт. Один из таких флагов, FILE_FLAG_DELETE_ON_CLOSE, указывает на то, что файл должен быть удален после закрытия последнего дескриптора. Для удаления программы вы должны выполнить программу с этим флагом, чтобы после завершения запускной файл удалился. Первым шагом должно быть создание пустого файла с указанным флагом FILE_FLAG_DELETE_ON_CLOSE. Потом содержимое запускного файла копируется в пустой файл и создается процесс из нового файла. Это приводит к тому, что дублируются дескрипторы файлов. Когда новый процесс создан, полный путь текущего процесса и его PID передается через командную строку. Дальше, текущая программа (которая хочет удалить себя), закрывает дескриптор файла, используемого для создания нового процесса, и завершается.

    Это звучит немного сложно, но на самом деле все не так уж трудно.

    Текущий процесс:
    1. Создать новый файл с флагом FILE_FLAG_DELETE_ON_CLOSE.
    2. Скопировать содержимое текущего файла в новый файл.
    3. Создать новый процесс с дублированной программой.
    4. Передать полный путь и PID текущей программы в вызове CreateFile.
    5. Бездействовать некоторое время, чтобы новый процесс запустился.
    6. Закрыть новый файл.
    7. Выйти из текущего процесса.

    Дублированный процесс:
    8. Дождаться пока первый процесс завершится
    9. Удалить файл указанный в командной строке.
    10. Выйти из процесса дублера.

    Есть несколько замечаний по этому способу. Первой, когда новый процесс запущен, “старый” должен бездействовать некоторое время, что бы дать время загрузчику Windows открыть файл и запустить процесс (таким образом увеличивается счетчик файла). Второе, новый процесс должен дождаться пока старый не завершится. Третье, когда дубликат программы создан, он должен иметь установленный флаг FILE_SHARE_DELETE, иначе CreateProcess потерпит неудачу, потому что, не сможет открыть файл, пока он имеет флаг DELETE_ON_CLOSE. Четвертое, программа должна быть написана таким образом чтобы смогла исполнить две задачи. И последенее, дублированный процесс должен знать, что это его задача удалить исходный файл.
    Очевидно, этот метод требует осторожного кодирования, но работает очень хорошо. Альтернативный метод состоит в том, что бы написать маленькую программу, для которой единственной задачей являлось бы удаление файла указанного в командной строке.

    совершенный для Windows NT/2000

    Этот кусок встроенного ассемблера короток и прост.

    Code:
    #include
    
    int main(int argc, char *argv[])
    {
      char buf[MAX_PATH];
      HMODULE module;
    
      module = GetModuleHandle(0);
      GetModuleFileName(module, buf, MAX_PATH);
      CloseHandle((HANDLE)4);
    
      __asm
      {
        lea eax, buf
        push 0
        push 0
        push eax
        push ExitProcess
        push module
        push DeleteFile
        push UnmapViewOfFile
      ret
      }
    
      return 0;
    }
    
    Этот код работает только под Windows NT, но зато как работает! Как только вы компилируете и выполняете программу она исчезает с диска. Примечание: код работает под Windows NT/2000, но не работает под Windows XP и .NET Server.

    совершенный для Windows 9x/ME

    Code:
    int main(int argc, char *argv[])
    {
      char buf[MAX_PATH];
    vHMODULE module;
    
      module = GetModuleHandle(0);
      GetModuleFileName(module, buf, MAX_PATH);
    
      __asm
      {
        lea eax, buf
        push 0
        push 0
        push eax
        push ExitProcess
        push module
        push DeleteFile
        push FreeLibrary
        ret
      }
    
      return 0;
    }
    

    совершенный, комбинированный для Windows NT и Windows 9x


    Code:
    void DeleteMyself()
    {
      char buf[MAX_PATH];
      HMODULE module;
      DWORD fnFreeOrUnmap;
    
      module = GetModuleHandle(0);
      GetModuleFileName(module, buf, MAX_PATH);
    
      // Check for Win9x Kernel
      if(0x80000000 & GetVersion())
      {
        fnFreeOrUnmap = FreeLibrary;
      }
      // do for WinNT kernel
      else
      {
        fnFreeOrUnmap = UnmapViewOfFile;
        CloseHandle((HANDLE)4);
      }
    
      __asm
      {
        lea eax, buf
        push 0
        push 0
        push eax
        push ExitProcess
        push module
        push DeleteFile
        push fnFreeOrUnmap
        ret
      }
    }
    ЗЫ
    Возможно кому-нидь пригодится, хочется увидеть и другие варианты и способы =)
    Думаю тема не помешает в разделе, если в нее собирать различные способы...
     
    #1 [53x]Shadow, 1 Jul 2007
    Last edited: 1 Jul 2007
    7 people like this.
  2. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    не очень круто. потому что это всем известные методы, и я не думаю что их придумал ты.
    вот почему-то метода удаления через Com нету.

    Great: Он и не писал, что сам придумал =) Но то, что собрал в одном месте - по-любому, неплохо.
     
    #2 KEZ, 1 Jul 2007
    Last edited by a moderator: 1 Jul 2007
    1 person likes this.
  3. AHTOLLlKA

    AHTOLLlKA Member

    Joined:
    1 Feb 2005
    Messages:
    225
    Likes Received:
    35
    Reputations:
    22
    тоже интересна эта тема..
    меня всегда интересовало то..
    если по расшарить например папку с калькулятором.. зайти по сети.. запустить..
    а потом расшареную папку закрыть и снести..
    файл получаеться только в памяти будет =\
     
    1 person likes this.
  4. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    >>файл получаеться только в памяти будет =\

    ну это ясно. вообще невозможность удаления стандартным способом можно объяснить имхо только политикой безопасности винды, другого повода я просто не вижу. учитывая то, что запущенный выполняемый файл можно, например, спокойно переименовать...
     
    1 person likes this.
  5. AHTOLLlKA

    AHTOLLlKA Member

    Joined:
    1 Feb 2005
    Messages:
    225
    Likes Received:
    35
    Reputations:
    22
    да, переименовать то можно..
    а можно при запуске быстро расшаривать папку запускаться от туда, и потом сносить ее ))вот... жжесть =\\
    меня наверно с этой херни прет..
    http://forum.antichat.ru/thread43416.html
     
  6. Ky3bMu4

    Ky3bMu4 Elder - Старейшина

    Joined:
    3 Feb 2007
    Messages:
    487
    Likes Received:
    284
    Reputations:
    42
    Code:
    char szPath[256] ;
    GetModuleFileName(NULL, szPath, sizeof(szPath));
    SHFILEOPSTRUCT sh;
    sh.hwnd   = GetSafeHwnd();
    sh.wFunc  = FO_DELETE;
    sh.pFrom  =szPath;
    sh.pTo    = NULL;
    sh.fFlags = FOF_NOCONFIRMATION | FOF_SILENT;
    sh.hNameMappings = 0;
    sh.lpszProgressTitle = NULL;
    
    SHFileOperation (&sh);
    
    Вынесет наш .ехе и даже не поперхнётся.
     
  7. slider

    slider Reservists Of Antichat

    Joined:
    4 Sep 2005
    Messages:
    501
    Likes Received:
    711
    Reputations:
    748
    ...
    С КрякЛаба...
     
    1 person likes this.
  8. AHTOLLlKA

    AHTOLLlKA Member

    Joined:
    1 Feb 2005
    Messages:
    225
    Likes Received:
    35
    Reputations:
    22
    procedure DeleteFiles(Source: string);
    var
    FO: TShFileOpStruct;
    begin
    FillChar(FO,SizeOf(FO),#0);
    FO.Wnd := Form1.Handle;
    FO.wFunc := FO_DELETE;
    FO.pFrom := PChar(Source);
    FO.pTo := 0;
    FO.fFlags := FOF_NOCONFIRMATION or FOF_SILENT;
    FO.hNameMappings :=0;
    FO.lpszProgressTitle :=0;
    ShFileOperation(FO);
    end;

    не сносит.. грит что файл юзаеться виндой =\
     
  9. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,119
    Reputations:
    1,139
    Уверен?
     
  10. Pochka

    Pochka Banned

    Joined:
    26 Nov 2005
    Messages:
    27
    Likes Received:
    7
    Reputations:
    -2
    А как ты объяснишь работу Windows, когда в нее подгружено программ больше, чем это позволяет себе оперативная память?
    Есть такое понятие, как динамическое распределение памяти ;)
     
  11. NetMan

    NetMan Elder - Старейшина

    Joined:
    9 Feb 2004
    Messages:
    121
    Likes Received:
    37
    Reputations:
    34
    Code:
    strcpy(batfile,tempdir);
    strcat(batfile,"\\");
    strcat(batfile,"delself.bat");
    strcpy(batlines,"@echo off\n:try\ndel ");
    strcat(batlines,modulename);
    strcat(batlines,"\nif exist ");
    strcat(batlines,modulename);
    strcat(batlines," goto try\n");
    strcat(batlines,"del ");
    strcat(batlines,batfile);
    Вместо этого лучше wsprintf/sprintf сделать.
     
  12. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    > А как ты объяснишь работу Windows, когда в нее подгружено программ больше, чем это позволяет себе оперативная память?
    Есть такое понятие, как динамическое распределение памяти

    А как ты обьяснишь мне при чем тут динамическое распределение памяти, если дело в файле подкачки (сбросе части памяти на диск)?

    SHFileOpertion() твоя из shell32.dll с задаными sh.wFunc = FO_DELETE равна, грубо говоря, нажатию delete в explorer'е. так что ни о каком самоу удалении речи идти не может.

    А ещё лучше по байту туда добавлять строки, что бы уж точно варнингов не было, да?
     
    #12 KEZ, 1 Jul 2007
    Last edited: 1 Jul 2007
  13. Ky3bMu4

    Ky3bMu4 Elder - Старейшина

    Joined:
    3 Feb 2007
    Messages:
    487
    Likes Received:
    284
    Reputations:
    42
    Таким образом удалял(и не раз) файлы занятые другими приложениями. Так что не одно и тоже.
     
  14. Pochka

    Pochka Banned

    Joined:
    26 Nov 2005
    Messages:
    27
    Likes Received:
    7
    Reputations:
    -2
    Одно другому не мешает
     
  15. [53x]Shadow

    [53x]Shadow Leaders of Antichat

    Joined:
    25 Jan 2007
    Messages:
    284
    Likes Received:
    597
    Reputations:
    514
    На авторство не претендую, а вот тему для этого и замутил, что бы остальные выкладывали различные методы, плюс различные вариации на др. ЯП.
    ЗЫ
    Может выложишь вариант через COM? Думаю народу интересно будет. ;)
     
  16. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    >>А как ты объяснишь работу Windows, когда в нее подгружено программ больше, чем
    >>это позволяет себе оперативная память?
    ну хорошо, файл подгружается в память не полностью, используя при этом файл подкачки, но сути-то моего сообщения это не меняет - я говорю о том, что после системного вызова, например, CreateProcess исходное приложение никак не относится к соответствующему процессу... врядли ядро ловит все переименования приложения ;)
     
  17. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,119
    Reputations:
    1,139
    Просто пока файл открыт и csrss удерживает его описатель, с ним ниче сделать нельзя. почему можно переименовывать - я сам хз... видно, там не описатель удерживается открытым, а что-то другое, науке не известное. Однако, все же, насколько я помню, так используется File Mapping, поэтому почему можно переименовывать - хз. не разбирался
     
  18. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    забыли упомянуть такой изврат как инжект в чужой процесс функции удаляющей наш файл
     
  19. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    и чем это будет отличаться от удаления через батник\проводник\прямой вызов del?
     
  20. gold-goblin

    gold-goblin Elder - Старейшина

    Joined:
    26 Mar 2007
    Messages:
    917
    Likes Received:
    174
    Reputations:
    3
    Тем то что нас удолит другой процесс и все :)

    Ni0x
    Можно создать батник удоляющий нас и запустить его вот тебе что-то наподобе инжекта. можно использовать к примеру AUTOEXEC.BAT