· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.WIN32 —› Как противостоять TerminateProcess

. 1 . 2 . 3 . 4 . >>

Посл.отвђт Сообщенiе


Дата: Апр 22, 2004 17:58:42

Допустим я запустил под отладкой некий процесс, который этого не хотел и
зная имя моей программы нашёл её в списке процессов и собирается убить,
вызвав TerminateProcess, ну моя программа предвидя сей поворот событий
захучила этот самый TerminateProcess, вопрос следующий, могу ли я по хэндлу,
передаваемому этой функции, определить точно мою ли программу сейчас
собираются прибить, или мне придётся ещё висеть на OpenProcess и следить за PID
и вытаскивать хэндл при нужном PID отсюда?

Только к Рихтеру пожалуйста не посылать :-)


Дата: Апр 22, 2004 18:37:14

А к MSDN? :) Шутка :)
А откуда ты свой хендл сам-то знаешь?
  Proc_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcInfo.dwProcessId);
  if(!TerminateProcess(Proc_handle, -1))
  {
    printf("  *** ERROR - Error in killing process");
    return;
  }



Дата: Апр 22, 2004 18:57:25

А чавой-то за код? :-)

Ну я так и думаю, PID я свой знаю, сажусь на OpenProcess и вытаскиваю хэндл, потом при срабатывании хука на TerminateProcess вытаскиваю хэндл и сравниваю со своим, при совпадении решаю как поступить иначе возвращаю управление.
Просто думалось может проще можно как-нить..


Дата: Апр 22, 2004 19:00:44

А проще - не по дзенски :)
А код я просто так привел - сам себя убеждал что хендл один и тот же :)


Дата: Апр 22, 2004 19:11:24

А убрать PROCESS_TERMINATE из своего SecurityDescriptor?


Дата: Апр 22, 2004 20:00:09

Ааа, я подумал, нафига мне ещё сидеть на TerminateProcess, я просто не дам ему открыть мой процесс, ну типа подменю PID в OpenProcess на нулевой и передам функции, пусть открывает :-)

hGoblin

Подробней, чего то не понял.. Есть рабочий пример?


Дата: Апр 22, 2004 20:02:34

Asterix

Ну, лентяй! MSDN читай! Черным по белому тебе написано:

The handle must have the PROCESS_TERMINATE access right. For more information, see Process Security and Access Rights.


Вот тебе и предлагают - убери из процесса эти права! Вот так:

To retrieve a process's security descriptor, call the GetSecurityInfo function. To change a process's security descriptor, call the SetSecurityInfo function.


Путем манипуляций с битиками сними флажок PROCESS_TERMINATE и усе :)


Дата: Апр 22, 2004 21:02:35

volodya

Ты хочешь сказать что после этого процесс будет не убиваем?
А после этого хотя бы ExitProcess работать будет?? а то так можно ведь и самому не выйти :-)


Дата: Апр 22, 2004 21:04:03

Вход - рупь, выход - два :)
MSDN читай :)


Дата: Апр 22, 2004 21:20:11

