Image: イベントログから起動・ログオン履歴を抽出する [PowerShell]

PowerShellを使ってイベントログを照会してそこからWindows起動・ユーザーログオンについてのログを抽出しようという試み。
コマンドプロンプトでもできなくはないですが、PowerShellならオブジェクトとしてデータを利用できて便利なので今回はPowerShellを利用しようと思います。

○対象とする動作環境と必要事項

  • Windows Vista、7、Windows Server 2008 R2
  • .net Framework 3.5以降
  • Windows PowerShell 2.0以降
  • イベントログの"Security"ログにアクセスするには管理者権限が必要
  • 監査ポリシーの各種イベント監査が有効であること

○"Get-EventLog"コマンドでWindowsの起動履歴を抽出

"Get-EventLog"コマンドでイベントログを取得して"Where-Object"コマンドでフィルターをかける方法です。PowerShellではよく用いる一般的な手法ですが、イベントログの取得は後述の"Get-WinEvent"コマンドのほうが便利です。
なお、次のコマンドはPowerShellを管理者権限で開いた上で実行してください。"Security"ログへのアクセスには管理者権限が必要です。管理者権限でない場合はエラーが返ってきます。

$ get-eventlog Security -newest 8000 | where-object {($_.Source -eq "Microsoft-Windows-Security-Auditing") -and ($_.InstanceID -eq 4608)}
   Index Time          EntryType   Source                 InstanceID Message
   ----- ----          ---------   ------                 ---------- -------
   67191 9 21 08:40    SuccessA... Microsoft-Windows...         4608 Windows を起動しています。...
   65480 9 19 16:38    SuccessA... Microsoft-Windows...         4608 Windows を起動しています。...
   62326 9 14 12:09    SuccessA... Microsoft-Windows...         4608 Windows を起動しています。...
   62190 9 14 04:53    SuccessA... Microsoft-Windows...         4608 Windows を起動しています。...
   61589 9 12 18:33    SuccessA... Microsoft-Windows...         4608 Windows を起動しています。...

"Security"で"Security"ログを参照します。ログを全て取得しようとすると大変時間がかかるので"-newest 8000"スイッチで抽出ログを最新8000件以内に絞っています。そして"Where-Object"コマンドでソースが"Microsoft-Windows-Security-Auditing"かつイベントIDが"4608"のイベントのみのログを抽出します。特定の種類のログを絞り込むにはイベントIDだけでなくソースを指定する必要があります。
これら自体はWindowsの起動ログではなく"Lsass.exe"(ローカルセキュリティ機関)の起動ログですが、Windows起動時に必ず実行されてかつログに残るのでこれを利用しています。スタンバイや休止状態への移行・復帰は含まないため、普段シャットダウンさせないテレビ兼用パソコン等ではほとんどログが出てこないと思います。
こちらに"4608 - Windows is starting up."という説明がありました。

ログの結果から日時だけをファイルに出力するには次のようにします。

get-eventlog  Security -newest 8000 | where-object {($_.Source -eq "Microsoft-Windows-Security-Auditing") -and ($_.InstanceID -eq 4608)} `
| format-table -property TimeGenerated -autosize | out-file ($env:userprofile + "\Desktop\logBootup.log")

ここではデスクトップの"logBootup.log"ファイルに保存するように指定しています。保存先は適宜変えてください。
後述の"Get-WinEvent"コマンドを利用する場合は次のようにします。この方法ならより待ち時間を短くできます、

get-winevent -logname Security -filterxpath "*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID='4608']]" `
| format-table -property TimeCreated -autosize | out-file ($env:userprofile + "\Desktop\logBootup.log")

"Get-EventLog"コマンドでは"TimeGenerated"プロパティ、"Get-WinEvent"コマンドでは"TimeCreated"プロパティにログの記録日時が格納されています。
この違いは返されるオブジェクトの型の違いによるものです。"Get-EventLog"コマンドでは"System.Diagnostics.EventLogEntry"クラス、"Get-WinEvent"コマンドでは"System.Diagnostics.Eventing.Reader.EventLogRecord"クラスのオブジェクト配列が返されます。

○"Get-WinEvent"コマンドで特定ユーザーのログオン履歴を抽出

"Get-WinEvent"は"Get-EventLog"をより強化したコマンドです。XMLベースのクエリを使ってフィルターをかけたり、各ログをXMLデータに変換することができます。このコマンドの実行にはWindows Vista、Windows Server 2008 R2以降かつ.NET Framework 3.5以降が必要です。

$ get-winevent -logname Security -filterxpath "*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID='4624']] and *[EventData[Data[@Name='TargetUserName']='hogeUser']]" -maxevents 10
TimeCreated            ProviderName                        Id Message
-----------            ------------                        -- -------
2011/09/19 23:42:54    Microsoft-Windows-Security...     4624 アカウントが正常にログオン...
2011/09/19 20:17:31    Microsoft-Windows-Security...     4624 アカウントが正常にログオン...
2011/09/19 19:32:42    Microsoft-Windows-Security...     4624 アカウントが正常にログオン...
2011/09/18 22:07:02    Microsoft-Windows-Security...     4624 アカウントが正常にログオン...
2011/09/18 21:23:58    Microsoft-Windows-Security...     4624 アカウントが正常にログオン...
2011/09/18 19:17:13    Microsoft-Windows-Security...     4624 アカウントが正常にログオン...
2011/09/17 19:09:37    Microsoft-Windows-Security...     4624 アカウントが正常にログオン...
2011/09/16 23:07:56    Microsoft-Windows-Security...     4624 アカウントが正常にログオン...
2011/09/16 20:02:26    Microsoft-Windows-Security...     4624 アカウントが正常にログオン...
2011/09/15 21:57:54    Microsoft-Windows-Security...     4624 アカウントが正常にログオン...

PowerShellにおけるXMLの扱い方や"Get-WinEvent"コマンドについては日本語の解説サイトがほとんどなかったためいろいろ苦労しました。

イベントログ XMLデータ
上の画像はログオンについてのイベントログのXMLデータをイベントビューアで見たところ。
このようにイベントログはそれぞれXMLデータとして参照・利用することができます。また、XPathで記述したクエリを使ってイベントログにフィルターをかけることもできます。

それを踏まえたうえでPowerShellの説明に戻ると、"-filterxpath"スイッチにはXPathでクエリ(フィルター)を記述します。ここでは"="比較演算子を使ってノード集合を絞り込んでいます。具体的には"System/Provider"の"Name"属性が"Microsoft-Windows-Security-Auditing"に一致し、かつ"System/EventID"タグの内容が"4624"に一致、さらに"EventData/Data Name='TargetUserName'"タグの内容が"hogeUser"に一致するイベントログを取得しています。"hogeUser"には対象とするユーザー名を入れてください。
最後に付いている"-maxevents 10"スイッチは最大10件までのイベントを返すように指定しています。ここも適宜変えてください。

上と同じように"Format-Table"コマンドや"Out-File"コマンドとパイプで連結することで日時をファイルに出力できます。
出力されるログオン履歴にはネットワークログオンも含まれます。特に他のコンピューターとファイルを共有している場合は接続セッション維持のためのログオンの履歴が多数出てくると思います。
ここまでコマンドが1行に収まるようにしてきましたが、スクリプトで実行するなら変数を使って代入や実行処理を複数行に分けてもいいでしょう。

今回は"Get-WinEvent"コマンドとXPathを使ったイベントログフィルターの利用を紹介しました。各イベントログを"ToXML()"メソッドでXMLデータに変換すればさらにいろんなことに応用できるのですが、今回はここまでにしておきます。

○更新履歴

  • 2011/12/07 get-wineventコマンドでログ名の指定を忘れていたので修正
  • 2011/09/28 3つ目の例のformat-tableコマンドで取り出すプロパティ名が間違っていたのを修正
  • 2011/09/23 Vistaで起動ログが取得できなかった問題、その他を訂正
  • 2011/09/21 作成

※コメント欄が表示されない場合はdisqusについてJavascriptが有効であることを確認して下さい。コメントはスパム防止フィルターによる承認制のため、投稿してもすぐに反映されない場合があります。

管理人 : Akamaki (akm)

は、PCとVTuberに夢中になっている電気技術者です。

私はレトロコンピューティングの愛好家ですが、そのようなリグはもう収集していません。

私の活動はトップページで見ることができます。読んでくれてありがとう!