Skip to content

Instantly share code, notes, and snippets.

@gcch
Last active September 9, 2023 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gcch/4ab0e4c90e7ed1d70e92723aaa2bc4d4 to your computer and use it in GitHub Desktop.
Save gcch/4ab0e4c90e7ed1d70e92723aaa2bc4d4 to your computer and use it in GitHub Desktop.
#
# Archive-FileShareAccesslogs.ps1
#
# Copyright (c) 2023 tag.
#
$ScriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent
Set-Location $ScriptDir
# デバッグモード
$DebugPreference = "SilentlyContinue"
$DebugPreference = "Continue"
<#
# ログフォルダの準備
$LogDirName = "Logs"
$LogDirPath = Join-Path $ScriptDir -ChildPath $LogDirName
if (-not (Test-Path($LogDirPath))) {
New-Item -ItemType Directory -Path $LogDirPath
}
$LogFileBaseName = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name)
$LogFileExtention = ".log"
#>
# アーカイブフォルダの準備
$ArchiveDirName = "Archives"
$ArchiveDirPath = Join-Path $ScriptDir -ChildPath $ArchiveDirName
if (-not (Test-Path($ArchiveDirPath))) {
New-Item -ItemType Directory -Path $ArchiveDirPath
}
$ArchiveFileBaseName = "SharedFileAccessAudit"
$ArchiveFileExtention = ".csv"
# セキュリティログの設定変更
Function Set-SecurityLogSize {
# Legacy Windows Event Log
#Limit-EventLog -LogName Security -MaximumSize 50MB -OverflowAction OverwriteOlder -RetentionDays 90
# 最大ログ サイズ: 20971520000 B = 2048000 KB
# イベントログサイズが最大値に達したとき: イベントを上書きしないでログをアーカイブする
wevtutil sl "Security" /retention:true /autobackup:true /maxsize:20971520000
}
Set-SecurityLogSize
# セキュリティログのパス取得
Function Get-SecurityEvtxPath {
$Xml = [XML](wevtutil gl "Security" /f:XML)
$SecurityEvtxPath = [Environment]::ExpandEnvironmentVariables($Xml.channel.logging.logFileName)
return [string]$SecurityEvtxPath
}
# 指定日のファイル共有監査ログの取得
Function Get-FileShareAuditLogByDate {
Param(
[string]$EvtxFilePath,
[datetime]$Date
)
Write-Debug "Get-FileShareAuditLogByDate: EvtxFilePath=$EvtxFilePath; Date=$Date"
$DateString = Get-Date $Date -Format "yyyy/MM/dd"
$StartDate = Get-Date "$DateString 00:00:00"
$EndDate = Get-Date "$DateString 23:59:59"
Write-Debug "SearchCondition: StartDate=$StartDate; EndDate=$EndDate"
# Audit Detailed File Share (Event ID: 5145)
# https://learn.microsoft.com/ja-jp/windows/security/threat-protection/auditing/audit-detailed-file-share
$Events = @()
$Result = Get-WinEvent -Path $EvtxFilePath -FilterXPath "Event/System/EventID='5145'" | where { ($_.TimeCreated -ge $StartDate) -and ($_.TimeCreated -le $EndDate) } | ForEach-Object {
$TimeCreated = Get-Date (Get-Date $_.TimeCreated).ToUniversalTime() -Format "o"
$Id = $_.Id
$LevelDisplayName = $_.LevelDisplayName
$KeywordsDisplayNames = $_.KeywordsDisplayNames
$Message = $_.Message
$Xml = [XML]($_.ToXml())
Write-Debug "Event: $TimeCreated"
$TimeCreatedUTC = $Xml.Event.System.TimeCreated.SystemTime
$TimeCreatedJST = Get-Date (Get-Date $TimeCreatedUTC) -Format "o"
$Computer = $Xml.Event.System.Computer
$SubjectUserSid = ($Xml.Event.EventData.Data | where Name -eq "SubjectUserSid")."#text"
$SubjectUserName = ($Xml.Event.EventData.Data | where Name -eq "SubjectUserName")."#text"
$SubjectLogonId = ($Xml.Event.EventData.Data | where Name -eq "SubjectLogonId")."#text"
$ObjectType = ($Xml.Event.EventData.Data | where Name -eq "ObjectType")."#text"
$IpAddress = ($Xml.Event.EventData.Data | where Name -eq "IpAddress")."#text"
$IpPort = ($Xml.Event.EventData.Data | where Name -eq "IpPort")."#text"
$ShareName = ($Xml.Event.EventData.Data | where Name -eq "ShareName")."#text"
$ShareLocalPath = ($Xml.Event.EventData.Data | where Name -eq "ShareLocalPath")."#text"
$RelativeTargetName = ($Xml.Event.EventData.Data | where Name -eq "RelativeTargetName")."#text"
$AccessMask = ($Xml.Event.EventData.Data | where Name -eq "AccessMask")."#text"
$AccessList = ($Xml.Event.EventData.Data | where Name -eq "AccessList")."#text"
$AccessReason = ($Xml.Event.EventData.Data | where Name -eq "AccessReason")."#text"
# ACLのヒューマンリーダブル化
if ($AccessList -ne $null) {
$AccessListDisplayName = @()
if ($AccessList.Contains("%%4416")) { $AccessListDisplayName += "ReadData/ListDir" }
if ($AccessList.Contains("%%4417")) { $AccessListDisplayName += "WriteData/AddFile" }
if ($AccessList.Contains("%%4418")) { $AccessListDisplayName += "AppendData/AddSubdir" }
if ($AccessList.Contains("%%4419")) { $AccessListDisplayName += "ReadExtendedAttirbutes" }
if ($AccessList.Contains("%%4420")) { $AccessListDisplayName += "WriteExtendedAttirbutes" }
if ($AccessList.Contains("%%4421")) { $AccessListDisplayName += "Execute/Traverse" }
if ($AccessList.Contains("%%4422")) { $AccessListDisplayName += "DeleteChildDir+Files" }
if ($AccessList.Contains("%%4423")) { $AccessListDisplayName += "ReadAttributes" }
if ($AccessList.Contains("%%4424")) { $AccessListDisplayName += "WriteAttributes" }
if ($AccessList.Contains("%%1537")) { $AccessListDisplayName += "Delete" }
if ($AccessList.Contains("%%1538")) { $AccessListDisplayName += "ReadSecurityDescriptor" }
if ($AccessList.Contains("%%1539")) { $AccessListDisplayName += "WriteDiscretionaryACL" }
if ($AccessList.Contains("%%1540")) { $AccessListDisplayName += "WriteOwner" }
if ($AccessList.Contains("%%1541")) { $AccessListDisplayName += "Sync" }
if ($AccessList.Contains("%%1542")) { $AccessListDisplayName += "Read+WriteSecACL" }
}
# 共有パスとローカルパスの復元
$SharePath = $ShareName -replace "\*", $Computer
$SharePath = Join-Path $SharePath -ChildPath $RelativeTargetName
$LocalPath = $ShareLocalPath -replace "\\\?\?\\", ""
if ($LocalPath -ne "") {
$LocalPath = Join-Path $LocalPath -ChildPath $RelativeTargetName
}
$Event = New-Object PSCustomObject
$Event | Add-Member -MemberType NoteProperty -Name EventId -Value $Id
$Event | Add-Member -MemberType NoteProperty -Name KeywordsDisplayNames -Value ($KeywordsDisplayNames -join "|")
$Event | Add-Member -MemberType NoteProperty -Name TimeCreatedUTC -Value $TimeCreatedUTC
$Event | Add-Member -MemberType NoteProperty -Name TimeCreatedJST -Value $TimeCreatedJST
$Event | Add-Member -MemberType NoteProperty -Name Computer -Value $Computer
$Event | Add-Member -MemberType NoteProperty -Name SubjectUserSid -Value $SubjectUserSid
$Event | Add-Member -MemberType NoteProperty -Name SubjectUserName -Value $SubjectUserName
$Event | Add-Member -MemberType NoteProperty -Name SubjectLogonId -Value $SubjectLogonId
$Event | Add-Member -MemberType NoteProperty -Name ObjectType -Value $ObjectType
$Event | Add-Member -MemberType NoteProperty -Name IpAddress -Value $IpAddress
$Event | Add-Member -MemberType NoteProperty -Name IpPort -Value $IpPort
$Event | Add-Member -MemberType NoteProperty -Name IpAddressAndPort -Value "${IpAddress}:${IpPort}"
$Event | Add-Member -MemberType NoteProperty -Name ShareName -Value $ShareName
$Event | Add-Member -MemberType NoteProperty -Name ShareLocalPath -Value $ShareLocalPath
$Event | Add-Member -MemberType NoteProperty -Name RelativeTargetName -Value $RelativeTargetName
$Event | Add-Member -MemberType NoteProperty -Name SharePath -Value $SharePath
$Event | Add-Member -MemberType NoteProperty -Name LocalPath -Value $LocalPath
$Event | Add-Member -MemberType NoteProperty -Name AccessList -Value ($AccessListDisplayName -join "|")
$Events += $Event
}
# バックアップイベントの存在確認
$Result = Get-WinEvent -Path $EvtxFilePath -FilterXPath "Event/System/EventID='1105'" | where { ($_.TimeCreated -ge $StartDate) -and ($_.TimeCreated -le $EndDate) } | ForEach-Object {
$Xml = [XML]($_.ToXml())
$BackupPath = $Xml.Event.UserData.AutoBackup.BackupPath
if (Test-Path $BackupPath) {
$OldEvents = Get-FileShareAuditLogByDate -EvtxFilePath $BackupPath -Date $Date
foreach ($OldEvent in $OldEvents) {
$Events += $OldEvent
}
}
}
return $Events
}
# 処理
for ($i = 1; $i -le 7; $i++) {
$Date = (Get-Date).AddDays(-1 * $i)
$SecurityEvtxPath = Get-SecurityEvtxPath
Write-Debug "--------"
Write-Debug "Date: $Date"
Write-Debug "SecurityEvtxPath: $SecurityEvtxPath"
$Result = Get-FileShareAuditLogByDate -EvtxFilePath $SecurityEvtxPath -Date $Date
$DataStringForFilename = Get-Date $Date -Format "yyyyMMdd"
$ArchiveFileName = "${ArchiveFileBaseName}_${DataStringForFilename}${ArchiveFileExtention}"
$ArchiveFullPath = Join-Path $ArchiveDirPath -ChildPath $ArchiveFileName
if (-not $(Test-Path($ArchiveFullPath))) {
$Result | Export-Csv -Encoding Default -Path $ArchiveFullPath
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment