Оглавление
- Введение
- Существенные изменения планировщика задач в Windows 8
- Новые (не)удобные фичи и их последствия
- Структура Actions
- Плагин «4RAYS TaskCache» для Registry Explorer
- Выводы
Введение
Команда 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 образует следующую структуру:
В младших версиях 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.
В 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 информацию о владельце или группе.
При этом данные действия могут быть выполнены не только с разделом самой задачи, но и с разделом, который является частью пути до задачи:
Таким образом, любые задачи, которые будут размещаться по пути «\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 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, которое содержит командлайн задачи:
Данное значение можно посмотреть вручную, но там отображается лишь бинарная структура, требующая дополнительной обработки.
Однако Registry Explorer – единственное ПО, которое хоть каким-то образом обрабатывает значения TaskCache: колонки Created On, Last Start и Last Stop – это результат обработки значения DynamicInfo, которое также является бинарной структурой. Впрочем, требуется помнить, что данные значения могут быть подменены атакующими.
Ситуация с популярным нынче Velociraptor двоякая. В документации были обнаружены весьма обнадеживающие страницы:
1) Задачи уже считаются сущностью из реестра, а логика сбора артефактов не связана с xml-файлами. Но здесь нас встречает абзац TODO, где обещано добавить данный артефакт в основной репозиторий. На момент исследования в сентябре 2024 в релизной версии всё ещё отсутствует данное обновление.
Однако при ручном добавлении данного модуля выяснилось, что значение Actions не обрабатывается и сохраняется в base64, которое абсолютно непригодно для просмотра человеком и требует дополнительной ручной обработки или автоматизации. Еще один недостаток – отсутствие обработки значения DynamicInfo.
2) Отдельно подготовлен модуль для поиска скрытых задач, но он опирается лишь на значение SD в разделах задач, без учета случаев с Index и модификации SD в разделе, который является частью пути. В релизной версии данного модуля также не обнаружено. Дополнительно отмечается, что данный модуль лишь проверяет значение SD на null, когда задача может быть скрыта модификацией значения, а не с помощью его удаления.
Прочие популярные инструменты, такие как 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
Структура этих данных выглядит следующим образом:
|
Типы данных |
Описание |
---|---|---|
|
int16 версия int32 длина строки Unicode string
|
Заголовок структуры. Содержит версию, а также Context задачи |
|
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 байта флагов, которые пока нам не встречались (флаги имеются лишь с третьей версии структуры) |
|
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» должен появиться новый плагин.
При открытии ключа 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 значения:
В дереве задач имеются значения:
Удаление xml-файла или ключей TaskCache равносильно удалению задачи После ручного изменения xml-файла возникает ошибка «образ задачи был поврежден», а задача перестанет выполняться |
Windows 8 Windows Server 2012 |
В разделах задач стало больше значений:
TaskCache становится основным хранилищем задач, но без соответствующего задаче файла по пути «C:\Windows\System32\Tasks» она не будет выполняться и отображаться в планировщике. При этом, содержимое файла не имеет значения для планировщика. Модифицированный xml-файл задачи будет восстановлен из реестра при перезагрузке службы планировщика задач |
Windows 10 Windows Server 2016 Windows Server 2019 Windows Server 2022 |
В разделах дерева появилось новое значение:
Для выполнения задач больше не требуется наличие какого-либо файла в «C:\Windows\System32\Tasks», также он больше не будет создаваться при перезагрузке службы Появление фич (багов) со скрытием задач, при изменении SD или Index в дереве |
Windows 11 |
Без изменений. Скрытие задач всё еще возможно. |
На этом у нас все. Пользуйтесь плагином на здоровье и, как говорится, happy hunting!
Полезные источники:
https://cyber.wtf/2022/06/01/windows-registry-analysis-todays-episode-tasks/