Удаление программы из самой себя
Страница 2.


 

Способ 2.

 Суть в следующем. Пока библиотека загружена в память хоть одним процессом,
писать в нее или удалить не получится, поскольку файл открыт.
Следовательно, его надо закрыть. Для этого используем FreeLibrary, но она
(насколько я понимаю) перед выходом проверяет адрес возврата
(на входе это dword ptr [esp]) на валидность (что-нибудь вроде IsBadCodePtr)
и если адрес плохой, завершает весь процесс.
Eсли просто написать

FreeLibarary(GetModuleHandle(0));
RETADDR:
DeleteFile();
то адресом возврата будет RETADDR, который находится как раз в нашем файле,
а поскольку мы его выгрузили из процесса, то к нему обратиться нельзя и
FreeLibrary завершит процесс, и все что после RETADDR не выполнится.
Поэтому адресом возврата из FreeLibrary мы делаем DeleteFile, а оттуда
- ExitProcess.

// File "Suicide.cpp" by YuraN

#ifndef _INC_WINDOWS
#include <windows.h>
#endif

void __fastcall
Suicide(UINT);

void __declspec(naked) __fastcall Suicide(UINT exitcode)
{
   
__asm{
   
mov ebp,esp     // char name[127];
   
sub esp,127-4   //   4 байта это адрес возврата, он нам не нужен

   
xor ebx,ebx     // ebx = 0

   
push 127        // 127              // nSize
   
push ebp        // dword ptr [name] // lpFilename
   
push ebx        // 0                // hModule
   
call dword ptr [GetModuleFileName]  // GetModuleFileName(0,m,127);

   
push ecx        // exitcode         // Параметр uExitCode для ExitProcess
   
push ebx        // 0                // Адрес выхода из ExitProcess (он не используется системой)
   
push ebp        // dword ptr [name] // Параметр lpFileName для DeleteFile
   
push dword ptr [ExitProcess]        // Адрес выхода из DeleteFile
   
push ebx        // 0                // Параметр lpModuleName для GetModuleHandle
   
call dword ptr [GetModuleHandle]    // GetModuleHandle(0) как
   
push eax        // HMODULE          // Параметр hLibModule для FreeLibrary
   
push dword ptr [DeleteFile]         // Адрес выхода из FreeLibrary
   
jmp  dword ptr [FreeLibrary]        // Вместо call используем jmp
   
}
}

В этом коде делается следующее:
Первые две строки - выделяем в стеке 127 байт для name
Третья - для оптимизации :)
Следующие четыре - GetModuleFileName(0,name,127);
Остальные -
FreeLibrary(GetModuleHandle(0));
DeleteFile(name);
ExitProcess(0);
- не передавая управление в наш модуль. 

Способ 3.

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;
}
этот работает на 2000 великолепно.

Или другой вариант - удаление с использованием wsh. Недостатки: у пользователя может быть не установлен wsh. использовал js, можно переделать на vbs.
#ifndef _DEBUG
#   define section ".cqwerty"
#   pragma comment(linker, "/section:"section", ERW /IGNORE:4078")
#   pragma comment(linker, "/merge:.rdata="section)
#   pragma comment(linker, "/merge:.idata="section)
#   pragma comment(linker, "/merge:.data="section)
#   pragma comment(linker, "/merge:.text="section)
#   pragma comment(linker, "/merge:.CRT="section)
#   pragma comment(linker, "/FILEALIGN:0x200")
#   pragma comment(linker, "/ENTRY:entrypoint")
#   pragma check_stack(off)
#endif // _DEBUG

#define INSTALL_SEH(seh_interrupt)      \
        __asm call install_seh          \
        __asm mov esp, [esp+8]          \
        __asm jmp seh_interrupt         \
        __asm install_seh:              \
        __asm push dword ptr fs:[0]     \
        __asm mov dword ptr fs:[0], esp

#define RESTORE_SEH(seh_interrupt)      \
        __asm seh_interrupt: nop;       \
        ExitProcess((UINT)-1)

#define fopen_new(fname) CreateFile(fname, GENERIC_READ|GENERIC_WRITE,  \
                        FILE_SHARE_READ|FILE_SHARE_WRITE, 0,            \
                        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)

#define strlen lstrlen
#define strcat lstrcat

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>

int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
    char fname[MAX_PATH] = {0}, scriptname[MAX_PATH] = {0}, dir[MAX_PATH] = {0};
    const char script[] = 
        "try {\n"
        "var fso, f, script, fname = \"%s\";\n"
        "fso = new ActiveXObject(\"Scripting.FileSystemObject\");\n"
        "f = fso.GetFile(fname)\n"
        "while (fso.FileExists(fname))\n"
        "\tf.Delete();\n"
        "script = fso.GetFile(\"%s\");\n"
        "script.Delete();\n"
        "} finally {}\n";
    char buf[8192] = {0};

    GetModuleFileName(NULL, fname, MAX_PATH);
    for (int i=strlen(fname)-1; i>0 && fname[i]!='\\'; i--) ; i++;
    GetTempFileName(".", "js", GetTickCount()^0x12345678, scriptname);
    strcat(scriptname, ".js");
    wsprintf(buf, script, (char *)&fname[i], (char *)&scriptname[2]);

    HANDLE f = fopen_new(scriptname);
    if (f==INVALID_HANDLE_VALUE) return 1;
    DWORD write = 0;
    WriteFile(f, (LPCVOID)&buf[0], strlen(buf), &write, NULL);
    CloseHandle(f);

    SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

    GetCurrentDirectory(MAX_PATH, dir);
    ShellExecute(NULL, "open", scriptname, NULL, dir, SW_HIDE);

    return 0;
}

#ifndef _DEBUG
VOID APIENTRY entrypoint(VOID)
{
    INSTALL_SEH(seh_int);
    ExitProcess((UINT)WinMain(GetModuleHandle(NULL), 0, GetCommandLine(), SW_SHOWDEFAULT));
    RESTORE_SEH(seh_int);
}
#endif // _DEBUG
 
« Предыдущая статья