#はじめに
PowerShellのGet-WinEventコマンドレットを使ってWindowsイベントログを取得すると、ログの詳細はMessageプロパティにフォーマットされていない文字列で入っています。
そのため、例えば、プロセスの生成を記録したログを検索し、個々のログに記録されているプロセスID、プロセス名を取得したいとき、Messageプロパティから正規表現で取り出すしかなさそうに見えます。
しかしイベントビューアーのGUIでは、個々のログの「詳細」タブからXML形式でプロセスID、プロセス名などを閲覧できるので、PowerShellでもXML形式で取り出す方法があるはずだ。
そう思って調べた結果が以下の方法です。
#方法
たとえばローカルコンピュータの一定時間内のプロセス生成ログを検索します。(SecurityログのEventID 4688番)
$logs = Get-WinEvent -FilterHashtable @{LogName="Security";Id=4688;StartTime="2020-11-11 10:00";EndTime="2020-11-11 10:03"}
個々のログに記録されている新規生成プロセスはMessageプロパティのテキストにしか現れないように見えます。
PS C:\WINDOWS\system32> $logs[1].Message
新しいプロセスが作成されました。
作成元サブジェクト:
セキュリティ ID: S-1-5-21-1390067357-nnnnnnnnn-nnnnnnnnn-nnnn
アカウント名: yamada.taro
アカウント ドメイン: HOGEHOGE
ログオン ID: 0xD4E06
ターゲット サブジェクト:
セキュリティ ID: S-1-0-0
アカウント名: -
アカウント ドメイン: -
ログオン ID: 0x0
プロセス情報:
新しいプロセス ID: 0x2454
新しいプロセス名: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
トークン昇格の種類: %%1936
必須ラベル: S-1-16-4096
作成元プロセス ID: 0x3f08
作成元プロセス名: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
プロセスのコマンド ライン:
(以下略)
しかし、ToXml()メソッドを使うと、XML形式で取り出すことができます。
PS C:\WINDOWS\system32> $logs[1].ToXml()
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-a5ba-3e3b0328c30d}'/><EventID>4688</EventID><Version>2</Version><Level>0</Level><Task>13312</Task><Opcode>0</Opcode><Keywords>0x8020000000000000</Keywords><TimeCreated SystemTime='2020-11-11T01:02:33.227966500Z'/><EventRecordID>632158</EventRecordID><Correlation/><Execution ProcessID='4' ThreadID='13816'/><Channel>Security</Channel><Computer>XXXXX.hogehoge.com</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-5-21-1390067357-nnnnnnnnn-nnnnnnnnn-nnnn</Data><Data Name='SubjectUserName'>yamada.taro</Data><Data Name='SubjectDomainName'>HOGEHOGE</Data><Data Name='SubjectLogonId'>0xd4e06</Data><Data Name='NewProcessId'>0x2454</Data><Data Name='NewProcessName'>C:\Program Files (x86)\Google\Chrome\Application\chrome.exe</Data><Data Name='TokenElevationType'>%%1936</Data><Data Name='ProcessId'>0x3f08</Data><Data Name='CommandLine'></Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>-</Data><Data Name='TargetDomainName'>-</Data><Data Name='TargetLogonId'>0x0</Data><Data Name='ParentProcessName'>C:\Program Files (x86)\Google\Chrome\Application\chrome.exe</Data><Data Name='MandatoryLabel'>S-1-16-4096</Data></EventData></Event>
このXMLをパースして変数に代入します。
$xml = [XML]($logs[1].ToXml())
これでEventノードの子ノードEventDataから必要なデータを取り出せます。
PS C:\WINDOWS\system32> $xml.Event.EventData.ChildNodes
Name #text
---- -----
SubjectUserSid S-1-5-21-1390067357-nnnnnnnnn-nnnnnnnnn-nnnn
SubjectUserName yamada.taro
SubjectDomainName HOGEHOGE
SubjectLogonId 0xd4e06
NewProcessId 0x2454
NewProcessName C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
TokenElevationType %%1936
ProcessId 0x3f08
CommandLine
TargetUserSid S-1-0-0
TargetUserName -
TargetDomainName -
TargetLogonId 0x0
ParentProcessName C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
MandatoryLabel S-1-16-4096
例えば、新規作成されたプロセス名(NewProcessName)を取り出すには以下のとおり。
$procname = ($xml.Event.EventData.Data | where Name -eq "NewProcessName")."#text"
これを検索したログについてループ処理すればよい、ということです。
以上です。