Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Удаление исполняемого файла самим приложением


Автор: null56 28.1.2010, 15:28
Всем привет
Возникла задача, чтобы по истечению работы приложения, удалялся бы исполняемый файл самого приложения. Как известно, операционка помечает файлы, которые используются в данный момент и стандартным способом не получится
Код

DeleteFile(argv[0]);

Я порыл в интернете нашел 1,5 способа:
1) создание bat файла в процессе работы программы, который бы в бесконечном цикле пытался удалить нужный файл, а потом закрывался (или сам себя тоже удалял, я так и не понял)
http://sources.ru/cpp/faqs/47.htm

2) Второй способ, который я нашел, связан с использованием функции
Код

MoveFileEx

но я так и не понял, можно ли выполнить с помощью неё задуманное

Вопрос: существует ли способ (алтернативный от создания вспомогательных файлов на жестком диске) удаления, в процессе выполнения, собственного исполняемого файла? если есть, подскажите пожалуйста

Заранее благодарен всем откликнувшимся
ЗЫ: вариант через временные файлы может решить мою проблему?

Автор: GremlinProg 28.1.2010, 15:48
используй MoveFileEx с флагом MOVEFILE_DELAY_UNTIL_REBOOT и путем назначения NULL
Цитата(MoveFileEx Function @  MSDN)

If dwFlags specifies MOVEFILE_DELAY_UNTIL_REBOOT and lpNewFileName is NULL, MoveFileEx registers the lpExistingFileName file to be deleted when the system restarts. If lpExistingFileName refers to a directory, the system removes the directory at restart only if the directory is empty.

это нормальная операция, когда удалить файл больше некому,
не надо мусорить батниками

Автор: null56 28.1.2010, 15:49
Создание нового процесса не решит эту проблему?
1) Создаю новый процесс
2) Тут же завершаю текущий
3) Удаляю из нового процесса файл
... кажется вряд ли (

Добавлено через 46 секунд
GremlinProg, да, я тоже к этому склоняюсь

Автор: null56 28.1.2010, 17:43
Немного не в ту степь....
Раз под вындой нет fork, то реально ли сэмитировать его собственноручно?
В смысле:
1) Создать область памяти
2) Загрузить туда исполняемый код
3) Передать указатель на эту область
4) Завершить первоначальный процесс

или пускай не через память, а через какие - нибудь "временные файлы", которые бы находились на на жестком диске, а в памяти, которые можно было бы заполнить и запустить, а позже они бы почистились?
нет ли ничего подобного в винде?

Автор: GoldFinch 28.1.2010, 18:22
null56, инжектом в другой процесс)

но вообще, наверное можно создать скрипт wsh (.vbs, .js) который сам себя удалит

Добавлено через 3 минуты и 8 секунд
вообще в идее с инжектом чтото есть.
можно взять любой .exe, например notepad.exe, запустить его замороженным (SUSPENEDED) заменить в памяти код на нужный тебе, который в конце делает ExitProcess()

тогда у этой запускаемой программы выполнение не дойдет даже до ее точки входа и загрузки ее длл, фактически от нее будет просто позаимствован файл.

Автор: null56 28.1.2010, 19:05
GoldFinch, а ты реализовывал подмену кода другого процесса? я нет. подсказать можешь куда смотреть?

Автор: GoldFinch 28.1.2010, 21:16
Такая задача  весьма нетривиальная и занимательная.
Здесь есть несколько нюансов - в дочерний процесс надо писать шеллкод, а С++ и шеллкоды - вещи малосовместимые, поэтому шеллкод проще написать на асме, благо он короткий.
Само собой если писать 32-разрядный шеллкод, его надо внедрять в 32-разрядный процесс, для 64-разрядного- 64-разрядный процесс.

Собственно вот код:
Код

#include <Windows.h>

#pragma comment(linker,"/entry:main") // добавлено для более удобной отладки в OllyDbg

static int ReportError( const wchar_t* title )
{    
    const int buf_size = 1024;
    wchar_t errorMsgBuf[buf_size];
    FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM+FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,GetLastError(),NULL,errorMsgBuf,buf_size,NULL );
    MessageBoxW( 0,errorMsgBuf,title,0 );
    return 0;
}

/***********************************************
;исходный текст шеллкода, удаляющего файл родительского процесса
;синтаксис - fasm

macro print_shellcode_dw_patch name {  display "*(DWORD*)(shellcode+", ($-4)/10+'0', ($-4)mod 10+'0', ")=", name, ";",13,10 }

    use32

    ;jmp $ ; debug!!!
    mov eax,eax ; nodebug!!!

    ;получаем базу kernel32
    mov eax, [fs:30h]
    mov eax, [eax+0ch]
    mov eax, [eax+1ch]
    mov eax, [eax+0]
    mov ebx, [eax+08h]

    jmp loo
;---------------------------

back:
    lea eax,[ebx+0xAAAAAAAA]
    print_shellcode_dw_patch "rvaDeleteFileA"
    call eax
    test eax,eax
    jz  loo
    ;вызываем ExitProcess(0)
    push 0
    lea eax,[ebx+0xAAAAAAAA]
    print_shellcode_dw_patch "rvaExitProcess"
    call eax
;--------------------------

loo:
    ;вызываем Sleep(500)
    push 500
    lea eax,[ebx+0xAAAAAAAA]
    print_shellcode_dw_patch "rvaSleep"
    call eax
    ;вызываем DeleteFile("...")
    call back
    ;тут будут байты пути к файлу
    display "GetModuleFileNameA( 0, (char*)shellcode+", $/10+'0', $ mod 10+'0', ", MAX_PATH );",13,10
    ;...........

***********************************************/

unsigned char shellcode[61+MAX_PATH] = {
    0x89, 0xC0, 0x64, 0xA1, 0x30, 0x00, 0x00, 0x00, 0x8B, 0x40, 0x0C, 0x8B, 0x40, 0x1C, 0x8B, 0x00, 
    0x8B, 0x58, 0x08, 0xEB, 0x16, 0x8D, 0x83, 0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0xD0, 0x85, 0xC0, 0x74, 
    0x0A, 0x6A, 0x00, 0x8D, 0x83, 0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0xD0, 0x68, 0xF4, 0x01, 0x00, 0x00, 
    0x8D, 0x83, 0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0xD0, 0xE8, 0xD8, 0xFF, 0xFF, 0xFF
};

int main()
{
    HMODULE localKernel32Base = GetModuleHandleA( "kernel32.dll" );
    DWORD rvaSleep = (DWORD)GetProcAddress( localKernel32Base, "Sleep" ) - (DWORD)localKernel32Base;
    DWORD rvaDeleteFileA = (DWORD)GetProcAddress( localKernel32Base, "DeleteFileA" ) - (DWORD)localKernel32Base;
    DWORD rvaExitProcess = (DWORD)GetProcAddress( localKernel32Base, "ExitProcess" ) - (DWORD)localKernel32Base;
    
    char child_path[MAX_PATH];
    GetSystemDirectoryA( child_path, MAX_PATH );
    strcat_s( child_path, MAX_PATH, "\\notepad.exe" );
    
    PROCESS_INFORMATION processInformation;
    STARTUPINFOA startupInfo = {0};
    if( !CreateProcessA( child_path, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation) )
        return ReportError(L"Ошибка CreateProcessA");

    *(DWORD*)(shellcode+23)=rvaDeleteFileA;
    *(DWORD*)(shellcode+37)=rvaExitProcess;
    *(DWORD*)(shellcode+50)=rvaSleep;
    GetModuleFileNameA( 0, (char*)shellcode+61, MAX_PATH );

    LPVOID injectedBase = VirtualAllocEx(processInformation.hProcess,NULL,sizeof(shellcode),MEM_COMMIT,PAGE_READWRITE);
    if( !injectedBase )
        return ReportError(L"Ошибка VirtualAllocEx");

    if( !WriteProcessMemory(processInformation.hProcess,injectedBase,shellcode,sizeof(shellcode),NULL ) )
        return ReportError(L"Ошибка WriteProcessMemory");

    CONTEXT context;
    context.ContextFlags = CONTEXT_CONTROL;
    if( !GetThreadContext( processInformation.hThread, &context ) )
        return ReportError(L"Ошибка GetThreadContext");

    context.Eip = (DWORD)injectedBase;
    if( !SetThreadContext( processInformation.hThread, &context ) )
        return ReportError(L"Ошибка SetThreadContext");

    ResumeThread( processInformation.hThread );
}

тестировал на 32рязрядной winXP, 
при этом заметил что если запускать калькулятор - шеллкод не срабатывает, и ollydbg почему-то не может приаттачиться к калькулятору (не видит его в списке процессов), а с блокнотом и другими программами все работает.

Автор: GremlinProg 29.1.2010, 06:55
GoldFinch, ты это под каким антивирусом запускал?

Автор: GoldFinch 29.1.2010, 09:10
GremlinProg, nod32

Вобщем-то если процесс создает дочерний процесс, то он имеет право делать с дочерним чтоугодно, так что антивирусы не должны этому мешать. Другое дело инжект уже в работающий процесс.

Автор: GremlinProg 29.1.2010, 09:37
Цитата(GoldFinch @  29.1.2010,  11:10 Найти цитируемый пост)
Вобщем-то если процесс создает дочерний процесс, то он имеет право делать с дочерним чтоугодно, так что антивирусы не должны этому мешать.

гениально!
т.е. ты считаешь, что если ты запускаешь чужой софт из своего,
значит антивирус считает тебя добропорядочным юзером и спокойно смотрит на твои в нем ковыряния?

выбери более правдоподобный ответ
Цитата(GoldFinch @  29.1.2010,  11:10 Найти цитируемый пост)
 nod32

вопрос был риторический, но скорее всего, теперь найдутся те, кто захочет это проверить

null56, если еще не понятно, GoldFinch, тебе предлагает полагаться на то, что пользователь твоего софта ничего не знает об антивирусах (в принципе, большинство советов GoldFinch в этом разделе предполагают именно такой расклад), если это не так - сам делай выводы что использовать разумнее

Автор: GoldFinch 29.1.2010, 11:16
Цитата(GremlinProg @  29.1.2010,  09:37 Найти цитируемый пост)
т.е. ты считаешь, что если ты запускаешь чужой софт из своего,
значит антивирус считает тебя добропорядочным юзером и спокойно смотрит на твои в нем ковыряния?

Есть куча программ которые запускают другие программы, например TotalCommander, если ты не знал, программы можно запускать не только через ярлычок или через эксплорер.
Антивирус (и фаервол) никуда не смотрит и ничего не считает, там есть проактивка которая перехватывает часть функций АПИ ОС, и проверяет опасность тех или иных действий. Например фаерфол может запрещать инжект в процесс который добавлен в настройки фаервола как приложение которому разрешено работать с сетью. Но он не будет запрещать любой инжект как таковой, т.к. это вполне легальное действие.

"антивирус считает тебя добропорядочным юзером и спокойно смотрит на твои в нем ковыряния"
при чем тут юзер? в чем ковыряния? в антивирусе? пиши грамотно, по русски, а то я ничего не понимаю.

Автор: GremlinProg 29.1.2010, 11:39
Цитата(GoldFinch @  29.1.2010,  13:16 Найти цитируемый пост)
Есть куча программ которые запускают другие программы, например TotalCommander, если ты не знал, программы можно запускать не только через ярлычок или через эксплорер.

не надо путать редьку с хреном
Цитата(GoldFinch @  29.1.2010,  13:16 Найти цитируемый пост)
Антивирус (и фаервол) никуда не смотрит и ничего не считает, там есть проактивка которая перехватывает часть функций АПИ ОС, и проверяет опасность тех или иных действий

smile надо же, а я думал антивирусы обычно орехи колят
Цитата(GoldFinch @  29.1.2010,  13:16 Найти цитируемый пост)
Но он не будет запрещать любой инжект как таковой, т.к. это вполне легальное действие

