Powershellでイベントログを取得する場合、Get-EventLog や Get-WinEvent が便利です。
ただ、コンソールに表示させたり、Export-Csv を利用してCSVファイルに出力することはできますが、evtx形式での出力には対応していません。
wevtutil を使って、ログオン履歴のイベントログをEVTX形式でエクスポートする方法を説明します。
条件を変更すればログオン履歴ではないイベントも出力することができるかと思います。
イベントログをEVTX形式でエクスポートする方法
今回はイベントログをエクスポートするサーバで wevtutil を実行する想定です。オプションでリモートサーバのイベントログをエクスポートすることも可能です。
以下の条件でイベントログを出力します。現場では「前月1ヶ月分のログを取得」するなどという要件が多いことを踏まえて、対象期間を設定しています。
- スクリプト実行するサーバのイベントログをエクスポート
- ファイル形式 :.evtx
- イベントID :4624(ログオンの履歴)
- ログオンタイプ:10(リモートデスクトップ接続)
- 対象期間 :前月1日0時 ~ 当月1日0時まで
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
### イベントログ エクスポート(evtx形式) ### スクリプト設置パス $Current = Split-Path $myInvocation.MyCommand.path ### ホスト名取得 $Target_host=$(hostname) ### XPathフィルタリング # イベントID/ログオンタイプ(RDPのみを対象) $event_id="4624" $Logon_Type="10" # ログの日付_開始日を取得(前月) $LastMonth_year =((Get-Date).AddMonths(-1)).Year $LastMonth_month=((Get-Date).AddMonths(-1)).month $LastMonth_month=$LastMonth_month.ToString("00") $startdate=echo $LastMonth_year/$LastMonth_month [DateTime]$startdate=$startdate # ログの日付_終了日を取得(現在の年月) [DateTime]$enddate=Get-Date -Format "yyyy/MM" # ログの日付_開始/終了日をUTC時間に変換 $startUTCdate = [System.TimeZoneInfo]::ConvertTimeToUtc($startdate).ToString("yyyy-MM-ddTHH:mm:ssZ") $endUTCdate = [System.TimeZoneInfo]::ConvertTimeToUtc($enddate).ToString("yyyy-MM-ddTHH:mm:ssZ") #イベントログ エクスポートファイルパス $YearMonth="$LastMonth_year$LastMonth_month" $evtx_filename="${Target_host}_${YearMonth}.evtx" $LocalFilePath="$Current\$evtx_filename" # イベントログ エクスポート wevtutil export-log Security $LocalFilePath ` /q:"*[System[ (EventID=$event_id) and TimeCreated[@SystemTime>='$startUTCdate'] and TimeCreated[@SystemTime<='$endUTCdate'] ] and EventData[Data[@Name='LogonType']='$Logon_Type'] ]" exit 0 |
以下で詳細を説明します。
まずは、スクリプトが設置されるパスを取得しています。以下を書いておくことで、サーバのどのフォルダに設置しても、ベースとなるパスが取得できます。
1 2 |
### スクリプト設置パス $Current = Split-Path $myInvocation.MyCommand.path |
以下で、スクリプトを実行するホストのホスト名を取得します。今回はファイル名にホスト名を使いたかったためです。
1 2 |
### ホスト名取得 $Target_host=$(hostname) |
以下で、対象期間の開始日時(前月1日の0時0分)を取得します。
ポイントとしては yyyy/MM を DateTime型 に変換することで、イベントログフィルタ時に指定する yyyy/MM/dd HH:mm:ss形式 で取得できます。
1 2 3 4 5 6 7 |
# ログの日付_開始日を取得(前月) $LastMonth_year =((Get-Date).AddMonths(-1)).Year # 前月の年(yyyy)を取得 $LastMonth_month=((Get-Date).AddMonths(-1)).month # 前月の月(MM)を取得 $LastMonth_month=$LastMonth_month.ToString("00") # 取得した MM を2桁に固定 $startdate=echo $LastMonth_year/$LastMonth_month # 取得した yyyyMM を yyyy/MM にする [DateTime]$startdate=$startdate # yyyy/MM をDateTime型に変換 |
以下で、対象期間の終了日時(当月1日の0時0分)を取得します。
開始日時と同じように yyyy/MM をDateTime型に変換することで、yyyy/MM/dd HH:mm:ss形式 で取得します。
1 2 3 |
# ログの日付_終了日を取得(現在の年月) [DateTime]$enddate=Get-Date -Format "yyyy/MM" |
以下で、対象期間の開始/終了日時を UTC時間に変換します。
イベントログのフィルタリングで期間を指定する場合は、UTC時間で指定する必要があるためです。
1 2 3 4 |
# ログの日付_開始/終了日をUTC時間に変換 $startUTCdate = [System.TimeZoneInfo]::ConvertTimeToUtc($startdate).ToString("yyyy-MM-ddTHH:mm:ssZ") $endUTCdate = [System.TimeZoneInfo]::ConvertTimeToUtc($enddate).ToString("yyyy-MM-ddTHH:mm:ssZ") |
以下で、出力するイベントログ(EVTX形式)の保存パスを指定します。
このへんは好みですね。以下では、スクリプトを実行したフォルダ内に「hostname_yyyyMM.evtx」というファイル名で出力されるようにしています。
1 2 3 4 5 |
#イベントログ エクスポートファイルパス $YearMonth="$LastMonth_year$LastMonth_month" $evtx_filename="${Target_host}_${YearMonth}.evtx" $LocalFilePath="$Current\$evtx_filename" |
以下では、指定したフィルタ条件でイベントログをエクスポートしています。
/q 以降がフィルタリング設定で、XPathクエリと呼ばれるもので、XML形式で書き方が厄介で少しとっつきにくいですが、かなり細かくフィルタ条件を指定できるので、個人的には知っていると重宝するかなぁと。
1 2 3 4 5 6 7 8 9 10 |
# イベントログ エクスポート wevtutil export-log Security $LocalFilePath ` /q:"*[System[ (EventID=$event_id) and TimeCreated[@SystemTime>='$startUTCdate'] and TimeCreated[@SystemTime<='$endUTCdate'] ] and EventData[Data[@Name='LogonType']='$Logon_Type'] ]" |
書き方に関しては、イベントログをGUIでフィルターすることで、おおまかな内容は取得できます。例えば、セキュリティログを以下のようにフィルター設定を行います。
←の画像では、以下のようにフィルター設定をしています。
- イベントレベル:重大・エラー・警告 を選択
- ログの名前:セキュリティログ を指定
- イベントID:4624 を指定
設定が完了したら、XMLタブを選択します。
すると、右画像のように、XML形式でのフィルタ設定が表示されます。
下部の「手動でクエリを編集する」をチェックすることで、手動でXML形式のフィルター設定をすることもできますので、GUIでXMLのフィルター設定の動作を確認することもできます。
これの便利なところは、イベントログ共通ではない項目 もフィルターすることができることです。
イベントログ共通ではない項目とは、例えば、ログオンのログに記録されるアカウント名や接続元IPアドレスなどです。例えば、Applicationのエラーやファイルシステムの異常ログにアカウント名や接続元IPアドレスなんて記録されないですよね。そういった特定のイベントにのみ存在する項目は、GUIのフィルターでは設定できないため、XMLで指定する必要があります。
逆の視点でいうと、XMLでフィルターすれば大概の項目は指定できるということです。
まとめ
最近の現場では、監査目的でログを取得したい!という要望をよく聞きますので、触れるようにしておくといつかどこかで役立つかもしれません。
Windowsはなんか複雑でとっつきにくいことが多い(触り始めたのがLinuxだった人は特に)と思うこともありますが、頑張れば意外といろいろなことができますね。クライアントマシンとして使うOSもWindowsが大半だと思いますので、こういった小技を知っていると重宝されますよ。
↓↓↓ 持っていると便利な一冊 ↓↓↓