Как сделать процесс неубиваемым

Обновлено: 06.07.2024

Как в NT системах сделать процесс неубиваемым как например "Бездействие системы" и т.д. код желательно на Delphi

-------
Нет повести печальнее на свете чем повесть о заклинившем реcете.

Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Surround
А можно поподробней(желательно с кодом)
Kuper
Перезапуск не подходит.

2 Surround
Но некоторые процессы пользователя "SYSTEM" можно убить.

-------
Нет повести печальнее на свете чем повесть о заклинившем реcете.

Все просто. Обзываете exeшник чем-то системным (services.exe, svchost.exe и прочее) и Task Manager его уже не берет.
После этого можно отобрать права у пользователя
Написать драйвер/хук, который будет не давать киллить процесс.
И самое страшное: дебаггить процесс так или иначе. Это(дебаг) прокатывает в 99% случаев.

Обзываете exeшник чем-то системным (services.exe, svchost.exe и прочее)
А энтот процесс неубиваем вообще, т.к. является критически важной частью систему.

-------
Нет повести печальнее на свете чем повесть о заклинившем реcете.

Принудительное завершение процесса

Рано или поздно в программистской практике возникает задача по управлению процессами, в частности их принудительного завершения. Для дочерних процессов, порожденных собственным приложением, обычно хватает вызова TerminateProcess, но в некоторых случаях требуется принудительно завершить чужой процесс. Зная идентификатор процесса сделать это не составит большого труда. Открываем процесс функцией OpenProcess с правами PROCESS_TERMINATE, а затем, в случае успеха, отдаем полученный хэндл функции TerminateProcess. Вроде бы все просто, но не тут-то было. При попытке открыть некоторые процессы, как правило системные, возвращается ошибка ERROR_ACCESS_DENIED. Это связано с тем, что дескрипторы безопасности системных процессов блокируют такой доступ для всех пользователей, включая Администраторов. Чтобы обойти запрет, требуется поднять привилегии нашего процесса, а именно получить привилегию отладчика SE_DEBUG_NAME. Как повышать привилегии процесса в системе я уже писал. Напомню только, что необходимые структуры и константы в FASM отсутствуют и их придется определить самостоятельно.

  1. ; Константы для работы привилегиями
  2. TOKEN_ADJUST_PRIVILEGES = 20h
  3. TOKEN_QUERY = 8h
  4. SE_PRIVILEGE_ENABLED = 2h
  5. ; Структуры для работы привилегиями
  6. struct LUID
  7. lowPart dd ?
  8. HighPart dd ?
  9. ends
  10. struct LUID_AND_ATTRIBUTES
  11. pLuid LUID
  12. Attributes dd ?
  13. ends
  14. struct _TOKEN_PRIVILEGES
  15. PrivilegeCount dd ?
  16. Privileges LUID_AND_ATTRIBUTES
  17. ends

Когда данные подготовлены, можно поднять привилегии нашего процесса. Этот код вам уже должен быть знаком и трудностей не вызовет.

  1. invoke GetCurrentProcess
  2. invoke OpenProcessToken , eax , TOKEN_ADJUST_PRIVILEGES + TOKEN_QUERY , TTokenHd
  3. ; Получить привилегии процесса
  4. invoke LookupPrivilegeValue , NULL , SE_DEBUG_NAME , udtLUID
  5. ; Повысить привилегии процесса
  6. mov [ tkp . PrivilegeCount ] , 1
  7. mov [ tkp . Privileges . Attributes ] , SE_PRIVILEGE_ENABLED
  8. moveax , [ udtLUID . lowPart ]
  9. mov [ tkp . Privileges . pLuid . lowPart ] , eax
  10. moveax , [ udtLUID . HighPart ]
  11. mov [ tkp . Privileges . pLuid . HighPart ] , eax
  12. invoke AdjustTokenPrivileges , [ TTokenHd ] , 0 , tkp , 0 , 0 , 0

Все, теперь у нас есть доступ ко всем процессам, включая сервисы и системные приложения. Конечно, есть особые программы типа антивирусов и фаерволов, которые на уровне ядра системы защищаются от манипуляций с их процессами, с ними такой трюк не сработает.

Усложним задачу. Предположим, что нам надо завершать не только произвольный процесс, но также и все процессы, порожденные им и его дочерними процессами. То есть нам надо обработать дерево процессов. Воспользуемся функцией CreateToolhelp32Snapshot для получения списка процессов, а затем переберем их по очереди и завершим все процессы, идентификатор родительского процесса которых равняется идентификатору убиваемого процесса. Но это только первый уровень, значит придется вызывать функцию завершения рекурсивно, указывая в качестве параметра идентификаторы дочерних процессов. Вот что у меня получилось:

Функция универсальная, она позволяет завершать как отдельный процесс, так и дерево процессов. Все "неубиваемые" процессы пропускаются, свой собственный процесс также не завершается, независимо от того, на каком уровне иерархии дерева он находится.

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

критичный процесс Windows

Дело в том, что организовать хорошую защиту процесса от завершения, когда пользователь работает под админом, практически невозможно. Существуют различные способы, но на настоящую защиту они совсем не тянут. Например, можно использовать драйверы режима ядра, но в 64-битных операционных системах не так просто преодолеть механизм Kernel Patch Protection. Остается прибегать к шаманство с бубнами о них мы поговорим далее.

