Check-LSAPackageExtensions.ps1

<#PSScriptInfo

.VERSION 1.0.1

.GUID d5e6f7a8-b9c0-1234-5678-90abcdef1234

.AUTHOR Krishnaramanan

.COMPANYNAME Krishnaramanan

.COPYRIGHT (c) 2024 Krishnaramanan

.TAGS LSA Security Windows PowerShell Audit Authentication Hardening

.PROJECTURI

.LICENSEURI

.ICONURI

.EXTERNALMODULEDEPENDENCIES

.REQUIREDSCRIPTS

.EXTERNALSCRIPTDEPENDENCIES

.RELEASENOTES

.PRIVATEDATA

#>


<#
.SYNOPSIS
    Checks for non-Microsoft LSA packages on local or remote Windows Servers.
.DESCRIPTION
    This script queries the LSA registry keys (Authentication Packages, Notification Packages, Security Packages)
    on localhost or specified remote computers and checks the signature of each configured DLL.
    It reports any DLLs that are not properly signed by a trusted publisher.
    Also checks OSConfig\Security Packages, LSA Protection (RunAsPPL), and DLL metadata.
    Uses WinRM/PowerShell Remoting for remote connections. Ensure WinRM is configured on target machines.
.PARAMETER ComputerName
    An array of computer names or IPs to check. Defaults to localhost if not specified.
.PARAMETER IncludeMicrosoft
    Also include Microsoft-signed packages in the output (for audit purposes).
.PARAMETER AllowedPublishers
    An array of allowed publisher name patterns. DLLs signed by these publishers will not be flagged.
.PARAMETER ExportPath
    Optional path to export results to a CSV file.
.PARAMETER CheckOnline
    Open a web browser search for each flagged DLL to verify legitimacy.
.PARAMETER OnlineOnly
    Only report packages that are NOT in the built-in known-good Microsoft LSA package list.
.EXAMPLE
    PS C:\> .\Check-LSAPackageExtensions.ps1
.EXAMPLE
    PS C:\> .\Check-LSAPackageExtensions.ps1 -ComputerName "MyADServer01", "MyNPSServer01"
.EXAMPLE
    PS C:\> .\Check-LSAPackageExtensions.ps1 -ComputerName "MyADServer01" -IncludeMicrosoft -ExportPath "C:\Temp\lsa_report.csv"
.EXAMPLE
    PS C:\> .\Check-LSAPackageExtensions.ps1 -CheckOnline
#>


[CmdletBinding()]
param (
    [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
    [string[]]$ComputerName = @("localhost"),

    [switch]$IncludeMicrosoft,

    [string[]]$AllowedPublishers = @(),

    [string]$ExportPath,

    [switch]$CheckOnline,

    [switch]$OnlineOnly
)

# Known legitimate Microsoft LSA packages (base list - can be extended)
$KnownGoodLsaPackages = @(
    'msv1_0',
    'rassfm',
    'scecli',
    'kerberos',
    'schannel',
    'wdigest',
    'tspkg',
    'pku2u',
    'cloudap',
    'aadp',
    'mskdc',
    'kdc',
    'negotiate',
    'livessp'
)

function Test-HostReachable {
    param([string]$ComputerName)

    if ($ComputerName -eq "localhost" -or $ComputerName -eq "." -or $ComputerName -eq $env:COMPUTERNAME) {
        return $true
    }

    try {
        $ping = Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop
        return $ping
    }
    catch {
        Write-Verbose "Ping failed for $ComputerName. $_"
        return $false
    }
}

function Test-WinRMAvailable {
    param([string]$ComputerName)

    if ($ComputerName -eq "localhost" -or $ComputerName -eq "." -or $ComputerName -eq $env:COMPUTERNAME) {
        return $true
    }

    try {
        $session = New-PSSession -ComputerName $ComputerName -ErrorAction Stop
        Remove-PSSession -Session $session -ErrorAction SilentlyContinue
        return $true
    }
    catch {
        Write-Verbose "WinRM not available on $ComputerName. $_"
        return $false
    }
}

function Get-SignerInfo {
    param([string]$FilePath)

    try {
        $signature = Get-AuthenticodeSignature -FilePath $FilePath -ErrorAction Stop
        $publisher = if ($signature.SignerCertificate) { $signature.SignerCertificate.Subject } else { "Not Signed" }
        $thumbprint = if ($signature.SignerCertificate) { $signature.SignerCertificate.Thumbprint } else { "N/A" }
        $isMicrosoft = $publisher -like "*Microsoft*" -or $publisher -like "*Windows*"

        return [PSCustomObject]@{
            Status      = $signature.Status
            Publisher   = $publisher
            Thumbprint  = $thumbprint
            IsMicrosoft = $isMicrosoft
        }
    }
    catch {
        return [PSCustomObject]@{
            Status      = "Error"
            Publisher   = "Error reading signature: $_"
            Thumbprint  = "N/A"
            IsMicrosoft = $false
        }
    }
}

function Get-DllMetadata {
    param([string]$FilePath)

    try {
        $item = Get-Item -Path $FilePath -ErrorAction Stop
        $versionInfo = $item.VersionInfo
        return [PSCustomObject]@{
            FileDescription = $versionInfo.FileDescription
            ProductName     = $versionInfo.ProductName
            CompanyName     = $versionInfo.CompanyName
            FileVersion     = $versionInfo.FileVersion
            ProductVersion  = $versionInfo.ProductVersion
        }
    }
    catch {
        return [PSCustomObject]@{
            FileDescription = "Error: $_"
            ProductName     = "N/A"
            CompanyName     = "N/A"
            FileVersion     = "N/A"
            ProductVersion  = "N/A"
        }
    }
}

function Test-PackageAllowed {
    param([string]$Publisher, [string[]]$AllowedPublishers)

    foreach ($pattern in $AllowedPublishers) {
        if ($Publisher -like $pattern) {
            return $true
        }
    }
    return $false
}

function Get-LegitimacyInfo {
    param([string]$PackageName, [string]$Publisher, [string]$FilePath)

    $isKnownGood = $false
    $legitimacyNote = ""
    $searchUrl = ""

    if ($KnownGoodLsaPackages -contains $PackageName.ToLower()) {
        $isKnownGood = $true
        $legitimacyNote = "Known Microsoft LSA package"
    }

    if ($isKnownGood) {
        return [PSCustomObject]@{
            PackageName    = $PackageName
            IsKnownGood    = $true
            LegitimacyNote = $legitimacyNote
            SearchUrl      = "https://learn.microsoft.com/en-us/search/?terms=$PackageName.dll"
            Recommendation = "LEGITIMATE - Microsoft built-in package"
        }
    }
    else {
        $encoded = [System.Web.HttpUtility]::UrlEncode("$PackageName.dll LSA package legitimate OR malware")
        $searchUrl = "https://www.bing.com/search?q=$encoded"
        return [PSCustomObject]@{
            PackageName    = $PackageName
            IsKnownGood    = $false
            LegitimacyNote = "Not in known-good Microsoft LSA list"
            SearchUrl      = $searchUrl
            Recommendation = "UNKNOWN - Requires manual review"
        }
    }
}

function Get-LSAProtectionStatus {
    param([string]$ComputerName)

    try {
        $regPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa'
        $runAsPPL = Get-ItemProperty -Path $regPath -Name 'RunAsPPL' -ErrorAction SilentlyContinue
        if ($runAsPPL -and $runAsPPL.RunAsPPL -eq 1) {
            return [PSCustomObject]@{
                LSAProtectionEnabled = $true
                Status               = "ENABLED"
                Recommendation       = "LSA Protection is enabled. This adds an extra layer of security by requiring LSA plugins to run as Protected Process Light (PPL)."
            }
        }
        else {
            return [PSCustomObject]@{
                LSAProtectionEnabled = $false
                Status               = "DISABLED"
                Recommendation       = "LSA Protection is DISABLED. Consider enabling RunAsPPL=1 to protect LSA from unauthorized plugins. Warning: May break third-party LSA packages that are not PPL-compatible."
            }
        }
    }
    catch {
        return [PSCustomObject]@{
            LSAProtectionEnabled = $false
            Status               = "UNKNOWN"
            Recommendation       = "Could not determine LSA Protection status. Check registry key: HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\RunAsPPL"
        }
    }
}

function Invoke-LSACheck {
    param(
        [string]$ComputerName,
        [bool]$UseWinRM,
        [bool]$IncludeMicrosoft,
        [string[]]$AllowedPublishers
    )

    $scriptBlock = {
        param($IncludeMicrosoft, $AllowedPublishers)

        function Get-SignerInfoLocal {
            param([string]$FilePath)
            try {
                $signature = Get-AuthenticodeSignature -FilePath $FilePath -ErrorAction Stop
                $publisher = if ($signature.SignerCertificate) { $signature.SignerCertificate.Subject } else { "Not Signed" }
                $thumbprint = if ($signature.SignerCertificate) { $signature.SignerCertificate.Thumbprint } else { "N/A" }
                $isMicrosoft = $publisher -like "*Microsoft*" -or $publisher -like "*Windows*"
                return [PSCustomObject]@{ Status = $signature.Status; Publisher = $publisher; Thumbprint = $thumbprint; IsMicrosoft = $isMicrosoft }
            }
            catch {
                return [PSCustomObject]@{ Status = "Error"; Publisher = "Error: $_"; Thumbprint = "N/A"; IsMicrosoft = $false }
            }
        }

        function Get-DllMetadataLocal {
            param([string]$FilePath)
            try {
                $item = Get-Item -Path $FilePath -ErrorAction Stop
                $versionInfo = $item.VersionInfo
                return [PSCustomObject]@{ FileDescription = $versionInfo.FileDescription; ProductName = $versionInfo.ProductName; CompanyName = $versionInfo.CompanyName; FileVersion = $versionInfo.FileVersion }
            }
            catch {
                return [PSCustomObject]@{ FileDescription = "Error: $_"; ProductName = "N/A"; CompanyName = "N/A"; FileVersion = "N/A" }
            }
        }

        $PackageTypes = @('Authentication Packages', 'Notification Packages', 'Security Packages')
        $Results = foreach ($PackageType in $PackageTypes) {
            try {
                $PackagesProperty = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa' -Name $PackageType -ErrorAction Stop
                if ($PackagesProperty) {
                    $PackageList = $PackagesProperty.$PackageType
                    if ($PackageList -isnot [array]) { $PackageList = @($PackageList) }
                    foreach ($Package in $PackageList) {
                        $cleanPackage = $Package.Trim()
                        if (-not [string]::IsNullOrEmpty($cleanPackage) -and $cleanPackage -ne '""') {
                            $dllPath = Join-Path -Path $env:SystemRoot -ChildPath "System32\$cleanPackage.dll"
                            $dllPathWow = Join-Path -Path $env:SystemRoot -ChildPath "SysWOW64\$cleanPackage.dll"
                            $foundPath = $null
                            if (Test-Path $dllPath) { $foundPath = $dllPath }
                            elseif (Test-Path $dllPathWow) { $foundPath = $dllPathWow }

                            if ($foundPath) {
                                $signer = Get-SignerInfoLocal -FilePath $foundPath
                                $meta = Get-DllMetadataLocal -FilePath $foundPath
                                $isRisk = $false; $riskReason = @()
                                if ($signer.Status -ne 'Valid') { $isRisk = $true; $riskReason += "Invalid signature ($($signer.Status))" }
                                if (-not $isRisk -and $AllowedPublishers -and $AllowedPublishers.Count -gt 0) {
                                    $allowed = $false; foreach ($p in $AllowedPublishers) { if ($signer.Publisher -like $p) { $allowed = $true; break } }
                                    if (-not $allowed) { $isRisk = $true; $riskReason += "Not in allowed publishers list" }
                                }
                                if (-not $isRisk -and -not $signer.IsMicrosoft) {
                                    $isRisk = $true; $riskReason += "Non-Microsoft package"
                                }
                                if (-not $isRisk -and $IncludeMicrosoft -and $signer.IsMicrosoft) {
                                    $isRisk = $true; $riskReason += "Microsoft package (audit mode)"
                                }
                                if ($isRisk) {
                                    [pscustomobject]@{
                                        ComputerName    = $env:COMPUTERNAME
                                        PackageType     = $PackageType
                                        Package         = $cleanPackage
                                        Path            = $foundPath
                                        Publisher       = $signer.Publisher
                                        Status          = $signer.Status
                                        IsMicrosoft     = $signer.IsMicrosoft
                                        RiskReason      = $riskReason -join "; "
                                        FileDescription = $meta.FileDescription
                                        ProductName     = $meta.ProductName
                                        CompanyName     = $meta.CompanyName
                                        FileVersion     = $meta.FileVersion
                                    }
                                }
                            } else {
                                [pscustomobject]@{
                                    ComputerName    = $env:COMPUTERNAME
                                    PackageType     = $PackageType
                                    Package         = $cleanPackage
                                    Path            = "Not Found in System32 or SysWOW64"
                                    Publisher       = "N/A"
                                    Status          = "N/A"
                                    IsMicrosoft     = $false
                                    RiskReason      = "DLL not found on disk"
                                    FileDescription = "N/A"
                                    ProductName     = "N/A"
                                    CompanyName     = "N/A"
                                    FileVersion     = "N/A"
                                }
                            }
                        }
                    }
                }
            } catch { Write-Verbose "Registry key '$PackageType' not found." }
        }
        return $Results
    }

    try {
        if ($UseWinRM) {
            $Splat = @{
                ComputerName = $ComputerName
                ErrorAction   = 'Stop'
                ScriptBlock   = $scriptBlock
            }
            $Splat.ArgumentList = @($IncludeMicrosoft, $AllowedPublishers)
            return Invoke-Command @Splat
        }
        else {
            throw "WinRM is not available on $ComputerName. Cannot perform full LSA package check remotely. Configure WinRM on the target machine or run this script locally on the target."
        }
    }
    catch {
        throw "Failed to execute LSA check on $ComputerName. $_"
    }
}

function Invoke-LSACheckLocal {
    param($IncludeMicrosoft, $AllowedPublishers)

    $PackageTypes = @('Authentication Packages', 'Notification Packages', 'Security Packages')
    $Results = foreach ($PackageType in $PackageTypes) {
        try {
            $PackagesProperty = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa' -Name $PackageType -ErrorAction Stop
            if ($PackagesProperty) {
                $PackageList = $PackagesProperty.$PackageType
                if ($PackageList -isnot [array]) { $PackageList = @($PackageList) }
                foreach ($Package in $PackageList) {
                        $cleanPackage = $Package.Trim()
                        if (-not [string]::IsNullOrEmpty($cleanPackage) -and $cleanPackage -ne '""') {
                            $dllPath = Join-Path -Path $env:SystemRoot -ChildPath "System32\$cleanPackage.dll"
                            $dllPathWow = Join-Path -Path $env:SystemRoot -ChildPath "SysWOW64\$cleanPackage.dll"
                            $foundPath = $null
                            if (Test-Path $dllPath) { $foundPath = $dllPath }
                            elseif (Test-Path $dllPathWow) { $foundPath = $dllPathWow }

                            if ($foundPath) {
                                $signer = Get-SignerInfo -FilePath $foundPath
                                $meta = Get-DllMetadata -FilePath $foundPath
                                $isRisk = $false; $riskReason = @()
                                if ($signer.Status -ne 'Valid') { $isRisk = $true; $riskReason += "Invalid signature ($($signer.Status))" }
                                if (-not $isRisk -and $AllowedPublishers -and $AllowedPublishers.Count -gt 0) {
                                    $allowed = $false; foreach ($p in $AllowedPublishers) { if ($signer.Publisher -like $p) { $allowed = $true; break } }
                                    if (-not $allowed) { $isRisk = $true; $riskReason += "Not in allowed publishers list" }
                                }
                                if (-not $isRisk -and -not $signer.IsMicrosoft) {
                                    $isRisk = $true; $riskReason += "Non-Microsoft package"
                                }
                                if (-not $isRisk -and $IncludeMicrosoft -and $signer.IsMicrosoft) {
                                    $isRisk = $true; $riskReason += "Microsoft package (audit mode)"
                                }
                                if ($isRisk) {
                                    [pscustomobject]@{
                                        ComputerName    = $env:COMPUTERNAME
                                        PackageType     = $PackageType
                                        Package         = $cleanPackage
                                        Path            = $foundPath
                                        Publisher       = $signer.Publisher
                                        Status          = $signer.Status
                                        IsMicrosoft     = $signer.IsMicrosoft
                                        RiskReason      = $riskReason -join "; "
                                        FileDescription = $meta.FileDescription
                                        ProductName     = $meta.ProductName
                                        CompanyName     = $meta.CompanyName
                                        FileVersion     = $meta.FileVersion
                                    }
                                }
                            } else {
                                [pscustomobject]@{
                                    ComputerName    = $env:COMPUTERNAME
                                    PackageType     = $PackageType
                                    Package         = $cleanPackage
                                    Path            = "Not Found in System32 or SysWOW64"
                                    Publisher       = "N/A"
                                    Status          = "N/A"
                                    IsMicrosoft     = $false
                                    RiskReason      = "DLL not found on disk"
                                    FileDescription = "N/A"
                                    ProductName     = "N/A"
                                    CompanyName     = "N/A"
                                    FileVersion     = "N/A"
                                }
                            }
                        }
                }
            }
        } catch { Write-Verbose "Registry key '$PackageType' not found." }
    }
    return $Results
}

function Invoke-OSConfigCheck {
    param($IncludeMicrosoft, $AllowedPublishers)

    $Results = @()
    $regPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig'

    try {
        $PackagesProperty = Get-ItemProperty -Path $regPath -Name 'Security Packages' -ErrorAction Stop
        if ($PackagesProperty) {
            $PackageList = $PackagesProperty.'Security Packages'
            if ($PackageList -isnot [array]) { $PackageList = @($PackageList) }
            foreach ($Package in $PackageList) {
                $cleanPackage = $Package.Trim()
                if (-not [string]::IsNullOrEmpty($cleanPackage) -and $cleanPackage -ne '""') {
                    $dllPath = Join-Path -Path $env:SystemRoot -ChildPath "System32\$cleanPackage.dll"
                    $dllPathWow = Join-Path -Path $env:SystemRoot -ChildPath "SysWOW64\$cleanPackage.dll"
                    $foundPath = $null
                    if (Test-Path $dllPath) { $foundPath = $dllPath }
                    elseif (Test-Path $dllPathWow) { $foundPath = $dllPathWow }

                    if ($foundPath) {
                        $signer = Get-SignerInfo -FilePath $foundPath
                        $meta = Get-DllMetadata -FilePath $foundPath
                        $isRisk = $false; $riskReason = @()
                        if ($signer.Status -ne 'Valid') { $isRisk = $true; $riskReason += "Invalid signature ($($signer.Status))" }
                        if (-not $isRisk -and $AllowedPublishers -and $AllowedPublishers.Count -gt 0) {
                            $allowed = $false; foreach ($p in $AllowedPublishers) { if ($signer.Publisher -like $p) { $allowed = $true; break } }
                            if (-not $allowed) { $isRisk = $true; $riskReason += "Not in allowed publishers list" }
                        }
                        if (-not $isRisk -and -not $signer.IsMicrosoft) {
                            $isRisk = $true; $riskReason += "Non-Microsoft package"
                        }
                        if (-not $isRisk -and $IncludeMicrosoft -and $signer.IsMicrosoft) {
                            $isRisk = $true; $riskReason += "Microsoft package (audit mode)"
                        }
                        if ($isRisk) {
                            $Results += [pscustomobject]@{
                                ComputerName    = $env:COMPUTERNAME
                                PackageType     = "OSConfig\Security Packages"
                                Package         = $cleanPackage
                                Path            = $foundPath
                                Publisher       = $signer.Publisher
                                Status          = $signer.Status
                                IsMicrosoft     = $signer.IsMicrosoft
                                RiskReason      = $riskReason -join "; "
                                FileDescription = $meta.FileDescription
                                ProductName     = $meta.ProductName
                                CompanyName     = $meta.CompanyName
                                FileVersion     = $meta.FileVersion
                            }
                        }
                    } else {
                        $Results += [pscustomobject]@{
                            ComputerName    = $env:COMPUTERNAME
                            PackageType     = "OSConfig\Security Packages"
                            Package         = $cleanPackage
                            Path            = "Not Found in System32 or SysWOW64"
                            Publisher       = "N/A"
                            Status          = "N/A"
                            IsMicrosoft     = $false
                            RiskReason      = "DLL not found on disk"
                            FileDescription = "N/A"
                            ProductName     = "N/A"
                            CompanyName     = "N/A"
                            FileVersion     = "N/A"
                        }
                    }
                }
            }
        }
    }
    catch {
        Write-Verbose "OSConfig\Security Packages registry key not found. This is normal on some systems."
    }
    return $Results
}

function Add-LegitimacyInfo {
    param([System.Collections.ArrayList]$Results)

    for ($i = 0; $i -lt $Results.Count; $i++) {
        $r = $Results[$i]
        if ($r.RiskReason -eq "DLL not found on disk") {
            $Results[$i] | Add-Member -NotePropertyName Legitimacy -NotePropertyValue "UNKNOWN - File missing" -Force
            $Results[$i] | Add-Member -NotePropertyName SearchUrl -NotePropertyValue "" -Force
        }
        else {
            $legitimacy = Get-LegitimacyInfo -PackageName $r.Package -Publisher $r.Publisher -FilePath $r.Path
            $Results[$i] | Add-Member -NotePropertyName Legitimacy -NotePropertyValue $legitimacy.Recommendation -Force
            $Results[$i] | Add-Member -NotePropertyName SearchUrl -NotePropertyValue $legitimacy.SearchUrl -Force
        }
    }
}

function Show-InvestigationGuidance {
    param([object]$Result)

    Write-Host "`n --- Investigation Steps for $($Result.Package) ---" -ForegroundColor Yellow
    Write-Host " 1. Identify which application installed this package." -ForegroundColor White
    Write-Host " Path: $($Result.Path)" -ForegroundColor Gray
    Write-Host " 2. Verify digital signature details:" -ForegroundColor White
    Write-Host " Publisher: $($Result.Publisher)" -ForegroundColor Gray
    Write-Host " Status: $($Result.Status)" -ForegroundColor Gray
    Write-Host " 3. Check file metadata:" -ForegroundColor White
    Write-Host " Description: $($Result.FileDescription)" -ForegroundColor Gray
    Write-Host " Product: $($Result.ProductName)" -ForegroundColor Gray
    Write-Host " Company: $($Result.CompanyName)" -ForegroundColor Gray
    Write-Host " Version: $($Result.FileVersion)" -ForegroundColor Gray
    Write-Host " 4. Confirm whether the application is approved in your environment." -ForegroundColor White
    Write-Host " 5. Check vendor documentation for LSA/PPL compatibility." -ForegroundColor White
    Write-Host " 6. Review relevant Windows event logs (Event Viewer > Applications and Services Logs > Microsoft > Windows > LSA)." -ForegroundColor White
    Write-Host " 7. Update the application to a supported version." -ForegroundColor White
    Write-Host " 8. Remove ONLY after confirming it is unnecessary or unauthorized." -ForegroundColor White
    Write-Host " Search for more info: $($Result.SearchUrl)" -ForegroundColor Cyan
    Write-Host ""
}

function Main {
    Write-Host '=== LSA Package Extension Checker ===' -ForegroundColor Cyan
    Write-Host ""

    $allResults = @()

    foreach ($Computer in $ComputerName) {
        Write-Host "--- Checking LSA packages on $Computer ---"

        $isLocal = $Computer -eq "localhost" -or $Computer -eq "." -or $Computer -eq $env:COMPUTERNAME

        if (-not $isLocal) {
            if (-not (Test-HostReachable -ComputerName $Computer)) {
                Write-Warning "[SKIP] Host $Computer is not reachable. Skipping."
                Write-Host "--- Finished check for $Computer ---`n"
                continue
            }

            $hasWinRM = Test-WinRMAvailable -ComputerName $Computer
            if ($hasWinRM) {
                Write-Host "[INFO] Using WinRM for $Computer." -ForegroundColor Cyan
            } else {
                Write-Warning "[BLOCKED] WinRM is not available on $Computer. Cannot check this host remotely."
                Write-Warning " To enable WinRM on the target, run: Enable-PSRemoting -Force"
                Write-Warning " Alternatively, copy and run this script directly on the target machine."
                Write-Host "--- Finished check for $Computer ---`n"
                continue
            }
        } else {
            Write-Host "[INFO] Checking local machine." -ForegroundColor Cyan
        }

        try {
            $results = if ($isLocal) {
                $localResults = Invoke-LSACheckLocal -IncludeMicrosoft $IncludeMicrosoft -AllowedPublishers $AllowedPublishers
                $osConfigResults = Invoke-OSConfigCheck -IncludeMicrosoft $IncludeMicrosoft -AllowedPublishers $AllowedPublishers
                $localResults + $osConfigResults
            } else {
                Invoke-LSACheck -ComputerName $Computer -UseWinRM $hasWinRM -IncludeMicrosoft $IncludeMicrosoft -AllowedPublishers $AllowedPublishers
            }

            $lsaProtection = Get-LSAProtectionStatus -ComputerName $Computer
            Write-Host "`n LSA Protection Status: $($lsaProtection.Status)" -ForegroundColor $(if ($lsaProtection.LSAProtectionEnabled) { "Green" } else { "Yellow" })
            Write-Host " $($lsaProtection.Recommendation)`n" -ForegroundColor Gray

            if ($results) {
                $resultsArrayList = [System.Collections.ArrayList]@($results)
                Add-LegitimacyInfo -Results $resultsArrayList
                $results = $resultsArrayList

                if ($OnlineOnly) {
                    $results = $results | Where-Object { $_.Legitimacy -ne "LEGITIMATE - Microsoft built-in package" }
                }

                if ($results) {
                    $allResults += $results
                    Write-Host "[ALERT] Found $($results.Count) LSA package(s) that may pose a security risk on $Computer."
                    $results | Format-Table -AutoSize

                    if ($CheckOnline) {
                        Write-Host "`n--- Opening Online Legitimacy Checks ---" -ForegroundColor Yellow
                        foreach ($r in $results) {
                            Write-Host "[$($r.Package)] $($r.Legitimacy)" -ForegroundColor $(if ($r.Legitimacy -like "LEGITIMATE*") { "Green" } else { "Red" })
                            Write-Host " Search: $($r.SearchUrl)"
                            try {
                                Start-Process $r.SearchUrl
                            } catch {
                                Write-Warning " Could not open browser: $_"
                            }
                        }
                    }

                    foreach ($r in $results) {
                        Show-InvestigationGuidance -Result $r
                    }
                }
            } else {
                Write-Host "[OK] No risky LSA packages found on $Computer." -ForegroundColor Green
            }
        }
        catch {
            Write-Warning "[ERROR] Failed to check $Computer. WinRM may not be configured. To enable: Run 'Enable-PSRemoting -Force' on the target machine, or run this script directly on the target. Message: $($_.Exception.Message)"
        }
        Write-Host "--- Finished check for $Computer ---`n"
    }

    if ($allResults.Count -gt 0 -and $ExportPath) {
        try {
            $allResults | Export-Csv -Path $ExportPath -NoTypeInformation -Encoding UTF8 -ErrorAction Stop
            Write-Host "`nResults exported to: $ExportPath" -ForegroundColor Cyan
        }
        catch {
            Write-Warning "Failed to export results: $_"
        }
    }

    Write-Host ""
    Write-Host "=== Summary ===" -ForegroundColor Cyan
    Write-Host "Total computers checked: $($ComputerName.Count)"
    Write-Host "Total risky packages found: $($allResults.Count)"
}

Main