Dargslan.WinRegistryAudit.psm1

<#
.SYNOPSIS
    Windows Registry auditing toolkit — registry key analysis, security assessment, startup entries, autorun detection, and registry backup

.DESCRIPTION
    Part of the Dargslan Windows Admin Toolkit collection.
    More tools and resources at https://dargslan.com
    Free Cheat Sheets: https://dargslan.com/cheat-sheets

.LINK
    https://dargslan.com

.LINK
    https://github.com/Dargslan/powershell-admin-scripts
#>


function Get-RegistryAudit {
    <#
    .SYNOPSIS
        Audit critical Windows Registry keys for security issues
    .DESCRIPTION
        Scans autorun locations, startup entries, security policies, and identifies suspicious registry modifications.
        Part of Dargslan.WinRegistryAudit — https://dargslan.com
    #>

    [CmdletBinding()] param([switch]$Json)

    Write-Host "`n [Registry Security Audit]" -ForegroundColor Cyan
    $autorunPaths = @(
        "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
        "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
        "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
        "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
        "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices",
        "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run"
    )
    $report = [ordered]@{
        AutorunEntries = @()
        SecurityPolicies = @()
        SuspiciousKeys = @()
    }
    foreach ($path in $autorunPaths) {
        if (Test-Path $path) {
            $entries = Get-ItemProperty $path -ErrorAction SilentlyContinue
            $entries.PSObject.Properties | Where-Object { $_.Name -notmatch "^PS" } | ForEach-Object {
                $report.AutorunEntries += [PSCustomObject]@{
                    Location = $path.Replace("HKLM:\","HKLM\").Replace("HKCU:\","HKCU\")
                    Name = $_.Name
                    Value = $_.Value.ToString().Substring(0, [math]::Min(100, $_.Value.ToString().Length))
                }
            }
        }
    }
    $uac = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -ErrorAction SilentlyContinue
    $report.SecurityPolicies += [PSCustomObject]@{ Policy = "UAC Enabled"; Value = $uac.EnableLUA; Expected = 1; OK = $uac.EnableLUA -eq 1 }
    $report.SecurityPolicies += [PSCustomObject]@{ Policy = "UAC Admin Consent"; Value = $uac.ConsentPromptBehaviorAdmin; Expected = ">=2"; OK = $uac.ConsentPromptBehaviorAdmin -ge 2 }
    $rdp = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -ErrorAction SilentlyContinue
    $report.SecurityPolicies += [PSCustomObject]@{ Policy = "RDP Disabled"; Value = $rdp.fDenyTSConnections; Expected = 1; OK = $rdp.fDenyTSConnections -eq 1 }
    $winlogon = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -ErrorAction SilentlyContinue
    if ($winlogon.AutoAdminLogon -eq "1") { $report.SuspiciousKeys += [PSCustomObject]@{ Key = "Winlogon\AutoAdminLogon"; Risk = "HIGH"; Detail = "Auto-login enabled — credentials may be stored in registry" } }
    if ($winlogon.DefaultPassword) { $report.SuspiciousKeys += [PSCustomObject]@{ Key = "Winlogon\DefaultPassword"; Risk = "CRITICAL"; Detail = "Password stored in plain text in registry" } }
    $lsa = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -ErrorAction SilentlyContinue
    if ($lsa.LimitBlankPasswordUse -ne 1) { $report.SuspiciousKeys += [PSCustomObject]@{ Key = "Lsa\LimitBlankPasswordUse"; Risk = "HIGH"; Detail = "Blank password network access allowed" } }
    $report.Summary = [PSCustomObject]@{ AutorunCount = $report.AutorunEntries.Count; PolicyChecks = $report.SecurityPolicies.Count; SuspiciousFindings = $report.SuspiciousKeys.Count }
    if ($Json) { return $report | ConvertTo-Json -Depth 4 }
    $report.Summary | Format-List
    Write-Host " Autorun Entries:" -ForegroundColor Yellow
    $report.AutorunEntries | Format-Table -AutoSize
    Write-Host " Security Policies:" -ForegroundColor Yellow
    $report.SecurityPolicies | Format-Table -AutoSize
    if ($report.SuspiciousKeys) { Write-Host " Suspicious Findings:" -ForegroundColor Red; $report.SuspiciousKeys | Format-Table -AutoSize }
    return $report
}

function Export-RegistryBackup {
    <#
    .SYNOPSIS
        Export critical registry keys for backup
    .DESCRIPTION
        Exports important registry branches to .reg files for backup and disaster recovery.
        Part of Dargslan.WinRegistryAudit — https://dargslan.com
    #>

    [CmdletBinding()] param([string]$Path = ".\registry-backup")

    if (-not (Test-Path $Path)) { New-Item -ItemType Directory -Path $Path -Force | Out-Null }
    $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
    $keys = @(
        @{Name="System"; Key="HKLM\SYSTEM\CurrentControlSet"},
        @{Name="Software"; Key="HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion"},
        @{Name="Security"; Key="HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies"}
    )
    foreach ($k in $keys) {
        $file = Join-Path $Path "$($k.Name)-$timestamp.reg"
        try { reg export $k.Key $file /y 2>$null; Write-Host " Exported: $($k.Name) -> $file" -ForegroundColor Green }
        catch { Write-Host " Failed: $($k.Name) — $_" -ForegroundColor Red }
    }
    Write-Host "`n Backup saved to: $Path" -ForegroundColor Cyan
}

Export-ModuleMember -Function *