Как создать критичный процесс Windows

Давайте посмотрим, как создать критичный процесс в Windows, как узнать, что процесс является критичным, и как его прибить без ухода системы в BSOD. Строго говоря, создавать мы с вами будем не процесс, а критичный поток. Ведь процесс в Винде — это что-то вроде контейнера для потоков, в которых и выполняется сам код.

Весь код, который я приведу в статье, настоятельно рекомендую выполнять только в виртуальной машине, так как завершение критического процесса вызовет общесистемный сбой и уход системы в синий экран смерти с кодом CRITICAL_PROCESS_DIED и возможной потерей данных. Все эти эксперименты я проводил в виртуалке VirtualBox и в качестве хоста использовать Windows 10 LTSB x64.

RtlSetProcessIsCritical

Первая функция Native API, которая поможет нам пометить процесс как критичный, — это RtlSetProcessIsCritical . Ее прототип выглядит так:

Вызов функции для получения SE_DEBUG_NAME будет таким:

Другой способ получить ее — это нативная функция RtlAdjustPrivilege : нужно передать ей в качестве первого параметра значение 20 ( SE_DEBUG_NAME ). Разумеется, перед вызовом этой функции ее адрес следует получить из ntdll . dll динамически. Вызов будет выглядеть таким образом:

Итак, привилегия получена, приступаем к реализации основной функциональности.

typedef NTSTATUS ( NTAPI * pRtlSetProcessIsCritical ) ( BOOLEAN bNewValue , BOOLEAN * pbOldValue , BOOLEAN CheckFlag ) ;

pRtlSetProcessIsCritical RtlSetProcessIsCritical = ( pRtlSetProcessIsCritical ) GetProcAddress ( LoadLibrary ( ( "ntdll.dll" ) ) , "RtlSetProcessIsCritical" ) ;

Здесь все понятно: функцию RtlSetProcessIsCritical получаем динамической линковкой средствами GetProcAddress / LoadLibrary напрямую из ntdll . dll . Самая интересная строчка кода для нас — это

Здесь мы передаем значение TRUE , указывая функции RtlSetProcessIsCritical сделать процесс критичным. Одновременно мы проверяем возвращаемое ей значение, и в случае удачи наша функция возвращает TRUE . Если вызвать RtlSetProcessIsCritical с параметром FALSE , процесс перестанет быть критичным.

Давайте копнем немного глубже и разберемся, как именно работает функция RtlSetProcessIsCritical . Она вызывает функцию NtSetInformationProcess из Native API, которая обращается к PEB процесса и меняет в нем поле ThreadBreakOnTermination — оно и отвечает за то, чтобы операционная система считала наш процесс критичным.

Блок окружения процесса (Process Environment Block, PEB) заполняется загрузчиком операционной системы, находится в адресном пространстве процесса и может быть модифицирован из режима usermode. Он содержит много полей — например, отсюда можно узнать информацию о текущем модуле, об окружении, о загруженных модулях. Получить структуру PEB можно, обратившись к ней напрямую по адресу fs : [ 30h ] для x86-систем и gs : [ 60h ] для x64.

Таким образом, мы переходим ко второму методу, который продемонстрирует нам создание критичных процессов.

NtSetInformationProcess

NtSetInformationProcess — это нативная функция, которая поможет нам изменить значение поля ThreadBreakOnTermination в PEB на нужное нам. Адрес этой функции необходимо получить динамически из ntdll . dll , как мы уже делали с RtlSetProcessIsCritical . Этот метод универсален, поскольку, используя эту функцию, мы обеспечиваем совместимость с более старыми версиями Windows: RtlSetProcessIsCritical появилась только в Windows 8.

Способ 1. Process Explorer

В случаях, в которых стандартный диспетчер задач не справляется, поможет более продвинутая утилита — Process Explorer. Она распространяется на сайте Microsoft абсолютно бесплатно, хоть и выпущена сторонним разработчиком. При этом программа не требует установки и работает на Windows Vista, 7, 8, 8.1 и 10.

kill-process-windows_1.jpg

После загрузки перед вами предстанет список всех активных процессов, представленный в древовидном виде. По своей сути Process Explorer мало чем отличается от Диспетчера задач, поэтому разобраться с ним не составит труда.

kill-process-windows_2.jpg

kill-process-windows_3.jpg
kill-process-windows_4.jpg

Способ 2. Tasklist

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

kill-process-windows_5.jpg

kill-process-windows_6.jpg

kill-process-windows_7.jpg

Теперь, если всё было сделано правильно, зависший процесс будет закрыт и перестанет загружать процессор.

Как видно из статьи, завершить даже зависший процесс не составит труда и можно сделать даже стандартными способами. Для этого не придется перезагружать компьютер и несохранённые данные не будут потеряны.

А знаете ли вы какие-нибудь ещё способы, кроме упомянутых выше, чтобы закрыть зависшую программу? Поделитесь ими в комментариях или в нашем Telegram-чате.

Niko

Автор Niko

Читайте также: