Hoe ik inzicht kreeg in ASR-regels en Controlled Folder Access met één PowerShell-script

Tijdens een implementatie van Microsoft Defender Attack Surface Reduction (ASR) liep ik tegen een veelvoorkomend probleem aan: op welke machines zijn welke ASR-regels nu daadwerkelijk ingeschakeld? Natuurlijk kun je via Intune of GPO configureren, maar hoe weet je zeker dat ze ook goed zijn toegepast op de endpoints? En hoe krijg je daarnaast snel overzicht van eventuele uitzonderingen of instellingen zoals Controlled Folder Access?

Ik zocht dus naar een eenvoudige, overzichtelijke manier om in één oogopslag te zien:

  • Welke ASR-regels zijn ingeschakeld?
  • Welke staan in audit- of waarschuwingsmodus?
  • Zijn er uitzonderingen (exclusions) geconfigureerd?
  • Is Controlled Folder Access (CFA) actief, en zo ja: op welke mappen of applicaties?

Het script

Na wat zoekwerk of ik dit eenvouwdig met powershell bovenwater zou kunnen krijgen kwam ik op github een script van Roy Klooster tegen. Dit script deed al exact wat het moest doen voor mij:

✅ Of je over de juiste beheerdersrechten beschikt
✅ Welke ASR-regels actief zijn en in welke modus (Enabled, Audit, Warn)
✅ Welke exclusions er zijn ingesteld (bijv. mappen of bestanden die uitgesloten zijn van ASR)
✅ De status van Controlled Folder Access, inclusief de mappen en applicaties die beschermd worden

Hieronder een korte toelichting van de belangrijkste onderdelen van het script.

Voor de zekerheid heb ik wel even de tijd genomen om het script even te analyseren. Want ondanks dat ik al vaker scripts van Roy gebruikt heb, controlleer ik altijd wel scripts die ik download. Je weet maar nooit.

Hieronder staat een korte toelichting van de belangrijkste onderdelen van het script.

1. Controle op beheerdersrechten

Voordat het script van start gaat, controleert het of je sessie als administrator draait. ASR-instellingen zitten in de registry onder HKLM, en daar kom je zonder elevated rechten niet bij:





