I used copilot to create these powershell scripts to check this windows 10 operating system, because not work well.I think is a hacking with admnistrator access over ehernet.
Purpose : Collect Kerberos and NTLM authentication events from the Windows Security Log and export them into a JSON file for SIEM ingestion.
What it does:
Reads key authentication events (4768, 4769, 4771, 4624, 4625, 4776).
Extracts useful fields (user, IP, ticket type, failure reason, timestamp).
Converts everything into structured JSON.
Saves the JSON file so Splunk, Sentinel, ELK, Wazuh, or Graylog can ingest it.
Does not perform analysis — it only collects and exports raw data.
# ============================
# AUDIT AUTENTIFICARI KERBEROS + NTLM
# Compatibil: AD, SIEM, WEF
# ============================
$OutputFile = "C:\Logs\Kerberos_Audit_$(Get-Date -Format yyyyMMdd_HHmmss).json"
# Evenimente relevante
$EventIDs = @(4768, 4769, 4771, 4624, 4625, 4776)
# Preluare evenimente din Security Log
$Events = Get-WinEvent -FilterHashtable @{
LogName = "Security"
Id = $EventIDs
} -ErrorAction SilentlyContinue
# Parsare evenimente
$Parsed = foreach ($ev in $Events) {
$xml = [xml]$ev.ToXml()
$data = $xml.Event.EventData.Data
[PSCustomObject]@{
TimeCreated = $ev.TimeCreated
EventID = $ev.Id
Machine = $ev.MachineName
User = $data[1].'#text'
IP = $data[18].'#text'
TicketType = switch ($ev.Id) {
4768 { "TGT Request" }
4769 { "Service Ticket (TGS)" }
4771 { "Kerberos Failure" }
4776 { "NTLM Authentication" }
4624 { "Logon Success" }
4625 { "Logon Failure" }
default { "Unknown" }
}
Status = $data[2].'#text'
ServiceName = $data[3].'#text'
FailureReason = $data[5].'#text'
RawMessage = $ev.Message
}
}
# Export JSON pentru SIEM
$Parsed | ConvertTo-Json -Depth 5 | Out-File $OutputFile -Encoding UTF8
Write-Host "Audit complet. Log salvat în: $OutputFile"The advanced script : alerts + dashboards + TXT report for detect suspicious authentication behavior and generate human-readable alerts.
It analyzes the events and identifies:
Brute-force attacks
Too many failures from the same user or IP in a short time window.
NTLM fallback
Detects when authentication falls back from Kerberos to NTLM (Event 4776).
Useful for spotting misconfigurations or downgrade attacks.
Kerberos failures
Detects repeated 4771 errors (bad passwords, clock skew, SPN issues).
# ============================
# AUDIT AUTENTIFICARI KERBEROS + NTLM
# DETECTIE: BRUTEFORCE, NTLM FALLBACK, KERBEROS FAILURES
# ============================
$LogFolder = "C:\Logs"
if (!(Test-Path $LogFolder)) {
New-Item -ItemType Directory -Path $LogFolder | Out-Null
}
$Timestamp = Get-Date -Format yyyyMMdd_HHmmss
$JsonFile = "$LogFolder\Kerberos_Audit_$Timestamp.json"
$ReportFile = "$LogFolder\Kerberos_Alerts_$Timestamp.txt"
# Interval analiză (ex: ultimele 2 ore)
$HoursBack = 2
$StartTime = (Get-Date).AddHours(-$HoursBack)
# Praguri detecție
$BruteForceThreshold = 5 # minim X eșecuri
$BruteForceWindowMin = 10 # în Y minute
$EventIDs = @(4768, 4769, 4771, 4624, 4625, 4776)
$Events = Get-WinEvent -FilterHashtable @{
LogName = "Security"
Id = $EventIDs
StartTime = $StartTime
} -ErrorAction SilentlyContinue
$Parsed = foreach ($ev in $Events) {
$xml = [xml]$ev.ToXml()
$data = $xml.Event.EventData.Data
[PSCustomObject]@{
TimeCreated = $ev.TimeCreated
EventID = $ev.Id
Machine = $ev.MachineName
User = $data[1].'#text'
IP = $data[18].'#text'
TicketType = switch ($ev.Id) {
4768 { "TGT Request" }
4769 { "Service Ticket (TGS)" }
4771 { "Kerberos Failure" }
4776 { "NTLM Authentication" }
4624 { "Logon Success" }
4625 { "Logon Failure" }
default { "Unknown" }
}
Status = $data[2].'#text'
ServiceName = $data[3].'#text'
FailureReason = $data[5].'#text'
RawMessage = $ev.Message
}
}
# Export JSON brut pentru SIEM
$Parsed | ConvertTo-Json -Depth 5 | Out-File $JsonFile -Encoding UTF8
# ============================
# DETECTIE: NTLM FALLBACK
# ============================
$NtlmEvents = $Parsed | Where-Object { $_.EventID -eq 4776 }
$NtlmCount = $NtlmEvents.Count
# ============================
# DETECTIE: KERBEROS FAILURES
# ============================
$KerbFailEvents = $Parsed | Where-Object { $_.EventID -eq 4771 }
$KerbFailCount = $KerbFailEvents.Count
# ============================
# DETECTIE: BRUTE FORCE (USER / IP)
# ============================
$FailureEvents = $Parsed | Where-Object { $_.EventID -in 4625, 4771, 4776 }
$BruteForceAlerts = @()
# Grupare pe User
$FailureEvents | Group-Object User | ForEach-Object {
$user = $_.Name
if ([string]::IsNullOrWhiteSpace($user)) { return }
$events = $_.Group | Sort-Object TimeCreated
for ($i = 0; $i -lt $events.Count; $i++) {
$startTime = $events[$i].TimeCreated
$windowEnd = $startTime.AddMinutes($BruteForceWindowMin)
$windowEvents = $events | Where-Object { $_.TimeCreated -ge $startTime -and $_.TimeCreated -le $windowEnd }
if ($windowEvents.Count -ge $BruteForceThreshold) {
$BruteForceAlerts += [PSCustomObject]@{
Type = "BruteForce_User"
User = $user
Count = $windowEvents.Count
FirstEvent = $startTime
LastEvent = $windowEvents[-1].TimeCreated
}
break
}
}
}
# Grupare pe IP
$FailureEvents | Group-Object IP | ForEach-Object {
$ip = $_.Name
if ([string]::IsNullOrWhiteSpace($ip)) { return }
$events = $_.Group | Sort-Object TimeCreated
for ($i = 0; $i -lt $events.Count; $i++) {
$startTime = $events[$i].TimeCreated
$windowEnd = $startTime.AddMinutes($BruteForceWindowMin)
$windowEvents = $events | Where-Object { $_.TimeCreated -ge $startTime -and $_.TimeCreated -le $windowEnd }
if ($windowEvents.Count -ge $BruteForceThreshold) {
$BruteForceAlerts += [PSCustomObject]@{
Type = "BruteForce_IP"
IP = $ip
Count = $windowEvents.Count
FirstEvent = $startTime
LastEvent = $windowEvents[-1].TimeCreated
}
break
}
}
}
# ============================
# GENERARE RAPORT TXT
# ============================
$ReportLines = @()
$ReportLines += "=== KERBEROS / NTLM AUDIT REPORT ==="
$ReportLines += "Interval analizat: ultimele $HoursBack ore"
$ReportLines += "Generat la: $(Get-Date)"
$ReportLines += ""
$ReportLines += "Total evenimente analizate: $($Parsed.Count)"
$ReportLines += "NTLM Authentication (4776): $NtlmCount"
$ReportLines += "Kerberos Failures (4771): $KerbFailCount"
$ReportLines += ""
$ReportLines += "=== NTLM FALLBACK DETECTIE ==="
if ($NtlmCount -gt 0) {
$ReportLines += "ATENTIE: Exista $NtlmCount evenimente NTLM (posibil fallback de la Kerberos)."
} else {
$ReportLines += "Nu au fost detectate evenimente NTLM (4776) in interval."
}
$ReportLines += ""
$ReportLines += "=== KERBEROS FAILURES DETECTIE ==="
if ($KerbFailCount -gt 0) {
$ReportLines += "ATENTIE: Exista $KerbFailCount esecuri Kerberos (4771)."
} else {
$ReportLines += "Nu au fost detectate esecuri Kerberos (4771) in interval."
}
$ReportLines += ""
$ReportLines += "=== BRUTE FORCE DETECTIE ==="
if ($BruteForceAlerts.Count -gt 0) {
foreach ($alert in $BruteForceAlerts) {
if ($alert.Type -eq "BruteForce_User") {
$ReportLines += "Brute force pe USER: $($alert.User) | Count: $($alert.Count) | Interval: $($alert.FirstEvent) - $($alert.LastEvent)"
} elseif ($alert.Type -eq "BruteForce_IP") {
$ReportLines += "Brute force pe IP: $($alert.IP) | Count: $($alert.Count) | Interval: $($alert.FirstEvent) - $($alert.LastEvent)"
}
}
} else {
$ReportLines += "Nu au fost detectate pattern-uri brute force (user/IP) peste pragul $BruteForceThreshold in $BruteForceWindowMin minute."
}
$ReportLines += ""
$ReportLines += "=== SUGESTII DASHBOARD (Splunk / Sentinel / Kibana) ==="
$ReportLines += "Splunk - Kerberos Failures:"
$ReportLines += " index=kerberos EventID=4771 | stats count by User, IP, FailureReason"
$ReportLines += ""
$ReportLines += "Splunk - NTLM Fallback:"
$ReportLines += " index=kerberos EventID=4776 | stats count by User, IP, Machine"
$ReportLines += ""
$ReportLines += "Splunk - Brute Force (User):"
$ReportLines += " index=kerberos EventID=4625 OR EventID=4771 OR EventID=4776"
$ReportLines += " | bin _time span=10m"
$ReportLines += " | stats count by User, _time"
$ReportLines += " | where count >= $BruteForceThreshold"
$ReportLines += ""
$ReportLines += "Kibana / Elastic:"
$ReportLines += " Filtre pe campurile: EventID, User, IP, FailureReason, Machine"
$ReportLines += ""
$ReportLines += "Sentinel:"
$ReportLines += " SecurityEvent"
$ReportLines += " | where EventID in (4768, 4769, 4771, 4624, 4625, 4776)"
$ReportLines += " | summarize count() by Account, IPAddress, EventID, bin(TimeGenerated, 10m)"
$ReportLines += ""
$ReportLines | Out-File $ReportFile -Encoding UTF8
# ============================
# AFISARE IN CONSOLA
# ============================
Write-Host "=== REZUMAT AUDIT ==="
Write-Host "JSON log: $JsonFile"
Write-Host "Raport TXT: $ReportFile"
Write-Host "Evenimente: $($Parsed.Count)"
Write-Host "NTLM (4776): $NtlmCount"
Write-Host "KerbFail: $KerbFailCount"
Write-Host ""
if ($BruteForceAlerts.Count -gt 0) {
Write-Host "Brute force detectat:"
$BruteForceAlerts | Format-Table -AutoSize
} else {
Write-Host "Nu au fost detectate pattern-uri brute force peste prag."
}
if ($NtlmCount -gt 0) {
Write-Host ""
Write-Host "ATENTIE: Exista evenimente NTLM (4776) - posibil fallback de la Kerberos."
}
if ($KerbFailCount -gt 0) {
Write-Host ""
Write-Host "ATENTIE: Exista esecuri Kerberos (4771) - verifica SPN, parole, clock skew."
}