на счет его легальности мы уже давно все выяснили, "НЕ ЛЕГАЛЬНО", безтолку не спорь, все доказано документально

а вот на счет "не будет запрещать любой инжект",
ну давай, пускай на тройке более-менее популярных антивирусов свой инжект в калькулятор, нодпад и т.п. софт ))
кто первый пропустит?

только вот если хоть один не пропустит, любой дальнейший выпад на эту тему будешь обсуждать с остальными,
кто не осилил почитать учебник по информатике

Автор: GoldFinch 29.1.2010, 11:54
Цитата(GremlinProg @  29.1.2010,  11:39 Найти цитируемый пост)
"НЕ ЛЕГАЛЬНО", безтолку не спорь, все доказано документально

пруфлинк давай
Цитата(GremlinProg @  29.1.2010,  11:39 Найти цитируемый пост)
ну давай, пускай на тройке более-менее популярных антивирусов свой инжект в калькулятор, нодпад и т.п. софт ))
кто первый пропустит?

тебе охота проверить - вот и займись.

Автор: null56 29.1.2010, 11:56
не ссортесь, ребята...
на счет легитимности способа GoldFinch я сам особо не уверен надо проверять на различных антивирях и смотреть как они себя ведут.
По своей сути я попросил GoldFinch показать мне метод инжекции, как его можно реализовать в винде, с другой стороны стоит палево со стороны антивирусов... сейчас стоит задача найти компромисс методами проверок...
спасибо вам обоим за участие

Автор: GremlinProg 29.1.2010, 11:57
Цитата(GoldFinch @  29.1.2010,  13:54 Найти цитируемый пост)
пруфлинк давай

http://forum.vingrad.ru/forum/topic-269823/kw-non-dll-inject/view-all.html

Автор: xvr 29.1.2010, 12:58
Вариант с батником намного проще и безопаснее. Надо только не забыть из батника стереть его самого (после exe'ника). Для батников такой фокус проходит  smile 

Вариант с MOVEFILE_DELAY_UNTIL_REBOOT оставит болтаться exe'ник в системе до ближайшего reboot'а, а он может случиться нескоро  smile 

Автор: GremlinProg 29.1.2010, 13:08
реально проходит!
к примеру, для C:\a.bat, последняя команда должна быть del C:\a.bat

Автор: null56 29.1.2010, 14:56
знаю, что проходит... просто искал альтернативные решения

Автор: bra1ny 29.1.2010, 17:39
GremlinProg
Абсолютно прав ,  на нормальнйо системе вам даже этого запустить не дадут. Взял пример с инжектом из этого топика , собрал , результат не заставил себя долго ждать 
user posted image

Никто не даст вам писать в ап процесса и "мутить с потоком" , хотя бы потому что хукаются NtWriteVirtualMemory и NtSetContnextThread.

Автор: cvid 6.3.2010, 18:43
А никому в голову не пришло использовать для удаления cmd? Просто делаем ShellExecute и удаляем командой "del" собственный файл. Вот готовый код:
Код

bool SelfDelete()
{
 TCHAR szFile[MAX_PATH], szCmd[MAX_PATH];
    
 if((GetModuleFileName(0,szFile,MAX_PATH)!=0) &&

 (GetShortPathName(szFile,szFile,MAX_PATH)!=0))

 {

 wcscpy(szCmd,L"/c del ");

 wcscat(szCmd,szFile);

 wcscat(szCmd,L" >> NUL");

 if((GetEnvironmentVariable(L"ComSpec",szFile,MAX_PATH)!=0) &&

 ((INT)ShellExecute(0,0,szFile,szCmd,0,SW_HIDE)>32))

 return TRUE;

 }
 return FALSE;
}


Проверенно собственноручно уже много раз.


P.S: данный способ  абсолютно легален и антивири на него не ругаются)))

Автор: xvr 6.3.2010, 19:02
Цитата(cvid @ 6.3.2010,  18:43)
А никому в голову не пришло использовать для удаления cmd? Просто делаем ShellExecute и удаляем командой "del" собственный файл. 

Приходило, о чем и было написанно несколько постов назад  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)