Страница 2 из 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 | |