Introduction to Windows Defender Application Control
Windows Defender Application Control (WDAC) is Microsoft’s next-generation application control technology, introduced in Windows 10 and fully supported on Windows Server 2019. Unlike AppLocker, which operates in user space, WDAC policies are enforced by the Windows kernel and can be protected by Virtualization-Based Security (HVCI). WDAC supersedes Device Guard application control and is the preferred application whitelisting solution going forward. It controls which drivers, executables, COM objects, scripts, and even PE files loaded into memory are allowed to run. This tutorial covers creating, configuring, and deploying WDAC policies on Windows Server 2019.
WDAC vs AppLocker
The key differences: WDAC policies are kernel-enforced (cannot be bypassed at user mode level), support virtualization-based security protection, apply to all users uniformly (no per-user policy support), can protect against admin-level tampering when locked via UEFI, and are the only option for Secured-Core servers. AppLocker supports per-user policies, integrates with Group Policy more easily for Windows Server, and has a longer deployment history. The recommendation is to use WDAC for the strongest protection and supplement it with AppLocker for user-level granularity.
Understanding WDAC Policy Types
WDAC has two policy types in Windows Server 2019: Base Policies (standalone policies that define the allowed code) and Supplemental Policies (additive policies that extend a base policy). Multiple supplemental policies can be layered on top of a single base policy. A single base policy per device is the recommended architecture—keep the base policy restrictive and use supplemental policies to add trusted applications.
Creating a Default Allow Policy
The ConfigCI module (included in Windows Server 2019) provides PowerShell cmdlets for creating and managing WDAC policies. Start with a reference system that has all approved software installed, then scan it to create a policy that allows exactly those applications.
# Create a WDAC policy from a reference computer
New-CIPolicy -Level Publisher -FilePath C:WDACReferenceMachinePolicy.xml `
-UserPEs -ScanPath C:Windows -Fallback Hash
# Add Program Files to the scan
New-CIPolicy -Level Publisher -FilePath C:WDACProgramFilesPolicy.xml `
-UserPEs -ScanPath "C:Program Files" -Fallback Hash
# Merge the two policies
Merge-CIPolicy -PolicyPaths "C:WDACReferenceMachinePolicy.xml",
"C:WDACProgramFilesPolicy.xml" `
-OutputFilePath "C:WDACMergedPolicy.xml"
Using Built-in Policy Templates
Windows Server 2019 includes built-in WDAC policy templates in C:WindowsschemasCodeIntegrityExamplePolicies. These provide starting points for common scenarios: AllowMicrosoft.xml (allows all Microsoft-signed code), DefaultWindows.xml (allows only Windows components), DenyAllAudit.xml (audit-mode deny-all policy). Copy and modify a template as your starting point.
# Copy the Allow Microsoft template as a starting point
Copy-Item "C:WindowsschemasCodeIntegrityExamplePoliciesAllowMicrosoft.xml" `
-Destination "C:WDACBasePolicy.xml"
# View the policy in XML
[xml](Get-Content "C:WDACBasePolicy.xml") | Select-Xml -XPath "//FileRule" |
Select-Object -ExpandProperty Node
Setting Policy Rules Options
WDAC policies have configurable rule options that control policy behavior. Key options include: Option 3 (Enabled:Audit Mode—log violations without blocking), Option 4 (Disabled:Flight Signing—block flight-signed code), Option 6 (Enabled:Unsigned System Integrity Policy), Option 10 (Enabled:Boot Audit on Failure), Option 12 (Enabled:Allow Debug Policy Augmentation), and Option 16 (Enabled:Update Policy No Reboot). Set audit mode during testing.
# Add audit mode rule option to the policy
Set-RuleOption -FilePath "C:WDACBasePolicy.xml" -Option 3
# Remove audit mode to switch to enforcement
Set-RuleOption -FilePath "C:WDACBasePolicy.xml" -Option 3 -Delete
# Enable UMCI (User Mode Code Integrity) to also control user-mode executables
Set-RuleOption -FilePath "C:WDACBasePolicy.xml" -Option 0 -Delete # Removes Enabled:UMCI delete to re-enable UMCI
Adding Publisher Rules to WDAC
Add rules to allow specific publisher-signed applications. Use New-CIPolicyRule to create individual rules from a signed file, then add them to the policy.
# Create a publisher rule for a specific application
$rule = New-CIPolicyRule -Level Publisher -DriverFiles "C:Program FilesMyAppmyapp.exe"
# Merge the new rule into the existing policy
Merge-CIPolicy -PolicyPaths "C:WDACBasePolicy.xml" `
-OutputFilePath "C:WDACBasePolicy_Updated.xml" `
-Rules $rule
# Create rules for an entire directory
New-CIPolicy -Level Publisher `
-ScanPath "C:Program FilesMyVendorApp" `
-FilePath "C:WDACMyVendorAppRules.xml" `
-UserPEs `
-Fallback Hash
Converting and Deploying the Binary Policy
WDAC policies are deployed as binary .p7 files, not XML. Convert the XML policy to binary format and place it in the correct location for deployment.
# Convert XML to binary
ConvertFrom-CIPolicy -XmlFilePath "C:WDACBasePolicy.xml" `
-BinaryFilePath "C:WDACSIPolicy.p7b"
# Deploy locally by copying to the System32CodeIntegrity folder
Copy-Item "C:WDACSIPolicy.p7b" `
-Destination "C:WindowsSystem32CodeIntegritySIPolicy.p7b"
For deployment via Group Policy or MDM, the binary policy file is referenced in the AppLocker CSP or through the Code Integrity GPO settings.
Monitoring WDAC Events
WDAC audit and enforcement events are written to the CodeIntegrity event log. Event ID 3076 indicates an audit-mode block, Event ID 3077 indicates an enforcement-mode block.
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-CodeIntegrity/Operational'
Id = @(3076, 3077)
StartTime = (Get-Date).AddDays(-7)
} | Select-Object TimeCreated, Id, Message | Format-List
# Parse blocked files from event log
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-CodeIntegrity/Operational'
Id = 3076
} | ForEach-Object {
$xml = [xml]$_.ToXml()
[PSCustomObject]@{
Time = $_.TimeCreated
FilePath = $xml.Event.EventData.Data |
Where-Object Name -eq 'File Name' | Select-Object -ExpandProperty '#text'
Publisher = $xml.Event.EventData.Data |
Where-Object Name -eq 'Publisher' | Select-Object -ExpandProperty '#text'
}
} | Sort-Object FilePath -Unique
Conclusion
Windows Defender Application Control on Windows Server 2019 provides kernel-enforced application whitelisting that, combined with HVCI, creates a strong defense against code execution attacks. The recommended deployment approach is to start with a template policy in audit mode, collect event data for 30 days, iteratively add rules for all blocked legitimate software, then switch to enforcement mode. WDAC is most effective on servers with well-defined software inventories—domain controllers, web servers, and database servers are ideal candidates for WDAC enforcement as they run a narrow, predictable set of applications.