Оглавление



Введение

Команда Solar 4RAYS изучила множество материалов, посвященных DFIR в операционных системах Windows, и мы заметили, что сообщество информационной безопасности игнорирует важное изменение в работе планировщика задач, которому уже исполнилось 12 лет. Об обнаруженных нами проблемах писали в том или ином виде, но данная информация не освещается широко и разбросана по разным статьям без общего вывода о критичности. А проблемы связаны с тем, что при анализе систем начиная с Windows 8 вы можете не видеть часть задач, которые выполняет планировщик.

Представьте, что вы являетесь начинающим специалистом-форензиком и вам требуется изучить «Windows Persistence». Что вы будете читать? Чем пользоваться? Курсы или книги могут отличаться, однако с высокой вероятностью вы все равно столкнетесь с проблемой, когда ваше обучение дойдет до «Scheduled Task/Job T1053.005».

Для начала давайте ответим на вопрос:

Вам предоставили на анализ систему Windows 10, где атакующие точно закрепились с использованием планировщика задач, и система даже включена! Увы, все журналы были очищены. Где вы будете искать командлайн вредоносной задачи?

Ответ:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache
Так как иные артефакты могут содержать недействительные данные о задачах, а некоторые задачи могут быть скрыты из вывода популярных утилит и WinAPI, но продолжать работать

Если на данный вопрос вы ответили иначе, то добро пожаловать! Мы собрали в одном месте всё, что вы могли не знать о планировщике задач в Windows.



Существенные изменения планировщика задач в Windows 8

В Windows 8 были внесены существенные изменения в расположение хранилища задач: хоть xml-файлы и продолжают создаваться по пути «C:\Windows\System32\Tasks», на самом деле планировщик задач загружает данные из реестра, а именно – из ключа TaskCache, который появился еще во времена Windows 7:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache

В ключе TaskCache имеется несколько разделов, и в актуальных версиях Windows образует следующую структуру:

Актуальная структура TaskCache в Windows 10-11
Актуальная структура TaskCache в Windows 10-11

В младших версиях Windows некоторые значения отсутствуют, однако сама структура не изменяется.

Далее остановимся на разделах и значениях, интересных с точки зрения DFIR:

Раздел\Значение

Описание

TaskCache\Tree

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

TaskCache\Tree\TaskPath\Task\Index

Тип триггера задачи.

Имеет значение от 1 до 4:

1 – Boot

2 – Logon

3 – Plain

4 – Maintenance
Значение обладает недокументированной фичей, которая будет описана далее

TaskCache\Tree\TaskPath\Task\Id

UUID задачи

TaskCache\Tree\SD

TaskCache\Tree\TaskPath\SD

TaskCache\Tree\TaskPath\Task\SD

Security Descriptor, описывающий права доступа на просмотр данной задачи или дерева. Не связан с правами на выполнение. Имеется у всех разделов TaskCache\Tree

*появился лишь в Windows 10

TaskCache\Tasks

Используется системой для хранения данных о задачах, включая командлайн. Содержит разделы, имена которых соответствуют UUID задач.

TaskCache\Tasks\{Id}\Actions

Действия, которые должны выполниться после выполнения условий триггера

TaskCache\Tasks\{Id}\Author

Может содержать УЗ, с помощью которой была создана задача, но чаще всего содержит ссылку на dll

TaskCache\Tasks\{Id}\DynamicInfo

Содержит временные метки создания, последнего запуска и последнего завершения выполнения задачи

TaskCache\Tasks\{Id}\Hash

CRC32 или SHA256 хэш xml-файла задачи (C:\Windows\System32\Tasks\)

TaskCache\Tasks\{Id}\Path

Содержит относительный путь до объекта в дереве или xml-файла в директории Tasks

TaskCache\Tasks\{Id}\SecurityDescriptor

Права, определяющие кому и что разрешено делать с задачей

TaskCache\Tasks\{Id}\Triggers

Триггеры, запускающие задачу

TaskCache\Boot

TaskCache\Logon

TaskCache\Maintenance

TaskCache\Plain

