LoginSignup
3
4

More than 3 years have passed since last update.

PowerShellを使って共有フォルダのアクセスログを取る

Posted at

個人ブログから過去記事を移転。
方法2に関してはこちらのほうが良記事 → ファイルサーバのアクセスログをPowerShellで取得する


サーバーの共有フォルダへのアクセスがどれだけあるのか統計を取りたい。

以下要件

  • Windowsの標準機能で実装
  • 同時接続100人程度

方法1:SMBを監視する

ネットワーク上にある共有フォルダなら、SMBのイベントを監視すればいいじゃない。
ということでプロトコルの監視。

  • 利点
    • 事前の仕掛けが必要ない
  • 欠点
    • 常時プロセスが動きっぱなし
    • ローカルのアクセスは把握できない

WMIEventを使う方法を紹介。
NetEventを使う場合は注釈参照1
永続化するにはMOF作成が必要っぽい。

$smb_namespace = "root\Microsoft\Windows\SMB"
$smb_query = "Select * From __InstanceCreationEvent WITHIN 1 Where TargetInstance ISA 'MSFT_SmbOpenFile'"
$fs = New-Object System.IO.StreamWriter("D:\log.txt",$true,[Text.Encoding]::GetEncoding("UTF-8"))
$fs.AutoFlush = $true

#イベントが発生すると実行されるAction
$smb_event = {
    $e = $Event.SourceEventArgs.NewEvent
    $out = [DateTime]::FromFileTime($e.TIME_CREATED).ToString() + "|" + $e.TargetInstance.ClientUserName + "|" + $e.TargetInstance.Path
    $fs.WriteLine($out)
}

#「SMBLog」という名前のイベントを作成
Register-WmiEvent -Namespace $smb_namespace -Query $smb_query -SourceIdentifier "SMBLog" -Action $smb_event

#Get-EventSubscriberで動作中のイベントを確認
#Unregister-eventでイベント停止

方法2:Windowsログの監査ログを利用する

Windowsの監査ログを使って特定のファイルアクセスを監視する
上記記事を参考に監査ポリシーの設定をいじると、イベントビューアで閲覧可能なログを吐いてくれる。

  • 利点
    • 常時ジョブを走らせなくていい
  • 欠点
    • ログの取得が細かく取捨選択出来ないため、不要なログが貯まる。例えば、1ファイル開くだけでハンドル操作やらオープンやらのログが大量に発生する。

XPathで抽出条件を指定

$fromDay = -20
$days = 20
$startTime = [DateTime](Get-Date).AddDays($fromDay).ToString("yyyy/MM/dd 00:00:00")
$startUTCTime = [System.TimeZoneInfo]::ConvertTimeToUtc($startTime).ToString("yyyy-MM-ddTHH:mm:ssZ")
$endUTCTime = [System.TimeZoneInfo]::ConvertTimeToUtc($startTime.AddDays($days)).ToString("yyyy-MM-ddTHH:mm:ssZ")

#ログ抽出処理
#対象のEvent=4656
#explorerのアクセスは取得しない
$filter = @"
    Event/System/EventID='4656' and
    Event/EventData[
    Data[@Name='ProcessName']!='C:\Windows\explorer.exe'
    ] and
    Event/EventData[
    Data[@Name='ObjectType']='File'
    ] and
    Event/System/TimeCreated[@SystemTime>='$startUTCTime'] and
    Event/System/TimeCreated[@SystemTime<'$endUTCTime']
"@

#ログ抽出
try{
    Get-WinEvent -LogName security -FilterXPath $filter | % {
        $eventxml = [xml]$_.toXML()
        #名前空間を指定しないと抽出不可能
        $ns = New-Object Xml.XmlNamespaceManager $eventxml.NameTable
        $ns.AddNamespace("e", "http://schemas.microsoft.com/win/2004/08/events/event")

        $prop = @{"Time"=[DateTime]$eventxml.SelectSingleNode('e:Event/e:System/e:TimeCreated', $ns).Attributes.GetNamedItem("SystemTime").Value;
                  "User"=$eventxml.SelectSingleNode('e:Event/e:EventData/e:Data[@Name="SubjectUserName"]', $ns).InnerText;
                  "Domain"=$eventxml.SelectSingleNode('e:Event/e:EventData/e:Data[@Name="SubjectDomainName"]', $ns).InnerText;
                  "Path"=$eventxml.SelectSingleNode('e:Event/e:EventData/e:Data[@Name="ObjectName"]', $ns).InnerText;
                  "Process"=$eventxml.SelectSingleNode('e:Event/e:EventData/e:Data[@Name="ProcessName"]', $ns).InnerText}
                  return New-Object -TypeName PSObject -Property $prop
        }
}
catch {
    Write-Host "該当ログなし"
    $error | Select-Object -Last 1
}
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4