Глава 2. Конвейеры PowerShell

Организация конвейера (Pipelining) является ключевым свойством PowerShell, которое позволит нам настраивать интеграцию Python и PowerShell. Все примеры и иллюстрации из этой главы были выбраны для объяснения организации конвейера и представляют внутренние тонкости CmdLet и методов, которые являются полезными при расследованиях.

Что представляют собой конвейеры PowerShell

Организация Конвейера CmdLet создаёт некую сборочную линию команд для исполнения в некоторой определённой последовательности по мере перемещения данных или результатов от каждого из CmdLetю Наилучшим способом описания этого является пара связанных с расследованием примеров.

Пример 1: Get-Service

Допустим что мы желаем увидеть какие службы в настоящий момент исполняются в некоторой системе, которую мы исследуем. Процесс фильтрации получаемого вывода от одного из CmdLet в другой это один из наиболее применяемых способов использования конвейера. Кроме того, мы бы желали отображать получаемый вывод в неком табличном виде. Рисунок 2-1 является образцом конвейера, который решит данную задачу.

 

Рисунок 2-1


Иллюстрация Конвейера для отображения исполняемых процессов

Как вы можете видеть, наш конвейер начинается с CmdLet Get-Service без каких либо параметров командной строки.

[Замечание]Замечание

Естественно вы можете добавит параметры командной строки перед символом конвейера |, например, -ComputerName, что позволило бы исполнить CmdLet Get-Service удалённо в заданном компьютере.

Наш CmdLet Get-Service произведёт некий объект, который передаётся в получаемом Конвейере в идущий следующим в нашей цепочке CmdLet.

CmdLet Where-Object выполняет действия по фильтрации, которые вычисляют состояние объекта Cmdlet Get-Service эквивалентным "Running". Получаемый в результате вывод CmdLet Where-Object фильтрует полученный результат с тем чтобы в нём содержались лишь те службы, которые в данный момент исполняются. Получаемый теперь результат затем передаётся в следующий CmdLet Конвейера.

 

Рисунок 2-2


Решение задачи

Наконец, CmdLet Format-Table производит некий табличный результат с теми отфильтрованными службами, которые применялись в связанном с Get-Service выводом по умолчанию. Рисунок 2-2 отображает нашу реальную команду в действии - полученные результаты для краткости усечены.

[Замечание]Замечание

Воспользовавшись соответствующей операцией Get-Service | Get-Member вы можете выбрать все те методы и свойства, которые доступны в рамках объекта CmdLet Get-Service для дополнительных возможностей фильтрации.

Выдача отчёта о том какие из служб остановлены может быть в равной степени важным в процессе расследования. Например, утончённое вредоносное программное обеспечение будет отключать защиту от вирусов, межсетевые экраны и прочие службы защиты предназначенные для ограждения. Рисунок 2-3 изменяет основную команду для отображения только тех служб, которые в настоящий момент остановлены. И снова для краткости мы обрезаем полученные результаты.

 

Рисунок 2-3


Отображение остановленных служб

Одно заключительное замечание: Если вы желаете получить дополнительные сведения относительно Format-Table, помните что можно воспользоваться Get-Help, как это отражено на Рисунке 2-4.

 

Рисунок 2-4


Обзор CmdLet Format-Table

Пример 2: Get-Process

Также важны подробности исполнения процессов и они способны предоставлять дополнительные сведения относительно того к чему подключены процессы. Например, может быть важным при расследовании в реальном времени определять какие именно активные интернет подключения используются Google Chrome. Для данного примера давайте вначале разобъём этот пример на персональные компоненты и введём само понятие переменных в PowerShell.

 

Переменные PowerShell

Что представляют из себя переменные PowerShell: некая переменная в PowerShell это просто именованное место в памяти, выделенное под хранение значений данных. Все имена переменных в PowerShell начинаются с $, что делает простым их обнаружение. Одно дополнительное замечание: Имена переменных в PowerShell НЕ чувствительны к регистру; таким образом, $ipAddress и $IPaddress представляют одну и ту же переменную. Вы можете назначать значения переменным следующим образом:


$InvestigatorName = "Chet Hosmer"
		

или


$CaseNumber = "BC-0234"
		
 

Автоматические переменные PowerShell

Кроме того, существует ряд встроенных или автоматических переменных, которые доступны, но не могут изменяться самим пользователем. Нкоторые их примеры приводятся на Рисунке 2-5.

 

Рисунок 2-5


Пример автоматических переменных

 

Разбиение на части CmdLet, применяемого в Примере 2

Теперь, когда у нас имеется общее представление относительно переменных, мы поместим их для использования в выборке информации из Get-Process. Чтобы снизить вывод от Get-Process, давайте сосредоточимся только на одном работающем процессе. В своей системе вы можете применять иные браузеры, такие как Internet Explorer или Firefox. Подставьте соответствующее название своего браузера в качестве цели тех процессов, которые создаются им. Кроме того, всегда запущен процесс с названием svchost, следовательно вы можете также подставлять и его. Команда PowerShell, выполняющая это показана далее, а её результаты отображены на Рисунке 2-6.


Get-Process -Name chrome
		
 

Рисунок 2-6


Get-Process -Name chrome

Ключевым моментом в сведениях, который необходим от CmdLet Get-Process, это Process ID связанный с моим примером для Google ChromeМы можем применять этот идентификатор процесса для увязки своего процесса со связанными с ним действиями в Интернете. Как вы скорее всего предвосхитили, мы будем применять ещё и прочие CmdLet из PowerShell для изучения имеющихся соединений между Google Chrome и Интернетом. Для осуществления этого буде собрана некая команда для сохранения получаемых от CmdLet результатовв некой переменной с названием $id, вместо того чтобы просто отображать получаемые результаты:


$id = Get-Process -Name Chrome `
   | select -ExpandProperty Id
		

Обратим ваше внимание на то, что я применил символ отметки (`) с последующим Shift+Enter для продолжения ввода своей команды на следующей строке для простоты отображения. Получаемая в результате команда Get-Process -Name Chrome затем выстраивается в конвейер к команде select -ExpandProperty для опиределения единственного поля Id. Вы, естественно, можете ввести данную команду и в одной строке, но это прекрасный способ сделать её более читаемой.

Рисунок 2-7 сохраняет результат значения искомого Get-Process ID в переменной $id. Затем задавая имя переменной $id в своей следующей строке (естественно, следующей за нажатием на клавишу Enter), мы отображаем содержимое данной переменной $id.

 

Рисунок 2-7


Сохранение результатов CmdLet Get-Process в нашей переменной $id

 

Добавление CmdLet NetTCPConnections

Нашу переменную $id теперь можно применять в качестве параметра в прочих CmdLet. Например, CmdLet Get-NetTCPConnections имеет некий паркаметр -OwningProcess, который позволяет нам ограничивать вывод нашего CmdLet только указанной целью идентификатора процесса. Изучив Get-NetTCPConnections при помощи Get-Help, получаем следующие сведения (см. Рисунок 2-8).

 

Рисунок 2-8


Справка Get-NetTCPConnections

 

Как находить CmdLet?

Один из вопросов, который вы бы могли задать состоит в том как среди тысяч CmdLet я могу узнать какую именно применять для получения связанных подключений TCP с владеющим ими процессом? Ответ заключается в применении Get-Help. Сама архитектура имеющейся системы подсказок, встроенных в PowerShell выступает основным ключом для максимально действенного использования PowerShell и связанных CmdLet. Так как система подсказок обновляется ежедневно, она предназначена для того чтобы идти в ногу с новыми CmdLet, которые создаются одновременно со всеми обновлениями имеющихся CmdLet. Тем не менее, вы также можете искать CmdLet, относящиеся к определённым ключевым словам. Например, посмотрите как применять Get-Help с использованием некого ключевого слова вместо CmdLet на Рисунке 2-9.

 

Рисунок 2-9


Get-Help применяющий неко ключевое слово вместо CmdLet

Когда вы предоставляете Get-Help некое ключевое слово, как в нашем случае с TCP, это выдаст отчёт об известных CmdLet, причём все они относятся к TCP. Как вы можете видеть, первым попаданием является Get-NetTCPConnection. Как только вы получили само название CmdLet, вы затем можете воспользоваться Get-Help с названием этого CmdLet, для определения того как его применять, как я это сделал на Рисунке 2-8.

 

