Привет, Хабр!

Меня зовут Валерия Мавлютова, я младший аналитик-исследователь киберугроз в компании R-Vision. Эта статья является продолжением серии материалов об инструментах для горизонтального перемещения и посвящена достаточно объемному с точки зрения используемых методов — инструменту DCOMExec. Ранее мы уже подробно разобрали такие инструменты, как PsExec, SMBExec и AtExec.

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

Ну что же, начнем!

Общее представление DCOMExec

Инструмент DCOMExec — еще один скрипт из набора Impacket, который использует технологию вызова функций COM-интерфейсов удалённо. Технология называется DCOM (Distributed COM) и работает, как и многое в Windows, через протокол RPC, подробнее про нее мы расскажем чуть позже, но напомним читателю про еще одну нашу статью: RPC и способы его мониторинга.

Инструмент DCOMExec может использовать как минимум три COM-объекта для взаимодействия с удалённой машиной, это:

Каждый из этих объектов имеет функции для запуска произвольного процесса. Собственно, удалённый вызов этих функций можно использовать для горизонтального перемещения.

Для детектирования удаленного вызова функций нам нужно уметь фиксировать две вещи:

1. Сам запрос на использование технологии COM по сети.

2. Какой именно COM-объект был использован.

Все эти данные и немного больше, мы можем получить, проведя анализ трафика. В данном случае он будет полезным источником для понимания того, что происходит во время атаки, так как общение происходит с помощью протокола RPC поверх TCP, поэтому будут видны вызываемые DCOM функции и аргументы к ним.

Таким образом, предлагаем разобраться, как в целом работает DCOM именно на примере сетевого трафика.

Принцип работы DCOM

Алгоритм работы технологии DCOM следующий:

  • вначале происходит классический Bind запрос, где клиент сообщает серверу о желании запустить DCOM;

  • затем клиент вызывает ISystemActivator. ISystemActivator (GUID: {000001a0-0000-0000-c000-000000000046}) — это запрос, посредством которого говорится серверу «я хочу использовать именно этот COM интерфейс». Сервер его понимает и загружает в память нужный COM интерфейс, чтобы клиент мог им пользоваться. Затем сервер возвращает ответ, что его интерфейс загружен и им можно пользоваться.

  • далее клиент делает другой Bind запрос на другой интерфейс (так как для каждого RPC интерфейса нужен отдельный Bind запрос). И теперь клиент сообщает о желании «общаться» c главным интерфейсом DCOM — IDispatcher (GUID: {00020400-0000-0000-C000-000000000046}).

Пример DCOM трафика показан на рисунке 1:

Рисунок 1. DCOM трафик
Рисунок 1. DCOM трафик

Чтобы понять, почему IDispatcher главный, нужно взглянуть на классический COM без буквы D в начале. Подробно о СОМ можно прочитать в нашем цикле статей Тайная жизнь COM: часть 1, часть 2, часть 3.

COM работает так, что клиент не общается напрямую с COM, а просто говорит определенному COM интерфейсу — IUnknown, что именно он хочет сделать. Можно сравнить с тимлидом, к которому нужно идти, чтобы попробовать протолкнуть какую-нибудь фичу.

Так вот, в мире DCOM IDispatch является аналогом IUnknown, который расширяет его функционал и позволяет управлять созданными COM интерфейсами, вызывая его методы и передавая аргументы.

Чтобы заставить COM объект что-то сделать, нам нужно найти функцию, которую мы хотим, чтобы он выполнил. Как нам её найти? Также, как в папках на компьютере — открыть родительскую папку и искать, пока не найдём нужную функцию.

У IDispatcher есть 2 функции, которые клиенту всегда нужно использовать, это:

  1. GetIDsOfNames, которая конвертирует имя функции в число, называемое DISPID, загружает объект в память итд;

  2. Invoke, запускающая функцию. Но для запуска ей передается как раз не имя функции, а число, которое отдаёт GetIDsOfNames. То есть, получается, чтобы вызвать какую-то функцию, нам нужно вызвать эти две по очереди.

Для применения определённого COM метода через DCOM необходимо до него «дойти», так как он может принадлежать атрибуту COM объекта, и чтобы обратиться к методу, нужно сначала обратиться к атрибуту. Эту цепь можно сравнить с вложенностью формата JSON.

