The -IncludeCredentialValidation parameter provides comprehensive pre-authentication event tracking. This feature collects both Kerberos (EventIDs 4768-4772) and NTLM (EventID 4776) authentication events to provide complete visibility into the authentication protocol flow.
When a user attempts to connect via RDP, Windows first tries Kerberos authentication. If Kerberos fails or is unavailable, Windows falls back to NTLM authentication. Understanding this process is crucial for:
- Security Analysis - Identify why secure Kerberos failed and NTLM fallback occurred
- Attack Detection - NTLM-only connections may indicate downgrade attacks or misconfiguration
- Compliance - Track which authentication protocols are being used
- Troubleshooting - Diagnose authentication failures before session creation
1. EventID 4768 - Kerberos TGT Request (user requests ticket from domain)
2. EventID 4769 - Kerberos Service Ticket Request (user requests ticket for TERMSRV)
3. EventID 4624 - Successful Logon (RDP session begins)
1. EventID 4768 - Kerberos TGT Request (user tries Kerberos)
2. EventID 4771 - Kerberos Pre-authentication Failed (shows error code/reason)
3. EventID 4776 - NTLM Credential Validation (Windows falls back to NTLM)
4. EventID 4624 - Successful Logon (RDP session begins)
1. EventID 4776 - NTLM Credential Validation (Kerberos not attempted)
2. EventID 4624 - Successful Logon (RDP session begins)
- Purpose: User requests a Ticket Granting Ticket from the domain controller
- Key Fields:
- Account Name (username)
- Client Address (source IP)
- Result Code (0x0 = success, other codes = specific failures)
- Ticket Options
- Forensic Value: First step in Kerberos authentication
- Purpose: User requests a service ticket for a specific service (e.g., TERMSRV for RDP)
- Key Fields:
- Account Name
- Service Name (look for "TERMSRV" for RDP)
- Client Address
- Failure Code (0x0 = success)
- Forensic Value: Shows which service was accessed with Kerberos
- Purpose: User renews an existing service ticket
- Key Fields:
- Account Name
- Service Name
- Client Address
- Forensic Value: Indicates long-running sessions
- Purpose: Shows WHY Kerberos authentication failed before NTLM fallback
- Key Fields:
- Account Name
- Client Address
- Failure Code - Critical for understanding the failure reason
- Common Failure Codes:
0x6- Client not found in Kerberos database0x7- Server not found in Kerberos database0xC- Workstation restriction violated0x12- Client account disabled or revoked0x17- Password expired0x18- Wrong password provided0x25- Clock skew too large (time sync issue)
- Forensic Value: MOST IMPORTANT - Explains why Kerberos failed and NTLM was used
- Purpose: Kerberos ticket request failed for other reasons
- Key Fields:
- Account Name
- Failure Code
- Forensic Value: Additional Kerberos failure tracking
- Purpose: NTLM authentication attempt (used when Kerberos fails/unavailable)
- Key Fields:
- Logon Account (DOMAIN\Username format)
- Source Workstation
- Error Code (0x0 = success, 0xC0000064 = wrong password)
- Authentication Package (usually "MICROSOFT_AUTHENTICATION_PACKAGE_V1_0")
- Forensic Value: Shows NTLM fallback occurred; may indicate Kerberos issues
🔴 High Priority:
-
Multiple EventID 4771 (Kerberos failures) followed by 4776 (NTLM)
- May indicate downgrade attacks or misconfiguration
- Check failure codes to understand why Kerberos failed
-
EventID 4771 with error code 0x18 (wrong password)
- Possible brute-force attempts
- Especially if followed by successful 4776/4624
-
Only EventID 4776 with no Kerberos attempts
- Client may not support Kerberos
- Could indicate legacy systems or attack tools
🟡 Medium Priority:
-
EventID 4771 with error code 0x25 (clock skew)
- Time synchronization issues
- Can cause legitimate authentication failures
-
EventID 4771 with error code 0x12 (client revoked)
- Account may be disabled or expired
- Verify account status
✅ Expected Behavior:
- Successful 4768 → 4769 → 4624 (normal Kerberos flow)
- 4768 → 4771 (0x17) → 4776 → 4624 (password expired, NTLM fallback)
- Multiple 4776 events with same ActivityID (normal Windows authentication rounds)
# Include Kerberos and NTLM events in analysis
# ⚠️ NOTE: Will only find events if running on Domain Controller
# Running on Terminal Server will show NO Kerberos/NTLM events
Get-RDPForensics -IncludeCredentialValidation -GroupBySession- Kerberos event count: 0 (events are on DC, not Terminal Server)
- NTLM event count: 0 (events are on DC, not Terminal Server)
- RDP session events: Normal (events are local)
✅ Expected Result on Domain Controller:
- Kerberos event count: High (all domain Kerberos authentications)
- NTLM event count: High (all NTLM authentications)
- RDP session events: Only if DC is also an RDP target
# Get all events with authentication details
$events = Get-RDPForensics -IncludeCredentialValidation -StartDate (Get-Date).AddDays(-7)
# Filter for Kerberos pre-auth failures (EventID 4771)
$events | Where-Object { $_.EventID -eq 4771 } |
Select-Object TimeCreated, User, EventType, Details, SourceIP |
Format-Table -AutoSize# Group by session and look for sessions with 4776 but no 4768/4769
$sessions = Get-RDPForensics -IncludeCredentialValidation -GroupBySession -StartDate (Get-Date).AddDays(-7)
# Sessions that used NTLM (have 4776 events)
$ntlmSessions = $sessions | Where-Object {
($_.Events | Where-Object { $_.EventID -eq 4776 }).Count -gt 0
}
# Check if they also have Kerberos attempts
foreach ($session in $ntlmSessions) {
$kerberosAttempts = ($session.Events | Where-Object { $_.EventID -in 4768,4769,4771,4772 }).Count
$ntlmAttempts = ($session.Events | Where-Object { $_.EventID -eq 4776 }).Count
[PSCustomObject]@{
SessionStart = $session.SessionStart
User = $session.User
KerberosAttempts = $kerberosAttempts
NTLMAttempts = $ntlmAttempts
AuthType = if ($kerberosAttempts -eq 0) { "Pure NTLM" } else { "Kerberos → NTLM Fallback" }
}
}# Get authentication statistics for last 30 days
$events = Get-RDPForensics -IncludeCredentialValidation -StartDate (Get-Date).AddDays(-30)
$stats = @{
KerberosTGT = ($events | Where-Object { $_.EventID -eq 4768 }).Count
KerberosService = ($events | Where-Object { $_.EventID -eq 4769 }).Count
KerberosFailures = ($events | Where-Object { $_.EventID -eq 4771 }).Count
NTLM = ($events | Where-Object { $_.EventID -eq 4776 }).Count
}
Write-Host "`nAuthentication Protocol Statistics (Last 30 Days):" -ForegroundColor Cyan
Write-Host " Kerberos TGT Requests: $($stats.KerberosTGT)" -ForegroundColor Green
Write-Host " Kerberos Service Tickets: $($stats.KerberosService)" -ForegroundColor Green
Write-Host " Kerberos Failures: $($stats.KerberosFailures)" -ForegroundColor Yellow
Write-Host " NTLM Validations: $($stats.NTLM)" -ForegroundColor $(if ($stats.NTLM -gt $stats.KerberosService) { "Red" } else { "Green" })
if ($stats.NTLM -gt $stats.KerberosService) {
Write-Host "`n⚠️ WARNING: More NTLM than Kerberos - investigate configuration!" -ForegroundColor Red
}The toolkit uses two different correlation methods depending on event location:
For events logged locally on the Terminal Server:
- ✅ EventIDs: 1149, 4624, 21-25, 4778, 4779, 4634, 4647
- ✅ Method: ActivityID (Windows native correlation)
- ✅ Accuracy: Exact - all events share the same ActivityID
- ✅ Use Case: Perfect for tracking RDP session lifecycle
For pre-authentication events from the Domain Controller:
⚠️ EventIDs: 4768-4772 (Kerberos), 4776 (NTLM)⚠️ Method: Username match + timestamp proximity (0-10 seconds before session)⚠️ Accuracy: Heuristic - best-effort matching⚠️ Why: These events have DC's ActivityID, which doesn't match TS's ActivityID
Correlation Rules:
- Pre-auth events occur 0-10 seconds before the RDP session (EventID 4624 with Logon Type 10/7/3/5)
- Username must match exactly
- Closest timestamp match wins if multiple candidates
- Only RDP-correlated pre-auth events are included - non-RDP authentications (SMB, SQL, Exchange, etc.) are filtered out
| Event Type | Event IDs | Logged On | Available When Running on TS? |
|---|---|---|---|
| RDP Session | 4624, 1149, 21-25, 4778, 4779 | Terminal Server | ✅ YES |
| Kerberos Auth | 4768-4772 | Domain Controller | ❌ NO |
| NTLM Auth | 4776 | Domain Controller | ❌ NO |
| NTLM Auth | 4776 | On member servers or clients when a local account is authenticated. | ✅ YES |
Why ActivityID Cannot Correlate Across Machines:
- ActivityID is provider-specific and machine-local
- Kerberos events (4768-4772) are logged on the Domain Controller with DC's ActivityID
- RDP session events (4624) are logged on the Terminal Server with TS's ActivityID
- These ActivityIDs are completely unrelated - they come from different systems
- Time-based correlation (username + timestamp) is the only viable method for cross-machine correlation
Use Cases:
✅ PRIMARY USE CASE: Running tool on Terminal Server to analyze RDP sessions
- Excellent ActivityID correlation between 4624 → 4778 → 4634 (all on same machine)
- Perfect for session lifecycle tracking
-IncludeCredentialValidationwill return ZERO Kerberos/NTLM events (they're on DC)
- Will see authentication events (4768-4772, 4776) for ALL domain authentications
- But will NOT see Terminal Server session events (21-25, 4778, 4779)
- Different purpose (DC authentication monitoring, not RDP session tracking)
🔧 ADVANCED SCENARIO: Multi-system correlation
- Collect DC logs separately:
Get-RDPForensics -IncludeCredentialValidationon DC - Collect TS logs separately:
Get-RDPForensics -GroupBySessionon Terminal Server - Correlate manually using username + timestamp matching
Kerberos and NTLM authentication events are logged where authentication validation occurs:
- Kerberos (4768-4772) → Logged on Domain Controller
- NTLM (4776) → Logged on Domain Controller (or authenticating server)
- RDP Sessions (4624) → Logged on Terminal Server
# Enable Kerberos authentication tracking (ON DOMAIN CONTROLLER)
auditpol /set /subcategory:"Kerberos Authentication Service" /success:enable /failure:enable
# Enable NTLM credential validation tracking (ON DOMAIN CONTROLLER)
auditpol /set /subcategory:"Credential Validation" /success:enable /failure:enable
# Verify
auditpol /get /category:"Account Logon"Computer Configuration → Policies → Windows Settings → Security Settings →
Advanced Audit Policy Configuration → Audit Policies → Account Logon
Apply to: Domain Controllers OU
Enable:
- Audit Kerberos Authentication Service (Success, Failure)
- Audit Credential Validation (Success, Failure)
Note: Enabling Kerberos and NTLM auditing generates significantly more events than just RDP tracking:
- 4768 - Fires for ALL Kerberos TGT requests (not just RDP)
- 4769 - Fires for ALL service ticket requests (file shares, SQL, HTTP, etc.)
- 4776 - Fires for ALL NTLM authentication (not just RDP)
Impact:
- Security log on Domain Controller will grow much faster
- May need to increase Security log size (Default: 20 MB → Recommend: 100+ MB on DC)
- Event collection will initially gather ALL authentications from DC
Automatic Filtering: ✅ The tool automatically filters pre-authentication events to show only those that correlate to RDP sessions (Logon Type 10/7/3/5):
- Non-RDP authentications (SMB file shares, SQL, Exchange, HTTP) are excluded from results
- Only pre-auth events within 0-10 seconds before an RDP logon with matching username are kept
- This dramatically reduces noise in the output
Mitigation:
- Use
-IncludeCredentialValidationonly when needed for detailed analysis - Set appropriate retention policies
- Consider dedicated logging server for high-volume environments
When -IncludeCredentialValidation is used:
✅ Optimized:
- Events filtered to relevant time range (StartDate/EndDate)
- 4776 events filtered to exclude local/localhost (remote only)
- Time-based correlation only processes events within 10-second window
- First run may be slow in high-activity environments (many events to process)
- Subsequent runs with narrow date ranges are fast
- Kerberos events (4768-4772) are not filtered by source - may include non-RDP events
-
Enable Auditing in Test Environment First
- Assess event volume before production deployment
- Verify log size requirements
-
Use Time Ranges
- Always specify
-StartDateand-EndDatefor faster processing - Example:
-StartDate (Get-Date).AddHours(-4)for recent activity
- Always specify
-
Monitor Security Log Size
- Check current size:
Get-EventLog -List | Where-Object {$_.Log -eq "Security"} - Increase if needed:
Limit-EventLog -LogName Security -MaximumSize 200MB
- Check current size:
-
Combine with Session Grouping
- Use
-GroupBySessionto see complete authentication + session lifecycle - Easier to identify which sessions used which authentication method
- Use
-
Review Kerberos Failures
- EventID 4771 is KEY - always investigate these first
- Error codes tell you exactly why Kerberos failed
- Fix root cause rather than accepting NTLM fallback
Check Audit Policy:
auditpol /get /category:"Account Logon"Should show:
- Kerberos Authentication Service: Success and Failure
- Credential Validation: Success and Failure
Check Event Logs:
# Test if events exist
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4768,4769,4771,4776
StartTime = (Get-Date).AddHours(-1)
} -MaxEvents 10- Time Window: Events must occur 0-10 seconds before session
- Username: Must match exactly (domain\username format)
- Date Range: Ensure date range includes pre-authentication time
- Narrow date range:
-StartDate (Get-Date).AddHours(-4) - Use specific username:
-Username "john.doe" - Consider separate analysis runs for different purposes
The -IncludeCredentialValidation parameter provides comprehensive authentication visibility by tracking:
✅ What: Kerberos (4768-4772) and NTLM (4776) pre-authentication events
✅ Why: Understand authentication protocol flow and failure reasons
✅ When: Time-correlated 0-10 seconds before session creation
✅ Who: Username-matched and ActivityID-linked where available
✅ Value: Security analysis, compliance, troubleshooting, attack detection
Use this feature when you need to understand not just what happened in an RDP session, but how the user authenticated to get there.
See Also:
- README.md - Main documentation
- QUICK_REFERENCE.md - Command reference
- GETTING_STARTED.md - Tutorial