![]() |
Добро пожаловать, гость ( Вход | Регистрация )
![]() |
-=CHE@TER=- |
![]()
Сообщение
#1
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,371 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 318 раз(а) ![]() |
Вот, есть такая статья: Self-Deleting Executables.
Она рассказывает о нелёгких поисках способа удалить программно .EXE файл изнутри. Т.е. написать такую программу, которая сможет себя удалить, когда вы её запустите. Как известно в DOS такой проблемы не существует и я, в своё время, делал Uninstall'ер для своей программы, который удалял всё, включая и себя самого, ибо после запуска .EXE файл уже был не нужен. В Windows .EXE файл недоступен (занят системой) до тех пор, пока запущенная программа не прекратила работать, в частности удалить его тоже нельзя. Из данной статьи я взял универсальный способ-пример, довольно оригинального решения, файл "selfdel05.c" и попытался переписать его на Delphi (оригинал можно взять по ссылке выше - см. Download source). CODE // // selfdel.c // // Self deleting executable for Win9x/WinNT (all versions) // // J Brown 1/10/2003 // // This source file must be compiled with /GZ turned OFF // (basically, disable run-time stack checks) // // Under debug build this is always on (MSVC6) // // Uses Windows; // #pragma pack(push, 1) // #define Const CODESIZE = $200; // // Structure to inject into remote process. Contains // function pointers and code to execute. // Type PSELFDEL = ^TSELFDEL; TSELFDEL = Packed Record ARG0: PSELFDEL; // pointer to self opCodes: Array[0..CODESIZE-1] Of Byte; // code hParent: THandle; // parent process handle fnWaitForSingleObject: Function(hHandle: THandle; dwMilliseconds: DWORD): DWORD; stdcall; fnCloseHandle: Function(hObject: THandle): BOOL; stdcall; fnDeleteFile: Function(lpFileName: PChar): BOOL; stdcall; fnSleep: Procedure(dwMilliseconds: DWORD); stdcall; fnExitProcess: Procedure(uExitCode: UINT); stdcall; fnRemoveDirectory: Function(lpPathName: PChar): BOOL; stdcall; fnGetLastError: Function: DWORD; stdcall; fRemDir: LongBool; szFileName: Array[0..MAX_PATH-1] Of Char; // file to delete End; //#pragma pack(pop) {$ifdef _DEBUG} //{$define FUNC_ADDR(func) (PVOID)(*(DWORD *)((BYTE *)func + 1) + (DWORD)((BYTE *)func + 5))} {$else} //{$define FUNC_ADDR(func) func} {$endif} // // Routine to execute in remote process. // procedure remote_thread(remote: PSELFDEL); stdcall; Begin // wait for parent process to terminate remote^.fnWaitForSingleObject(remote^.hParent, INFINITE); remote^.fnCloseHandle(remote^.hParent); // try to delete the executable file while (not remote^.fnDeleteFile(remote^.szFileName)) Do Begin // failed - try again in one second's time remote^.fnSleep(1000); End; // finished! exit so that we don't execute garbage code remote^.fnExitProcess(0); End; // // Delete currently running executable and exit // Function SelfDelete(fRemoveDirectory: LongBool): Boolean; Var si: STARTUPINFO; pi: PROCESS_INFORMATION; context: TContext; oldProt: DWORD; local: TSELFDEL; entrypoint: DWORD; szExe: Array[0..MAX_PATH-1] Of Char; remdel: Pointer; dummy: dword; Begin result:=FALSE; szExe:='explorer.exe'#0; // // Create executable suspended // ZeroMemory(@si, SizeOf(si)); si.cb:=SizeOf(si); if CreateProcess(Nil, szExe, Nil, Nil, False, CREATE_SUSPENDED Or IDLE_PRIORITY_CLASS, Nil, Nil, si, pi) Then Begin local.fnWaitForSingleObject := @WaitForSingleObject; local.fnCloseHandle := @CloseHandle; local.fnDeleteFile := @DeleteFile; local.fnSleep := @Sleep; local.fnExitProcess := @ExitProcess; local.fnRemoveDirectory := @RemoveDirectory; local.fnGetLastError := @GetLastError; local.fRemDir := fRemoveDirectory; // Give remote process a copy of our own process handle DuplicateHandle(GetCurrentProcess, GetCurrentProcess, pi.hProcess, @local.hParent, 0, FALSE, 0); GetModuleFileName(0, local.szFileName, MAX_PATH); // copy in binary code remdel:=@remote_thread; move(remdel, local.opCodes, CODESIZE); //move(local.opCodes, @remdel, CODESIZE); {!} // // Allocate some space on process's stack and place // our SELFDEL structure there. Then set the instruction pointer // to this location and let the process resume // context.ContextFlags := CONTEXT_INTEGER Or CONTEXT_CONTROL; GetThreadContext(pi.hThread, context); // Allocate space on stack (aligned to cache-line boundary) entrypoint := (context.Esp - sizeof(TSELFDEL)) And Cardinal(Not $1F); // // Place a pointer to the structure at the bottom-of-stack // this pointer is located in such a way that it becomes // the remote_thread's first argument!! // local.Arg0:=Ptr(entrypoint); // local.Arg0 := TSELFDEL(entrypoint); context.Esp := entrypoint - 4; // create dummy return address context.Eip := entrypoint + 4; // offset of opCodes within structure // copy in our code+data at the exe's entry-point VirtualProtectEx(pi.hProcess, Ptr(entrypoint), sizeof(local), PAGE_EXECUTE_READWRITE, Ptr(oldProt)); WriteProcessMemory(pi.hProcess, Ptr(entrypoint), Pointer(@local), sizeof(local), dummy); FlushInstructionCache(pi.hProcess, Ptr(entrypoint), sizeof(local)); SetThreadContext(pi.hThread, context); // Let the process continue ResumeThread(pi.hThread); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); result:=TRUE; End; End; Begin SelfDelete(False); End. Однако, где-то я чего-то упустил, ибо программа запускается, но ничего не делает. Кто-нибудь может помочь? |
![]() ![]() |
Axsis |
![]()
Сообщение
#2
|
Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 121 Регистрация: 6-February 08 Пользователь №: 374 Спасибо сказали: 149 раз(а) ![]() |
QUOTE Ого! Моё почтение! Ты, наверное, тестированием антивирусных систем занимаешься? (*улыбается*) Спасибо тебе большое за отчёт! На самом деле были у меня подозрения, но ты их развеял. (*улыбается*) Спасибо! И правда, антивирусов, которые считают программу трояном - мало. И к тому же они все (ИМХО) аутсайдеры - т.е. их мало кто использует. Хех, конечно я не вручную его проверял, есть такой замечательный сайтик http://www.virustotal.com/ на котором можно через форму загрузить свой файл и он проверится всеми этими антивирусами, всё это разумеется халявное, но вот в зависимости от загруженности сервера придётся подождать от 1 до 30 минут в очереди (+ 1-2 минуты на проверку) Поэтому когда нужно что-либо быстро проверить обхожусь онлайн-сканером каспера - http://www.kaspersky.ru/scanforvirus/ . Я думал ты слышал о вирустотал'е ![]() QUOTE QUOTE Дома ещё с аутпостом проверю, глянем на его реакцию. Ещё бы с KIS проверить, тока нету его у меня Я даже слов таких не знаю. (*улыбается*) А KIS - это что? Аутпост - это Agnitum Outpost Firewall - фаервол, как и следует из названия ![]() KIS - это Kaspersky Internet Security, в который входят Kasp. AntiVirus и Kasp. AntiHacker (последнее - тоже фаервол ![]() Так вот у обеих прог с некоторых пор есть проактивная защита, которая отслеживает всякие действия, которые в основном используются вредоносным ПО, такие как внедрение в адресное пространство другого процеса, установка перехватчиков нажатий клавиш, модификация критических ключей реестра и т.д. Результатом работы этой защиты у аутпоста является вот такое окошко (как я и предполагал) : ![]() Если нажать "Allow Once" то файл удаляется, а если "Block Once" то память не модифицируется и просто запускается проводник, то есть оригинальный explorer.exe ![]() Даю 99% что КИС отреагирует точно так. QUOTE Понимаешь, с ключом-параметром, ты даёшь (теоретически) возможность пользователю самому этот ключ использовать. Он может например даже другим пользователям какую-нибудь гадость сделать. Помню ты упоминал что работал бета-тестером ![]() - запускаем оригинал prog.exe (или prog.tmp) - prog.exe (prog.tmp) проверяет своё расширение если exe: - проверка и загрузка обновления в prog.tmp, если обновления нет - продолжаем нормально работать - prog.exe запускает prog.tmp а сам завершается иначе: - ждём завершения prog.exe и переименовываем себя (prog.tmp) в prog.exe надеюсь ты поймёшь что я имел ввиду ![]() ![]() вариантов решения для конкретно этого случая (когда надо не удалить а обновить) много и ИМХО код без внедрения будет безопаснее, ведь в твоём случае, код, записываемый в explorer, "злодеи" тоже могут подправить ![]() ![]() |
-=CHE@TER=- |
![]()
Сообщение
#3
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,371 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 318 раз(а) ![]() |
Хех, конечно я не вручную его проверял, есть такой замечательный сайтик http://www.virustotal.com/ на котором можно через форму загрузить свой файл и он проверится всеми этими антивирусами, всё это разумеется халявное, но вот в зависимости от загруженности сервера придётся подождать от 1 до 30 минут в очереди (+ 1-2 минуты на проверку) Поэтому когда нужно что-либо быстро проверить обхожусь онлайн-сканером каспера - http://www.kaspersky.ru/scanforvirus/ . Я думал ты слышал о вирустотал'е Теперь - слышал. Ещё раз спасибо! (*улыбается*)![]() KIS - это Kaspersky Internet Security, в который входят Kasp. AntiVirus и Kasp. AntiHacker (последнее - тоже фаервол Аутпост-то я знаю. KIS первый раз слышу. Хотя предпологал, что "K" - от кашпировского.![]() Результатом работы этой защиты у аутпоста является вот такое окошко (как я и предполагал) : А-а-а! Засада. (*улыбается*) Заблочили...Если нажать "Allow Once" то файл удаляется, а если "Block Once" то память не модифицируется и просто запускается проводник, то есть оригинальный explorer.exe ![]() Даю 99% что КИС отреагирует точно так. Помню ты упоминал что работал бета-тестером (*слава богу я там больше не работаю*)![]() - ждём завершения prog.exe и переименовываем себя (prog.tmp) в prog.exe У меня было сильно сомнение, но я всё-таки переборол свою лень и проверил твоё предложение из предыдущего поста - действительно, оказывается, во время работы .EXE файл можно переименовывать. Кхех - весело. (*улыбается*) Думаю, что это решает тогда все мои проблемы без внедрения кода. Спасибо за дельный совет (хотя какая идея и реализация были красивые... (*улыбается*))! |
![]() ![]() |
Упрощённая версия | Сейчас: 30th April 2025 - 20:45 |