Например, чтобы использовать метод ExecuteShellCommand, который входит в состав COM объекта MMC20.Application, нужно обратиться сначала к объекту Document, потом к дочернему атрибуту ActiveView и затем к методу ExecuteShellCommand. Каждый из этих объектов/атрибутов должен быть вызван с помощью ISystemActivator и IDispatch, как и любой другой метод.

Поэтому в трафике будет хорошо видна последовательность вызовов, из которой можно составить путь до COM метода и просмотреть аргументы, с которыми этот метод вызывается.

Предлагаем посмотреть трафик при вызове COM объектов, которые использует инструмент DCOMExec, а также посмотреть, чем они отличаются.

Объект MMC20.Application

MMC20.Application —  это COM-объект, позволяющий создавать сценарии для компонентов оснастки MMC. DCOMExec использует метод с именем ExecuteShellCommand в Document.ActiveView для удаленного выполнения команд.

На рисунке 2 показан трафик при вызове данного объекта инструментом DCOMExec:

Рисунок 2. Трафик при вызове объекта MMC20.Application
Рисунок 2. Трафик при вызове объекта MMC20.Application

В трафике можно увидеть все вызовы, которые мы рассматривали ранее. Алгоритм вызова методов, следующий:

  1. Document;

  2. ActiveView;

  3. ExecuteShellCommand;

Также в трафике можно увидеть аргументы к вызову метода, в нашем случае это C:\Windows\system32\cmd (рисунок 3):

Рисунок 3. Аргументы при вызове метода ExecuteShellCommand
Рисунок 3. Аргументы при вызове метода ExecuteShellCommand

Теперь рассмотрим еще один COM-объект, который использует DCOMExec, и это ShellWindows.

Объект ShellWindows

Объект ShellWindows представляет коллекцию открытых окон оболочки (Shell). Чтобы добиться фактического взаимодействия с удаленным хостом, необходимо получить доступ к методу WindowsShell. Item, который вернет нам объект, представляющий окно оболочки Windows. А с помощью метода с именем ShellExecute мы можем удаленно выполнить нужные команды.

На рисунке 4 показан трафик при вызове данного объекта инструментом DCOMExec:

Рисунок 4. Трафик при вызове объекта ShellWindows
Рисунок 4. Трафик при вызове объекта ShellWindows

В случае с ShellWindows порядок вызова методов такой:

  1. Item;

  2. Document;

  3. Application;

  4. ShellExecute;

Точно также в трафике можно увидеть аргументы к вызову метода, в нашем случае это C:\Windows\system32\cmd.

Рисунок 5. Аргументы при вызове метода ShellExecute
Рисунок 5. Аргументы при вызове метода ShellExecute

Объект ShellBrowserWindow

Как и в случае с объектом ShellWindow, при использовании объекта ShellBrowserWindows с помощью метода ShellExecute можно удаленно выполнить нужные команды (рисунок 6), однако нужно отметить, что данный объект не существует в Windows 7, и он напрямую взаимодействует с оболочкой Windows, поэтому в этом случае вызов WindowsShell.Item будет отсутствовать.

Рисунок 6. Трафик при вызове объекта ShellBrowserWindows
Рисунок 6. Трафик при вызове объекта ShellBrowserWindows

В случае с ShellBrowserWindow порядок вызова методов, следующий:

  1. Document;

  2. Application;

  3. ShellExecute;

Также как и с другими объектами в трафике, можно посмотреть аргументы метода (рисунок 7):

Рисунок 7. Аргументы при вызове метода ShellExecute
Рисунок 7. Аргументы при вызове метода ShellExecute

Теперь, когда мы разобрали порядок вызова методов в рассматриваемых объектах и как они вызываются при эксплуатации DCOMExec в трафике, посмотрим, как можно отследить эксплуатацию данного инструмента по событиям журнала Windows.

Журнал Windows EventLog

И сначала посмотрим, по каким событиям журнала Security можно обнаружить факт эксплуатации DCOMExec в случае использования COM объекта MMC20.Application.

События при использовании объекта MMC20.Application

Первым делом нужно понимать, что COM объект был вызван по сети.

