Skip to content

Instantly share code, notes, and snippets.

@JohanSelmosson
Last active September 5, 2024 09:18
Show Gist options
  • Save JohanSelmosson/0e05ffd2157f0578fe4eb9cf9a9c19b1 to your computer and use it in GitHub Desktop.
Save JohanSelmosson/0e05ffd2157f0578fe4eb9cf9a9c19b1 to your computer and use it in GitHub Desktop.
get-nordloshcannelloggingevents.ps1
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