使用Powershell进行日志文件分析

使用Powershell进行日志文件分析

PowerShell 是 DFIR(数字取证与事件响应)流程中最常用的脚本工具之一,能帮助在应急响应场景下快速读取日志、提取 IOC、过滤攻击流量、实时监控可疑行为。

使用 PowerShell 检查日志文件

PowerShell 是分析日志的非常有效的工具。通过 Get-ContentSelect-StringConvertFrom-JsonConvertTo-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 查询要求日期必须是这种格式。

脚本的输出结果与我们之前的脚本相同,但当你分别运行两个脚本时,会发现第二种方法运行得更快,并且占用更少的系统资源。在分析大型应急响应现场的主机(包含数百万条事件)时,这种方式会显著减少分析时间。

赞赏

微信赞赏支付宝赞赏

Zgao

愿有一日,安全圈的师傅们都能用上Zgao写的工具。

发表评论