使用Powershell进行日志文件分析
PowerShell 是 DFIR(数字取证与事件响应)流程中最常用的脚本工具之一,能帮助在应急响应场景下快速读取日志、提取 IOC、过滤攻击流量、实时监控可疑行为。
使用 PowerShell 检查日志文件
PowerShell 是分析日志的非常有效的工具。通过 Get-Content、Select-String、ConvertFrom-Json、ConvertTo-Json 等 Cmdlet,我们可以读取、搜索并操作日志文件。
我们从 IIS Web 服务器的日志文件开始。首先读取日志文件内容:
Get-Content -Path "C:\inetpub\logs\LogFiles\W3SVC1\u_ex250605.log"
执行后PowerShell 会将日志内容打印到屏幕上。

在处理 WebShell、攻击来源、SQL 注入、爆破等安全事件时,IIS 日志是最重要的取证数据来源之一,此步骤是“初步采集证据”的阶段。
在日志中查找特定内容
如果我们只关心包含“web”的日志行,可以使用以下命令:
Get-Content -Path "C:\inetpub\logs\LogFiles\W3SVC1\u_ex250605.log" | Select-String -Pattern "web"
运行后仅输出包含该关键词的行。

这是 IOC 匹配 的典型操作。当有攻击者域名、恶意 URL、恶意参数时,可以快速搜索是否存在对应访问行为。
实时监控日志变化
若希望实时观察日志新增内容(类似 tail -f),可使用:
Get-Content -Path "C:\inetpub\logs\LogFiles\W3SVC1\u_ex230629.log" -Wait | Select-String -Pattern "letsdefend"
该命令会先输出当前日志内容,然后持续监控文件更新情况。任何新增且匹配搜索条件的日志都会实时显示。
统计来自同一 IP 的访问次数
我们编写一个脚本,统计每个 IP 的访问数量。
# log file location
$filePath = "C:\inetpub\logs\LogFiles\W3SVC1\u_ex250605.log"
# Get 'c-ip' (client IP) field index from log file header
$ipFieldIndex = (Get-Content -Path $filePath | Where-Object { $_ -match "^#Fields:" }).Split(' ').IndexOf('c-ip') -1
# Skip informational lines
$logContent = Get-Content -Path $filePath | Where-Object { $_ -notmatch "^#" }
$ipCount = @{}
foreach($line in $logContent) {
$ip = $line.Split(' ')[$ipFieldIndex]
if ($ipCount.ContainsKey($ip)) {
$ipCount[$ip]++
} else {
$ipCount[$ip] = 1
}
}
$ipCount

执行脚本后即可看到每个 IP 对应的访问次数。
修改字段统计其他维度
通过调整 #Fields 提取逻辑,我们也可以统计:
- 最常访问的 URL
- 最常被攻击的接口
- 出现最多的 User-Agent(如自动化扫描器 UA)
输出为 JSON、CSV、XML、HTML 或写入文件
PowerShell object 的好处是能轻松转换输出格式。例如:
$events | Sort-Object -Property EventDate | ConvertTo-Json
或写入文件:
$events | Sort-Object -Property EventDate | ConvertTo-Json | Set-Content -Path "result.json"
在撰写事件报告或将数据导入 SIEM(如 Splunk、ELK)时,需要结构化数据,这些 Cmdlet 极其有用。
使用PowerShell 进行 Windows 事件日志分析
Windows Event Logs 是 Microsoft Windows 操作系统的一个特性,用于记录系统组件和应用程序运行过程中产生的各种事件。这些事件可能包括服务启动和停止、应用程序错误、安全告警等等。
Windows 事件日志分类
应用程序日志(Application Logs)
记录来自 Windows 应用程序的错误、警告以及其他事件。应用程序会将需要通知用户或系统管理员的情况写入此日志。如果发生“应用程序崩溃、WAF 拦截、WebShell 注入失败日志”等情况,通常首先检查 Application Log 以寻找程序异常根因。
系统日志(System Logs)
记录与操作系统组件有关的事件。例如:
- 硬件错误
- 驱动安装
- 系统错误
- 组件故障等
当怀疑攻击者利用驱动漏洞、关闭安全组件、尝试破坏系统功能时,可以从 System Log 中找到关键证据。
安全日志(Security Logs)
记录安全相关事件。例如:
- 登录与登出
- 文件与对象访问
- 用户 / 组管理
- 权限变更
- 本地安全策略变化
此外,Windows 还会根据配置记录更多事件类型,如:
- 审计日志(Audit Logs)
- 操作日志(Operational Logs)
- 调试日志(Debug Logs)等

事件查看器 (Event Viewer),图形化界面可用于查看、筛选和分析日志,但在需要跨多个事件进行关联分析、自动提取信息、快速生成报告时,GUI 的效率不足。
推荐使用 Get-WinEvent(比旧版 Get-EventLog 更强大)。
示例 1:列出系统所有日志源
Get-WinEvent -ListLog * | Select-Object LogName, RecordCount, IsClassicLog, IsEnabled, logMode, logType | Format-Table -AutoSize
输出内容中:
RecordCount:该日志源中当前包含多少条事件。
IsClassicLog:表示事件格式是传统风格(.mc 文件)还是新式 XML 事件记录方式。
IsEnabled:日志是否启用。若为 False,则事件不会被记录。
LogMode:日志空间不足时系统如何处理
- Circular:循环覆盖(最常见)
- Retain:停止记录
- AutoBackup:自动归档并继续写入
LogType:日志类型
- Administrative(管理日志)
- Analytical(分析日志)
- Debug(调试日志)
- Operational(运行日志)

如果攻击者试图清除日志,则日志计数 RecordCount 会突然减少。如果日志被禁用(IsEnabled=False),很可能有恶意行为。
示例 2:列出 Application 日志中最近 100 条事件
Get-WinEvent -LogName 'Application' -MaxEvents 100 | Select-Object TimeCreated, ID, ProviderName, LevelDisplayName, Message | Format-Table -AutoSize

输出包含关键信息:
- 事件时间
- 事件 ID
- 来源(Provider)
- 严重性等级
- 事件描述(Message)
示例 3:编写脚本列出用户登录记录(Event ID 4624)
PowerShell 脚本:列出某用户在指定日期范围内的登录记录。
# Set Username
$username = "zgao"
# Set start and end dates
$startDate = Get-Date "2025/01/01 00:00:00"
$endDate = Get-Date "2025/12/31 23:59:59"
# Get 4624 Events into HashTable
$events = Get-WinEvent -FilterHashTable @{
LogName = 'Security'
ID = 4624
StartTime = $startDate
EndTime = $endDate
}
# Print data to screen
foreach ($event in $events) {
$xml = [xml]$event.ToXml()
$eventUsername = $xml.Event.EventData.Data |
Where-Object {$_.Name -eq 'TargetUserName'} |
Select-Object -ExpandProperty '#text'
if ($eventUsername -eq $username) {
Write-Host "User $username, Login Date: $($event.TimeCreated)"
}
}

实测这种方式方式的查询速度非常慢,不推荐使用。
优化事件检索:使用 XPath 查询
直接通过 XPath 查询减少无用事件,提高速度与资源效率:
$username = "zgao"
$startDate = Get-Date "2025/12/01 00:00:00"
$endDate = Get-Date "2025/12/31 23:59:59"
$query = @"
<QueryList>
<Query Id="0">
<Select Path="Security">
*[System[(EventID=4624) and TimeCreated[@SystemTime>='{0}' and @SystemTime<='{1}']]]
and
*[EventData[Data[@Name='TargetUserName'] and (Data='{2}')]]
</Select>
</Query>
</QueryList>
"@ -f $startDate.ToUniversalTime().ToString("o"),
$endDate.ToUniversalTime().ToString("o"),
$username
$events = Get-WinEvent -FilterXml $query
foreach ($event in $events) {
Write-Host "User $username, Login Date: $($event.TimeCreated)"
}

这段脚本使用 XPath 查询,直接获取特定用户在特定日期范围内的登录事件。通过这种方式,我们只获取所需事件,而不必接收大量无关事件,从而减少系统资源的使用。
-f 运算符用于将字符串中的 {0}、{1} 和 {2} 占位符,分别替换为 $startDate、$endDate 和 $username 变量的值。ToString(“o”) 方法将日期转换为 ISO 8601 格式,因为 XPath 查询要求日期必须是这种格式。
脚本的输出结果与我们之前的脚本相同,但当你分别运行两个脚本时,会发现第二种方法运行得更快,并且占用更少的系统资源。在分析大型应急响应现场的主机(包含数百万条事件)时,这种方式会显著减少分析时间。
赞赏
微信赞赏
支付宝赞赏
发表评论