Public/Get-UnquotedServicePath.ps1

function Get-UnquotedServicePath {
    <#
    .SYNOPSIS
        Finds Windows services with unquoted executable paths that contain spaces.
    .DESCRIPTION
        Enumerates all Win32 services and identifies those whose ImagePath contains spaces
        but is not enclosed in quotation marks. An unquoted path with spaces is a privilege
        escalation vulnerability: Windows will attempt to execute each space-delimited path
        segment as a candidate executable before reaching the real one.
        Returns one object per vulnerable service. Returns nothing if no vulnerable services
        are found.
    .INPUTS
        None. Parameters must be supplied directly.
    .OUTPUTS
        System.Management.Automation.PSCustomObject
    .PARAMETER ComputerName
        The target computer. Defaults to the local machine.
    .EXAMPLE
        Get-UnquotedServicePath

        Returns all services on the local machine with unquoted paths containing spaces.
    .EXAMPLE
        Get-UnquotedServicePath -ComputerName 'Server01'

        Returns vulnerable services on Server01.
    .EXAMPLE
        Get-UnquotedServicePath | Enable-ServicePathQuoting

        Pipes each vulnerable service directly into Enable-ServicePathQuoting to remediate all findings.
    .NOTES
        Read-only. Does not modify any system state.
        Remote operations require WinRM to be configured on the target machine.
    #>


    [CmdletBinding()]
    [OutputType([System.Management.Automation.PSCustomObject])]

    param (
        [Parameter(Mandatory = $false)]
        [string]$ComputerName = $env:COMPUTERNAME
    )

    $isLocal = ($ComputerName -ieq $env:COMPUTERNAME) -or
               ($ComputerName -ieq 'localhost') -or
               ($ComputerName -eq '127.0.0.1')

    $scan = {
        Get-CimInstance -ClassName Win32_Service | ForEach-Object {
            $pathName = $_.PathName
            if ([string]::IsNullOrWhiteSpace($pathName)) { return }
            if ($pathName.TrimStart().StartsWith('"'))    { return }

            if ($pathName -imatch '^(.*?\.exe)') {
                $exePath = $Matches[1].Trim()
                if ($exePath -notmatch ' ') { return }
            } else {
                return
            }

            [PSCustomObject]@{
                ServiceName = $_.Name
                DisplayName = $_.DisplayName
                ImagePath   = $pathName
            }
        }
    }

    if ($isLocal) {
        & $scan | ForEach-Object {
            [PSCustomObject]@{
                ComputerName = $ComputerName
                ServiceName  = $_.ServiceName
                DisplayName  = $_.DisplayName
                ImagePath    = $_.ImagePath
            }
        }
    } else {
        Invoke-Command -ComputerName $ComputerName -ScriptBlock $scan | ForEach-Object {
            [PSCustomObject]@{
                ComputerName = $ComputerName
                ServiceName  = $_.ServiceName
                DisplayName  = $_.DisplayName
                ImagePath    = $_.ImagePath
            }
        }
    }
}