Сначала эксплоит делает RPC вызовы, которые передаются сервису RPCSS (Или RPC Service Subsystem отвечает за серверную обработку RPC функций), тот в последствии передаёт их DCOM сервису, имеющему следующие параметры при запуске экземпляра сервиса:

C:\Windows\system32\svchost.exe -k DcomLaunch -p

Конкретно в случае MMC20 сервис запускает mmc.exe с флагом -Embedding (EventID 4688) (рисунок 8).

Так как из событий журнала Windows Security сложно понять, какой именно сервис скрывается под процессом svchost.exe, можно ориентироваться только на параметры запуска mmc.exe, при тестах не было найдено ни одного другого процесса, который запускает mmc.exe с таким параметром.

Рисунок 8. Запуск mmc.exe с флагом -Embedding
Рисунок 8. Запуск mmc.exe с флагом -Embedding

На этом моменте мы уже знаем, что запрос пришел извне, так как задействован DCOM сервис. Но мы пока не знаем, что именно будет делать mmc.exe. Будем это исправлять.

При исследовании выяснилось, что mmc.exe при вызове COM интерфейса смотрит в реестр вот по такому пути HKCU\Software\Classes\CLSID\{49B2791A-B1AE-4C90-9B8E-E860BA07F889}, где указан CLSID COM интерфейса MMC20.Application, который применяется для запуска произвольной команды (EventID 4663 - An attempt was made to access an object) (рисунок 9). Таким образом, можно понять, что mmc.exe вызывает этот конкретный COM объект, и этот способ мы будем использовать в дальнейшем для всех COM интерфейсов, которые могут быть применены для горизонтального перемещения.

Рисунок 9. Доступ до ветки реестра с CLSID COM объекта MMC20.Application
Рисунок 9. Доступ до ветки реестра с CLSID COM объекта MMC20.Application

После этого mmc. exe запустит произвольный исполняемый файл с переданными ему параметрами. На этом моменте мы точно знаем, что произошла DCOM «атака».

Рисунок 10. Запуск cmd от имени mmc.exe
Рисунок 10. Запуск cmd от имени mmc.exe

События при использовании объекта ShellWindows

В этом методе используется COM объект ShellWindows, который имеет возможность запуска произвольного исполняемого файла из-под explorer.exe.
В отличии от MMC20, при детекте этого метода довольно сложно понять, что COM объект был вызван по сети, так как explorer.exe всегда запущен в Windows, и нельзя проверить родительский процесс и его флаги, чтобы убедиться в удалённом характере этого вызова.

Самый первый маркер атаки — это запрос от имени explorer. exe ветки реестра нужного COM объекта, который не используется при «обычной», ежедневной работе Windows (рисунок 11).

Рисунок 11.  Запрос от имени explorer.exe ветки реестра COM объекта ShellWindows
Рисунок 11. Запрос от имени explorer.exe ветки реестра COM объекта ShellWindows

Второй шаг, он же финальный и не такой «яркий» — событие запуска произвольного исполняемого файла от имени explorer. exe (рисунок 12). Не такой он по причине «нормальности» такой ситуации, ведь пользователь чаще всего запустит приложение двойным нажатием, и оно запустится как дочерний процесс explorer. exe.

Рисунок 12. Запуск cmd от имени explorer.exe
Рисунок 12. Запуск cmd от имени explorer.exe

События при использовании объекта ShellBrowserWindow

Этот метод аналогичен предыдущему, но с использованием COM-объекта ShellBrowserWindow, отличия только в его CLSID. Тут также имеется возможность запуска произвольного бинарника из-под explorer. exe, а также есть сложности с пониманием откуда был вызван COM объект.

Самый первый маркер атаки — это запрос от имени explorer. exe ветки реестра нужного COM объекта, который так же не используется при «обычной» работе Windows (рисунок 13).

Рисунок 13.  Запрос от имени explorer.exe ветки реестра COM объекта ShellBrowserWindow
Рисунок 13. Запрос от имени explorer.exe ветки реестра COM объекта ShellBrowserWindow

И также, как и в случае с ShellWindows, мы наблюдаем за дочерним процессом explorer.exe.

Рисунок 14. Запуск cmd от имени explorer.exe
Рисунок 14. Запуск cmd от имени explorer.exe

