【问题标题】:Regex Pattern in Powershell doesn't work as expectedPowershell 中的正则表达式模式无法按预期工作
【发布时间】:2021-11-15 00:34:57
【问题描述】:

我在 Powershell 中有一个字符串,其中包含以下数据

  An account failed to log on.

Subject:
    Security ID:        S-1-5-18
    Account Name:       TEX
    Account Domain:     TD2
    Logon ID:       0x3E7

Logon Type:         8

Account For Which Logon Failed:
    Security ID:        S-1-0-0
    Account Name:       test_mathysf
    Account Domain:     tdlz2

Failure Information:
    Failure Reason:     Unknown user name or bad password.
    Status:         0xC000006D
    Sub Status:     0xC000006A

Process Information:
    Caller Process ID:  0x4f80
    Caller Process Name:    C:\Windows\System32\inetsrv\w3wp.exe

Network Information:
    Workstation Name:   T22
    Source Network Address: 192.168.10.28
    Source Port:        45221

Detailed Authentication Information:
    Logon Process:      Advapi  
    Authentication Package: Negotiate
    Transited Services: -
    Package Name (NTLM only):   -
    Key Length:     0

This event is generated when a logon request fails. It is generated on the computer where access was attempted.

The Subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Ser
ver service, or a local process such as Winlogon.exe or Services.exe.

The Logon Type field indicates the kind of logon that was requested. The most common types are 2 (interactive) and 3 (network).

The Process Information fields indicate which account and process on the system requested the logon.

The Network Information fields indicate where a remote logon request originated. Workstation name is not always available and may be l
eft blank in some cases.

The authentication information fields provide detailed information about this specific logon request.
    - Transited services indicate which intermediate services have participated in this logon request.
    - Package name indicates which sub-protocol was used among the NTLM protocols.
    - Key length indicates the length of the generated session key. This will be 0 if no session key was requested.

我想使用以下正则表达式模式转义 Subject 和 Key Lenght 之间的所有内容。

$pattern = "(?<=.*Subject:)\w+?(?=Length:*)"

正则表达式的结果应该是这样的

Subject:
    Security ID:        S-1-5-18
    Account Name:       TEX
    Account Domain:     TD2
    Logon ID:       0x3E7

Logon Type:         8

Account For Which Logon Failed:
    Security ID:        S-1-0-0
    Account Name:       test_mathysf
    Account Domain:     tdlz2

Failure Information:
    Failure Reason:     Unknown user name or bad password.
    Status:         0xC000006D
    Sub Status:     0xC000006A

Process Information:
    Caller Process ID:  0x4f80
    Caller Process Name:    C:\Windows\System32\inetsrv\w3wp.exe

Network Information:
    Workstation Name:   T22
    Source Network Address: 192.168.10.28
    Source Port:        45221

Detailed Authentication Information:
    Logon Process:      Advapi  
    Authentication Package: Negotiate
    Transited Services: -
    Package Name (NTLM only):   -
    Key Length:     0

但在我的项目中,正则表达式不起作用。 (它没有匹配)

之后,我将使用 ConvertFrom-StringData cmdlet 创建包含条目的哈希表(例如 Security ID --> Key = S-1-5-18)

有人知道问题出在哪里吗?

【问题讨论】:

  • 这个字符串是从哪里来的?如果您可以访问底层事件数据,则将其提取为 XML 会容易得多
  • 肯定需要基础数据样本。另外,您是否将正则表达式复制/粘贴到您的帖子中,或者您是否手动输入 - 我注意到您的模式中的“长度”一词拼写错误。
  • 正则表达式字符串中有类型吗? ...(?=长度:*)...
  • 主题前的 * 在 regex101.com 中给出错误。这也不会匹配多行字符串。使用 get-winevent 和使用 toxml() 肯定更容易。
  • @WaitingForGuacamole 数据来自 syslog api 作为 json。 Json 具有“文本”字段,其中包含作为普通字符串的文本

标签: regex powershell


【解决方案1】:

您似乎想从事件文本中提取结构化信息。

这就是我要做的。

function ExtractEventData {
    param(
        [string]$EventText
    )
    $pattern = [regex]"(?m)^(.*):\s*(^    \S.*:.*\n)+"
    $result = @{}

    foreach ($match in $pattern.Matches($EventText)) {
        $section_name = $match.Groups[1].Value
        $result[$section_name] = @{}
        foreach ($line in $match.Groups[2].Captures) {
            $key, $value = $line.Value.Split(':'.ToCharArray(), 2)
            $result[$section_name][$key.Trim()] = $value.Trim()
        }
        $result[$section_name] = [pscustomobject]$result[$section_name]
    }
    [pscustomobject]$result
}

当你用上面的示例字符串这样调用它时

$result = ExtractEventData -EventText $sampleEvent

它产生这个数据结构:

进程信息:@{Caller Process ID=0x4f80;调用方进程名称=C:\Windows\System32\inetsrv\w3wp.exe} 详细的认证信息:@{Key Length=0;登录过程=Advapi;包名称(仅限 NTLM)=-;认证包=协商;中转服务=-} 主题:@{账户域=TD2;安全 ID=S-1-5-18;账户名=TEX;登录 ID=0x3E7} 登录失败的帐户:@{Account Domain=tdlz2;安全 ID=S-1-0-0;账户名=test_mathysf} 失败信息:@{Status=0xC000006D;失败原因=未知用户名或密码错误。;子状态=0xC000006A} 网络信息:@{工作站名称=T22;源网络地址=192.168.10.28;源端口=45221}

你可以直接访问,例如

$result.'Network Information'.'Workstation Name'   # => T22

正则表达式是

(?m) # 多行模式 ^ # 行首 (.*):\s* # 任何内容(例如“网络信息”进入第 1 组)、冒号、空格 (# group 2 (e.g. 'Workstation Name: T22') ^ \S.*:.*\n # 行首,4 个空格,一个非空格,一个冒号,任何内容,换行符 )+ # 结束组 2,重复

这样,每个部分都得到单独处理,并且在每个部分中,每一行都得到处理。

【讨论】:

    【解决方案2】:

    这是您从Get-WinEvent 获得的Message 属性,它是具有LOCALIZED 属性的多行字符串。

    与其将字符串转换为对象数组,不如使用事件 XML 表示法,您可以在其中获得通用命名的属性。

    类似这样的:

    $filter = @{LogName='Security';ProviderName='Microsoft-Windows-Security-Auditing';ID=4625 }
    $result = Get-WinEvent -FilterHashtable $filter -ComputerName SECRETSERVER | ForEach-Object {
        # convert the event to XML and grab the Event node
        $eventXml = ([xml]$_.ToXml()).Event
        # output the properties you need in your output
        [PSCustomObject]@{
            Time     = [DateTime]$eventXml.System.TimeCreated.SystemTime
            UserName = ($eventXml.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
            UserSID  = ($eventXml.EventData.Data | Where-Object { $_.Name -eq 'TargetUserSid' }).'#text'
            Computer = ($eventXml.EventData.Data | Where-Object { $_.Name -eq 'WorkstationName' }).'#text'
        }
    }
    
    # output on screen
    $result | Format-Table -AutoSize
    
    # output to CSV file
    $result | Export-Csv -Path 'X:\FailedLogons.csv' -NoTypeInformation
    

    Here您可以看到 XML 将包含的事件 4625 的所有属性。上面的示例仅列出了登录失败发生的时间、进行该尝试的计算机以及登录失败的用户名。

    【讨论】:

      【解决方案3】:

      你可以使用

      (?ms)^Subject:.*?Length:(?-s).*
      

      请参阅regex demo

      正则表达式详细信息

      • (?ms) - 内联修饰符,m 使 ^ 匹配任何行的开头,$ 匹配任何行结束位置,s 使 . 匹配任何字符,包括 LF 字符
      • ^ - 行首
      • Subject: - 文字文本
      • .*? - 尽可能少的零个或多个字符
      • Length: - 文字文本
      • (?-s) - 现在,. 不能再匹配 LF 字符了
      • .* - 除换行符 (LF) 字符之外的任何零个或多个字符,尽可能多。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多