Часто задаваемые вопросы и ответы по C/C++/Visual C++
Последнее обновление: 27.08.2003
FAQ по C/C++/Visual C++
Работа с сетью
Как создать ярлык
Вариант Yura Nev
Составители: SUnteXx, Leprecon
Как удалить прогу из самой себя
A: (Yura Nev)
Оригинальная ссылка: нету

Суть в следующем. Пока библиотека загружена в память хоть одним процессом,
писать в нее или удалить не получится, поскольку файл открыт.
Следовательно, его надо закрыть. Для этого используем 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);
- не передавая управление в наш модуль.
Содержание Обсудить на форуме « Предыдущая статья | Следующая статья »
Перейти к FAQ:  
FAQ составлен по материалам Форума на Исходниках.Ру.
Copyright © 2002 by Sources.ru. All rights reserved.