function Test-AdminElevation {
    $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
    return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
PowerShell

2. Status van ASR-regels

Alle bekende ASR-regels (GUIDs) zijn opgenomen in een array, zodat je snel kunt controleren of ze geconfigureerd zijn op het systeem – en in welke modus:

Function Get-ASRStatus {
    # Haalt ASR-regels uit de registry en vergelijkt ze met de bekende lijst
}
PowerShell

De output ziet er overzichtelijk uit in een tabel:

  • Naam van de regel
  • GUID
  • Interpretatie van die waarde (Disabled, Enabled, Audit, Warn)

3. Uitzonderingen (Exclusions)

Soms moet je applicaties of paden uitsluiten van ASR, bijvoorbeeld bij legacy software. Dit onderdeel haalt die exclusions op uit de registry:

function Get-ASRStatusExclusions {
    # Zoekt ASROnlyExclusions in het register en toont of bestanden of mappen zijn uitgesloten
}
PowerShell

4. Controlled Folder Access (CFA)

Controlled Folder Access beschermt mappen tegen ongeautoriseerde wijziging door onbekende applicaties. Het script toont:

  • Of CFA aanstaat
  • Welke mappen beschermd zijn
  • Welke applicaties toegang hebben gekregen
function get-CFAStatus {
    # Controleert CFA status en haalt lijst op met mappen en toegestane apps
}
PowerShell

Waarom dit handig is

Dit script is ideaal voor:

  • Audits: snel inzicht krijgen in de beveiligingsstatus van een machine
  • Troubleshooting: controleren waarom een aanval wel/niet geblokkeerd werd
  • Implementaties: checken of policies correct zijn uitgerold
  • Rapportages: eenvoudig te exporteren output via PowerShell (CSV, JSON etc.)

Tot slot

Het script is met zorg opgebouwd en goed te lezen, ook voor beheerders met beperkte scriptingervaring. Het is eenvoudig uit te breiden, bijvoorbeeld met logging of CSV-export. En het mooiste: je hebt in één run een compleet overzicht van de belangrijkste Defender ASR- en CFA-instellingen op een machine.


Wil je het script direct gebruiken? Je vindt het op de github van Roy Klooster

function Test-AdminElevation {
    # Check for elevated permissions
    $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
    return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}


Function Get-ASRStatus {
    $check = Test-AdminElevation

    $asrrules = @(
        [PSCustomObject]@{ Name = "Block executable content from email client and webmail"; GUID = "BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550" },
        [PSCustomObject]@{ Name = "Block all Office applications from creating child processes"; GUID = "D4F940AB-401B-4EFC-AADC-AD5F3C50688A" },
        [PSCustomObject]@{ Name = "Block Office applications from creating executable content"; GUID = "3B576869-A4EC-4529-8536-B80A7769E899" },
        [PSCustomObject]@{ Name = "Block Office applications from injecting code into other processes"; GUID = "75668C1F-73B5-4CF0-BB93-3ECF5CB7CC84" },
        [PSCustomObject]@{ Name = "Block JavaScript or VBScript from launching downloaded executable content"; GUID = "D3E037E1-3EB8-44C8-A917-57927947596D" },
        [PSCustomObject]@{ Name = "Block execution of potentially obfuscated scripts"; GUID = "5BEB7EFE-FD9A-4556-801D-275E5FFC04CC" },
        [PSCustomObject]@{ Name = "Block Win32 API calls from Office macros"; GUID = "92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B" },
        [PSCustomObject]@{ Name = "Block executable files from running unless they meet a prevalence, age, or trusted list criterion"; GUID = "01443614-cd74-433a-b99e-2ecdc07bfc25" },
        [PSCustomObject]@{ Name = "Use advanced protection against ransomware"; GUID = "c1db55ab-c21a-4637-bb3f-a12568109d35" },
        [PSCustomObject]@{ Name = "Block credential stealing from the Windows local security authority subsystem (lsass.exe)"; GUID = "9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2" },
        [PSCustomObject]@{ Name = "Block process creations originating from PSExec and WMI commands"; GUID = "d1e49aac-8f56-4280-b9ba-993a6d77406c" },
        [PSCustomObject]@{ Name = "Block untrusted and unsigned processes that run from USB"; GUID = "b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4" },
        [PSCustomObject]@{ Name = "Block Office communication application from creating child processes"; GUID = "26190899-1602-49e8-8b27-eb1d0a1ce869" },
        [PSCustomObject]@{ Name = "Block Adobe Reader from creating child processes"; GUID = "7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c" },
        [PSCustomObject]@{ Name = "Block persistence through WMI event subscription"; GUID = "e6db77e5-3df2-4cf1-b95a-636979351e5b" },
        [PSCustomObject]@{ Name = "Block abuse of exploited vulnerable signed drivers"; GUID = "56a863a9-875e-4185-98a7-b882c64b5ce5" },
        [PSCustomObject]@{ Name = "Block rebooting machine in Safe Mode (preview)"; GUID = "33ddedf1-c6e0-47cb-833e-de6133960387" },
        [PSCustomObject]@{ Name = "Block use of copied or impersonated system tools (preview)"; GUID = "c0033c00-d16d-4114-a5a0-dc9b3a7d2ceb" },
        [PSCustomObject]@{ Name = "Block Webshell creation for Servers"; GUID = "a8f5898e-1dc8-49a9-9878-85004b8a61e6" }
    )

    # Get the ASR rules on the device
    try {
        $ASRRUlesOnDevice = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender\Policy Manager" -ErrorAction SilentlyContinue).asrrules).split("|")
    } catch {
        Write-Host "Requested registry access is not allowed." -ForegroundColor Red
        break
    }
    $ASRRUlesOnDeviceCount = ($ASRRUlesOnDevice | Where-Object { $_ -match "=" }).Count               # Count the number of ASR rules on the device (=1, =2, =6, =0)

    if ($ASRRUlesOnDeviceCount -gt 0) {
        # Define the values
        $enabledvalues = @{
            "Not Configured/Disabled" = 0
            "Enabled"                 = 1
            "Audit"                   = 2
            "Warn"                    = 6
        }

        $ASROnDeviceResults = @()
        foreach ($rule in $asrrules) {
            $Found = $ASRRUlesOnDevice | Where-Object { $_ -match $($rule.GUID) } 

            if ($found) {
                $ruleValue = $Found.Split("=")[1]
                $status = $enabledvalues.GetEnumerator() | Where-Object { $_.Value -eq $ruleValue } | Select-Object -ExpandProperty Key
                if (-not $status) {
                    $status = "Unknown"
                }
                $ASROnDeviceResults += [PSCustomObject]@{
                    Name   = $rule.Name
                    GUID   = $rule.GUID
                    Value  = $ruleValue
                    Status = $status
                }
            } else {
                $ASROnDeviceResults += [PSCustomObject]@{
                    Name   = $rule.Name
                    GUID   = $rule.GUID
                    Value  = $null
                    Status = "Not Configured"
                }
            }
        }
        Return $ASROnDeviceResults

    }
}
function Get-ASRStatusExclusions {
    # Find all exclusions
    Try {
        $ASRExclusions = Get-Item "HKLM:\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR\ASROnlyExclusions" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Property

        if ($ASRExclusions.count -eq 0) {
            $ASRExclusionsResults = "No ASR exclusions found"
            $skipsteps = $true
            Return $ASRExclusionsResults
        }
    } catch {
        $SkipSteps = $true
        $ASRExclusionsResults = "No ASR exclusions found"
        Return $ASRExclusionsResults
    }

    if (-not($SkipSteps)) {
        $ASRExclusionResults = @()
        foreach ($exclusion in $ASRExclusions) {
            $type = if ($exclusion -match "\.\w+$") { "File" } else { "Folder" }

            if ($type -eq "Folder") {
                $files = (Get-ChildItem -Path $exclusion -Recurse -Force).fullname 
                foreach ($file in $files) {
                    if ($file -match "\.\w+$") {
                        $ASRExclusionResults += [PSCustomObject]@{
                            Type = "File"
                            Path = $file
                        }
                    } else {
                        $ASRExclusionResults += [PSCustomObject]@{
                            Type = "Folder"
                            Path = $exclusion
                        }
                    }
                }
            }
            $ASRExclusionResults = $ASRExclusionResults | Sort-Object Type, Path -Descending
        }
    }
    Return $ASRExclusionResults
}

function get-CFAStatus {
    try {
       $CFAStatus = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\Controlled Folder Access" -Name EnableControlledFolderAccess
    } catch {
        $SkipSteps = $true
        $CFAStatusResults = "Controlled Folder Access is not enabled"
        Return $CFAStatusResults
    }

    if (-not ($SkipSteps)) {
    $enabledvalues = @{
        "Not Configured/Disabled"                   = 0
        "Enabled"                     = 1
        "Audit"                       = 2
        "AuditDiskModificationOnly"   = 4
        "BlockDiskModificationOnly"   = 3
    }

    if ($CFAStatus) {
        $CFAStatus = $enabledvalues.GetEnumerator() | Where-Object { $_.Value -eq $CFAStatus } | Select-Object -ExpandProperty Key
    } else {
        $CFAStatus = "Not Configured/Disabled"
    }

    $ProtectedFolders = Get-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\Controlled Folder Access\ProtectedFolders\" -ErrorAction SilentlyContinue  | Select-Object -ExpandProperty Property | Sort-Object
    $ProtectedApplications = Get-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender\Windows Defender Exploit Guard\Controlled Folder Access\AllowedApplications\" -ErrorAction SilentlyContinue  | Select-Object -ExpandProperty Property | Sort-Object
    
    $CFAStatusResults = @()

    $CFAStatusResults += [PSCustomObject]@{
        Type  = "Controlled Access Folder Status"
        Value = $CFAStatus
    }

    if ($ProtectedFolders) {
        foreach ($folder in $ProtectedFolders) {
            $CFAStatusResults += [PSCustomObject]@{
                Type = "Protected Folder"
                Value = $folder
            }
        }
    }

    if ($ProtectedApplications) {
        foreach ($application in $ProtectedApplications) {
            $CFAStatusResults += [PSCustomObject]@{
                Type = "Protected Application"
                Value = $application
            }
        }
    }

    Return $CFAStatusResults
    } 
} 

Clear-Host

$banner = @"

    █████╗ ███████╗██████╗     ██████╗ ██╗   ██╗██╗     ███████╗    ██╗███╗   ██╗███████╗██████╗ ███████╗ ██████╗████████╗ ██████╗ ██████╗ 
    ██╔══██╗██╔════╝██╔══██╗    ██╔══██╗██║   ██║██║     ██╔════╝    ██║████╗  ██║██╔════╝██╔══██╗██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗
    ███████║███████╗██████╔╝    ██████╔╝██║   ██║██║     █████╗      ██║██╔██╗ ██║███████╗██████╔╝█████╗  ██║        ██║   ██║   ██║██████╔╝
    ██╔══██║╚════██║██╔══██╗    ██╔══██╗██║   ██║██║     ██╔══╝      ██║██║╚██╗██║╚════██║██╔═══╝ ██╔══╝  ██║        ██║   ██║   ██║██╔══██╗
    ██║  ██║███████║██║  ██║    ██║  ██║╚██████╔╝███████╗███████╗    ██║██║ ╚████║███████║██║     ███████╗╚██████╗   ██║   ╚██████╔╝██║  ██║
    ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝    ╚═╝  ╚═╝ ╚═════╝ ╚══════╝╚══════╝    ╚═╝╚═╝  ╚═══╝╚══════╝╚═╝     ╚══════╝ ╚═════╝   ╚═╝    ╚═════╝ ╚═╝  ╚═╝

"@

$ASRRulesOnDevice_Count = (Get-ASRStatus).count
$ASRRulesOnDevice_Count_Configured = (Get-ASRStatus | Where-Object { $_.Status -ne "Not Configured" }).count

if ($ASRRUlesOnDevice_Count -eq 0) {
    Write-Host $banner -ForegroundColor Yellow
    Write-Host "No ASR rules found on the device" -ForegroundColor Red
    Return
} 

if ($ASRRUlesOnDevice_Count -gt 0) {
    Write-Host $banner -ForegroundColor Yellow 
    Write-Host "FOUND: $ASRRUlesOnDevice_Count_Configured of $ASRRUlesOnDevice_Count ASR rules on the device" -ForegroundColor Yellow
    Get-ASRStatus | Format-Table -AutoSize

    Write-Host "Exclusions`n" -ForegroundColor Yellow -BackgroundColor Black -NoNewline
    Get-ASRStatusExclusions | Format-Table -AutoSize

    Write-Host "Controlled Folder Access`n" -ForegroundColor Yellow -BackgroundColor Black -NoNewline
    get-CFAStatus | Format-Table -AutoSize
}
PowerShell
Expand

Geef een reactie

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *