NETLOGON Analyzer Tool

<#
.SYNOPSIS
NETLOGON Analyzer Tool

.DESCRIPTION
This script analyzes NETLOGON-related issues, log files, and configurations across Domain Controllers
in an Active Directory environment.

.NOTES
File Name      : NETLOGONAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, Active Directory module, and appropriate AD permissions
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\NETLOGONAnalyzer.ps1
#>

# Import required modules
Import-Module ActiveDirectory

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\NETLOGON_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== NETLOGON Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "1. Check NETLOGON Service Status"
    Write-Host "2. Analyze NETLOGON Log Files"
    Write-Host "3. Verify NETLOGON Share Accessibility"
    Write-Host "4. Check NETLOGON Registry Settings"
    Write-Host "5. Analyze NETLOGON-related Group Policies"
    Write-Host "6. Check Secure Channel Status"
    Write-Host "7. Analyze NETLOGON Performance Counters"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Checks NETLOGON service status on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing NETLOGON service status for each DC.
#>
function Check-NETLOGONServiceStatus {
    Write-Host "`nChecking NETLOGON Service Status..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $serviceStatus = @()
    foreach ($dc in $dcs) {
        $status = Get-Service -ComputerName $dc.HostName -Name "Netlogon" -ErrorAction SilentlyContinue
        $serviceStatus += [PSCustomObject]@{
            DomainController = $dc.HostName
            Status = if ($status) { $status.Status } else { "Unable to retrieve" }
            StartType = if ($status) { $status.StartType } else { "Unknown" }
        }
    }
    $serviceStatus | Format-Table -AutoSize
    return $serviceStatus
}

<#
.SYNOPSIS
Analyzes NETLOGON log files on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing NETLOGON log analysis for each DC.
#>
function Analyze-NETLOGONLogFiles {
    Write-Host "`nAnalyzing NETLOGON Log Files..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $logAnalysis = @()
    foreach ($dc in $dcs) {
        $logPath = "\\$($dc.HostName)\c$\Windows\debug\netlogon.log"
        if (Test-Path $logPath) {
            $logContent = Get-Content $logPath -Tail 100
            $errorCount = ($logContent | Select-String -Pattern "ERROR" -CaseSensitive).Count
            $warningCount = ($logContent | Select-String -Pattern "WARNING" -CaseSensitive).Count
            $recentErrors = $logContent | Select-String -Pattern "ERROR" -CaseSensitive | Select-Object -Last 5

            $logAnalysis += [PSCustomObject]@{
                DomainController = $dc.HostName
                ErrorCount = $errorCount
                WarningCount = $warningCount
                RecentErrors = $recentErrors -join "`n"
            }
        } else {
            $logAnalysis += [PSCustomObject]@{
                DomainController = $dc.HostName
                ErrorCount = "N/A"
                WarningCount = "N/A"
                RecentErrors = "Unable to access log file"
            }
        }
    }
    $logAnalysis | Format-Table -AutoSize
    return $logAnalysis
}

<#
.SYNOPSIS
Verifies NETLOGON share accessibility on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing NETLOGON share accessibility status for each DC.
#>
function Verify-NETLOGONShareAccessibility {
    Write-Host "`nVerifying NETLOGON Share Accessibility..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $shareStatus = @()
    foreach ($dc in $dcs) {
        $sharePath = "\\$($dc.HostName)\NETLOGON"
        $accessible = Test-Path $sharePath -ErrorAction SilentlyContinue
        $shareStatus += [PSCustomObject]@{
            DomainController = $dc.HostName
            ShareAccessible = $accessible
            SharePath = $sharePath
        }
    }
    $shareStatus | Format-Table -AutoSize
    return $shareStatus
}

<#
.SYNOPSIS
Checks NETLOGON-related registry settings on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing NETLOGON registry settings for each DC.
#>
function Check-NETLOGONRegistrySettings {
    Write-Host "`nChecking NETLOGON Registry Settings..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $registrySettings = @()
    foreach ($dc in $dcs) {
        $settings = Invoke-Command -ComputerName $dc.HostName -ScriptBlock {
            $netlogonParams = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" -ErrorAction SilentlyContinue
            return @{
                MaximumLogFileSize = $netlogonParams.MaximumLogFileSize
                DebugFlag = $netlogonParams.DbFlag
                ScavengeInterval = $netlogonParams.ScavengeInterval
            }
        } -ErrorAction SilentlyContinue

        $registrySettings += [PSCustomObject]@{
            DomainController = $dc.HostName
            MaxLogFileSize = if ($settings) { $settings.MaximumLogFileSize } else { "Unable to retrieve" }
            DebugFlag = if ($settings) { $settings.DebugFlag } else { "Unable to retrieve" }
            ScavengeInterval = if ($settings) { $settings.ScavengeInterval } else { "Unable to retrieve" }
        }
    }
    $registrySettings | Format-Table -AutoSize
    return $registrySettings
}

<#
.SYNOPSIS
Analyzes NETLOGON-related Group Policies.

.OUTPUTS
Array of PSObjects containing NETLOGON-related Group Policy settings.
#>
function Analyze-NETLOGONGroupPolicies {
    Write-Host "`nAnalyzing NETLOGON-related Group Policies..." -ForegroundColor Yellow
    $gpos = Get-GPO -All | Where-Object { $_.DisplayName -like "*NETLOGON*" -or $_.DisplayName -like "*Secure Channel*" }
    $gpAnalysis = @()
    foreach ($gpo in $gpos) {
        $report = Get-GPOReport -Guid $gpo.Id -ReportType XML
        $netlogonSettings = ([xml]$report).GPO.Computer.ExtensionData.Extension.Policy | 
            Where-Object { $_.Name -like "*NETLOGON*" -or $_.Name -like "*Secure Channel*" }
        
        foreach ($setting in $netlogonSettings) {
            $gpAnalysis += [PSCustomObject]@{
                GPOName = $gpo.DisplayName
                PolicyName = $setting.Name
                PolicyState = $setting.State
            }
        }
    }
    $gpAnalysis | Format-Table -AutoSize
    return $gpAnalysis
}

<#
.SYNOPSIS
Checks Secure Channel status for all Domain Controllers.

.OUTPUTS
Array of PSObjects containing Secure Channel status for each DC.
#>
function Check-SecureChannelStatus {
    Write-Host "`nChecking Secure Channel Status..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $secureChannelStatus = @()
    foreach ($dc in $dcs) {
        $status = Test-ComputerSecureChannel -Server $dc.HostName -ErrorAction SilentlyContinue
        $secureChannelStatus += [PSCustomObject]@{
            DomainController = $dc.HostName
            SecureChannelStatus = if ($status) { "Healthy" } else { "Unhealthy" }
        }
    }
    $secureChannelStatus | Format-Table -AutoSize
    return $secureChannelStatus
}

<#
.SYNOPSIS
Analyzes NETLOGON-related performance counters on all Domain Controllers.

.OUTPUTS
Array of PSObjects containing NETLOGON performance counter data for each DC.
#>
function Analyze-NETLOGONPerformanceCounters {
    Write-Host "`nAnalyzing NETLOGON Performance Counters..." -ForegroundColor Yellow
    $dcs = Get-ADDomainController -Filter *
    $perfCounters = @()
    foreach ($dc in $dcs) {
        $counters = Invoke-Command -ComputerName $dc.HostName -ScriptBlock {
            $netlogonCounters = Get-Counter -Counter @(
                "\Netlogon(*)\*"
            ) -ErrorAction SilentlyContinue
            return $netlogonCounters.CounterSamples | Select-Object Path, CookedValue
        } -ErrorAction SilentlyContinue

        if ($counters) {
            $perfCounters += [PSCustomObject]@{
                DomainController = $dc.HostName
                Semaphore_Acquires = ($counters | Where-Object { $_.Path -like "*Semaphore Acquires*" }).CookedValue
                Semaphore_Timeouts = ($counters | Where-Object { $_.Path -like "*Semaphore Timeouts*" }).CookedValue
                Semaphore_Holders = ($counters | Where-Object { $_.Path -like "*Semaphore Holders*" }).CookedValue
                Semaphore_Waiters = ($counters | Where-Object { $_.Path -like "*Semaphore Waiters*" }).CookedValue
            }
        } else {
            $perfCounters += [PSCustomObject]@{
                DomainController = $dc.HostName
                Semaphore_Acquires = "Unable to retrieve"
                Semaphore_Timeouts = "Unable to retrieve"
                Semaphore_Holders = "Unable to retrieve"
                Semaphore_Waiters = "Unable to retrieve"
            }
        }
    }
    $perfCounters | Format-Table -AutoSize
    return $perfCounters
}

<#
.SYNOPSIS
Generates a comprehensive HTML report of all analyses.

.PARAMETER AllResults
Hashtable containing all analysis results.

.OUTPUTS
Saves an HTML report to the desktop.
#>
function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>NETLOGON Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>NETLOGON Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>NETLOGON Service Status</h2>
    $($AllResults.ServiceStatus | ConvertTo-Html -Fragment)

    <h2>NETLOGON Log File Analysis</h2>
    $($AllResults.LogAnalysis | ConvertTo-Html -Fragment)

    <h2>NETLOGON Share Accessibility</h2>
    $($AllResults.ShareStatus | ConvertTo-Html -Fragment)

    <h2>NETLOGON Registry Settings</h2>
    $($AllResults.RegistrySettings | ConvertTo-Html -Fragment)

    <h2>NETLOGON-related Group Policies</h2>
    $($AllResults.GPAnalysis | ConvertTo-Html -Fragment)

    <h2>Secure Channel Status</h2>
    $($AllResults.SecureChannelStatus | ConvertTo-Html -Fragment)

    <h2>NETLOGON Performance Counters</h2>
    $($AllResults.PerfCounters | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-9)"

    switch ($choice) {
        "1" { $allResults.ServiceStatus = Check-NETLOGONServiceStatus }
        "2" { $allResults.LogAnalysis = Analyze-NETLOGONLogFiles }
        "3" { $allResults.ShareStatus = Verify-NETLOGONShareAccessibility }
        "4" { $allResults.RegistrySettings = Check-NETLOGONRegistrySettings }
        "5" { $allResults.GPAnalysis = Analyze-NETLOGONGroupPolicies }
        "6" { $allResults.SecureChannelStatus = Check-SecureChannelStatus }
        "7" { $allResults.PerfCounters = Analyze-NETLOGONPerformanceCounters }
        "8" { Generate-HTMLReport -AllResults $allResults }
        "9" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "9") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "9")

This NETLOGON Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of NETLOGON:
    • NETLOGON Service Status check
    • NETLOGON Log File analysis
    • NETLOGON Share accessibility verification
    • NETLOGON Registry Settings check
    • NETLOGON-related Group Policy analysis
    • Secure Channel status check
    • NETLOGON Performance Counter analysis
  3. Comprehensive error handling for each analysis function.
  4. A function to generate an HTML report of all collected data.

Key features:

  • Detailed analysis of NETLOGON service status across all Domain Controllers
  • Examination of NETLOGON log files for errors and warnings
  • Verification of NETLOGON share accessibility
  • Analysis of NETLOGON-related registry settings
  • Review of Group Policies affecting NETLOGON
  • Checking Secure Channel status for each DC
  • Analysis of NETLOGON performance counters
  • HTML report generation for easy sharing and viewing of results

This tool is particularly useful for:

  • Active Directory administrators
  • System administrators troubleshooting NETLOGON issues
  • IT professionals performing AD health checks
  • Security teams auditing AD configurations

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query Domain Controllers and access NETLOGON-related information
  3. Have the Active Directory PowerShell module installed

This script provides a comprehensive overview of NETLOGON-related configurations and potential issues across an Active Directory environment. It can significantly streamline the process of troubleshooting NETLOGON problems and maintaining a healthy AD infrastructure.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *