Введение
Каждый день глобальная команда экстренного реагирования на киберинциденты (GERT) «Лаборатории Касперского» работает с различными артефактами в рамках расследований, и одним из самых ценных среди них является UserAssist. Он содержит полезную информацию о выполнении программ, которая помогает выявлять и отслеживать активность злоумышленников, а также обнаруживать образцы вредоносного ПО. Тем не менее детальное исследование UserAssist еще не проводилось, и остаются пробелы в таких областях, как интерпретация данных, условия логирования и триггеры. В этой статье приводится детальный анализ артефакта UserAssist и разъясняется его неоднозначное представление данных. Мы рассмотрим порядок создания и обновления данных артефакта, назначение структуры UEME_CTLSESSION и ее роль в логировании данных UserAssist, а также опишем ранее неизученную часть структуры данных этого артефакта.
Общие сведения об артефакте UserAssist
UserAssist — известный среди цифровых криминалистов артефакт Windows, логирующий выполнение программ с графическим интерфейсом. В этом артефакте сохраняются различные данные о каждом приложении с GUI, запущенном в системе, а именно:
- Имя программы — полный путь к программе.
- Счетчик выполнений — сколько раз запускалась программа.
- Счетчик фокусировок — сколько раз программа оказывалась в фокусе, то есть становилась активной после переключения с других приложений или иным образом выводилась на передний план.
- Время в фокусе — общее время, в течение которого программа находилась в фокусе.
- Время последнего запуска — дата и время последнего выполнения программы.
Артефакт UserAssist представляет собой ключ в кусте реестра HKEY_CURRENT_USER по следующему пути: Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\. Он хранится в файле NTUSER.DAT. Внутри этого ключа находятся подключи, названные по GUID. Два важнейших подраздела имеют следующие GUID:
{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}— здесь регистрируются выполняемые файлы EXE.{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}— здесь регистрируются выполняемые файлы LNK.
В каждом подключе есть свой подключ с именем Count. Параметры в нем указывают на ранее запущенные программы. Имена параметров — это пути к программам, зашифрованные с помощью алгоритма ROT-13.
В значениях содержатся структурированные бинарные данные, включающие счетчики выполнений и фокусировок, а также время последнего запуска соответствующей программы. Эта структура изучена и представляет собой объект CUACount. Однако описания и анализ байтов, расположенных между значениями времени фокусировки и времени последнего запуска, ранее не публиковались. Нам удалось выяснить их назначение — об этом мы расскажем далее в статье. При этом роль последних четырех байтов остается неизвестной — во всех проанализированных нами наборах данных они были заполнены нулями.
Расхождения в данных
В ходе многих расследований мы сталкивались с вариативностью состава данных в записях UserAssist: некоторые из них содержали все упомянутые выше значения, тогда как другие записи, например, включали только счетчик выполнений и время последнего запуска. Всего нам встречалось пять вариантов состава данных.
| Вариант | Счетчик выполнений | Счетчик фокусировок | Время в фокусе | Время последнего запуска |
| 1 | ✓ | ✓ | ✓ | ✓ |
| 2 | ✓ | ✕ | ✕ | ✓ |
| 3 | ✕ | ✓ | ✓ | ✕ |
| 4 | ✓ | ✕ | ✓ | ✓ |
| 5 | ✕ | ✕ | ✓ | ✕ |
Порядок логирования в UserAssist
Описание функций shell32.dll
Чтобы разобраться в причинах расхождений, нам необходимо изучить работу компонента, отвечающего за регистрацию и обновление данных UserAssist. В ходе анализа мы выяснили, что этим занимается shell32.dll, в частности функция FireEvent, входящая в класс CUserAssist.
|
1 |
virtual long CUserAssist::FireEvent(struct _GUID const *, enum tagUAEVENT, unsigned short const *, unsigned long) |
Далее приведены аргументы функции FireEvent:
- Аргумент 1: GUID — подключ ключа реестра UserAssist, содержащий логируемые данные. В основном этот аргумент принимает значение
{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}, поскольку выполняемые программы чаще всего являются файлами EXE. - Аргумент 2: целочисленное значение, определяющее, какие счетчики и данные подлежат обновлению:
- 0: обновление счетчика выполнений и времени последнего запуска.
- 1: обновление счетчика фокусировок.
- 2: обновление времени в фокусе.
- 3: неизвестно.
- 4: неизвестно (мы полагаем, что это значение отвечает за удаление записи).
- Аргумент 3: полный путь к исполняемому файлу, который был запущен, выведен на передний план или закрыт.
- Аргумент 4: время в фокусе для исполняемого файла в миллисекундах. Аргумент содержит ненулевое значение, если аргумент 2 имеет значение 2; в противном случае равен нулю.
Функция FireEvent зависит от двух других функций shell32.dll — s_Read и s_Write, которые отвечают за чтение бинарных значений данных UserAssist из реестра и их запись при каждом обновлении определенной программы:
|
1 2 |
static long CUADBLog::s_Read(void *, unsigned long, struct NRWINFO *) static long CUADBLog::s_Write(void *, unsigned long, struct NRWINFO *) |
Функция s_Read считывает бинарное значение данных UserAssist из реестра в память, а s_Write записывает бинарное значение из памяти в реестр. Обе функции имеют следующие одинаковые аргументы:
- Аргумент 1: указатель на буфер памяти (структуру CUACount), который получает или содержит бинарные данные UserAssist.
- Аргумент 2: размер бинарных данных UserAssist, которые будут считываться из реестра или записываться в него, в байтах.
- Аргумент 3: недокументированная структура с двумя указателями:
- указатель на экземпляр CUADBLog по смещению 0x0;
- полный путь к исполняемому файлу, с которым связаны бинарные данные UserAssist, подлежащие считыванию из реестра или записи в него.
Когда программа запускается впервые и соответствующей записи в UserAssist нет, функция s_Read считывает значение UEME_CTLCUACount:ctor, которое служит шаблоном структуры бинарных данных UserAssist (CUACount). Это значение мы подробно опишем позже в статье.
Отметим, что функции s_Read и s_Write также отвечают за шифрование имен значений с помощью ROT-13.
Обновление данных UserAssist
Любое взаимодействие с программой, имеющей графический интерфейс, является событием-триггером, вызывающим функцию CUserAssist::FireEvent. Существует четыре типа событий-триггеров:
- Запуск программы.
- Фокусировка на программе.
- Снятие фокуса с программы.
- Закрытие программы.
Порядок выполнения функции CUserAssist::FireEvent зависит от типа события-триггера. Оно влияет на значение, которое передается в качестве второго аргумента функции FireEvent и определяет, какие счетчики и данные должны быть обновлены в бинарных данных UserAssist.
Функция CUserAssist::FireEvent вызывает функцию CUADBLog::s_Read, чтобы считать бинарные данные из реестра в память. Затем функция CUserAssist::FireEvent обновляет соответствующие счетчики и данные, после чего вызывает функцию CUADBLog::s_Write, чтобы записать данные обратно в реестр.
На схеме ниже показан порядок обновления данных UserAssist в зависимости от того, как пользователь взаимодействует с программой.
Функции, вызывающие FireEvent, могут различаться в зависимости от события-триггера, ставшего результатом взаимодействия пользователя с программой. В таблице ниже приведен стек вызовов для каждого события-триггера с указанием модулей, содержащих соответствующие функции.
| Событие-триггер | Модуль | Функции стека вызовов | Подробности |
| Запуск программы (двойной щелчок) | SHELL32 | CUserAssist::FireEvent | Эта цепочка вызовов обновляет счетчик выполнений и время последнего запуска. Она срабатывает только при двойном щелчке по исполняемому файлу в проводнике Windows (как для графических, так и для консольных программ). |
| Windows.storage | UAFireEvent | ||
| Windows.storage | NotifyUserAssistOfLaunch | ||
| Windows.storage | CInvokeCreateProcessVerb:: _OnCreatedProcess |
||
| Фокусировка на программе | SHELL32 | CUserAssist::FireEvent | Эта цепочка вызовов обновляет счетчик фокусировок. Она применима только к исполняемым файлам с графическим интерфейсом. |
| Explorer | UAFireEvent | ||
| Explorer | CApplicationUsageTracker:: _FireDelayedSwitch |
||
| Explorer | CApplicationUsageTracker:: _FireDelayedSwitchCallback |
||
| Снятие фокуса с программы | SHELL32 | CUserAssist::FireEvent | Эта цепочка вызовов обновляет время фокусировки. Она применима только к исполняемым файлам с графическим интерфейсом. |
| Explorer | UAFireEvent | ||
| Explorer | <lambda_2fe02393908a23e7 ac47d9dd501738f1>::operator() |
||
| Explorer | shell::TaskScheduler:: CSimpleRunnableTaskParam <<lambda_2fe02393908a23e7 ac47d9dd501738f1>, CMemString<CMemString _PolicyCoTaskMem> >::InternalResumeRT |
||
| Закрытие программы | SHELL32 | CUserAssist::FireEvent | Эта цепочка вызовов обновляет время фокусировки. Она применима к исполняемым файлам и с графическим, и с консольным интерфейсом. Однако записи консольных программ обновляются только в том случае, если они были запущены двойным щелчком или если они порождают в качестве дочернего процесса conhost. |
| Explorer | UAFireEvent | ||
| Explorer | shell::TaskScheduler:: CSimpleRunnableTaskParam<< lambda_5b4995a8d0f55408566e10 b459ba2cbe>,CMemString<CMemString _PolicyCoTaskMem> >:: InternalResumeRT |
Варианты состава данных
Как уже упоминалось, мы встречали пять вариантов состава данных в записях UserAssist. Наш подробный анализ показывает, что такие расхождения возникают в зависимости от того, каким образом пользователь взаимодействует с программой и какие функции вызывают FireEvent. Давайте подробнее рассмотрим, какие именно события-триггеры влияют на состав данных.
1. Все данные
Первая комбинация — в записи UserAssist указаны все четыре параметра: счетчик выполнений, счетчик фокусировок, время в фокусе и время последнего запуска. В этом сценарии программа обычно выполняется согласно стандартному потоку, имеет графический интерфейс и запускается двойным щелчком в проводнике Windows.
- При запуске программы вызывается функция FireEvent, чтобы обновить счетчик выполнений и время последнего запуска.
- Когда происходит фокусировка на программе, вызывается функция FireEvent для обновления счетчика фокусировок.
- При снятии фокуса или закрытии программы вызывается функция FireEvent для обновления времени в фокусе.
2. Счетчик выполнений и время последнего запуска
Вторая комбинация — запись содержит только счетчик выполнений и время последнего запуска. В этом сценарии программа запускается двойным щелчком в проводнике Windows, но появившийся графический интерфейс принадлежит другой программе. Примерами такого сценария могут быть запуск приложения через LNK-ярлык или использование установщика, который запускает другую программу с графическим интерфейсом и тем самым переключает фокус на файл этой программы.
Мы провели тест, запустив копию calc.exe двойным щелчком в проводнике Windows, после чего появился графический интерфейс UWP-приложения калькулятора Microsoft.WindowsCalculator_8wekyb3d8bbwe!App.
В UserAssist появилась запись о запуске копии классического приложения calc.exe, но она содержит только счетчик выполнений и время последнего запуска. А счетчик фокусировок и время в фокусе были записаны в данные UserAssist для UWP-приложения калькулятора Microsoft.WindowsCalculator_8wekyb3d8bbwe!App.
3. Счетчик фокусировок и время в фокусе
Третья комбинация — запись содержит только счетчик фокусировок и время в фокусе. В этом сценарии программа имеет графический интерфейс, но запускается не двойным щелчком в проводнике Windows, а другим способом, например через командную строку.
В ходе теста мы запустили копию Process Explorer из пакета Sysinternals через cmd. При этом в UserAssist появилась запись, включающая только счетчик фокусировок и время в фокусе.
4. Счетчик выполнений, время последнего запуска и время в фокусе
Четвертая комбинация — запись включает счетчик выполнений, время последнего запуска и время в фокусе. Этот сценарий применим только к консольным программам, которые запускаются двойным щелчком и сразу закрываются. Выполнение по двойному щелчку приводит к обновлению счетчика выполнений и времени последнего запуска. Затем событие закрытия программы активирует лямбда-функцию (5b4995a8d0f55408566e10b459ba2cbe), которая вызывает функцию FireEvent для обновления времени в фокусе.
В рамках нашего теста мы запустили копию whoami.exe двойным щелчком, в результате на долю секунды открылся консольный интерфейс, после чего программа была закрыта.
5. Время в фокусе
Пятая комбинация — запись содержит только время в фокусе. Этот сценарий применяется только к консольным программам, которые запускаются любым способом, кроме двойного щелчка, открывают консольный интерфейс на долю секунды и сразу закрываются.
В ходе нашего теста копия whoami.exe была запущена с помощью PsExec вместо cmd. PsExec запустил whoami как дочерний процесс, в результате чего whoami породил процесс conhost.exe. Это обязательное условие, чтобы консольная программа попала в записи UserAssist в рамках описываемого сценария.
Все пять комбинаций с соответствующими интерпретациями представлены в таблице ниже.
| Комбинация данных | Интерпретация | События-триггеры |
| Все данные | Программа с графическим интерфейсом была запущена двойным щелчком и закрыта обычным способом. | · Запуск программы · Фокусировка на программе · Снятие фокуса с программы · Закрытие программы |
| Счетчик выполнений и время последнего запуска | Программа с графическим интерфейсом была запущена двойным щелчком, но переключила фокус на другую программу. | · Запуск программы |
| Счетчик фокусировок и время в фокусе | Программа с графическим интерфейсом была запущена способом, отличным от двойного щелчка. | · Фокусировка на программе · Снятие фокуса с программы · Закрытие программы |
| Счетчик выполнений, время последнего запуска и время в фокусе | Консольная программа была запущена двойным щелчком и затем закрыта. | · Запуск программы · Закрытие программы |
| Время в фокусе | Консольная программа была запущена способом, отличным от двойного щелчка, породила процесс conhost и затем была закрыта. | · Закрытие программы |
CUASession и UEME_CTLSESSION
Теперь, когда мы разобрались с расхождениями в составе данных UserAssist, перейдем ко второй части нашего исследования, в которой рассматривается другая составляющая этого артефакта — класс CUASession и структура UEME_CTLSESSION.
База данных UserAssist содержит значения для каждой запущенной программы, однако существует одно неизвестное значение — UEME_CTLSESSION. В отличие от бинарных данных, записываемых для каждой программы, эта структура представляет собой довольно объемный фрагмент — 1612 байт, тогда как обычный размер записи о запущенной программе составляет 72 байта.
CUASession — это класс в shell32.dll, отвечающий за ведение статистики всей сессии логирования UserAssist для всех программ. В эту статистику входят общее количество выполнений, общее количество фокусировок, общее время в фокусе и данные о трех самых активно используемых программах (записи NMax), которые мы рассмотрим позже. Структура UEME_CTLSESSION содержит свойства объекта CUASession. Ниже перечислены некоторые функции класса CUASession:
| CUASession::AddLaunches(uint) | CUASession::GetTotalLaunches(void) |
| CUASession::AddSwitches(uint) | CUASession::GetTotalSwitches(void) |
| CUASession::AddUserTime(ulong) | CUASession::GetTotalUserTime(void) |
| CUASession::GetNMaxCandidate(enum _tagNMAXCOLS, struct SNMaxEntry *) | CUASession::SetNMaxCandidate(enum _tagNMAXCOLS, struct SNMaxEntry const *) |
В контексте CUASession и UEME_CTLSESSION, когда речь идет о параметрах всех запущенных программ в рамках одной сессии логирования, а не о данных отдельной программы, вместо счетчика выполнений мы будем говорить о счетчике запусков (Launches), вместо счетчика фокусировок — о счетчике переключений (Switches), а вместо времени в фокусе — о пользовательском времени (User Time).
UEME_CTLSESSION имеет следующую специфическую структуру данных:
- Смещение 0x0: общая суммарная статистика (16 байт)
- 0x0: идентификатор сессии логирования (Logging Session ID, 4 байта)
- 0x4: общий счетчик запусков (Total Launches, 4 байта)
- 0x8: общий счетчик переключений (Total Switches, 4 байта)
- 0xC: общее пользовательское время в миллисекундах (Total User Time, 4 байта)
- Смещение 0x10: три записи NMax (1596 байт)
- 0x10: первая запись NMax (532 байта)
- 0x224: вторая запись NMax (532 байта)
- 0x438: третья запись NMax (532 байта)
При каждом вызове функции FireEvent для обновления данных любой программы CUASession также обновляет свои свойства и сохраняет их в UEME_CTLSESSION.
- Если функция FireEvent вызывается для обновления счетчика выполнений программы, CUASession увеличивает значение общего счетчика запусков (Total Launches) в UEME_CTLSESSION.
- Если FireEvent вызывается для обновления счетчика фокусировок программы, CUASession увеличивает значение общего счетчика переключений (Total Switches).
- Если FireEvent вызывается для обновления времени в фокусе программы, CUASession обновляет общее пользовательское время (Total User Time).
Записи NMax
Запись NMax — это фрагмент данных UserAssist для конкретной программы, содержащий счетчик выполнений, счетчик фокусировок, время в фокусе и полный путь. Записи NMax входят в состав структуры UEME_CTLSESSION. Каждая запись NMax имеет следующую структуру данных:
- Смещение 0x0: счетчик выполнений программы (Run Count, 4 байта)
- Смещение 0x4: счетчик фокусировок программы (Focus Count, 4 байта)
- Смещение 0x8: время в фокусе программе в миллисекундах (Focus Time, 4 байта)
- Смещение 0xC: имя программы или полный путь к ней в кодировке Юникод (Full Path, 520 байт, что соответствует максимальной длине пути в Windows, умноженной на два)
В записях NMax отслеживаются самые часто выполняемые, переключаемые и используемые программы. При каждом вызове функции FireEvent для обновления какой-либо программы также вызывается функция CUADBLog::_CheckUpdateNMax, которая проверяет и обновляет соответствующие записи NMax.
В первой записи NMax хранятся данные о самой часто запускаемой программе (с наибольшим значением счетчика выполнений). Если значения счетчиков выполнений двух программ (уже сохраненной в записи NMax и той, для которой сработало обновление через FireEvent) совпадают, то в запись сохраняется та из них, у которой больше значение N. Оно вычисляется по следующей формуле:
Значение N = счетчик выполнений программы * (общее пользовательское время / общий счетчик запусков) + время в фокусе программы + счетчик фокусировок программы * (общее пользовательское время / общий счетчик переключений)
Во второй записи NMax хранятся данные о самой часто переключаемой программе (с наибольшим значением счетчика фокусировок). Если значения счетчиков фокусировок двух программ совпадают, то в запись сохраняется программа с наибольшим значением N.
В третьей записи NMax хранятся данные о самой часто используемой программе (с наибольшим значением N).
Пример результата парсинга для структуры UEME_CTLSESSION с записями NMax приведен ниже.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
{ "stats": { "Session ID": 40, "Total Launches": 118, "Total Switches": 1972, "Total User Time": 154055403 }, "NMax": [ { "Run Count": 20, "Focus Count": 122, "Focus Time": 4148483, "Executable Path": "Microsoft.Windows.Explorer" }, { "Run Count": 9, "Focus Count": 318, "Focus Time": 34684910, "Executable Path": "Chrome" }, { "Run Count": 9, "Focus Count": 318, "Focus Time": 34684910, "Executable Path": "Chrome" } ] } |
Данные UEME_CTLSESSION
Сброс данных UserAssist
Данные UEME_CTLSESSION сохраняются даже после выхода пользователя из системы или перезагрузки. Однако, когда общее пользовательское время достигает порога в два дня (то есть общее время в фокусе для всех запущенных программ текущего пользователя составляет два дня), сессия логирования завершается: почти все данные UserAssist сбрасываются.
Происходит сброс практически всех данных UEME_CTLSESSION, включая общие счетчики запусков и переключений, общее пользовательское время и записи NMax. Затем идентификатор сессии увеличивается и начинается новая сессия логирования.
Обновленный идентификатор сессии копируется в смещение 0x0 данных UserAssist каждой программы. Помимо UEME_CTLSESSION, сбрасываются и другие данные UserAssist для каждой программы: счетчики выполнений и фокусировок, время в фокусе и последние 4 байта, назначение которых по-прежнему неизвестно (они всегда равны нулю). Не сбрасывается только время последнего запуска программы. Однако перед сбросом все эти данные сохраняются в виде показателей использования.
Показатели использования и счетчик
Мы проанализировали данные UserAssist различных программ, пытаясь определить назначение неизвестных байтов между секциями времени в фокусе и времени последнего запуска. Как выяснилось, в этом блоке вначале идет список относительных показателей использования — для каждой из десяти последних сессий указано, насколько реже самой «востребованной» программы в этой сессии использовалась искомая программа. За списком следует счетчик перезаписи (индекс последнего записанного значения в этом списке). Теперь мы можем пересмотреть структуру бинарных данных UserAssist с учетом наших находок и полностью описать все ее составляющие.
- 0x0: идентификатор сессии логирования (4 байта)
- 0x4: счетчик выполнений программы (4 байта)
- 0x8: счетчик фокусировок программы (4 байта)
- 0xc: время в фокусе (4 байта)
- 0x10: элемент [0] в списке показателей использования (4 байта)
- 0x14: элемент [1] в списке показателей использования (4 байта)
- 0x18: элемент [2] в списке показателей использования (4 байта)
- 0x1c: элемент [3] в списке показателей использования (4 байта)
- 0x20: элемент [4] в списке показателей использования (4 байта)
- 0x24: элемент [5] в списке показателей использования (4 байта)
- 0x28: элемент [6] в списке показателей использования (4 байта)
- 0x2c: элемент [7] в списке показателей использования (4 байта)
- 0x30: элемент [8] в списке показателей использования (4 байта)
- 0x34: элемент [9] в списке показателей использования (4 байта)
- 0x38: индекс последнего записанного элемента в списке показателей использования (4 байта)
- 0x3c: время последнего запуска (структура Windows FILETIME) (8 байт)
- 0x44: неизвестное значение (4 байта)
По смещениям от 0x10 до 0x37 записаны так называемые значения r0, представляющие собой относительные показатели использования, которые рассчитываются по приведенной ниже формуле.
Значение r0 [индекс] = значение N программы / значение N самой часто используемой программы в сессии (третья запись NMax)
Если программа запускается впервые в рамках текущей сессии логирования, ее значение r0 равно -1 (это заполнитель, не рассчитываемый по формуле).
По смещению 0x38 находится индекс последнего элемента, записанного в список. Он инкрементируется при каждом сбросе UEME_CTLSESSION. Индекс может принимать значения от 0 до 9, поскольку список содержит только значения r0 последних десяти сессий.
Последние четыре байта заполнены нулями. Их назначение остается неизвестным. Согласно нашим наблюдениям, они задействуются только один раз: во время сброса после завершения сессии.
В таблице ниже представлен образец данных UserAssist после парсинга с описанием всех компонентов.
Применение в реагировании на инциденты
Значения r0 содержат очень ценные сведения об использовании программ конкретным пользователем. Они могут существенно помочь в расследовании инцидентов, например:
- Программы со множеством значений 1 в списке r0 — это самые часто используемые программы пользователя.
- Программы со множеством значений 0 в списке r0 — наименее используемые программы, знать которые может быть полезно при поиске угроз, поскольку так можно обнаружить вредоносное ПО либо легитимное ПО, применяемое злоумышленниками.
- Программы со множеством значений -1 в списке r0 — это относительно новые программы, данные по которым еще не были сброшены в рамках двухдневной сессии логирования действий пользователя.
Шаблон данных UserAssist
Как упоминалось выше, когда программа запускается впервые и еще не имеет собственной записи UserAssist (объекта CUACount), создается новая запись со значением UEME_CTLCUACount:ctor. Оно служит шаблоном для бинарных данных UserAssist новой программы и имеет следующие значения:
- Идентификатор сессии логирования = -1 (0xffffffff). Однако это значение сразу перезаписывается значением из текущей сессии UEME_CTLSESSION.
- Счетчик выполнений = 0.
- Счетчик фокусировок = 0.
- Время в фокусе = 0.
- Список показателей использования [0–9] = -1 (0xbf800000, поскольку эти значения представлены числами с плавающей запятой).
- Индекс (счетчик) показателей использования = -1 (0xffffffff).
- Время последнего запуска = 0.
- Последние четыре байта = 0.
Новый парсер
По результатам этого исследования мы разработали новый парсер на основе аналогичной утилиты с открытым исходным кодом. Созданный нами инструмент проводит парсинг всех значений структуры UEME_CTLSESSION и сохраняет результат в файл JSON. Он также анализирует данные UserAssist с учетом знаний о структуре r0, разобранной нами в этом отчете, и сохраняет результат в формате CSV.
Заключение
Мы тщательно изучили артефакт UserAssist и структуру его данных, выявив в процессе анализа разные варианты их состава. Основная функция, отвечающая за обновление данных UserAssist, — это FireEvent из shell32.dll. К вызову функции FireEvent могут приводить разные действия с программами, и в зависимости от этих действий состав данных в записях UserAssist тоже может быть разным.
Мы также исследовали структуру UEME_CTLSESSION, отвечающую за текущую сессию логирования UserAssist. Сессия завершается, когда общее время в фокусе всех программ достигает двух дней. Дальнейшее изучение UEME_CTLSESSION позволило раскрыть назначение ранее не задокументированных бинарных данных UserAssist, которые оказались списком показателей использования программ и счетчиком перезаписи значений.
Артефакт UserAssist является ценным инструментом для реагирования на инциденты, и наши исследования помогут максимально эффективно использовать содержащиеся в нем данные.











Артефакт UserAssist: потенциал для реагирования на инциденты