セキュリティログから PowerShell でログオン履歴を抽出する

# 使い方

1. イベントログを開く（eventvwr.exe）
2. [Windows ログ] - [セキュリティ] を選択
3. [すべてのイベントを名前をつけて保存...] を選択
4. 名前をつけて保存する
5. PowerShell を実行する
6. csv が出力されます

# PowerShell

```セキュリティログから PowerShell でログオン履歴を抽出する.ps1
# System.Windows.Formsアセンブリを有効化
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

# OpenFileDialogクラスをインスタンス化し、必要な情報を設定
$dialog = New-Object System.Windows.Forms.OpenFileDialog
$dialog.Filter = "イベント ログ ファイル (*.evtx;*.evt;*.elt)|*.evtx;*.evt;*.elt"
$dialog.InitialDirectory = $Env:USERPROFILE + "\Documents"
$dialog.Title = "保存されたログを開く"

Set-Location -Path $dialog.InitialDirectory

# ログオン履歴取得
function GetLogonHistry(){

	# ログオン成功
	$LogonSuccess = 4624

	# ログオン失敗
	$LogonFail = 4625

	# ログオンイベントの抽出
	Write-Host (Get-Date -Format "yyyy/MM/dd HH:mm:ss") ログオンイベントの抽出開始

	if($evtxPath -eq $null){
		$tempEvents = Get-WinEvent -LogName Security
	} else {
		$tempEvents = Get-WinEvent -Path $evtxPath
	}

	Write-Host (Get-Date -Format "yyyy/MM/dd HH:mm:ss") ログオンイベントの抽出終了
	Write-Host (Get-Date -Format "yyyy/MM/dd HH:mm:ss") ログオンイベントの精製開始
	$LogonEvents = $tempEvents | ? {($_.Id -eq $LogonSuccess) -or ($_.Id -eq $LogonFail)}
	Write-Host (Get-Date -Format "yyyy/MM/dd HH:mm:ss") ログオンイベントの精製終了

	# ログオン履歴
	$LogonHistry = @()

	foreach( $LogonEvent in $LogonEvents ){
		$LogonStatus = New-Object PSObject | Select-Object `
			EventTime,		# ログオン時刻
			Success,		# ログオン成功
			LogonUser,		# ユーザー
			Domain,			# ドメイン
			LogonTypeName,	# ログオンタイプ名
			LogonTypeCode,	# ログオンタイプ コード
			IpAddress		# IP アドレス

		# ログオン時刻
		$LogonStatus.EventTime = $LogonEvent.TimeCreated

		# ログオン成功
		$LogonStatus.Success = $LogonEvent.Id -eq $LogonSuccess

		$LogonEventXml = [XML]$LogonEvent.ToXml()

		# ログオンユーザー
		$LogonStatus.LogonUser = ($LogonEventXml.Event.EventData.Data | ? {$_.Name -eq "TargetUserName"}).'#text'

		# ドメイン
		$LogonStatus.Domain = ($LogonEventXml.Event.EventData.Data | ? {$_.Name -eq "TargetDomainName"}).'#text'

		# 接続元 IP
		$LogonStatus.IpAddress = ($LogonEventXml.Event.EventData.Data | ? {$_.Name -eq "IpAddress"}).'#text'

		# ログオンタイプ
		[int]$LogonType = ($LogonEventXml.Event.EventData.Data | ? {$_.Name -eq "LogonType"}).'#text'
		$LogonStatus.LogonTypeCode = $LogonType
		switch ($LogonType){
			2 { $LogonStatus.LogonTypeName = "対話型" }
			3 { $LogonStatus.LogonTypeName = "ネットワーク" }
			4 { $LogonStatus.LogonTypeName = "Batch" }
			5 { $LogonStatus.LogonTypeName = "サービス" }
			7 { $LogonStatus.LogonTypeName = "ロック解除" }
			8 { $LogonStatus.LogonTypeName = "Network Cleartext" }
			9 { $LogonStatus.LogonTypeName = "New Credentials" }
			10 { $LogonStatus.LogonTypeName = "RDP" }
			11 { $LogonStatus.LogonTypeName = "Cached Interactive" }
		}

		$LogonHistry += $LogonStatus
	}

	return $LogonHistry
}

# ダイアログを表示
if($dialog.ShowDialog() -eq "OK"){
	$filePath = (Get-ChildItem -Path $dialog.FileName).DirectoryName + "\"
	$evtxFile = (Get-ChildItem -Path $dialog.FileName).Name

	$evtxPath = Join-Path $filePath $evtxFile
	if(!(Test-Path $evtxPath)){
		exit
	} else {
		$csvFile = (Get-ChildItem -Path $dialog.FileName).BaseName + ".csv"
		$csvJoin = Join-Path $filePath $csvFile
	}

	Write-Host (Get-Date -Format "yyyy/MM/dd HH:mm:ss") 処理の開始
	GetLogonHistry | Export-Csv -Append -Path $csvJoin -Encoding Default -NoTypeInformation
	Write-Host (Get-Date -Format "yyyy/MM/dd HH:mm:ss") 処理の終了
	Write-Host $csvJoin に出力されました。
} else {
	Write-Host ダイアログから読み込まれませんでした。ローカルのログを読み込みます。

	$evtxPath = $null
	$csvJoin  = $Env:USERPROFILE + "\Desktop\Eventlog_" + $env:COMPUTERNAME + "_" + $(Get-Date -Format "yyyyMMdd") + ".csv"

	Write-Host (Get-Date -Format "yyyy/MM/dd HH:mm:ss") 処理の開始
	GetLogonHistry | Export-Csv -Append -Path $csvJoin -Encoding Default -NoTypeInformation
	Write-Host (Get-Date -Format "yyyy/MM/dd HH:mm:ss") 処理の終了
	Write-Host $csvJoin に出力されました。
}
```