Содержит разделы, имена которых соответствуют UUID задач. Наличие раздела означает наличие ссылки для конкретного триггера. Прямая связь с значением TaskCache\Tree\TaskPath\Index

 

Boot – содержит ссылки на задачи, которые требуется выполнить при загрузке системы

Logon – при входе в систему

Maintenance – при автоматическом обслуживании системы

Plain – иные задачи

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

Чтобы убедиться в этом, достаточно создать новую задачу в Windows 10 и удалить ее файл из директории «C:\Windows\System32\Tasks» – планировщик продолжит корректно отображать и запускать «удаленную» задачу даже после перезагрузки, а файл восстановится лишь в случае модификации задачи непосредственно через WinAPI.

Задача без xml-файла в Windows 10
Задача без xml-файла в Windows 10

В Windows 7 аналогичные действия приведут к полному удалению задачи из системы.

Удаление xml-файла в Windows 7
Удаление xml-файла в Windows 7

При этом в Windows 8 существование xml-файла задачи является обязательным для ее запуска и отображения в интерфейсе планировщика, но содержимое данного файла никак не влияет на параметры задачи – файл может быть модифицирован или даже очищен, а задача продолжит выполняться корректно, так как данные берутся из реестра. Однако при перезагрузке службы планировщика задач файл будет восстановлен до исходного состояния.

Описанные далее выявленные проблемы в работе планировщика задач применимы ко всем версиям Windows с 8 по 11, включая их серверные версии.



Новые (не)удобные фичи и их последствия

Новая логика работы планировщика принесла с собой несколько новых функций, которые обернулись неприятными последствиями.


Легаси

Как уже было написано выше, xml-файл задачи по стандартному пути продолжает появляться при создании или модификации задачи через интерфейс планировщика или утилиту командной строки schtasks. Однако он никак не влияет на работу задачи, поэтому начиная с Windows 8 пользователь может модифицировать (а в Windows 10-11 даже удалить) xml-файл, не изменив параметры задачи и не нарушив работу системы.

Содержимое xml-файлов в «C:\Windows\System32\Tasks\» начиная с Windows 8 не является достоверным источником информации о задачах, которые работают в системе, так как целостность файла существующей задачи может быть нарушена без влияния на систему

❗ Если ваша BlueTeam в выключенной системе смотрит лишь xml-файлы, вредоносные задачи с поддельным или удаленным xml-файлом могут быть пропущены.

Начиная с Windows 8 удаление задач требуется выполнять лишь через интерфейс планировщика или утилиту schtasks. В крайнем случае требуется удалить соответствующие задаче 3 раздела реестра.

❗ Если ваши системные администраторы продолжают удалять лишь xml-файлы задач в надежде удалить задачу из планировщика, как это было в Windows 7 и частично подходит для Windows 8, то начиная с Windows 10 задача остается активной.


Скрытие задач из вывода WinAPI и основанных на нем утилит

Техники, о которых писали давно, но не получившие широкого распространения. Они связаны с значениями Index и SD раздела реестра в TaskCache\Tree.

  • В значении SD указываются права на просмотр задачи, и при установке невалидного значения задача пропадает из вывода утилит, использующих WinAPI, кроме прямого просмотра содержимого реестра;
  • В значении Index указывается тип триггера задачи (в диапазоне от 1 до 4), но если установить значение 0, то задача также скроется от WinAPI.

Баг это или фича – неизвестно, но одними из первых об этом написали сами же Microsoft в 2022 году в своем блоге, посвященном безопасности. Однако в указанной статье нет упоминания про значение Index, о котором далее напишут коллеги из R-Vision в своей статье на Habr. Реализацию техники с изменением Index со стороны атакующих мы также упомянули в статье «Reign of King: тактики и инструментарий группировки Obstinate Mogwai».

При исследовании данной техники выяснилось, что она работает лишь начиная с Windows 10. В Windows 8 еще не было реализовано значение SD, а изменение Index не влечет за собой сокрытия задачи.

Но что такое «невалидный SD»? В обнаруженных нами материалах многие пишут про случай, когда «SD = null», то есть значение удалено, однако это лишь часть большей проблемы с данным значением.

Для выполнения техники с сокрытием задачи, атакующий может:

1) Удалить значение SD;

2) Очистить или изменить на произвольные байты содержимое SD;

3) Удалить из структуры SD информацию о владельце или группе.

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

Модификация SD у раздела-пути
Модификация SD у раздела-пути

Таким образом, любые задачи, которые будут размещаться по пути «\Microsoft\Windows\Evil\», будут скрыты из вывода списка задач WinAPI, но продолжат работать.

Вывод списка задач с помощью стандартных утилит (или основанных на WinAPI) начиная с Windows 10 также не является достоверным источником данных о задачах, так как они могут быть скрыты из этого вывода.

❗ Если ваша BlueTeam в запущенной системе Windows 10 (и старше) смотрит задачи через утилиты, которые работают лишь с WinAPI и не берут данные из реестра, то вредоносная задача будет пропущена.

Интересный факт: если задача скрыта с помощью изменения значения Index, то хоть она и скрыта из вывода списка задач, прямой доступ к ней можно получить через консоль, если известен путь до неё. Из-за этого мы можем не только получить информацию о самой задаче, но и удалить её:

	
schtasks /query /tn "\Microsoft\Windows\Evil\Task"
schtasks /delete /tn "\Microsoft\Windows\Evil\Task"
	

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

Также можно отметить, что в Windows 10 и 11 атакующие могут удалить значение Index – без него задачи продолжат выполняться, но тогда «Внутренняя ошибка» будет возникать каждый раз при открытии планировщика задач, и из системы уже скроются абсолютно все задачи.

Отсутствие задач в планировщике в Windows 10
Отсутствие задач в планировщике в Windows 10

Обход логирования планировщика и изменение метадаты

Импорт, изменение или удаление значения в реестре системы, не является триггером для генерации событий планировщика задач.

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

	
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Plain\{00000000-0000-0000-0000-000000000001}]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Evil]
"SD"=hex:01,00,04,80,88,00,00,00,98,00,00,00,00,00,00,00,14,00,00,00,02,00,74,\
  00,04,00,00,00,00,10,18,00,9f,01,1f,00,01,02,00,00,00,00,00,05,20,00,00,00,\
  20,02,00,00,00,10,14,00,9f,01,1f,00,01,01,00,00,00,00,00,05,12,00,00,00,00,\
  10,18,00,ff,01,1f,00,01,02,00,00,00,00,00,05,20,00,00,00,20,02,00,00,00,00,\
  24,00,89,00,12,00,01,05,00,00,00,00,00,05,15,00,00,00,da,29,6a,f7,90,54,53,\
  10,ba,4e,d6,6f,e8,03,00,00,30,b5,26,31,01,02,00,00,00,00,00,05,20,00,00,00,\
  20,02,00,00,01,05,00,00,00,00,00,05,15,00,00,00,da,29,6a,f7,90,54,53,10,ba,\
  4e,d6,6f,01,02,00,00
"Id"="{00000000-0000-0000-0000-000000000001}"
"Index"=dword:00000003

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{00000000-0000-0000-0000-000000000001}]
"Path"="\\Evil"
"Triggers"=hex:17,00,00,00,00,00,00,00,00,df,17,79,58,00,00,00,00,00,00,00,00,\
  00,00,00,00,df,17,79,58,00,00,00,ff,ff,ff,ff,ff,ff,ff,ff,38,21,41,42,48,48,\
  48,48,cc,ca,a4,6b,48,48,48,48,0e,00,00,00,48,48,48,48,41,00,75,00,74,00,68,\
  00,6f,00,72,00,00,00,48,48,00,00,00,00,48,48,48,48,00,48,48,48,48,48,48,48,\
  00,48,48,48,48,48,48,48,01,00,00,00,48,48,48,48,1c,00,00,00,48,48,48,48,01,\
  05,00,00,00,00,00,05,15,00,00,00,da,29,6a,f7,90,54,53,10,ba,4e,d6,6f,e8,03,\
  00,00,48,48,48,48,1a,00,00,00,48,48,48,48,53,00,41,00,4e,00,44,00,42,00,4f,\
  00,58,00,5c,00,55,00,73,00,65,00,72,00,00,00,48,48,48,48,48,48,2c,00,00,00,\
  48,48,48,48,00,00,00,00,ff,ff,ff,ff,80,f4,03,00,ff,ff,ff,ff,07,00,00,00,00,\
  00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,48,48,\
  48,48,77,77,00,00,00,00,00,00,00,df,17,79,58,00,00,00,00,00,00,00,00,00,00,\
  00,00,df,17,79,58,00,00,00,ff,ff,ff,ff,ff,ff,ff,ff,00,00,00,00,ff,ff,ff,ff,\
  00,00,00,00,00,00,00,00,00,00,00,00,00,02,00,00,01,ff,ff,ff,00,00,00,00,00,\
  00,00,00,00,00,00,00,00,00,00,00,48,48,48,48,08,00,00,00,00,00,00,00,01,48,\
  48,48,48,48,48,48
"Actions"=hex:03,00,0c,00,00,00,41,00,75,00,74,00,68,00,6f,00,72,00,66,66,00,\
  00,00,00,06,00,00,00,63,00,6d,00,64,00,44,00,00,00,2f,00,63,00,20,00,73,00,\
  74,00,61,00,72,00,74,00,20,00,68,00,74,00,74,00,70,00,3a,00,2f,00,2f,00,6c,\
  00,6f,00,63,00,61,00,6c,00,68,00,6f,00,73,00,74,00,2f,00,6d,00,65,00,74,00,\
  61,00,64,00,61,00,74,00,61,00,00,00,00,00,00,00
"DynamicInfo"=hex:03,00,00,00,00,57,F1,FB,5D,44,D1,01,00,48,F1,AF,C5,B1,9D,01,\
  00,00,00,00,00,00,00,00,00,48,F1,AF,C5,B1,9D,01
	
Минимальный набор значений для работы задачи

Далее, обладая правами системы, требуется выполнить импорт значений в реестр. При перезагрузке службы планировщика задача начнет работать без генерации событий о ее создании. Таким же образом задача может быть модифицирована и удалена. Подробнее с примерами про это писали R-Vision в той же статье на Habr.

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

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

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

  • TaskCache\Tasks\{Id}\Author
  • TaskCache\Tasks\{Id}\Date
  • TaskCache\Tasks\{Id}\DynamicInfo
  • TaskCache\Tasks\{Id}\Hash
  • TaskCache\Tasks\{Id}\Schema
  • TaskCache\Tasks\{Id}\URI

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

  • TaskCache\Tasks\{Id}\ – модифицируется при работе задачи из-за изменения DynamicInfo;
  • TaskCache\Tree\Name\ – модифицируется лишь при создании/изменении самой задачи и, в случае подмены метки создания в метадате, может быть наиболее близко к действительной дате создания.

Значение Hash также может содержать недействительное значение – фильтрация по нему недопустима.


❗ Если ваша BlueTeam фильтрует задачи по хэшу xml-файла или значению TaskCache\Tasks\{Id}\Hash, то вредоносная задача может быть пропущена.


Сообщество разработчиков утилит для DFIR

Вероятно, многие действительно пропустили переезд задач в реестр или не отметили важность данного обновления. Безусловно, самая популярная утилита для удобного просмотра реестра Registry Explorer в 2024 году (спустя 12 лет после релиза Windows 8) все еще не обрабатывает их должным образом. А точнее, игнорирует значение Actions, которое содержит командлайн задачи:

Оригинальный плагин TaskCache в Registry Explorer
Оригинальный плагин TaskCache в Registry Explorer

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

Просмотр Actions через Type Viewer в Registry Explore
Просмотр Actions через Type Viewer в Registry Explorer

Однако Registry Explorer – единственное ПО, которое хоть каким-то образом обрабатывает значения TaskCache: колонки Created On, Last Start и Last Stop – это результат обработки значения DynamicInfo, которое также является бинарной структурой. Впрочем, требуется помнить, что данные значения могут быть подменены атакующими.

Ситуация с популярным нынче Velociraptor двоякая. В документации были обнаружены весьма обнадеживающие страницы:

