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

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

Не для кого не секрет, что часть процессов операционной системы Windows считаются «критичными» — если завершить один из них, операционная система может выпасть в синий экран смерти и уйти в перезагрузку. Этим свойством операционной системы частенько пользуются вирусописатели: если сделать свой процесс критичным, то его не получиться завершить просто так. В сегодняшней статье я расскажу, как создавать такие неубиваемые процессы и как их правильно в случае необходимости прибивать, причем без падения Windows.

Рекомендуем:

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

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

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

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

Существует несколько способов, которые помогут нам создать критичный процесс. Все методы основаны на манипуляции вызовами NTAPI (Native Windows API), самыми «низкоуровневыми», которые можно выполнить в режиме пользователя. Эти функции экспортируются ntoskrnl.exe. Через обертку ntdll.dll мы сможем получить их адреса и вызвать их.

RtlSetProcessIsCritical

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

Чтобы эта функция сработала, перед ее вызовом нужно будет получить привилегию SeDebugPrivilege. Это можно сделать через «обычные» функции WinAPI.

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

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

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

Здесь все понятно: функцию 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.

Реализация будет выглядеть следующим образом.

В функцию NtSetInformationProcess передаем хендл процесса, который будем делать критичным, и число 0x1D, которое означает ThreadBreakOnTermination в структуре PROCESSINFOCLASS.

Проверка критичности процесса

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

Здесь в функцию NtQueryInformationProcess передается хендл интересующего нас процесса и поле в структуре PROCESSINFOCLASS, которое нужно проверить. После выполнения функции NtQueryInformationProcess проверяем переменную count, которая станет равна единице, если процесс критичный.

Кроме функции NtQueryInformationProcess, есть специальная функция, предназначенная именно для наших нужд, — IsProcessCritical. Ее прототип выглядит таким образом.

Пример использования этой функции:

Функция IsProcessCritical изменит переменную test на TRUE, если процесс критичный, или оставит FALSE в том случае, если это не так.

Выводы

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

Понравилась статья? Поделиться с друзьями:
Комментариев: 2
  1. Катя

    Нечего не поняла ))

    1. Techgeek

      Это больше для программистов ;)

Добавить комментарий