Last active
September 5, 2024 09:18
-
-
Save JohanSelmosson/0e05ffd2157f0578fe4eb9cf9a9c19b1 to your computer and use it in GitHub Desktop.
get-nordloshcannelloggingevents.ps1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Get-NordloSChannelLoggingEvents { | |
<# | |
.SYNOPSIS | |
Extracts Schannel logging events from the Windows Event Log. | |
.DESCRIPTION | |
This function retrieves Schannel logging events from either the System or ForwardedEvents log. | |
It can filter events based on a specified time period and output the results to a CSV file. | |
.PARAMETER Period | |
Specifies the time period for which to retrieve events. Valid options are: | |
'Yesterday', 'ThisWeek', 'LastWeek', 'Today', 'All'. Default is 'All'. | |
.PARAMETER Eventlog | |
Specifies the event log to query. Valid options are 'System' or 'ForwardedEvents'. Default is 'System'. | |
.PARAMETER OutputCsv | |
Specifies the path for the output CSV file. If not specified, no CSV file will be created. | |
.PARAMETER CSVOnly | |
If specified, suppresses console output and only writes to the CSV file. | |
.EXAMPLE | |
Get-SchannelLoggingEvents -Period 'Today' -OutputCsv 'C:\Logs\SchannelEvents.csv' | |
This example retrieves all Schannel events from today and saves them to the specified CSV file. | |
.EXAMPLE | |
Get-SchannelLoggingEvents -Period 'LastWeek' -Eventlog 'ForwardedEvents' -Verbose | |
This example retrieves Schannel events from the ForwardedEvents log for the last week and displays verbose output. | |
.NOTES | |
Author: Johan Selmosson | |
Date: 2024-09-05 | |
#> | |
[CmdletBinding()] | |
param ( | |
[Parameter()] | |
[ValidateSet('Yesterday', 'ThisWeek', 'LastWeek', 'Today', 'All')] | |
[string] $Period = 'All', | |
[Parameter()] | |
[ValidateSet('System', 'ForwardedEvents')] | |
[string] $Eventlog = "System", | |
[Parameter()] | |
[string] $OutputCsv = $null, | |
[Parameter()] | |
[switch] $CSVOnly | |
) | |
# AlertDesc mapping | |
$alertDescMapping = @{ | |
"10" = "Close notify" | |
"20" = "Unexpected message" | |
"22" = "Bad record MAC" | |
"30" = "Decompression failure" | |
"40" = "Handshake failure" | |
"42" = "Bad certificate" | |
"43" = "Unsupported certificate" | |
"44" = "Certificate revoked" | |
"45" = "Certificate expired" | |
"46" = "Certificate unknown" | |
"47" = "Illegal parameter" | |
"48" = "Unknown CA" | |
"49" = "Access denied" | |
"50" = "Decode error" | |
"51" = "Decrypt error" | |
"70" = "Protocol version" | |
"71" = "Insufficient security" | |
"80" = "Internal error" | |
"90" = "User canceled" | |
"100" = "No renegotiation" | |
"110" = "Unsupported extension" | |
} | |
switch ($Period) { | |
'Yesterday' { | |
$startTime = (Get-Date).AddDays(-1).Date | |
$endTime = $startTime.AddDays(1).AddMilliseconds(-1) | |
} | |
'Today' { | |
$startTime = (Get-Date).Date | |
$endTime = $startTime.AddDays(1).AddMilliseconds(-1) | |
} | |
'ThisWeek' { | |
$startTime = (Get-Date).Date.AddDays(-[int](Get-Date).DayOfWeek + 1) | |
$endTime = $startTime.AddDays(7).AddMilliseconds(-1) | |
} | |
'LastWeek' { | |
$startTime = (Get-Date).Date.AddDays(-7 - [int](Get-Date).DayOfWeek + 1) | |
$endTime = $startTime.AddDays(7).AddMilliseconds(-1) | |
} | |
'All' { | |
$startTime = $null | |
$endTime = $null | |
} | |
} | |
$FilterHashtable = @{ | |
LogName = $Eventlog | |
ProviderName = "Schannel" | |
} | |
if ($startTime) { $FilterHashtable.StartTime = $startTime } | |
if ($endTime) { $FilterHashtable.EndTime = $endTime } | |
Write-Verbose "StartTime: $startTime" | |
Write-Verbose "EndTime: $endTime" | |
$FirstDateinDataSet = $null | |
$LastDateinDataSet = $null | |
$totalEvents = 0 | |
$bufferSize = 10000 | |
$eventBuffer = New-Object System.Collections.Generic.List[PSCustomObject] | |
# Initialize CSV file if OutputCsv is specified | |
if ($OutputCsv) { | |
if (Test-Path $OutputCsv) { | |
try { | |
Remove-Item $OutputCsv | |
} | |
catch { | |
Write-Warning "Failed to remove existing file: $_" | |
break | |
} | |
} | |
} | |
Get-WinEvent -FilterHashtable $FilterHashtable | ForEach-Object { | |
$eventXml = [xml]$_.ToXml() | |
$timeCreated = [datetime]$eventXml.Event.System.TimeCreated.SystemTime | |
if (-not $FirstDateinDataSet -or $timeCreated -lt $FirstDateinDataSet) { | |
$FirstDateinDataSet = $timeCreated | |
} | |
if (-not $LastDateinDataSet -or $timeCreated -gt $LastDateinDataSet) { | |
$LastDateinDataSet = $timeCreated | |
} | |
$totalEvents++ | |
# Initialize properties with default values | |
$properties = [ordered]@{ | |
TimeCreated = $timeCreated.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ") | |
ComputerName = $eventXml.Event.System.Computer | |
EventID = $eventXml.Event.System.EventID | |
Channel = $eventXml.Event.System.Channel | |
Type = "" | |
Protocol = "" | |
CipherSuite = "" | |
ExchangeStrength = "" | |
ContextHandle = "" | |
TargetName = "" | |
LocalCertSubjectName = "" | |
RemoteCertSubjectName = "" | |
CallerProcessId = "" | |
CallerProcessImageName = "" | |
AlertDesc = "" | |
AlertDescText = "" | |
} | |
# Assign values to properties based on event data | |
if ($eventXml.Event.UserData.EventXML) { | |
$eventData = $eventXml.Event.UserData.EventXML | |
$properties['Type'] = $eventData.Type | |
$properties['Protocol'] = $eventData.Protocol | |
$properties['CipherSuite'] = $eventData.CipherSuite | |
$properties['ExchangeStrength'] = $eventData.ExchangeStrength | |
$properties['ContextHandle'] = $eventData.ContextHandle | |
$properties['TargetName'] = $eventData.TargetName | |
$properties['LocalCertSubjectName'] = $eventData.LocalCertSubjectName | |
$properties['RemoteCertSubjectName'] = $eventData.RemoteCertSubjectName | |
} elseif ($eventXml.Event.EventData) { | |
$eventData = $eventXml.Event.EventData.Data | |
foreach ($data in $eventData) { | |
switch ($data.Name) { | |
'CallerProcessId' { $properties['CallerProcessId'] = $data.'#text' } | |
'CallerProcessImageName' { $properties['CallerProcessImageName'] = $data.'#text' } | |
'AlertDesc' { | |
$alertCode = $data.'#text' | |
$properties['AlertDesc'] = $alertCode | |
if ($alertDescMapping.ContainsKey($alertCode)) { | |
$properties['AlertDescText'] = $alertDescMapping[$alertCode] | |
} else { | |
$properties['AlertDescText'] = "Unknown alert code" | |
} | |
} | |
} | |
} | |
} | |
$result = [PSCustomObject]$properties | |
# Add result to buffer if OutputCsv is specified | |
if ($OutputCsv) { | |
$eventBuffer.Add($result) | |
if ($eventBuffer.Count -ge $bufferSize) { | |
try { | |
$eventBuffer | Export-Csv -Path $OutputCsv -Append -NoTypeInformation -Delimiter ";" -Encoding utf8 -ErrorAction Stop | |
} | |
catch { | |
Write-Warning "Failed to export CSV: $_" | |
if ($DebugPreference -eq 'Continue' -or $DebugPreference -eq 'Inquire') { | |
Write-Debug "Error details: $_" | |
} | |
} | |
$eventBuffer.Clear() | |
} | |
} | |
# Emit the result | |
if (-not $CSVOnly) { | |
$result | |
} | |
} | |
# Export any remaining events in the buffer if OutputCsv is specified | |
if ($OutputCsv -and $eventBuffer.Count -gt 0) { | |
try { | |
$eventBuffer | Export-Csv -Path $OutputCsv -Append -NoTypeInformation -Delimiter ";" -Encoding utf8 -ErrorAction Stop | |
} | |
catch { | |
Write-Warning "Failed to export CSV: $_" | |
if ($DebugPreference -eq 'Continue' -or $DebugPreference -eq 'Inquire') { | |
Write-Debug "Error details: $_" | |
} | |
} | |
} | |
Write-Verbose "Total Events: $totalEvents" | |
if ($FirstDateinDataSet) { | |
Write-Verbose "First Event: $FirstDateinDataSet" | |
} | |
if ($LastDateinDataSet) { | |
Write-Verbose "Last Event: $LastDateinDataSet" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment