有没有办法动态过滤事件日志?

时间:2019-03-25 15:57:47

标签: powershell

我正在尝试编写一个由事件执行的PowerShell脚本。 然后,该PowerShell脚本应运行:

Get-WinEvent -FilterHashtable @{Logname='security';ID=$instanceID} -MaxEvents 1

获取触发PS脚本的事件。

到目前为止,一切顺利,一旦我有这个活动,我想发送一封电子邮件。该邮件应包含事件消息中的某些内容。

例如:事件ID 4720(已创建用户帐户) 用户帐户xx由xx在xx时间创建。

现在我有大约10个事件ID,我想通过电子邮件对其进行响应。这些事件ID在消息中有所不同。

有动态的方法吗?

我尝试了以下操作:

param(
    [Parameter(Mandatory = $true)]$instanceID
)

#$instanceIDs = @(4661,4662,5139,5136,5137,5138,5139,5141,4720,4722,4723,4724,4725,4726,4738,4740,4767,4780,4781,4794,5376,5377,4741,4742,4743,4727,4728,4729)
$event = Get-WinEvent -FilterHashtable @{Logname='security';ID=$instanceID} -MaxEvents 1


Function EventIDxxx{
    Get-WinEvent -FilterHashtable @{Logname='security';ID=$instanceID} -MaxEvents 1 |
        Select-Object -Property timecreated,
        @{label='username';expression={$_.properties[0].value}},
        @{label='computername';expression={$_.properties[1].value}}
}

但是我必须为每个事件创建一个新功能。 有人有主意吗?

非常感谢您


**编辑**

我想拥有一个Powershell脚本,该脚本可以读取事件消息,并将需要的部分写入变量中。

A user account was created.

Subject:
    Security ID:        Contoso\Conlil
    Account Name:       Conlil
    Account Domain:     Contoso
    Logon ID:       0x1468731E

New Account:
    Security ID:        Contoso\ASD
    Account Name:       ASD
    Account Domain:     Contoso

Attributes:
    SAM Account Name:   ASD
    Display Name:       wSDSAD D. DSA
    User Principal Name:    ASD@Contoso.com
    Home Directory:     -
    Home Drive:     -
    Script Path:        -
    Profile Path:       -
    User Workstations:  -
    Password Last Set:  <never>
    Account Expires:        <never>
    Primary Group ID:   513
    Allowed To Delegate To: -
    Old UAC Value:      0x0
    New UAC Value:      0x15
    User Account Control:   
        Account Disabled
        'Password Not Required' - Enabled
        'Normal Account' - Enabled
    User Parameters:    -
    SID History:        -
    Logon Hours:        <value not set>

Additional Information:
    Privileges      -

例如,在此事件中,我想要  1.创建者的用户名和域  2.创建的帐户名称  3.创建帐户的域  4.创建帐户的电子邮件  5.也许HomeDrive  6. UserAccount控件

我可以使用以下代码进行此操作:

@{label='Username';expression={$_.properties[x].value}},

但这是静态的,我必须为每个事件创建一个新函数。

3 个答案:

答案 0 :(得分:1)

除了使用脚本(方法)之外,还可以使用事件查看器将Windows任务附加到该事件:

您右键单击事件,然后单击“将任务附加到此事件…”。然后您有多种选择,例如可以运行一个程序(可以是powershell.exe)或发送电子邮件。

参考:https://blogs.technet.microsoft.com/wincat/2011/08/25/trigger-a-powershell-script-from-a-windows-event/

更新

我不好的“从任务事件发送电子邮件”是deprecated

另一种替代方法是创建任务并使用“ powershell.exe”运行该任务,并将调用Send-MailMessage cmdlet的脚本作为参数传递: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/send-mailmessage?view=powershell-5.1

答案 1 :(得分:0)

This is what WMI Event consumers / watchers are designed for。您可以设置temporarypermanent

这是很常见的事情,并且在网络上有很多有关如何进行设置的示例,甚至可以使用预构建的脚本,也可以根据需要进行调整。

Powershell Centralized Log Monitor

监视指定日志事件的服务器集合,并在捕获监视的事件时发送电子邮件警报。

## Powershell Log Monitor Script ## 
## Contributing authors - mck74,mjolinor, 

param([switch]$ShowEvents = $false,[switch]$NoEmail = $false,[switch]$useinstanceid = $false) 


$log = "Application" 
$hist_file = $log + "_loghist.xml" 
$seed_depth = 200 

#run interval in minutes - set to zero for runonce, "C" for 0 delay continuous loop. 
$run_interval = 1 

$EmailFrom = "<user@domain.tld>" 
$EmailTo = "<user@domain.tld>" 
$EmailSubject = "Server event notification"   

$SMTPServer = "smtphost.domain.tld" 
$SMTPAuthUsername = "username" 
$SMTPAuthPassword = "password" 

$computers = @(gc monitored_computers.txt) 
$event_list = @{} 
Import-Csv alert_events.csv |% {$event_list[$_.source + '#' + $_.id] = 1} 


#see if we have a history file to use, if not create an empty $histlog 
if (Test-Path $hist_file){$loghist = Import-Clixml $hist_file} 
 else {$loghist = @{}} 


$timer = [System.Diagnostics.Stopwatch]::StartNew() 

function send_email { 
$mailmessage = New-Object system.net.mail.mailmessage  
$mailmessage.from = ($emailfrom)  
$mailmessage.To.add($emailto) 
$mailmessage.Subject = $emailsubject 
$mailmessage.Body = $emailbody 
$mailmessage.IsBodyHTML = $true 
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)   
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("$SMTPAuthUsername", "$SMTPAuthPassword")  
$SMTPClient.Send($mailmessage) 
} 
#START OF RUN PASS 
$run_pass = { 

$EmailBody = "Log monitor found monitored events. `n" 

$computers |%{ 
$timer.reset() 
$timer.start() 

Write-Host "Started processing $($_)" 

#Get the index number of the last log entry 
$index = (Get-EventLog -ComputerName $_ -LogName $log -newest 1).index 

#if we have a history entry calculate number of events to retrieve 
#   if we don't have an event history, use the $seed_depth to do initial seeding 
if ($loghist[$_]){$n = $index - $loghist[$_]} 
 else {$n = $seed_depth} 

if ($n -lt 0){ 
 Write-Host "Log index changed since last run. The log may have been cleared. Re-seeding index." 
 $events_found = $true 
 $EmailBody += "`n Possible Log Reset $($_)`nEvent Index reset detected by Log Monitor`n" | ConvertTo-Html 
 $n = $seed_depth 
 } 

Write-Host "Processing $($n) events." 

#get the log entries 

if ($useinstanceid){ 
$log_hits = Get-EventLog -ComputerName $_ -LogName $log -Newest $n | 
? {$event_list[$_.source + "#" + $_.instanceid]} 
} 

else {$log_hits = Get-EventLog -ComputerName $_ -LogName $log -Newest $n | 
? {$event_list[$_.source + "#" + $_.eventid]} 
} 

#save the current index to $loghist for the next pass 
$loghist[$_] = $index 

#report number of alert events found and how long it took to do it 
if ($log_hits){ 
 $events_found = $true 
 $hits = $log_hits.count 
 $EmailBody += "`n Alert Events on server $($_)`n" 
 $log_hits |%{ 
  $emailbody += "<br><br>" 
  $emailbody += $_ | select MachineName,EventID,Message | ConvertTo-Html  
 $emailbody += "<br><br>" 
 } 
 } 
 else {$hits = 0} 
$duration = ($timer.elapsed).totalseconds 
write-host "Found $($hits) alert events in $($duration) seconds." 
"-"*60 
" " 
if ($ShowEvents){$log_hits | fl | Out-String |? {$_}} 
} 

#save the history file to disk for next script run  
$loghist | export-clixml $hist_file 

#Send email if there were any monitored events found 
if ($events_found -and -not $NoEmail){send_email} 

} 
#END OF RUN PASS 

Write-Host "`n$("*"*60)" 
Write-Host "Log monitor started at $(get-date)" 
Write-Host "$("*"*60)`n" 

#run the first pass 
$start_pass = Get-Date 
&$run_pass 

#if $run_interval is set, calculate how long to sleep before the next pass 
while ($run_interval -gt 0){ 
if ($run_interval -eq "C"){&$run_pass} 
 else{ 
 $last_run = (Get-Date) - $start_pass 
 $sleep_time = ([TimeSpan]::FromMinutes($run_interval) - $last_run).totalseconds 
 Write-Host "`n$("*"*10) Sleeping for $($sleep_time) seconds `n" 

#sleep, and then start the next pass 
 Start-Sleep -seconds $sleep_time 
 $start_pass = Get-Date  
 &$run_pass 
 } 
 }

答案 2 :(得分:0)

我得到了答案。

$event = Get-WinEvent -FilterHashtable @{Logname='security';ID=$instanceID} -MaxEvents 1

foreach($entry in $event){
    #Get the XML...
    $XML = [xml]$entry.ToXml()

    #Some events use other nodes, like 'UserData' on Applocker events...
    $XMLData = $null
    if( $XMLData = @( $XML.Event.EventData.Data )) {
        For( $i=0; $i -lt $XMLData.count; $i++ ) {
            #We don't want to overwrite properties that might be on the original object, or in another event node.   
            Add-Member -InputObject $entry -MemberType NoteProperty -name "EventData$($XMLData[$i].name)" -Value $XMLData[$i].'#text' -Force
        }
    }
}

$entry | select EventData*