
Инструмент живого мониторинга удалённых сеансов PowerShell с использованием ETW для захвата и декодирования протокола WinRM/PSRP, предоставляющий трассировку выполнения команд и журналирование для анализа безопасности.
RemotePSpy обеспечивает мониторинг удалённых сеансов PowerShell в реальном времени, что особенно полезно для старых (до версии 5.0) версий PowerShell, в которых нет встроенных комплексных средств ведения журналов.
Инструмент использует Event Tracing for Windows (ETW) для получения данных сообщений из протокола WinRM, который используется в качестве транспорта для удалённого PowerShell, и декодирует различные уровни протокола, чтобы предоставить трассировку выполненных команд сценариев и их ввода/вывода.
В настоящее время это ранний исследовательский прототип, поэтому он не поддерживает все аспекты протокола удалённого PowerShell (PSRP). Тем не менее, он может дать полезное представление о том, что происходит в удалённом сеансе PowerShell.
Самый простой способ установки — с помощью pip:
pip install remotepspy
Зависимости должны устанавливаться автоматически при установке через pip, но если вы хотите установить из исходного кода, они перечислены здесь:
libwim-15.dll требуется только при использовании (рекомендуемого и используемого по умолчанию) поставщика ETW Microsoft-Windows-WinRM в качестве источника данных. Она используется для распаковки определённых потоковых объектов в протоколе WinRM/WSMan, которые содержат фрагменты сообщений PSRP. Просто поместите её в тот же каталог, что и основной скрипт Python.
Просто выполните RemotePSpy, чтобы начать мониторинг и ведение журнала, и нажмите Return, когда закончите. Журнал будет записан в текущий рабочий каталог с именем RemotePSpy.log.
Инструмент также выводит в stdout приблизительную копию того, что пользователь удалённого PowerShell видит на своём экране, наряду с более подробной информацией в файле журнала. Доступно более сложное ведение журнала — см. раздел «Ведение журнала» ниже.
Если вы установили Python так, что он находится в вашем PATH, исполняемые скрипты RemotePSpy также будут в вашем PATH. В противном случае вам, возможно, придётся искать их в каталоге site-packages вашего Python.
По умолчанию RemotePSpy использует (рекомендуемый) поставщик ETW WinRM в качестве источника данных. Если вы хотите использовать поставщик ETW PowerShell, вы можете выполнить RemotePSpy_powershell_prov.
Эта версия может выдавать некоторые ненужные предупреждения из-за дополнительной сложности отслеживания определённого состояния, основанного на том, как данные предоставляются в этом конкретном поставщике ETW.
Код состоит из ряда довольно модульных классов, которые могут принимать входные данные на разных уровнях стека протокола. Это позволяет подключать их друг к другу немного разными способами в зависимости от того, откуда и в каком виде получены данные. Большинство классов принимают функцию обратного вызова, которую они используют для передачи результата на следующий уровень стека.
Описание основных используемых классов приведено ниже, а затем следуют некоторые потоки обработки, которые показывают, какой класс питает какой в различных сценариях.
ETWWinRM — получает события ETW от поставщика WinRM.
ETWPowerShell — получает события ETW от поставщика PowerShell.
PowerShellETWParser — определяет контекст Shell для событий ETW PowerShell, передавая данные фрагментов в PSRPDefragmenter. Также обеспечивает синхронизацию потоков.
SoapDefragmenter — повторно собирает полные сообщения SOAP WSMan из событий ETW WinRM, передавая полный SOAP в WSManPS.
WSManPS — отфильтровывает WinRM, не связанный с PowerShell, отслеживает контекст Shell, извлекает данные фрагментов PSRP из SOAP WSMan и передаёт данные фрагментов в PSRPDefragmenter.
PSRPDefragmenter — повторно собирает фрагменты PSRP в полные сообщения PSRP. Фрагменты собираются по ObjectID, а уникальность ObjectID обеспечивается с учётом контекста Shell. Передаёт окончательные сообщения PSRP в PSRPParser.
PSRPParser — декодирует необработанное двоичное сообщение PSRP, извлекая детали заголовка, такие как RPID, Pipeline ID и MessageType. Передаёт декодированные сообщения в SimpleCommandTracer.
SimpleCommandTracer — интерпретирует сообщения PSRP с помощью MessageType, извлекает и выводит в журнал/печать команды, аргументы и их вывод. Включает частичное декодирование сериализованных объектов PowerShell. Это не полная реализация всех возможных функций, но она пытается охватить большинство распространённых случаев, чтобы обеспечить трассировку выполнения.
Поток обработки при использовании поставщика ETW Microsoft-Windows-WinRM:
ETWWinRM -> SoapDefragmenter -> WSManPS -> PSRPDefragmenter -> PSRPParser -> SimpleCommandTracer
Поток обработки при использовании поставщика ETW Microsoft-Windows-PowerShell:
ETWPowerShell -> PowerShellETWParser -> PSRPDefragmenter -> PSRPParser -> SimpleCommandTracer
На каждом уровне стека протокола ведётся комплексное журналирование. Это позволяет выполнять отладку на различных уровнях и было особенно полезно во время разработки. Надеемся, что это также будет полезно всем, кто хочет исследовать удалённый PowerShell в действии, поскольку можно получить полную трассировку протокола на всех ключевых уровнях.
В настоящее время для изменения конфигурации журналирования необходимо редактировать исходный код в конце скрипта, где настраиваются регистраторы. Будущие выпуски, надеюсь, предоставят лучший метод для такой настройки.
Имя каждого регистратора определяется константой LOGGER_NAME в классе, который его использует. Каждый регистратор определён как дочерний элемент «RemotePSpy» (например, RemotePSpy.etw). Программно регистраторы можно настроить с помощью logging.getLogger() с соответствующим именем журнала.
Для быстрой справки следующие регистраторы и уровни предоставят вам трассировки протокола на разных уровнях протокола:
| Ключевые данные журнала | Константа имени регистратора | Уровень |
|---|---|---|
| Трассировка команд | SimpleCommandTracer.LOGGER_NAME | INFO |
| Полная трассировка событий ETW | ETWWinRM.LOGGER_NAME | DEBUG |
| Полная трассировка сообщений SOAP WSMan | SoapDefragmenter.LOGGER_NAME | INFO |
| Полная трассировка каждого фрагмента PSRP | PSRPDefragmenter.LOGGER_NAME | DEBUG |
| Полная трассировка сообщений PSRP | PSRPParser.LOGGER_NAME | DEBUG |
Обратите внимание, что SimpleCommandTracer также выводит трассировку в stdout, и эта трассировка пытается в некоторой степени воспроизвести отображение, которое видит пользователь удалённого PowerShell. Это отличается от журнала трассировки команд, который регистрирует каждую команду, вызов метода конвейера и вывод конвейера более точным способом, включая дополнительный контекст, такой как RPID и Pipeline ID.
Более полная сводка того, что появляется в каждом журнале на каком уровне, приведена ниже:
ERROR:
WARNING:
INFO:
DEBUG:
DEBUG:
ERROR:
WARNING:
INFO:
DEBUG:
ERROR:
WARNING:
INFO:
DEBUG:
INFO:
DEBUG:
DEBUG:
ERROR:
DEBUG:
INFO: