Skip to content

WDAC Notes

HotCakeX edited this page Jun 10, 2023 · 48 revisions

Important Notes and Tips about WDAC policies

  • WDAC stands for Windows Defender Application Control
  • It's used for Application and File whitelisting in Windows.

Supplemental WDAC Policy considerations

Verify Policy type

We have to make sure the WDAC policy that we are going to use as a supplemental policy has PolicyType="Supplemental Policy" in the SiPolicy element of the XML file. If it doesn't, then we have to use this command to change it from base policy to supplemental policy of our base policy.

That will also change/create the <BasePolicyID>GUID</BasePolicyID> element in the supplemental policy XML file. The GUID will be the PolicyID of the base policy specified in the command.


Verify Policy Rule options

We have to make sure that the supplemental policy does not contain any policy rule options that only work with a base policy. This chart shows which ones can be used in a supplemental policy.


You can use this PowerShell code to automatically make sure non-supplemental policy rule options don't exist in a supplemental policy XML file:

$supplementalPolicyPath = ".\Supplemental_Policy.xml"
@(0, 1, 2, 3, 4, 8, 9, 10, 11, 12, 15, 16, 17, 19, 20) | ForEach-Object {
    Set-RuleOption -FilePath $supplementalPolicyPath -Option $_ -Delete
}

A supplemental policy can only have these policy rule options:

  • 5 Enabled:Inherit Default Policy
  • 6 Enabled:Unsigned System Integrity Policy (Default)
  • 7 Allowed:Debug Policy Augmented
  • 13 Enabled:Managed Installer
  • 14 Enabled:Intelligent Security Graph Authorization
  • 18 Disabled:Runtime FilePath Rule Protection

Deny rules in supplemental policy are invalid

Deny rules are ignored in supplemental policies by WDAC engine. Supplemental policies are only meant to expand what the base policy trusts, that's why only allow rules are supported in supplemental policies, and that's also the reason why we don't need to merge Microsoft recommended block rules or driver block rules with a supplemental policy.

When the base policy has a deny rule for a file and we allow the same file in a supplemental policy, the file will still be blocked, because explicit deny rules have the highest priority.

Rule Precedence


Signing a Supplemental policy

When adding the details of the code signing certificate to a base WDAC Policy, make sure you add the -Supplemental switch parameter to the add-signerrule cmdlet when signing a base WDAC policy that is going to have supplemental policies later on. That parameter can only be used for a base policy.

  • Using -Supplemental parameter with Add-SignerRule cmdlet on a Supplemental policy will cause boot failure after deploying it, because that parameter should only be used when adding singer rules to a base policy.

Removing Supplemental policies

Whether the deployed supplemental policy is unsigned or signed, you can remove it just like any unsigned policy using CITool.


What if you Deploy Unsigned Supplemental policy on Signed system?

If you deploy an unsigned supplemental policy on a system where all policies including base and supplemental, are signed, the deployed unsigned supplemental policy will be ignored.




How Deny rules for files and certificates/signers are specified

Denied File Rules

First, Block/Deny File rules are specified in <FileRules> element which is directly under <SiPolicy> element in the XML file. Deny rules are created by having <Deny ID="ID_DENY_" at the beginning of their lines, for example:

<Deny ID="ID_DENY_AGENT64_SHA1" FriendlyName=<Textual Description/Name> Hash=<Hash Numbers> />

Second, there are File Reference rules for each Deny rule that only mentions them by ID, and these are exactly the same as Allow rules because only Rule IDs are mentioned and nothing about the nature of the rule itself. These are in:

<SiPolicy>
    <SigningScenarios>
        <SigningScenario>
            <ProductSigners>
                <FileRulesRef>
                    <FileRuleRef RuleID="<The same ID of the Deny File rule mentioned earlier>" />
                </FileRulesRef>
            </ProductSigners>            
        </SigningScenario>
    </SigningScenarios>
</SiPolicy>

Denied Certificates/Singers

Denied certificates/singers are first mentioned in <SiPolicy => <Signers> with the following syntax:

<Signer ID="ID_SIGNER_VERISIGN_2010" Name="VeriSign Class 3 Code Signing 2010 CA">
... Other possible attributes ...
</Signer>

Unlike file rules, this first part doesn't specify whether the certificate/singer must be allowed or blocked by the WDAC policy.

In order to specify whether a certificate/singer should be denied/allowed, the ID of each signer must be specified in the second part of the XML policy file in <DeniedSigners> element:

<SigningScenarios>
    <SigningScenario Value="131" ID="ID_SIGNINGSCENARIO_<Some generic String>" FriendlyName="<Name>">
        <ProductSigners>
            <DeniedSigners>
                <DeniedSigner SignerId="<ID of the Signer mentioned above in the <Signers> section>" />
            </DeniedSigners>
        </ProductSigners>
    </SigningScenario>
</SigningScenarios>



How to verify the status of User-mode and Kernel-mode WDAC on a system

Using PowerShell

Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard | select -Property *codeintegrity* | fl

2 means Enforced, 1 means Audit mode, 0 means Disabled/Not running.

Using System Information

  • Windows Defender Application Control Policy (Kernel Mode)
  • Windows Defender Application Control User Mode Policy (User Mode)



Refreshing WDAC Policies

CITool --refresh

Old Method: using RefreshPolicy(AMD64).exe

Using RefreshPolicy(AMD64).exe only works when you add a new policy to the Windows folder, but when you delete a policy from that folder, running RefreshPolicy(AMD64).exe won't make the apps that were previously allowed to run by the policy we just deleted, to be blocked from running again. so after we remove a policy from Windows folder, a system restart is required.

This makes sense because apps that have been previously allowed to run by a policy that we just deleted might be still running in the background or even foreground, so to properly stop them, just running RefreshPolicy(AMD64).exe isn't enough and data loss could've occurred if that was the case.




About <SigningScenarios> node in the WDAC policy XML

It consists of 2 elements:

This one contains the Certificates/Singers of the Kernel-mode drivers

<SigningScenario Value="131" ID="ID_SIGNINGSCENARIO_DRIVERS_1" FriendlyName="Driver Signing Scenarios">

And this one contains the Certificates/Singers of the User-mode binaries

<SigningScenario Value="12" ID="ID_SIGNINGSCENARIO_WINDOWS" FriendlyName="User Mode Signing Scenarios">

Only the Value needs to stay the same. So, for Kernel-mode drivers it should always be 131 and for User-mode binaries it should always be 12, anything else can be customized.



Merging policies

Merge-cipolicy cmdlet does not include duplicates, neither duplicate rules nor rules with duplicate file hashes.



WDAC forces Allow-list architecture by nature

WDAC forces Allow-list architecture by nature, not deny-list architecture. An empty deployed policy allows nothing to run and leads to system failure. This is why Microsoft recommended blocklists include 2 Allow All rules with the Deny rules, that changes the WDAC policy's nature from being an Allow-list to being a Deny-list.



About Microsoft recommended block rules

Microsoft recommended block rules

From Microsoft recommended block rules document, copy the WDAC policy XML at the end (you might need to expand that section to view it), use a text editor like VS Code to edit it as recommended:

The blocklist policy includes "Allow all" rules for both kernel and user mode that make it safe to deploy as a standalone WDAC policy. We can even deploy it side-by-side with AllowMicrosoft policy, by keeping its allow rules in place. Refer to this document about how multiple base policies work.

"Only applications allowed by both policies (All Base policies) run without generating block events", that means even though the Microsoft recommended block rules have 2 allow all rules, they don't actually allow everything to run, because the same allow all rules don't exist in the default AllowMicrosoft policy, it only contains explicit allow rules.

On Windows versions 1903 and above, Microsoft recommends converting this policy to multiple policy format using the Set-CiPolicyIdInfo cmdlet with the -ResetPolicyId switch. Then, you can deploy it as a Base policy side-by-side with any other policies in your environment.

If merging into an existing policy that includes an explicit allowlist, you should first remove the two "Allow all" rules and their corresponding FileRuleRefs:

<Allow ID="ID_ALLOW_A_1" FriendlyName="Allow Kernel Drivers" FileName="*" />
<Allow ID="ID_ALLOW_A_2" FriendlyName="Allow User mode components" FileName="*" />
<FileRuleRef RuleID="ID_ALLOW_A_1" />
<FileRuleRef RuleID="ID_ALLOW_A_2" />

Microsoft recommended driver block rules


Citation: If you only manage Windows 11 22H2 systems (and above), then you don't need the recommended driver block rules in your WDAC policy. Otherwise, you should have the driver block rules in your policy. In either scenario, you should have the recommended user mode rules.


Citation: ISG does not include the recommended blocklist(s).


Citation: About deploying new Signed WDAC policies rebootlessly using CITool.




Miscellaneous

  • Set the hypervisor Code Integrity option for the WDAC policy XML file to Strict only after using Add-SignerRule cmdlet, because after running Add-SignerRule cmdlet, the <HvciOptions> resets to 0.

  • Using Signtool.exe with -fd certHash will default to the algorithm used on the signing certificate. For example, if the certificate has SHA512 hashing algorithm, the file that is being signed will use the same algorithm.

  • Sometimes New-CIPolicy Cmdlet creates 2 file rules for each driver file, such as .sys files. One of them is stored in Driver signing scenarios section under <SigningScenario Value="131" ID="ID_SIGNINGSCENARIO_DRIVERS_1" FriendlyName=""> and the other is stored in User mode signing scenarios section under <SigningScenario Value="12" ID="ID_SIGNINGSCENARIO_WINDOWS" FriendlyName="">. More info here

  • File rule levels and Cmdlets like New-CiPolicy only create rules for binaries such as .dll, .sys and .exe files.




Blocking individual Windows components

Blocking Microsoft Store

$Package = Get-AppXPackage -Name "Microsoft.WindowsStore"
$Rules += New-CIPolicyRule -Package $Package -Deny
New-CIPolicy -FilePath ".\store.xml" -Rules $Rules



File rule levels security

(For User Mode binaries only)

  • Hash (Best for any files, specially unsigned files)

  • FilePublisher (Best for Signed files)

  • SignedVersion (More permissive than FilePublisher, usable only for signed files)

The rest are less secure and more permissive than the 3 file rule levels mentioned above.

P.S FileName relies on the original filename for each binary, which can be modified.

Find more information in Microsoft Learn




How to remove flight signing certificates from default example policies

Removing these shouldn't cause any problem as long as you are using stable OS version

# Flight root Certs removal 
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_STORE_FLIGHT_ROOT"            
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_WINDOWS_FLIGHT_ROOT"
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_ELAM_FLIGHT"
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_HAL_FLIGHT"
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_WHQL_FLIGHT_SHA2"
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_WINDOWS_FLIGHT_ROOT_USER"
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_ELAM_FLIGHT_USER"
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_HAL_FLIGHT_USER"
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_WHQL_FLIGHT_SHA2_USER"
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_RT_FLIGHT"



How to remove WDAC policy Refresh tool certificates from default example policies

Starting with Windows 11 22H2, CITool is available in Windows by default and Refresh tool is no longer needed, so use the commands below to remove the certificates that allow that tool to be executed, their order of execution is important.

Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_SIGNER_MICROSOFT_REFRESH_POLICY"
Remove-CIPolicyRule -FilePath "DefaultWindows_Enforced.xml" -Id "ID_FILEATTRIB_REFRESH_POLICY"

Allowing questionable software in a WDAC policy

Questionable software such as pirated software are never recommended to be allowed to the WDAC policy because they are tampered with. Pirated software can have signed files too, but they are modified and as a result there is a mismatch between the file hash and the hash of the file saved in their digital signature. When such a mismatch exists for signed files, Authenticode reports the mismatch, and the file can't be allowed in a WDAC policy.

If you want to go through many files and see which ones have a mismatch between their file hash and signature hash, you can use the following PowerShell command:


Get-ChildItem -Recurse -Path "Path\To\a\Folder" -File | ForEach-Object {Get-AuthenticodeSignature -FilePath $_.FullName} | Where-Object {$_.Status -eq 'HashMismatch'}








C#


Clone this wiki locally