1

I am trying to get a specific Datafield (FailureReason) from the Event 4625 to a CSV field.

I have analyzed the event schema with the following code:

(Get-WinEvent -ListProvider Microsoft-Windows-Security-Auditing).Events |
    Where-Object {$_.Id -eq 4625}

which results in:

Id          : 4625
Version     : 0
LogLink     : System.Diagnostics.Eventing.Reader.EventLogLink
Level       : System.Diagnostics.Eventing.Reader.EventLevel
Opcode      : System.Diagnostics.Eventing.Reader.EventOpcode
Task        : System.Diagnostics.Eventing.Reader.EventTask
Keywords    : {}
Template    : <template xmlns="http://schemas.microsoft.com/win/2004/08/events">
                <data name="SubjectUserSid" inType="win:SID" outType="xs:string"/>
                <data name="SubjectUserName" inType="win:UnicodeString" outType="xs:string"/>
                <data name="SubjectDomainName" inType="win:UnicodeString" outType="xs:string"/>
                <data name="SubjectLogonId" inType="win:HexInt64" outType="win:HexInt64"/>
                <data name="TargetUserSid" inType="win:SID" outType="xs:string"/>
                <data name="TargetUserName" inType="win:UnicodeString" outType="xs:string"/>
                <data name="TargetDomainName" inType="win:UnicodeString" outType="xs:string"/>
                <data name="Status" inType="win:HexInt32" outType="win:HexInt32"/>
                <data name="FailureReason" inType="win:UnicodeString" outType="xs:string"/>
                <data name="SubStatus" inType="win:HexInt32" outType="win:HexInt32"/>
                <data name="LogonType" inType="win:UInt32" outType="xs:unsignedInt"/>
                <data name="LogonProcessName" inType="win:UnicodeString" outType="xs:string"/>
                <data name="AuthenticationPackageName" inType="win:UnicodeString" outType="xs:string"/>
                <data name="WorkstationName" inType="win:UnicodeString" outType="xs:string"/>
                <data name="TransmittedServices" inType="win:UnicodeString" outType="xs:string"/>
                <data name="LmPackageName" inType="win:UnicodeString" outType="xs:string"/>
                <data name="KeyLength" inType="win:UInt32" outType="xs:unsignedInt"/>
                <data name="ProcessId" inType="win:Pointer" outType="win:HexInt64"/>
                <data name="ProcessName" inType="win:UnicodeString" outType="xs:string"/>
                <data name="IpAddress" inType="win:UnicodeString" outType="xs:string"/>
                <data name="IpPort" inType="win:UnicodeString" outType="xs:string"/>
              </template>

Description : Fehler beim Anmelden eines Kontos.

              Antragsteller:
                Sicherheits-ID:     %1
                Kontoname:      %2
                Kontodomäne:        %3
                Anmelde-ID:     %4

              Anmeldetyp:           %11

              Konto, für das die Anmeldung fehlgeschlagen ist:
                Sicherheits-ID:     %5
                Kontoname:      %6
                Kontodomäne:        %7

              Fehlerinformationen:
                Fehlerursache:      %9
                Status:         %8
                Unterstatus::       %10

              Prozessinformationen:
                Aufrufprozess-ID:   %18
                Aufrufprozessname:  %19

              Netzwerkinformationen:
                Arbeitsstationsname:    %14
                Quellnetzwerkadresse:   %20
                Quellport:      %21

              Detaillierte Authentifizierungsinformationen:
                Anmeldeprozess:     %12
                Authentifizierungspaket:    %13
                Übertragene Dienste:    %15
                Paketname (nur NTLM):   %16
                Schlüssellänge:     %17

With this output I know the data fieldname is "FailureReason" or $_.properties[9]. I tried both variants in the following code snippet:

Get-WinEvent -FilterHashtable @{Path="c:\temp\test.evtx";} -ErrorAction SilentlyContinue |
    # which are the interesting Events in the Eventlog?
    Where-Object {($_.id -eq "4625")} |
    ForEach-Object {
        if ($_.Id -eq  4625) {
            # which extended Fields from the Eventlog are needed for further investigations?
            # example: how does the eventlog schema looks like?
            # can be examined with (Get-WinEvent -ListProvider Microsoft-Windows-Security-Auditing).Events | Where-Object {$_.Id -eq 4625}
            $SelectorStrings = [string[]]@(
                'Event/EventData/Data[@Name="TargetUserName"]',
                'Event/EventData/Data[@Name="TargetDomainName"]',
                'Event/EventData/Data[@Name="WorkstationName"]',
                'Event/EventData/Data[@Name="IpAddress"]',
                'Event/EventData/Data[@Name="IpPort"]',
                'Event/EventData/Data[@Name="LogonType"]',
                'Event/EventData/Data[@Name="FailureReason"]'
            )
            $PropertySelector = [System.Diagnostics.Eventing.Reader.EventLogPropertySelector]::new($SelectorStrings)

            $TargetUserName, $TargetDomainName, $WorkstationName, $IpAddress, $IpPort, $LogonType, $Remark, $FailureReason = $_.GetPropertyValues($PropertySelector)
            $Remark ="Failed Login !"
            #Create the PSCustomObject from the given Fieldnames
            [PSCustomObject]@{
                TimeCreated   = $_.TimeCreated
                UserName      = $TargetUserName
                Domain        = $TargetDomainName
                ComputerName  = $WorkstationName
                IPAddress     = $IpAddress
                Port          = $IpPort
                LogonType     = $LogonType
                Remark        = $Remark
                FailureReason = $FailureReason
                Message       = ($_.Message).Split(".")[0]
                #Export everything to CSV-File
            } | Export-Csv -NoTypeInformation -Force -Encoding UTF8 -Path 'c:\temp\failedlogin.csv' -Append
        }
    }

As result, all fields in the CSV file are filled, except the field "FailureReason". After that I changed the code to get the value of the field "ProcessId" with the same result, the CSV field then is empty, too.

Remark: The code is normaly much more complex, I reduced it to the required part.

Peter Core
  • 193
  • 1
  • 2
  • 16

1 Answers1

1

You filter for 7 properties with $SelectorStrings but then try to populate 8 variables. I think you need to remove $remark from this line:

$TargetUserName, $TargetDomainName, $WorkstationName, $IpAddress, $IpPort, $LogonType, $Remark, $FailureReason = $_.GetPropertyValues($PropertySelector)

Should be:

$TargetUserName, $TargetDomainName, $WorkstationName, $IpAddress, $IpPort, $LogonType, $FailureReason = $_.GetPropertyValues($PropertySelector)

I think the FailureReason value was going in to the $Remark variable which you were then immediately replacing in the line that follows it.

As a further aside if you move the | Export-CSV.. part to occur after the closing } of the ForEach-Object then you can do away with using -Append.

Mark Wragg
  • 22,105
  • 7
  • 39
  • 68
  • when changing this line something strange is in the csvfield: %%2313, but the code generally works. Any idea, how to solve the mysterious entry %%2313? – Peter Core Feb 07 '18 at 12:01
  • It looks like the failure reason field contains a code. They are described here: https://answers.microsoft.com/en-us/windows/forum/windows_vista-security/where-can-i-find-the-full-list-of-failure-reasons/d0269426-2183-4d99-8af0-cc009dee6658?auth=1 – Mark Wragg Feb 07 '18 at 12:03
  • 1
    It looks like that field should contain text, but sometimes doesn't. You could instead maybe get the status field from the failure information section and then lookup the code per my previous link: https://learn.microsoft.com/en-us/windows/device-security/auditing/event-4625 – Mark Wragg Feb 07 '18 at 12:06