Применение переменных PowerShell в CmdLet

Исполнение CmdLet Get-NetTCPConnection с применением параметра -OwningProcess и заданием $id выработает только те соединения TCP, которые ассоциированы с конкретными значениями идентификатора Google Chrome, ранее обнаруженного при помощи Get-Process. Ниже приводится та команда, которая именно это и выполняет, в некий пример вывода поуазан на Рисунке 2-10.


Get-NetTCPConnection -State Established -OwningProcess $id | Format-Table -Autosize
		
 

Рисунок 2-10


Выполнение Get-NetTCPConnection с переменной для идентификатора процесса

Как вы можете видеть, применяются параметры командной строки -State и -OwningProcess

  • Для -State в качестве аргумента задаётся Established. Это создаст перечень только тех подключений TCP, которые установлены в данный момент, поскольку я интересуюсь в данный момент лишь текущими соединениями.

  • Вместо этого для -OwningProcess определяется значение переменной $id, которое содержит список идентификаторов, ассоциирующихся с Google Chrome. Основная причина по которой это срабатывает состоит в том, что представляемое Get-Help определение для применяемого параметра -OwningProcess постулируется так:

    
    [-OwningProcess <UInt32[]>]
    		

    Данное определение устанавливает, что -OwningProcess требует некое Unsigned Integer с длиной в 32 бита. Следующая за UInt32 пара квадратных скобок [] указывает что он может получать некий список значений.

Как вы можете видеть, только один единственный идентификатор процесса Chrome (а именно 108404) связан с установленными подключениями в Интернет. Таким образом, все прочие процессы указанные процессы Google Chrome не выполняют прямых подключений к Интернет, за это отвечает только 108404.

Это великолепный пример того как применять некую промежуточную переменную для сохранения содержимого команды. Тем не менее, мы можем выполнять эту операцию при помощи одной единственной команды. Вооружившись знанием о том как рабоатют Get-Process, переменные PowerShell, а также Get-NetTCPConnections, можно создать некую отдельную команду, которая может устранить потребность в применении переменной $id. Чтобы сделать этот следующий шаг, нам понадобится CmdLet ForEach-Object.

 

ForEach-Object

ForEach-Object делает возможной обработку всех последовательно идущих результатов от предыдущей команды в данном конвейере. В данном примере это будут все результаты, вырабатываемые нашей командой Get-Process -Name Chrome.

Рисунок 2-11 применяет Get-Help для предоставления некого пояснения изучаемого нами ForEach-Object.

 

Рисунок 2-11


Обзор Get-Help для ForEach-Object

 

Создание отдельного решения с конвейером для Примера 2


Get-Process -Name Chrome | ForEach-Object {Get-NetTCPConnection -State Established -OwningProcess $_.Id -ErrorAction SilentlyContinue}| Format-Table -Autosize
		

В этом примере (см. результаты нашей операции с Рисунка 2-12), наши компоненты разбиваются далее следующим образом:


Get-Process -Name Chrome
		
  • Получаем подробности для всех процессов, содержащих в названии Chrome.

    
    ForEach-Object { }
    		
  • Обрабатываем все итерации (проще говоря, для каждого получаемого через конвейер предоставляемого Get-Process вывода).

    
    {Get-NetTCPConnection -State Established -OwningProcess $_.Id -ErrorAction SilentlyContinue}
    		
  • Для каждого результата выполняем CmdLet Get-NetTCPConnection.

  • -State Established фильтрует весь вывод чтобы он содержал лишь установленные в данный момент подключения.

  • -OwningProcess $_.Id задаёт значение идентификатора того процесса, для которого извлекается информация о подключении. Синтаксис $_.Id применяется для получения того идентификатора процесса данного процесса владельца для всех итераций по результатам работающего CmdLet Get-Process. Данное конкретное свойство направлено на применение следующего синтаксиса:

      $_.Id далее разбивается следующим образом:

    • $_ предоставляет значение текущего объекта, передаваемого через данный конвейер.

    • .Id определяет какое именно значение свойство связывается с данной операцией.

  • -ErrorAction -SilentlyContinue применяется для игнорирования любых ошибок, которые могут возникать в процессе CmdLet Get-NetTCPConnection. Например, когда значение идентификатора процесса не связано с каким- то соединением TCP, сбросит наш CmdLet и возбудит исключительную ситуацию. Данный параметр позволяет игнорировать такие исключительные ситуации.

  • Format-Table -Autosize применяется для форматирования получаемого вывода в более оптимальном виде.

 

Рисунок 2-12


Окончательное решение для выдачи соответствия IP подключений Google Chrome

 

Получение удалённых IP адресов

Все эти результаты выставляют следующий вопрос расследования, на какие именно IP адреса ссылается наш браузер Chrome? Это, естественно, CmdLet, который способен непосредственно обнаруживать данную информацию. Мы произвольным образом выбрали из своего приводимого на Рисунке 2-12 значение IP адреса 72.21.207.216. Затем был применён CmdLet Resolve-DnsName для получения относящейся к этому IP адресу информации.


Resolve-DnsName 72.21.207.216
		

Наш CmdLet Resolve-DnsName успешно определяет по указанному IP адресу developer.amazonservices.com (см. Рисунок 2-13).

 

Рисунок 2-13


Окончательное решение для выдачи соответствия IP подключений Google Chrome

Для получения дополнительных сведений относительно Resolve-DnsName попробуйте самостоятельно воспользоваться Get-Help.

Добавление стенографирования для отслеживания вашей деятельности

Для ваших расследовательских действий важно документирование (мягко говоря). Одним из простейших методов перехвата ваших действий и всех получаемых в результате данных является применение ещё других CmdLet PowerShell:


Start-Transaction
Stop-Transaction
		

Как и для всех CmdLets в PowerShell, получение относящейся к их применению и параметрам информации, связанным с CmdLet, состоит в применении Get-Help. Это может звучать слегка избыточным; тем не менее, многие люди всё ещё включают Google и прочие механизмы поиска для получения этих сведений. Несомненно, это полезно при определённых обстоятельствах, однако справочная система в PowerShell не просто мощная и отлично подогнана, но также и ежедневно обновляется. Тем самым, для получения самой последней, наиболее современной и точной информации о CmdLet применяйте Get-Help. Рисунок 2-14 предоставляет относящиеся к Start-Transcript результаты.

 

Рисунок 2-14


Get-Help Start-Transcript

Для данного примера определяется значение параметра -Path для направления вывода стенографирования (transcript) в некий заданный файл, как это отображено на Рисунке 2-15. Для демонстрации значения параметра -Append для Start-Transcript был применён Stop-Transcript, а затем стенографирование было вновь запущено. Для осуществления этого просто второй раз запустите CmdLet Start-Transcript с применением того же самого параметра -Path с последующим добавлением параметра -Append, как это показано на Рисунке 2-15. Это позволяет нам объединять сеансы PowerShell в одном и том же файле вывода.

 

Рисунок 2-15


PowerShell Start- и Stop-Transcript

Листинг 2-1 отображает получаемый в результате файл стенографирования. Отметим, что здесь был добавлен ещё один новый CmdLet, Out-File, - он отправляет получаемый из нашего CmdLet Get-Process вывод в файл IP-Result.txt на нашем рабочем месте. Таким образом, наше стенографирование не содержит вывода Get-Process или Get-Service, а вместо этого результаты сохраняются в обозначенных файлах вывода. Скорее всего в вашем случае это будет папака. Выделены строки Start и End Time для каждой добавляемой в конец транзакции. Отметим, что PowerShell применяет локальное время; в данном примере наше стенографирование было запущено 27 ноября, 2018, в 16:09:03, или 4:09 pm.

 

Листинг 2-1. Стенографирование PowerShell


**********************
Windows PowerShell transcript start
Start time: 20181127160903
Username: PYTHON-3\cdhsl
RunAs User: PYTHON-3\cdhsl
Configuration Name:
Machine: PYTHON-3 (Microsoft Windows NT 10.0.17134.0)
Host Application: C:\WINDOWS\system32\WindowsPowerShell\v1.0\PowerShell_ISE.exe
Process ID: 148432
PSVersion: 5.1.17134.407
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.17134.407
BuildVersion: 10.0.17134.407
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
Transcript started, output file is C:\Users\cdhsl\PS-TRANSCRIPTS\DEMO.txt
PS C:\WINDOWS\system32> Get-Process -Name chrome | Out-File C:\Users\cdhsl\Desktop\IP-Result.txt
PS C:\WINDOWS\system32> Stop-Transcript
**********************
Windows PowerShell transcript end
End time: 20181127160930
**********************
**********************
Windows PowerShell transcript start
Start time: 20181127161013
Username: PYTHON-3\cdhsl
RunAs User: PYTHON-3\cdhsl
Configuration Name:
Machine: PYTHON-3 (Microsoft Windows NT 10.0.17134.0)
Host Application: C:\WINDOWS\system32\WindowsPowerShell\v1.0\PowerShell_ISE.exe
Process ID: 148432
PSVersion: 5.1.17134.407
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.17134.407
BuildVersion: 10.0.17134.407
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
Transcript started, output file is C:\Users\cdhsl\PS-TRANSCRIPTS\DEMO.txt
PS C:\WINDOWS\system32> Get-Service | Format-Table -AutoSize | Out-File C:\Users\cdhsl\Desktop\Services.txt
PS C:\WINDOWS\system32> Stop-Transcript
**********************
Windows PowerShell transcript end
End time: 20181127161306
**********************
 	   

Задачи для изучения: эксперименты с cmdlet

Невозможно изучить работу с PowerShell лишь прочтя данный текст или какой- либо ещё аналогичным образом. Вместо этого вам придётся получать опыт PowerShell взаимодействуя с ним. Таблица 2-1 предоставляет краткий списко некоторых популярных CmdLet, которые полезны для расследований. Я выбрал для экспериментов лишь те CmdLet, которые выбирают или получают для вас информацию.

Таблица 2-1. Задачи для изучения CmdLet
   

Get-Process

Get-Service

Get-NetIPAddress

Get-NetIPConfguration

Get-NetIPv4Protocol

Get-NetIPv6Protocol

Get-NettCpConnection

Test-NetConnection

Get-Netroute

Get-MpComputerStatus

Get-Mpthreat

Get-NetFirewallSetting

Get-NetFirewallportFilter

Get-Volume

Get-Childitem

Get-Itemproperty

Get-EventLog

Get-LocalUser

Get-LocalGroup

Get-Content

Get-Location

Set-Location

Start-transcript

Stop-transcript

Format-table

 

[Предостережение]Предостережение

Если вы решите эксперементировать с иными CmdLet, которые вносят изменения в систему, делайте это на свой страх и риск. CmdLet PowerShell способны изменять, разрушать, удалять и даже уничтожать вашу систему.

Для каждого из приведённых в Таблице 2-1 CmdLet выполните следующее:

  1. Прсмотрите справочную информацию всех CmdLet, включая Details и Examples, то есть,

    1. Get-Help -Detailed

    2. Get-Help -Examples

  2. После просмотра опишите что делает данный CmdLet и рассмотрите чем он способен представлять ценность при расследовании.

  3. Исполните все CmdLet как минимум с одним параметром, а также проведите опыты с остальными.

  4. Воспользуйтесь конвейером для сборки CmdLet, начав с чего- то простого, например, отправки в конвейер вывода конкретного CmdLet для CmdLet Format-Table, а затем попробовав также и иные варианты.

  5. Убедитесь что в процессе своих экспериментов вы стартуете и завершаете стенографирование, это снабдит вас надлежащими отчётами о ваших действиях и результатах. Этим можно пользоваться в дальнейшем в качестве ссылки при ваших попытках дублирования сложных команд.

Решения для этих поставленных задач можно найти в Приложении и в исходных кодах данной книги.

Выводы

Данная глава была сосредоточена на некоторых ключевых областях PowerShell и ввела ряд новых CmdLet, а затем и приложение. Кроме того мы сделали введение в применение переменных PowerShell. Были созданы два примера конвейера для демонстрации того как подходить к организации конвейера в PowerShell. В Главе 3 будут введены новые CmdLet и будет проведена разработка множества законченных сценариев PowerShell.