Fix unquoted service path

Microsoft recently broke this with an Update for Defender they will need to deploy the fix due to Tamper Protection :


Context

[[“DefenderUpdateSvc”,”c:\\programdata\\microsoft\\microsoft defender\\defender update\\platform\\10.8838.26060.15013-0\\defenderupdateservice.exe”],[“Sense”,”c:\\programdata\\microsoft\\windows defender advanced threat protection\\platform\\versions\\10.8838.26060.15013-0\\mssense.exe”]]?

[“DefenderUpdateSvc”,”c:\\programdata\\microsoft\\microsoft defender\\defender update\\platform\\10.8838.26060.15013-0\\defenderupdateservice.exe”]?

[“Sense”,”c:\\programdata\\microsoft\\windows defender advanced threat protection\\platform\\versions\\10.8838.26060.15013-0\\mssense.exe”]

Advanced Hunting Query

DeviceTvmSecureConfigurationAssessment
| where IsApplicable == 1 and IsCompliant == 0
| join kind=inner (DeviceTvmSecureConfigurationAssessmentKB
    | where ConfigurationName has "unquoted") on ConfigurationId
| project DeviceName, ConfigurationName, Context, Timestamp

Detection.ps1

$rx = '^(?!")(?<exe>[^"]*?\.exe)(?<rest>.*)$'   # lazy: stops at the FIRST .exe
$hklm = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine','Registry64')
$svc  = $hklm.OpenSubKey('SYSTEM\CurrentControlSet\Services')
$bad  = foreach ($n in $svc.GetSubKeyNames()) {
    $k = $svc.OpenSubKey($n); if (-not $k) { continue }
    $p = $k.GetValue('ImagePath', $null, 'DoNotExpandEnvironmentNames'); $k.Close()
    if ($p -is [string] -and $p -match $rx -and $Matches.exe -match '\s') { "$n => $p" }
}
$svc.Close(); $hklm.Close()
if ($bad) { Write-Output ("Unquoted: " + ($bad -join ' | ')); exit 1 }
Write-Output "Compliant"; exit 0

Remmediation.ps1

$rx = '^(?!")(?<exe>[^"]*?\.exe)(?<rest>.*)$'
$hklm = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine','Registry64')
$svc  = $hklm.OpenSubKey('SYSTEM\CurrentControlSet\Services')
$fixed = @()
foreach ($n in $svc.GetSubKeyNames()) {
    $k = $null
    try { $k = $svc.OpenSubKey($n, $true) } catch { continue }
    if (-not $k) { continue }
    try {
        $p = $k.GetValue('ImagePath', $null, 'DoNotExpandEnvironmentNames')
        if ($p -is [string] -and $p -match $rx) {
            $exe = $Matches.exe; $rest = $Matches.rest
            if ($exe -match '\s') {
                $kind = $k.GetValueKind('ImagePath')
                $new  = '"' + $exe + '"' + $rest
                $k.SetValue('ImagePath', $new, $kind)
                $fixed += "$n : $p -> $new"
            }
        }
    } catch { Write-Output "Failed $n : $($_.Exception.Message)" }
    finally { $k.Close() }
}
$svc.Close(); $hklm.Close()
Write-Output ("Fixed {0}: {1}" -f $fixed.Count, ($fixed -join ' | '))
exit 0

(No Ratings Yet)