Привет, Хабр!
Изучая отчеты по разбору вредоносного ПО, приходишь к выводу, что в последнее время одним из популярных методов для закрепления в системе является COM Hijacking (T1546.015), применяемый атакующими для закрепления зловредов в ОС Windows через Component Object Model. Яркий тому пример - использование COM Hijacking группировкой Fancy Bear, а также вредоносными программами,такими как Jumplump и одной из недавних - RomCom.
При этом, если рассмотреть подробнее использование RomCom, можно увидеть, что он перезаписывает COM-объект с GUID {C90250F3-4D7D-4991-9B69-A5C5BC1C2AE6}
с соответствующим файломActXPrxy.dll
, предназначенным для управления компонентами «ActiveX» Windows, на prxyms.dll
. В то же время одним из процессов, который использует данный COM-объект, является explorer.exe
. Это означает, что закрепление в системе гарантированно, поскольку без данного процесса не обходится работа на устройстве с операционной системой Windows.
Таким образом, умение детектировать данный вид атаки является важным аспектом для Blue Team. Поэтому я решила подготовить серию статей, посвященных технологии Component Object Model (COM), а также разбору атаки COM Hijacking и ее детектированию.
Сегодня я начну с основ и расскажу вам о том, что представляет собой Component Object Model. Сразу отмечу, что данная тема очень обширная, и разобрать ее подробно в одном материале не получится. В этой статье мною будут рассмотренны базовые понятия COM, которые в будущем помогут нам лучше понимать принцип работ атаки COM Hijacking. После чего я проанализирую, какие стратегии может ипользовать злоумышленник для выбора подходящего COM-объекта с целью последующей атаки.
Немного определений
COM (Component Object Model) - это стандарт, позволяющий разработчикам повторно использовать в своем коде независимые компоненты ПО. При этом им не нужно знать внутреннее устройство данных компонентов, заниматься их совместимостью на разных языках программирования и повторной компиляцией.
Также в начале статьи я уже упомянула такое понятие, как COM-объект. За ним кроется определение объекта, в котором указаны данные о нем и о наборе интерфейсов для обеспечения его функциональности. COM-объект реализуется в форматах DLL или EXE.
На основе стандарта COM выполняется очень много процессов в Windows, поэтому отключить его с целью защитится от атакующих не получится. Соответственно, атаки с помощью COM-объектов становятся лакомым кусочком для злоумышленников.
Программное обеспечение для поиска необходимого COM-объекта использует реестр, поэтому далее мы рассмотрим, какие ключи задействованы в данном процессе и можно ли их применять для проведения атаки (Спойлер: ДА!).
Представление COM-объектов в реестре
Реестр содержит информацию обо всех установленных в системе COM-объектах, которая находится в следующих ветках:
HKEY_LOCAL_MACHINE\Software\Classes
(HKLM) - информация, применимая на локальном компьютере при любом активном пользователе;HKEY_CURRENT_USER\Software\Classes
(HKCU) - информация, применимая к текущему интерактивному пользователю;HKEY_CLASSES_ROOT
(HKCR) - виртуальный куст, объединяющий сведения из двух выше указанных веток. Объединение происходит по определенному правилу: включаются все разделы и ключи изHKCU\Software\Classes
, а изHKLM\Software\Classes
включаются разделы и ключи, отсутствующиеHKCU\Software\Classes
.
Так как архитектура 64-битной операционной системы поддерживает совместимость с x86 приложениями, существуют дополнительные ветки в реестре, представленные под спойлером:
COM-объекты в x64 архитектуре ОС для x86 приложений
Для поддержания 32-разрядных приложений в 64-разрядный операционных системах Windows используются аналогичная структура ключей, но вложены они в Wow6432Node. Например:
HKEY_CURRENT_USER\SOFTWARE\WOW6432Node\Classes;
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes;
HKEY_CLASSES_ROOT\WOW6432Node.
Во всех выше перечисленных ветках есть подраздел CLSID, содержащий идентификаторы (GUID) класса. А дальше, в зависимости исходных данных атакующего, используются следующие подразделы:
InprocServer/InprocServer32
- путь к dll-библиотеке, который будет подгружаться в процесс, вызванный COM-объектом;LocalServer/LocalServer32
- путь к исполняемому файлу (.exe). В данном случае COM-объект запускается в новом процессе;TreatAs
- перенаправляет на другой COM-объект, путем указанияCLSID
;ProgID
- текстовый идентификатор, который используется аналогичноCLSID
.ProgID
всегда сопоставляетсяCLSID
, и на последующих шагах используется именно он;VersionIndependentProgID
- аналогиченProgID
, но имеет некоторые исключения.ProgID
может содержать в себе версию COM-объекта и обслуживается непосредственно кодом приложения, в то время какVersionIndependentProgID
указывает единый независимый от версии идентификатор. И в ответ уже сопоставляется сCLSID
последней версии объекта.
Как мы видим, существует достаточно большое разнообразие ключей реестра. Здесь может возникнуть вопрос: а как система понимает, каким именно из этих ключей воспользоваться? Дальше мы как раз и поговорим о порядке проверки и применении ключей в реестре, что позволит в будущем нам оценить все возможные варианты атаки.
Порядок проверки ключей в реестре
Согласно документации Microsoft, параметры, указанные для интерактивного пользователя в HKCU\Software\Classes
, имеют приоритет над HKCR (HKLM). Если процесс запускается в интерактивном сеансе с правами администратор (т.е. уровень целостности выше среднего), и при этом UAC отключен, то применяется конфигурация, указанная в HKLM. Подробнее про UAC и методы его обхода можно почитать в статье моего коллеги. Процессы, которые не выполняются в контексте безопасности интерактивного пользователя, не используют HKCU и HKCR, а напрямую обращаются к HKEY_LOCAL_MACHINE\Software\Classes
.
Итак, с приоритетом веток мы разобрались. Выбор между ProgID и CLSID тоже понятен - он зависит от обращение к COM-объекту: идет ли оно через GUID или используется текстовый идентификатор. А вот приоритет внутри CLSID между параметрами InprocServer, LocalServer и TreatAs пока не известен. Поэтому давайте проверим его на практике и для этого проведем небольшой эксперимент.
Выбор приоритета внутри CLSID
Как правило, сразу три параметра не указываются, но нам ничего не мешает сделать это. Для этого я создала два dll-файла (для ключей InprocServer
и TreatAs
) и exe (для ключа LocalServer
) с разными MessageBox. Под спойлером представлен конфигурационный файл реестра для проведения эксперимента. В нем указаны сразу все три ключа, а также применение созданных мною соответствующих исполняемых файлов.
Конфигурация реестра
Для проведения эксперимента на устройстве применена следующая конфигурация реестра:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-0000FEEDACDC}]
@="ComHijacking"
[HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-0000FEEDACDC}\InprocServer32]
@="C:\\hijacking_dll_treatas.dll"
"ThreadingModel"="Apartment"
[HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\{72C34DD5-D70A-438B-8A42-98424B88AFB8}]
[HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\{72C34DD5-D70A-438B-8A42-98424B88AFB8}\TreatAs]
@="{00000001-0000-0000-0000-0000FEEDACDC}"
[HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\{72C34DD5-D70A-438B-8A42-98424B88AFB8}\InprocServer32]
@="C:\\hijacking_dll_inprocserver.dll"
"ThreadingModel"="Apartment"
[HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\{72C34DD5-D70A-438B-8A42-98424B88AFB8}\LocalServer32]
@="C:\\hijacking_exe_localserver.exe"
[HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\{72C34DD5-D70A-438B-8A42-98424B88AFB8}\ProgID]
@="Hijack.COM"
[HKEY_CURRENT_USER\SOFTWARE\Classes\Hijack.COM]
@=""
[HKEY_CURRENT_USER\SOFTWARE\Classes\Hijack.COM\CLSID]
@="{72C34DD5-D70A-438B-8A42-98424B88AFB8}"
Далее производится вызов COM-объекта по ProgID "Hijack.COM". На рисунке 1 видно, что заданных всех выше перечисленных параметров наивысший приоритет имеет TreatAs
. В свою очередь, Process Monitor показывает, что было обращение только к ключу TreatAs
, остальные ключи не проверялись (рисунок 2).
Ниже на рисунке 3 мы видим, что если из всех заданных ключей убрать TreatAs
, а оставить LocalServer32
и InprocServer32
, то в текущей ситуации приоритет будет иметь InproceServer32
. При этом Process Monitor показывает, что сначала был запрос к TreatAs
, но так как он не задан, запрос оказался безуспешным (рисунок 4). На следующем этапе было получено значение из InprocServer32
, а потом из LocalServer32
, но приоритет был отдан InprocServer32
.
Логично, что убрав все ключи, кроме LocalServer32
обращение будет произведено именно к нему (LocalServer32)
(рисунок 5) . В то же время, Process Monitor показывает, что сохраняется последовательность обращений к реестру, но к TreatAs
и InprocServer32
они безуспешны.
Подводя итог нашего эксперимента, сделаем вывод, что приоритет ключей в реестре определяется в следующем порядке: TreatAs
> InprocServer32
> LocalServer32
.
Интересно то, что приоритет этих ключей выше приоритета рассмотренных ранее веток. Это значит, что, например, наличие ключа InprocServer32
в HKCR приоритетнее, чем ключ LocalServer32
в HKCU. То есть более привилегированный ключ в менее привилегированной ветке будет иметь приоритет над менее привилегированным ключом в более привилегированной ветке реестра. Ниже показано это выглядит в схематичном виде:
Таким образом, определив приоритет выбора ключа, по которому будет исполняться COM-объект, мы поймем, что атакующий может этим воспользоваться и переопределить COM-объект, указав в более приоритетном ключе значение, ссылающееся на вредоносный объект.
Но то, какими правами нужно обладать для изменения этих ключей, разберем далее.
Права доступа на редактирование реестра
Как видно из рисунка 8, ветка HKCU может изменяться интерактивным пользователем без прав администратора.
А дальше мы видим, что HKLM и HKCR требует прав локального администратора или SYSTEM для изменения (рисунки 9 и 10) . Согласно документации Microsoft, если вносить изменения в HKCR, то они буду прописываться в HKEY_LOCAL_MACHINE\Software\Classes
.
В Windows существует большое количество COM-объектов, а при установке дополнительного прикладного ПО, это количество только растет.
Тогда как же злоумышленнику определиться, какой COM-объект лучше всего атаковать? Для этого мы посмотрим, каким критериям должен соответствовать выбранный COM-объект, а затем разберем стратегии, которыми может пользоваться атакующий при выборе COM-объекта для атаки.
Выбор COM-объекта для атаки
Безусловно, можно создать новый COM-объект и дальше попытаться его вызвать, но чтобы сделать этого без "лишнего шума" лучше воспользоваться существующими ключами, которые могут быть уже настроены на вызов по какому-либо триггеру. Выбранный COM-объект должен соответствовать двум критериям: первый их них - часто запускаться, а второй - не ломать логику работы приложений.
Для выбора подходящего COM-объекта существует несколько стратегий, давайте их рассмотрим поподробнее.
Часто используемые COM-объекты
Первая стратегия будет основываться на использовании такого инструмента, как Process Monitor. Суть метода заключается в том, чтобы собрать события запросов к реестру с ключами InprocServer32
, LocalServer32
, TreatAs
, ScriptletURL
, ProgID
или любой ключ в разделе \Classes\
(рисунок 11), а далее оценить какие COM-объекты наиболее часто используются (рисунок 12). При этом для удобства можно выгрузить в CSV файл, а далее в EXEL посчитать статистику.
На основании полученной оценки производится выбор наиболее подходящего COM-объекта для атаки COM-hijacking. О том, как используется выбранный объект дальше, я расскажу в последующих статьях.
Так с помощью данного метода можно обнаружить следующие COM-объекты:
Легитимное ПО |
GUID COM-объекта |
Легитимное значение по умолчанию |
Вредоносное ПО |
wmiprvse.exe |
{CF4CC405-E2C5-4DDD-B3CE-5E7582D8C9FA} |
|
|
firefox.exe |
{1f486a52-3cb1-48fd-8f50-b8dc300d9f9d} |
|
|
explorer.exe |
{42aedc87-2188-41fd-b9a3-0c966feabec1} |
|
Отсутствующие в HKCU COM-объекты
Вторая стратегия также основывается на использовании Process Monitor, но в данном случае выбираются не самые популярные, а отсутствующие в HKCU COM-объекты (рисунок 13). В HKCU проверка проходит раньше, чем в HKCR. Исключение составляют процессы с высоким уровнем целостности. Это сделано для того, чтобы предотвратить повышение привилегий.
Полученный результат можно сохранить в CSV формате, а далее отфильтровать уникальные значения в EXEL. Или воспользоваться автоматизацией, "скормив" данный CSV-файл acCOMplice. Этот набор скриптов предназначен для изучения атаки COM-hijacking: с его помощью можно определить подходящий COM-объект для использования в атаке, а затем провести на выбранный объект атаку COM-hijacking. Так, например, функция Extract-HijackableKeysFromProcmonCSV выводит уникальные COM-объекты из CSV-файла (рисунок 14).
Использование обнаруженных COM-объектов вредоносным ПО представлено в таблице:
Легитимное ПО |
GUID COM-объекта |
Легитимное значение по умолчанию |
Вредоносное ПО |
explorer.exe |
{00020424-0000-0000-c000-000000000046} |
|
Фантомные COM-объекты
Третья стратегия базируется на выявлении COM-объектов, ссылающихся на несуществующие dll или exe файлы. Пример получения списка COM-объектов с отсутствующими исполняемыми файлами показан на рисунке ниже. Таким образом можно будет положить файл по требуемому пути с нужным именем и не изменять реестр. Подобные COM-объекты называются Phantom COM.
Такого же результата возможно добиться и с помощью утилиты acCOMplice, что наглядно отображено на рисунке 16. В функции Find-MissingLibraries осуществляется получение значений ключей реестра inprocserver
и localserver
в ветке HKCR\CLSID
. Далее происходит проверка, на предмет существования на диске файла, полученного на предыдущем этапе из реестра. Дополнительно можно проверить права пользователя на данный файл. Если он не найден, то данный COM-объект является потенциальным для использования в атаке.
Если в представленной выше утилите для получения списка COM-объектов использовались запросы к реестру, то аналогичную информацию можно узнать с помощью wmi, выполнив командуgwmi Win32_COMSetting
.
Использование обнаруженных COM-объектов вредоносным ПО представлено в таблице:
Легитимное ПО |
GUID COM-объекта |
Легитимное значение по умолчанию |
Вредоносное ПО |
microsoftedgeupdate.exe |
<> |
|
COM-объекты в запланированных задачах
Четвертый способ строится на анализе запланированных задач (ScheduledTask). Данный метод был автоматизирован с помощью powershell скрипта Get-ScheduledTaskComHandler. Он осуществляет проверку всех ScheduledTask, где в качестве обработчика назначен Custom handler
(т.е. использование COM). Для этого скрипт получает описание запланированных задач в xml формате, которые располагаются по пути: C:\Windows\System32\Tasks
. Далее выбираются только те задачи, у которых в качестве Actions
используется ComHandler
. По полученному CLSID из xml осуществляется поиск dll в реестре по пути HKCR:\CLSID\{GUID}\InprocServer32
. Дополнительно происходит проверка, в каком контексте выполняется задача (InteractiveUsers, AllUsers, AnyUser) и выполняется ли задача при логоне пользователя или нет.
Просто запуск скрипта без каких-либо параметров выводит все задачи, использующие COM (рисунок 18).
Если использовать параметр -PersistenceLocations
, то в результате мы получим список задач, которые можно использовать для закрепления в системе с помощью COM Hijacked, что видно на рисунке 19. В данном случае осуществляется дополнительная проверка того, что задача выполняется в пользовательском контексте и запускается при входе пользователя.
Данный способ покрывает сразу два этапа атаки: выбор COM-объекта и вызов вредоносного объекта при каждом входе пользователя. Атакующему остается только заменить COM-объект на вредоносный (об этом будет рассказано в последующих статьях).
Примеры COM-объектов, используемые атакующими
Также мною были проанализированы отчеты по ransomware и APT за последнее время. Опираясь на них, можно сделать вывод, что наиболее популярными COM-объектами у атакующих в данной атаке являются следующие объекты:
GUID COM-объекта |
Легитимное значение по умолчанию |
{BCDE0395-E52F-467C-8E3D-C4579291692E} |
|
{00021401-0000-0000-C000-000000000046} |
|
{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5} |
|
{CF4CC405-E2C5-4DDD-B3CE-5E7582D8C9FA} |
|
{7C857801-7381-11CF-884D-00AA004B2E24} |
|
{ddc05a5a-351a-4e06-8eaf-54ec1bc2dcea} |
|
{1f486a52-3cb1-48fd-8f50-b8dc300d9f9d} |
|
{4590f811-1d3a-11d0-891f-00aa004b2e24} |
|
{4de225bf-cf59-4cfc-85f7-68b90f185355} |
|
{F56F6FDD-AA9D-4618-A949-C1B91AF43B1A} |
|
Такие COM-объекты по умолчанию присутствуют в Windows и часто вызываются легитимными процессами. Например, как можно заметить, часть из этих объектов относятся к WMI. Многие встроенные в Windows утилиты по типу tasklist.exe
, systeminfo.exe
и др., под капотом используют WMI и, следовательно, используют данные COM-объекты. Этот факт гарантирует атакующему, что после выполнения замены COM-объекта на вредоносный он будет вызываться в системе жертвы и при этом достаточно часто.
Заключение
В этой статье я рассмотрела базовые принципы устройства Component Object Model в Windows. Из всего выше сказанного особо важным является приоритет ключей InprocServer
, LocalServer
и TreatAs
. Именно игра на приоритетах делает возможным проведение атаки COM-Hijacking. COM-объекты в ветке HKCU имеют больший приоритет, а также данная ветка дает права на запись для интерактивного пользователя, т.е. атакующему не требуется искать способы для повышения привилегий.
Кроме этого, мною были проанализированы четыре основных способа выбора COM-объекта, любым из которых можно воспользоваться. Уверена, данные способы не являются исчерпывающими. Но если цель атакующего - закрепление в системе, а атака COM-Hijacking относиться именно к закреплению, то важно учитывать, что выбранный COM-объект должен часто запускаться на устройстве жертвы и не ломать логику работы других процессов, использующих его.
Надеюсь данная статья оказалась для вас полезной! Если у вас появились вопросы, пишите в комментариях!
Автор: Кожушок Диана( @wildresearcher), аналитик-исследователь киберугроз в компании R-Vision
Mingun
Что за чепуха. Сами же написали, что HKCR виртуальный куст, поэтому никаких "раньше" быть не может (между HKCU и HKCR, так как первое часть второго). Это самое обычное наследование свойств. Сначала читаются свойства из HKLM, затем на них накладываются свойства (и перекрывают, а если нечего перекрывать, то просто добавляются) из HKCU. Итоговое дерево называется HKCR.
wildresearcher Автор
Верно, HKCR состоит из HKLM+HKCU. Когда вы запускаете какой-либо COM-объект, то поиск осуществляется в двух ветках по очереди: в HKCU, а затем HKCR. Если в HKCU значение не найдено, то в HKCR будет хранится значение из HKLM. То есть по сути можно заменить "
InprocServer32
в HKLM приоритетнее, чем ключLocalServer32
в HKCU." Но напрямую не осуществляется запрос в HKLM, вместо этого используется HKCR. Чтобы увидеть о чем я говорю запустите Procmon, обратитесь к какому-либо COM-объекту и вы увидите данные события в этой очередности.wildresearcher Автор
Что касательно этой фразы, то исходные данные такие: есть COM-объект, у него заданы
InprocServer32 в HKLM и LocalServer32
в HKCU. В HKCR тогда будут иInprocServer32, и LocalServer32. Изначально будет поиск InprocServer32 напрямую в HKCU, но там он будет не найден по понятным причинам. Далее будет осуществляться поиск InprocServer32 в HKCR(но считай в HKLM). И по итогу будет выбран именно он для использования, хотя при всем этом в
HKCU был еще заданLocalServer32.