Windows事件日志安全分析脚本
分析Windows安全事件日志,检测登录失败、账户锁定、权限变更、异常进程创建等安全事件,生成安全分析报告,支持按时间范围和事件类型筛选
详细内容
<#
.SYNOPSIS
Windows事件日志安全分析脚本
.DESCRIPTION
分析Windows安全事件日志,检测异常登录、账户操作、权限变更等安全事件
.USAGE
.\event_log_analysis.ps1 # 分析最近24小时
.\event_log_analysis.ps1 -Hours 72 # 分析最近72小时
#>
param(
[int]$Hours = 24, # 分析最近多少小时
[string]$ReportPath = "C:\Windows\Temp\security_analysis_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
)
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host " Windows事件日志安全分析" -ForegroundColor Cyan
Write-Host " 计算机: $env:COMPUTERNAME" -ForegroundColor Cyan
Write-Host " 分析范围: 最近 $Hours 小时" -ForegroundColor Cyan
Write-Host " 时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Cyan
Write-Host "==========================================" -ForegroundColor Cyan
$startTime = (Get-Date).AddHours(-$Hours)
$risks = @()
function Add-Risk {
param([string]$Level, [string]$Description, [string]$Detail)
$script:risks += [PSCustomObject]@{
Level = $Level
Description = $Description
Detail = $Detail
Time = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
}
}
# 1. 登录失败事件 (Event ID 4625)
Write-Host "`n【1. 登录失败事件分析】" -ForegroundColor Yellow
try {
$failedLogins = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4625
StartTime = $startTime
} -ErrorAction Stop
Write-Host " 登录失败总数: $($failedLogins.Count)"
if ($failedLogins.Count -gt 0) {
# 按来源IP统计
$ipStats = @{}
$userStats = @{}
foreach ($event in $failedLogins) {
$xml = [xml]$event.ToXml()
$ip = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'IpAddress' }).'#text'
$user = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
if ($ip) { $ipStats[$ip] = ($ipStats[$ip] + 1) }
if ($user) { $userStats[$user] = ($userStats[$user] + 1) }
}
Write-Host "`n 来源IP Top 10:"
$ipStats.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 10 | ForEach-Object {
Write-Host " $($_.Key): $($_.Value) 次"
if ($_.Value -ge 10) {
Add-Risk -Level "High" -Description "疑似暴力破解" -Detail "IP $($_.Key) 在 $Hours 小时内登录失败 $($_.Value) 次"
}
}
Write-Host "`n 目标账户 Top 10:"
$userStats.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 10 | ForEach-Object {
Write-Host " $($_.Key): $($_.Value) 次"
}
Write-Host "`n 最近5次登录失败:"
$failedLogins | Select-Object -First 5 | ForEach-Object {
$xml = [xml]$_.ToXml()
$ip = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'IpAddress' }).'#text'
$user = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
Write-Host " $($_.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')) | 用户: $user | IP: $ip"
}
} else {
Write-Host " ✅ 无登录失败记录" -ForegroundColor Green
}
} catch {
Write-Host " ⚠️ 无法读取安全日志(需要管理员权限): $($_.Exception.Message)" -ForegroundColor Yellow
}
# 2. 账户锁定事件 (Event ID 4740)
Write-Host "`n【2. 账户锁定事件】" -ForegroundColor Yellow
try {
$lockouts = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4740
StartTime = $startTime
} -ErrorAction Stop
Write-Host " 账户锁定次数: $($lockouts.Count)"
if ($lockouts.Count -gt 0) {
$lockouts | ForEach-Object {
$xml = [xml]$_.ToXml()
$user = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
Write-Host " $($_.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')) | 账户: $user"
Add-Risk -Level "High" -Description "账户被锁定" -Detail "账户 $user 被锁定,时间: $($_.TimeCreated)"
}
}
} catch {
Write-Host " 无账户锁定记录或无法读取" -ForegroundColor Gray
}
# 3. 成功登录事件 (Event ID 4624)
Write-Host "`n【3. 成功登录事件分析】" -ForegroundColor Yellow
try {
$successLogins = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4624
StartTime = $startTime
} -MaxEvents 100 -ErrorAction Stop
# 按登录类型统计
$typeStats = @{}
foreach ($event in $successLogins) {
$xml = [xml]$event.ToXml()
$logonType = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonType' }).'#text'
$typeName = switch ($logonType) {
"2" { "交互式登录" }
"3" { "网络登录" }
"4" { "批处理登录" }
"5" { "服务登录" }
"7" { "解锁" }
"10" { "远程桌面(RDP)" }
default { "类型$logonType" }
}
$typeStats[$typeName] = ($typeStats[$typeName] + 1)
}
Write-Host " 最近100次成功登录类型分布:"
$typeStats.GetEnumerator() | Sort-Object Value -Descending | ForEach-Object {
Write-Host " $($_.Key): $($_.Value) 次"
}
# 检测非工作时间登录
$oddHoursLogins = $successLogins | Where-Object {
$hour = $_.TimeCreated.Hour
$hour -lt 6 -or $hour -gt 22
}
if ($oddHoursLogins.Count -gt 0) {
Write-Host "`n ⚠️ 非工作时间(22:00-06:00)登录: $($oddHoursLogins.Count) 次" -ForegroundColor Yellow
$oddHoursLogins | Select-Object -First 5 | ForEach-Object {
Write-Host " $($_.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss'))"
}
}
} catch {
Write-Host " 无法读取登录记录" -ForegroundColor Gray
}
# 4. 用户账户变更 (Event ID 4720, 4726, 4732)
Write-Host "`n【4. 用户账户变更】" -ForegroundColor Yellow
try {
$userChanges = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4720, 4726, 4732, 4733
StartTime = $startTime
} -ErrorAction Stop
Write-Host " 账户变更事件数: $($userChanges.Count)"
if ($userChanges.Count -gt 0) {
$userChanges | ForEach-Object {
$action = switch ($_.Id) {
4720 { "创建用户" }
4726 { "删除用户" }
4732 { "添加到安全组" }
4733 { "从安全组移除" }
}
Write-Host " $($_.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')) | $action"
Add-Risk -Level "Medium" -Description "账户变更" -Detail "$action,时间: $($_.TimeCreated)"
}
}
} catch {
Write-Host " 无账户变更记录" -ForegroundColor Gray
}
# 5. 进程创建事件 (Event ID 4688)
Write-Host "`n【5. 异常进程创建检测】" -ForegroundColor Yellow
try {
$processes = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4688
StartTime = $startTime
} -MaxEvents 500 -ErrorAction Stop
# 检测可疑进程路径
$suspiciousPatterns = @('\Temp\', '\AppData\', 'powershell.exe -enc', 'cmd.exe /c', 'wscript', 'cscript', 'regsvr32', 'mshta')
$suspicious = @()
foreach ($event in $processes) {
$xml = [xml]$event.ToXml()
$processName = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'NewProcessName' }).'#text'
$commandLine = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'CommandLine' }).'#text'
foreach ($pattern in $suspiciousPatterns) {
if ($processName -match $pattern -or $commandLine -match $pattern) {
$suspicious += [PSCustomObject]@{
Time = $event.TimeCreated
Process = $processName
Command = $commandLine
}
break
}
}
}
Write-Host " 扫描进程数: $($processes.Count)"
Write-Host " 可疑进程数: $($suspicious.Count)"
if ($suspicious.Count -gt 0) {
$suspicious | Select-Object -First 10 | ForEach-Object {
Write-Host " $($_.Time.ToString('HH:mm:ss')) | $($_.Process)" -ForegroundColor Red
Write-Host " 命令: $($_.Command)" -ForegroundColor DarkRed
Add-Risk -Level "Medium" -Description "可疑进程创建" -Detail "进程: $($_.Process), 命令: $($_.Command)"
}
}
} catch {
Write-Host " 无法读取进程创建日志(需要启用进程审计)" -ForegroundColor Gray
}
# 6. 风险汇总
Write-Host "`n==========================================" -ForegroundColor Cyan
Write-Host " 安全风险汇总" -ForegroundColor Cyan
Write-Host "==========================================" -ForegroundColor Cyan
if ($risks.Count -eq 0) {
Write-Host " ✅ 未发现明显安全风险" -ForegroundColor Green
} else {
$highCount = ($risks | Where-Object { $_.Level -eq 'High' }).Count
$mediumCount = ($risks | Where-Object { $_.Level -eq 'Medium' }).Count
Write-Host " 发现风险总数: $($risks.Count)" -ForegroundColor Red
Write-Host " 高危: $highCount | 中危: $mediumCount" -ForegroundColor Red
$risks | ForEach-Object {
$color = if ($_.Level -eq 'High') { 'Red' } else { 'Yellow' }
Write-Host "`n [$($_.Level)] $($_.Description)" -ForegroundColor $color
Write-Host " 详情: $($_.Detail)"
Write-Host " 时间: $($_.Time)"
}
}
# 保存报告
Write-Host "`n【报告已保存到】$ReportPath" -ForegroundColor Cyan
"Windows安全事件分析报告" | Out-File $ReportPath -Encoding UTF8
"计算机: $env:COMPUTERNAME" | Out-File $ReportPath -Encoding UTF8 -Append
"分析范围: 最近 $Hours 小时" | Out-File $ReportPath -Encoding UTF8 -Append
"风险总数: $($risks.Count)" | Out-File $ReportPath -Encoding UTF8 -Append
$risks | Format-Table -AutoSize | Out-File $ReportPath -Encoding UTF8 -Append
Write-Host "`n==========================================" -ForegroundColor Cyan
Write-Host " 分析完成" -ForegroundColor Cyan
Write-Host "==========================================" -ForegroundColor Cyan
适配环境
适配系统:Windows 10+,Windows Server 2016+
依赖环境:Windows PowerShell 5.1+
参数说明
[{"name": "Hours", "label": "\u5206\u6790\u6700\u8fd1\u591a\u5c11\u5c0f\u65f6", "default": "24"}, {"name": "ReportPath", "label": "\u62a5\u544a\u4fdd\u5b58\u8def\u5f84", "default": "C:\\Windows\\Temp\\security_analysis.txt"}]