1) Задачи уже считаются сущностью из реестра, а логика сбора артефактов не связана с xml-файлами. Но здесь нас встречает абзац TODO, где обещано добавить данный артефакт в основной репозиторий. На момент исследования в сентябре 2024 в релизной версии всё ещё отсутствует данное обновление.

Документация Velociraptor: запланированные задачи
Документация Velociraptor: запланированные задачи

Однако при ручном добавлении данного модуля выяснилось, что значение Actions не обрабатывается и сохраняется в base64, которое абсолютно непригодно для просмотра человеком и требует дополнительной ручной обработки или автоматизации. Еще один недостаток – отсутствие обработки значения DynamicInfo.

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

Документация Velociraptor: скрытые задачи
Документация Velociraptor: скрытые задачи

Прочие популярные инструменты, такие как AutoPsy, OsForensics и X-Ways, отображают реестр так же, как и стандартный редактор реестра Windows: значение Actions не обрабатывается и представлено в виде hex-string. Утилиты Sysinternals Autoruns и Nirsoft TaskSchedulerView не обнаруживают скрытые задачи в Windows 10-11, так как используют WinAPI, однако отображают задачи без xml-файла.

Популярные утилиты для DFIR всё еще не обрабатывают ключ TaskCache:

1) Type Viewer в Registry Explorer позволяет немного упростить просмотр разделов, но это потребует поочередного ручного просмотра значений, где их может быть более сотни;

2) Velociraptor при добавлении неопубликованных модулей позволяет собирать значения Actions, но сохранение значения в base64 требует дополнительной обработки. При использовании данной утилиты из коробки, задачи из TaskCache никак не обрабатываются.



Структура Actions

Если ни в одной из популярных утилит не реализована обработка значения Actions, неужели это невозможно? Структура значения не является задокументированной Microsoft, но данным вопросом уже занимались исследователи Windows еще в 2022 году. Мы не будем дублировать весь материал, представленный в исследовании с ресурса cyber.wtf, а рассмотрим и дополним лишь основные моменты.

Структура состоит из заголовка и от одного до множества тел Actions. Если задача выполняет 3 действия при срабатывании триггера, то структура будет иметь 3 последовательно записанных тела.

Тело Actions разделяется на несколько типов, которое определяется Magic-строкой в начале тела:

1) 0x6666 – прямой запуск исполняемого файла с необходимыми аргументами;

2) 0x7777 – запуск COM-объектов;

3) 0x8888 – отправка Email (устаревшее);

4) 0x9999 – вывод Message Box (устаревшее).

Отмечается, что планировщик задач не позволяет создавать устаревшие типы Actions.

Рассмотрим пример. В значении Actions хранятся данные:

03000C00000041007500740068006F00720066660000000010000000630061006C0063002E006500780065000000000000000000000077770000000029B731AEFDD51E40AF42784074835AFE3E0000002D0052006500670069007300740065007200550073006500720044006500760069006300650020002D004E00650077004100630063006F0075006E007400

Структура этих данных выглядит следующим образом:

Блок данных

Типы данных

Описание

0300

0C000000

    41007500740068006F007200

int16 версия

int32 длина строки

Unicode string

 

Заголовок структуры. Содержит версию, а также Context задачи

6666

00000000

    (0 bytes)

10000000

    630061006C0063002E00650078006500

00000000

   (0 bytes)

00000000

   (0 bytes)

0000

Magic: Action-Type

int32 длина строки

Unicode string

int32 длина строки

Unicode string

int32 длина строки

Unicode string

int32 длина строки

Unicode string

Флаги

Тело структуры, которое начинается с типа Action.

Для типа 6666, далее следует 4 пары int32 и Unicode строки, которые хранят в себе значения:

1) id

2) command

3) arguments

4) directory

Данный тип завешается на 2 байта флагов, которые пока нам не встречались (флаги имеются лишь с третьей версии структуры)

7777

00000000

   (0 bytes)

29B731AEFDD51E40AF42784074835AFE

3E000000

   2D005200650067006900730074006500

   72005500730065007200440065007600

   69006300650020002D004E0065007700

   4100630063006F0075006E007400

Magic: Action-Type

int32 длина строки

Unicode string

byte COM-object

int32 длина строки

Unicode string

Для типа Action 7777, далее также следует пара int и Unicode строки для хранения значения id, после которого хранится 16 байт COM-GUID вызываемого объекта. Структура завершается на еще одну пару int32 и Unicode строки, обозначающие аргументы для запуска

В результате обработки можно получить следующие данные:

Version:

Context:

3

Author

ID:

Command:

Arguments:

Working Directory:

null

calc.exe

null

null

ID:

COM-object:

Data:

null

{29B731AE-FDD5-1E40-AF42-784074835AFE}

-RegisterUserDevice -NewAccount

А чтобы автоматически обработать значение из примера, можно использовать следующий код на C#:

	
byte[] keyValue = StringToByteArray("03000C00000041007500740068006F00720066660000000010000000630" +
    "061006C0063002E006500780065000000000000000000000077770000000029B731AEFDD51E40AF42784074835A" +
    "FE3E0000002D0052006500670069007300740065007200550073006500720044006500760069006300650020002" +
    "D004E00650077004100630063006F0075006E007400");
using Stream stream = new MemoryStream(keyValue);
using BinaryReader reader = new BinaryReader(stream);

//Header
short version = reader.ReadInt16();string context = (version >= 2) ?
            Encoding.Unicode.GetString(reader.ReadBytes(reader.ReadInt32())) : string.Empty;

//ActionType 0x6666
short type_first = reader.ReadInt16();
string id_first = Encoding.Unicode.GetString(reader.ReadBytes(reader.ReadInt32()));
string path = Encoding.Unicode.GetString(reader.ReadBytes(reader.ReadInt32()));
string arguments = Encoding.Unicode.GetString(reader.ReadBytes(reader.ReadInt32()));
string workingDirectory = Encoding.Unicode.GetString(reader.ReadBytes(reader.ReadInt32()));
short flags = (version >= 3) ?
            reader.ReadInt16() : (short)0;

//ActionType 0x7777
short type_second = reader.ReadInt16();
string id_second = Encoding.Unicode.GetString(reader.ReadBytes(reader.ReadInt32()));
Guid clsid = new Guid(reader.ReadBytes(16));
string data = Encoding.Unicode.GetString(reader.ReadBytes(reader.ReadInt32()));
	


Плагин «4RAYS TaskCache» для Registry Explorer

Мы готовы поделиться собственным плагином для Registry Explorer, который позволяет просматривать значение Actions и помогает искать скрытые задачи:

  • Key Name – GUID задачи;
  • Path – путь до задачи в дереве;
  • Actions – перечисление командлайнов, которые выполняет задача;
  • Actions Type – перечисление типов, которые используется в задаче;
  • Tree Key Last Write – временная метка модификации раздела задачи в дереве;
  • Created On, Last Start, Last Stop – обработка значения DynamicInfo;
  • Index – соответствующее значение из дерева;
  • Tree SD – уникальные значения SD разделов, образующие путь до задачи в дереве, с подсвечиванием случаев, когда задача может быть скрыта из планировщика.

Если значение Index будет соответствовать 0 или возникнет один из описанных случаев с значением SD, то в колонке Alert будет отображаться значение True, по которому также можно отфильтровать таблицу.

Загрузить скомпилированный плагин, а также ознакомиться с исходным кодом можно в нашем GitHub.

Для его установки требуется поместить dll-файл в директорию «..\RegistryExplorer\Plugins», после запуска RegistryExplorer, при открытии «View» > «Plugins» должен появиться новый плагин.

Окно с плагинами «RegistryExplorer»
Окно с плагинами «RegistryExplorer»

При открытии ключа TaskCache, доступного в стандартных закладках, откроется таблица:

Демонстрация работы плагина
Демонстрация работы плагина

Поддержку данного плагина пока гарантировать не можем, однако о багах вы можете сообщить нам в GitHub в разделе Issues.



Выводы

С обновления планировщика задач прошло уже 12 лет. Вероятно, BlueTeam пора отреагировать на данное изменение:

  • Усовершенствовать инструменты для просмотра и сбора задач как для работы с работающими системами, так и при работе с артефактами;
  • Внести правки в обучающие материалы по DFIR;
  • Говорить об этой проблеме шире: некоторые системные администраторы всё ещё по привычке удаляют xml-файл задачи, сохраняя в системе Persistence.

Еще раз повторим, почему стоит все это сделать уже сейчас:

  • При работе с Windows 8, 10, 11 (и, вероятно, в будущих релизах) достоверные данные о работающих в системе задачах хранятся лишь в реестре в ветке TaskCache:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache

  • Xml-файлы по прежним путям – это лишь легаси файлы, которые могут быть модифицированы или удалены без влияния на значения в реестре;
  • Во включенной системе задачи могут быть скрыты из вывода стандартных утилит или иных утилит, основанных на WinAPI, если в значения Index или SD будут внесены изменения атакующим;
  • Создание, модификация и удаление задач с помощь импорта значений в реестр не генерирует событий соответствующих действий с задачами;
  • На момент написания статьи ни одна из популярных утилит для DFIR не отображает скрытые задачи, а также не обрабатывает все значения ключа TaskCache;
  • На текущий момент лучшим инструментом для просмотра и поиска подобных задач, по нашему мнению, является Registry Explorer, в котором уже давно реализован просмотр списка задач по данным из реестра (но, к сожалению, без командлайнов), а теперь для данного инструмента мы подготовили соответствующий плагин для дополнительной обработки значений;
  • Удаление задач требуется выполнять лишь с помощью планировщика (интерфейс или командлайн). В крайнем случае – удалять задачу напрямую из реестра.
  • Для удаления скрытых задач:

    • Если Index = 0: удалить с помощью командлайна;
    • Если значение SD не является валидным требуется удалить разделы реестра:

      • ..\TaskCache\Tasks\{Id}
      • ..\TaskCache\Tree\Path\TaskName
      • ..\TaskCache\ (Boot / Logon / Maintenance / Plain) \{Id}

Напоследок приведем памятку про скрытые задачи:

А также итоговый таймлайн изменений в планировщике задач:

Версия Windows

Изменения

Windows 7

Windows Server 2008 R2 Standard

Первое появление TaskCache. Разделы задач содержат лишь 4 значения:

  • DynamicInfo
  • Hash
  • Path
  • Triggers

В дереве задач имеются значения:

  • Index
  • Id

Удаление xml-файла или ключей TaskCache равносильно удалению задачи

После ручного изменения xml-файла возникает ошибка «образ задачи был поврежден», а задача перестанет выполняться

Windows 8

Windows Server 2012

В разделах задач стало больше значений:

  • Actions
  • Author
  • Data
  • Date
  • Description
  • DynamicInfo
  • Hash
  • Path
  • Schema
  • SecurityDescriptor
  • Source
  • Triggers
  • URI

TaskCache становится основным хранилищем задач, но без соответствующего задаче файла по пути «C:\Windows\System32\Tasks» она не будет выполняться и отображаться в планировщике. При этом, содержимое файла не имеет значения для планировщика. Модифицированный xml-файл задачи будет восстановлен из реестра при перезагрузке службы планировщика задач

Windows 10

Windows Server 2016

Windows Server 2019

Windows Server 2022

В разделах дерева появилось новое значение:

  • SD

Для выполнения задач больше не требуется наличие какого-либо файла в «C:\Windows\System32\Tasks», также он больше не будет создаваться при перезагрузке службы

Появление фич (багов) со скрытием задач, при изменении SD или Index в дереве

Windows 11

Без изменений. Скрытие задач всё еще возможно.

На этом у нас все. Пользуйтесь плагином на здоровье и, как говорится, happy hunting!

Полезные источники:

https://cyber.wtf/2022/06/01/windows-registry-analysis-todays-episode-tasks/

https://www.microsoft.com/en-us/security/blog/2022/04/12/tarrask-malware-uses-scheduled-tasks-for-defense-evasion/

https://habr.com/ru/companies/rvision/articles/723050/