Смотря на эти события, у нас фактически существует только одна проблема - нужно логировать факт удалённого вызова ShellWindows & ShellBrowserWindow.

Поэтому в дополнение к вышеописанным событиям можно также добавить следующее:

Рисунок 15. Событие сетевого входа в систему по протоколу NTLM с ip-адресом источника
Рисунок 15. Событие сетевого входа в систему по протоколу NTLM с ip-адресом источника

Данное событие однозначно не говорит об удаленном вызове ShellWindows & ShellBrowserWindow, однако указывает на то, что в систему залогинились удаленно. Соответственно, при удаленной эксплуатации DCOMExec в журнале присутствует событие логона EventID 4624 c LogonType 3 и не пустым полем SourceNetworkAddress. Так мы можем узнать ip-адрес хоста атакующего и поступление данного события одновременно с событиями 4663 и 4688, где будет фигурировать один и тот же пользователь, будет говорить об удаленной эксплуатации DCOMExec.

Посмотрим дополнительные источники событий, которые, возможно, тоже указывают эксплуатацию DCOM-exec, а именно на удаленный вызов методов ShellWindows & ShellBrowserWindow.

Event Tracing for Windows (ETW)

При работе с RPC и ETW сразу приходят мысли на выуживание информации из Microsoft-Windows-RPC провайдера, который покажет, какой объект с каким методом был вызван. Конкретно в этой атаке не стоит использовать ETW как полностью самостоятельный источник информации, так как он даёт лишь общую информацию о факте использования DCOM, но ничего о том, какой именно COM интерфейс использовался.

Попробуем посмотреть, как в ETW логах отображается DCOM lateral movement в хронологическом порядке.

Стоит сразу обозначить какой OpNum какой метод означает:

  • OpNum 4 == RemoteCreateInstance. COM интерфейс ISystemActivator

  • OpNum 5 == GetIDsOfNames. COM интерфейс IDispatch

  • OpNum 6 == Invoke. COM интерфейс IDispatch

Сначала мы можем увидеть подключение к ISystemActivator. Это определяется по GUID интерфейса и OpNum == 4 (рисунок 16).

Рисунок 16. Событие подключения к ISystemActivator
Рисунок 16. Событие подключения к ISystemActivator

Далее идёт IDispatch, использующий метод GetIDsOfNames для загрузки необходимого COM объекта в память (рисунок 17).

Рисунок 17. Событие вызова метода GetIDsOfNames
Рисунок 17. Событие вызова метода GetIDsOfNames

После этого вызывается метод Invoke интерфейса IDispatch, который служит уже для вызова метода определённого COM объекта (рисунок 18).

Рисунок 18. Событие вызова метода Invoke
Рисунок 18. Событие вызова метода Invoke

К сожалению, эти события не говорят ни о чём, кроме факта использования DCOM и вызова неизвестного COM объекта. Без информации о том, какой именно интерфейс был вызван, будет сложно связать эту деятельность с атакой. Ведь любой пользователь может вызывать DCOM и при этом не быть атакующим.

CombaseTraceLoggingProvider

Можно использовать CombaseTraceLoggingProvider для определения, какой именно COM объект был вызван на стороне сервера, то есть на атакуемой машине. Пример лога, который показывает вызов COM-объекта MMC20.Application (49B2791A-B1AE-4C90-9B8E-E860BA07F889) представлен ниже:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
        <System>
                <Provider Name="CombaseTraceLoggingProvider" Guid="{1aff6089-e863-4d36-bdfd-3581f07440be}" />
                <EventID>3484</EventID>
                <Version>0</Version>
                <Level>5</Level>
                <Task>0</Task>
                <Opcode>0</Opcode>
                <Keywords>0x400000000000</Keywords>
                <TimeCreated SystemTime="2022-07-05T15:01:31.447239200+02:59" />
                <Correlation ActivityID="{5193d10e-4434-4bce-a7f0-bc5db7292044}" />
                <Execution ProcessID="852" ThreadID="188" ProcessorID="0" KernelTime="0" UserTime="0" />
                <Channel />
                <Computer />
        </System>
        <EventData> 
                <Data Name="CLSID">{49B2791A-B1AE-4C90-9B8E-E860BA07F889}</Data>
                <Data Name="ACID"></Data>
                <Data Name="ExecutionPackageName"></Data>
                <Data Name="ClientPID">       0</Data>
                <Data Name="AAMActivationID">0</Data>
                <Data Name="ClientPackageName"></Data>
        </EventData>
        <RenderingInfo Culture="en-US">
                <Task>COMOutOfProcessServerLaunchStart</Task>
        </RenderingInfo>
</Event>

Мы также можем увидеть, что вызывающий этот COM объект процесс имеет PID == 0 в строке ClientPID, и, соответственно, можно предположить, что вызывающий процесс на самом деле на удалённой машине и у провайдера CombaseTraceLoggingProvider нет способов узнать, кто на самом деле клиент этого COM объекта, поэтому PID == 0.

Если лог лишь указывает на факт вызова объекта и то, что вызван он был с удалённой машины, то мы можем совместить его с логами из EventLog и решить проблему с ShellWindows & ShellBrowserWindow. Однако, данный провайдер "эфемерен" и есть не во всех версиях ОС, поэтому в основное правило детекта мы его не включили.

Теперь, рассмотрев возможные источники полезных для детекта логов, попробуем составить возможные правила детектирования эксплуатации DCOMExec.

Возможные правила детектирования

ShellWindows и ShellBrowserWindow

При использовании COM-объектов ShellWindows и ShellBrowserWindows можно выделить следующие моменты, которые помогут нам в построение логики детектирования.

В один и тот же момент времени происходит:

  • Запрос от Explorer.exe ветки реестра COM объектов ShellWindows и ShellBrowserWindow.

  • Запуск cmd.exe с определенными параметрами.

  • Фиксируется событие сетевого входа в систему.

  • Все действия происходят из-под одного и того же пользователя.

Пример псевдо-правила:

SELECT (host, TargetUserName) 
FROM EventCode = 4688 
WHERE 
(Process_Command_Line="\"C:\\Windows\\System32\\cmd.exe\" /Q /c*") AND
(process_command_line_arguments="*1&gt; \\\\127.0.0.1\\ADMIN$\\__16893 2&gt;&amp;1") AND
(process_exec="cmd.exe") 
(ParentProcessName="explorer.exe")
IN 
	( 
	SELECT (host, TargetUserName)
	FROM EventCode = 4663 
	WHERE ObjectName IN ("\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\CLSID\\{c08afd90-f2a1-11d1-8455-00a0c91f3880}", "\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\CLSID\\{9BA05972-F6A8-11CF-A442-00A0C90A8F39}") AND
	ProcessName="C:\\Windows\\explorer.exe" 
		SELECT (host, TargetUserName) 
		FROM EventCode = 4624 
		WHERE IpAddress!="-" AND
		LogonType!="3"
)

MMC20.Application

При использовании COM-объекта MMC20.Application можно выделить:

  • Запуск mmc.exe с параметром "- Embedding".

  • Запрос от имени mmc.exe ветки реестра COM объекта MMC20.Application.

  • Все действия происходят из-под одного и того же пользователя.

Пример псевдо-правила:

SELECT (host, TargetUserName) 
FROM EventCode = 4688 
WHERE 
(Process_Command_Line="C:\\Windows\\system32\\mmc.exe -Embedding") IN 
( 
	SELECT (host, TargetUserName)
	FROM EventCode = 4663 
	WHERE ObjectName="\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\CLSID\\{49B2791A-B1AE-4C90-9B8E-E860BA07F889}" AND
	ProcessName="*mmc.exe" 
)

Заключение

Сегодня мы рассказали об еще одном инструменте из набора скриптов Impacket, который применяют злоумышленники при горизонтальном перемещении, а именно DCOMExec.

В статье на примере сетевого трафика мы разобрали работу технологии DCOM, ведь на ней и строится работа инструмента DCOMExec. Рассмотрели теоретические аспекты обнаружения и на практике разобрали возможные источники логов для построения псевдо-правил. В качестве итога на основе журнала EventViewer были представлены варианты псевдо-правил для обнаружения эксплуатации DCOMExec в случае использования всех трех COM-объектов.

Оставляйте ваши комментарии ниже и пишите вопросы. Надеемся, статья оказалась вам полезной!

Комментарии (0)