Ох, в этих функциях столько параметров что без стакана не раберёшься как их применять :-(


Дата: Апр 22, 2004 21:28:58

Твой вопрос уже задавали в сети:

How can I make a process immortal, meaning that it can not be killed by TerminateProcess function. Thanks in advance for your help! 500 point is award!

1. Make it a service under the system context without the SERVICE_STOP attribute.

2. Since TreminateProcess() does not kill child processes, create a child process that monitors the parent and starts another one if it detects the parents demise. At the same time, the parent monitors the child and spawns another should the child be killed first. Do everything just so and you can probably lock your box up real good.

But a service without SERVICE_STOP is the proper way.


3. I didn't mention security attributes for the create, since an admin would have rights to kill it.

3-й вариант - это то, что тебе предложил hGoblin.

Дополнительно см. тут:
http://www.microsoft.com/msj/0899/security/security0899.aspx

Вот код на С++. Где неясно - спрашивай, вместе переведем на ассемблер.
# #define UNICODE
 #define _WIN32_WINNT 0x400
 #include <windows.h>
 #include <stdio.h>
 #include <aclapi.h>
 
 void Quit( const wchar_t* pszMsg, int nExitCode = 1 )
 {
     wprintf( L"%s\n", pszMsg );
     exit( nExitCode );
 }
 
 // brain-dead error routine that dumps the last error and exits
 void Err( const wchar_t* pszFcn, DWORD nErr = GetLastError() )
 {
     wchar_t szErr[256];
     wchar_t szMsg[512];
     if ( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, nErr, 0,
                         szErr, sizeof szErr / sizeof *szErr, 0 ) )
          swprintf( szMsg, L"%s failed: %s", pszFcn, szErr );
     else swprintf( szMsg, L"%s failed: 0x%08X", nErr );
     Quit( szMsg );
 }
 
 // This helper function simply grants PROCESS_TERMINATE to the WORLD sid
 // for simplicity - you can get more sophisticated if you like, but the
 // point of this app is to *kill* a process, so we ultimately won't care
 // what the DACL looks like, as long as it allows us to terminate it.
 void AdjustDacl( HANDLE h )
 {
     wprintf( L"Attempting to adjust process DACL..." );
 
     // the WORLD Sid is trivial to form programmatically (S-1-1-0)
     SID world = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, 0 };
 
     EXPLICIT_ACCESS ea =
     {
         PROCESS_TERMINATE,
         SET_ACCESS,
         NO_INHERITANCE,
         {
             0, NO_MULTIPLE_TRUSTEE,
             TRUSTEE_IS_SID,
             TRUSTEE_IS_USER,
             reinterpret_cast<wchar_t*>( &world )
         }
     };
     ACL* pdacl = 0;
     DWORD err = SetEntriesInAcl( 1, &ea, 0, &pdacl );
     if ( err )
         Err( L"SetEntriesInAcl", err );
 
     err = SetSecurityInfo( h, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
                            0, 0, pdacl, 0 );
     if ( err )
         Err( L"SetSecurityInfo", err );
 
     LocalFree( pdacl );
 }
 
 // Useful helper function for enabling a single privilege
 bool EnablePrivilege( HANDLE htok, const wchar_t* pszPriv,
                       TOKEN_PRIVILEGES& tpOld )
 {
     TOKEN_PRIVILEGES tp;
     tp.PrivilegeCount = 1;
     tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
     if ( !LookupPrivilegeValue( 0, pszPriv, &tp.Privileges[0].Luid ) )
         Err( L"LookupPrivilegeValue" );
 
     // htok must have been opened with the following permissions:
     // TOKEN_QUERY (to get the old priv setting)
     // TOKEN_ADJUST_PRIVILEGES (to adjust the priv)
     DWORD cbOld = sizeof tpOld;
     if ( !AdjustTokenPrivileges( htok, FALSE, &tp, cbOld, &tpOld, &cbOld ) )
         Err( L"AdjustTokenPrivileges" );
 
     // Note that AdjustTokenPrivileges may succeed, and yet
     // some privileges weren't actually adjusted.
     // You've got to check GetLastError() to be sure!
     return ( ERROR_NOT_ALL_ASSIGNED != GetLastError() );
 }
 
 // Corresponding restoration helper function
 void RestorePrivilege( HANDLE htok, const TOKEN_PRIVILEGES& tpOld )
 {
     if ( !AdjustTokenPrivileges( htok, FALSE,
                                  const_cast<TOKEN_PRIVILEGES*>(&tpOld),
                                  0, 0, 0 ) )
         Err( L"AdjustTokenPrivileges" );
 }
 
 void wmain( int argc, wchar_t* argv[] )
 {
     if ( 2 != argc )
         Quit( L"Usage: kill2 pid" );
 
     int pid = _wtoi(argv[1]);
     if ( !pid )
         Quit( L"Usage: kill2 pid" );
 
     // who knows, it might be really easy...
     HANDLE hp = OpenProcess( PROCESS_TERMINATE, FALSE, pid );
     if ( !hp )
     {
         // oh well, we need to grant ourselves PROCESS_TERMINATE
         HANDLE hpWriteDAC = OpenProcess( WRITE_DAC, FALSE, pid );
         if ( !hpWriteDAC )
         {
             // hmm, we don't have permissions to modify the DACL...
             // time to take ownership...
             HANDLE htok;
             if ( !OpenProcessToken( GetCurrentProcess(),
                 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &htok ) )
                 Err( L"OpenProcessToken" );
 
             TOKEN_PRIVILEGES tpOld;
             if ( !EnablePrivilege( htok, SE_TAKE_OWNERSHIP_NAME, tpOld ) )
                 Err( L"You don't posess SeTakeOwnershipPrivilege." );
 
             // SeTakeOwnershipPrivilege allows us to open objects with
             // WRITE_OWNER, but that's about it, so we'll update the owner,
             // and dupe the handle so we can get WRITE_DAC permissions.
             HANDLE hpWriteOwner = OpenProcess( WRITE_OWNER, FALSE, pid );
             if ( !hpWriteOwner )
                 Err( L"OpenProcess" );
 
             BYTE buf[512]; // this should always be big enough
             DWORD cb = sizeof buf;
             if ( !GetTokenInformation( htok, TokenUser, buf, cb, &cb ) )
                 Err( L"GetTokenInformation" );
 
             DWORD err = SetSecurityInfo( hpWriteOwner, SE_KERNEL_OBJECT,
                             OWNER_SECURITY_INFORMATION,
                             reinterpret_cast<TOKEN_USER*>(buf)->User.Sid,
                             0, 0, 0 );
             if ( err )
                 Err( L"SetSecurityInfo", err );
 
             // now that we're the owner, we've implicitly got WRITE_DAC
             // permissions, so ask the system to reevaluate our request,
             // giving us a handle with WRITE_DAC permissions
             if ( !DuplicateHandle( GetCurrentProcess(), hpWriteOwner,
                                    GetCurrentProcess(), &hpWriteDAC,
                                    WRITE_DAC, FALSE, 0 ) )
                 Err( L"DuplicateHandle" );
 
             // not truly necessary in this app,
             // but included for completeness
             RestorePrivilege( htok, tpOld );
         }
         if ( hpWriteDAC )
         {
             // we've now got a handle that allows us WRITE_DAC permission
             AdjustDacl( hpWriteDAC );
 
             // now that we've granted ourselves permission to terminate
             // the process, ask the system to reevaluate our request,
             // giving us a handle with PROCESS_TERMINATE permissions
             if ( !DuplicateHandle( GetCurrentProcess(), hpWriteDAC,
                                    GetCurrentProcess(), &hp,
                                    PROCESS_TERMINATE, FALSE, 0 ) )
                 Err( L"DuplicateHandle" );
             CloseHandle( hpWriteDAC );
         }
     }
     if ( hp )
     {
         // if all went well, we've now got a handle to the process
         // that grants us PROCESS_TERMINATE permissions
         if ( !TerminateProcess( hp, 1 ) )
             Err( L"TerminateProcess" );
     }
     wprintf( L"Success!" );
}



Дата: Апр 22, 2004 22:21:42

volodya
Я бы сказал что для меня здесь всё непонятно, кроме вызовов API ;-)
Что делает этот код, пытается убить не убиваемый процесс и для этого
оперирует с атрибутами?

ЗЫ: поисковик по теме нашёл(на русском) единственную ссылку по теме
http://www.danil.com.ua/mswin3.htm даже с исходниками на masm32


Дата: Апр 22, 2004 22:28:11

Тебя интересует функция AdjustDacl. Смысл состоит в постановке атрибута PROCESS_TERMINATE. Да, пытаемся прибить процесс. Если OpenProcess проваливается, начинаем делать себе привилегии. Показана работа с SetEntriesInAcl - мы формируем структуру, потом с помощью SetSecurityInfo мы запихиваем ее в этот процесс и смотрим, что из этого получится. Хочешь, могу откомпилить и бросить тебе ассемблерный листинг нужных функций.


Дата: Апр 22, 2004 23:55:15

[ volodya: Хочешь, могу откомпилить и бросить тебе ассемблерный листинг нужных функций.]

Не уверен что это много мне даст..

Вообще, это всё я спрашиваю для использования в плагине для Olly, что-то в последнее время некоторые злобные протекторы начали прибивать Олю наглым способом, например ACProtect.

И вообще предложенный способ мне даже очень нравится, т.к. в принципе прост, и т.к. я не верю что какой-нить протектор будет вот так мудрить с атрибутами пытаясь прибить Olly, то этот метод был бы вполне приемлемым, по крайней мере на первых порах..


Дата: Апр 23, 2004 11:14:51 · Поправил: RobinFood

[оффтоп]
А если пойти дальше в сторону ACL, то можно еще изменить SACL, и получать уведомления о попытках доступа к твоему объекту...

Вот только я в эту сторону еще не ходил :) По идее, уведомления будут приходить не тебе, а "сыпаться" в EventViewer.
[/оффтоп]

А ты уверен, что он пытается убить отладчик с помощью TerminateProcess? Вариантов куча - начиная от
CreateRemoteThread->ExitProcess, продолжая
SetWindowsHookEx->ExitProcess, и заканчивая
DebugActiveProcess->DebugSetProcessKillOnExit, не говоря уже о всяких
SuspendThread/WriteProcessMemory/SetThreadContext...

. 1 . 2 . 3 . 4 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.091