The new File Path rules in Windows Defender Application Control (WDAC) allow EXE and DLL files in the path, but not SYS, or MSI or script files. This is curious and, as far as I know, undocumented. And it means that we cannot simply allow all files in C:\Windows. If we do that, the system will not boot because the drivers will still be blocked. We will need to use another method to add drivers to a WDAC policy.
There are actually two types of file path rule, and no good way to identify them by different names. One is produced with the New-CIPolicy cmdlet, using the –Level parameter and a value of FilePath. The other is produced by generating an array of rules, using the New-CIPolicyRule cmdlet, then creating a new policy with New-CIPolicy and the –Rules parameter. The two methods handle drivers (SYS files) differently.
The first method is produced by a scan. It results in a collection of FileRules in the XML, with each rule being of the FilePath type, and having the fully qualified path and name of the file. I have edited the file to show only the first three drivers in C:\Windows\System32\drivers.
<?xml version="1.0" encoding="utf-8"?> <SiPolicy xmlns="urn:schemas-microsoft-com:sipolicy"> <VersionEx>10.0.0.0</VersionEx> <PlatformID>{2E07F7E4-194C-4D20-B7C9-6F44A6C5A234}</PlatformID> <Rules> <Rule> <Option>Enabled:Unsigned System Integrity Policy</Option> </Rule> <Rule> <Option>Enabled:Audit Mode</Option> </Rule> <Rule> <Option>Enabled:Advanced Boot Options Menu</Option> </Rule> <Rule> <Option>Required:Enforce Store Applications</Option> </Rule> <Rule> <Option>Enabled:UMCI</Option> </Rule> </Rules> <!--EKUS--> <EKUs /> <!--File Rules--> <FileRules> <Allow ID="ID_ALLOW_A_1" FriendlyName="C:\Windows\System32\drivers\1394ohci.sys FileRule" MinimumFileVersion="0.0.0.0" FilePath="C:\Windows\System32\drivers\1394ohci.sys" /> <Allow ID="ID_ALLOW_A_3" FriendlyName="C:\Windows\System32\drivers\3ware.sys FileRule" MinimumFileVersion="0.0.0.0" FilePath="C:\Windows\System32\drivers\3ware.sys" /> <Allow ID="ID_ALLOW_A_5" FriendlyName="C:\Windows\System32\drivers\acpi.sys FileRule" MinimumFileVersion="0.0.0.0" FilePath="C:\Windows\System32\drivers\acpi.sys" /> <Allow ID="ID_ALLOW_A_2" FriendlyName="C:\Windows\System32\drivers\1394ohci.sys FileRule" MinimumFileVersion="0.0.0.0" FilePath="C:\Windows\System32\drivers\1394ohci.sys" /> <Allow ID="ID_ALLOW_A_4" FriendlyName="C:\Windows\System32\drivers\3ware.sys FileRule" MinimumFileVersion="0.0.0.0" FilePath="C:\Windows\System32\drivers\3ware.sys" /> <Allow ID="ID_ALLOW_A_6" FriendlyName="C:\Windows\System32\drivers\acpi.sys FileRule" MinimumFileVersion="0.0.0.0" FilePath="C:\Windows\System32\drivers\acpi.sys" /> </FileRules> <!--Signers--> <Signers /> <!--Driver Signing Scenarios--> <SigningScenarios> <SigningScenario Value="131" ID="ID_SIGNINGSCENARIO_DRIVERS_1" FriendlyName="Auto generated policy on 11-27-2019"> <ProductSigners> <FileRulesRef> <FileRuleRef RuleID="ID_ALLOW_A_1" /> <FileRuleRef RuleID="ID_ALLOW_A_3" /> <FileRuleRef RuleID="ID_ALLOW_A_5" /> </FileRulesRef> </ProductSigners> </SigningScenario> <SigningScenario Value="12" ID="ID_SIGNINGSCENARIO_WINDOWS" FriendlyName="Auto generated policy on 11-27-2019"> <ProductSigners> <FileRulesRef> <FileRuleRef RuleID="ID_ALLOW_A_2" /> <FileRuleRef RuleID="ID_ALLOW_A_4" /> <FileRuleRef RuleID="ID_ALLOW_A_6" /> </FileRulesRef> </ProductSigners> </SigningScenario> </SigningScenarios> <UpdatePolicySigners /> <CiSigners /> <HvciOptions>0</HvciOptions> <PolicyTypeID>{A244370E-44C9-4C06-B551-F6016E563076}</PolicyTypeID> </SiPolicy>
You can see that:
- Each driver is listed in two file rules
- For each driver, one of the file rules is used in the Signing Scenario ID=”ID_SIGNINGSCENARIO_DRIVERS_1″ and the other is used in the Signing Scenario ID=”ID_SIGNINGSCENARIO_WINDOWS”
This policy catches all types of files, including EXE, DLL, SYS, MSI, PowerShell scripts and modules. The only files it excludes are files in user-writeable folders.
The trouble with a FilePath level is that it does not allow any new files at all. You would not even be able to run an update because, even if an updated file had the same name, the file delivering the update would be new.
The second method also results in a collection of FileRules in the XML, also of the FilePath type, but this time each rule is a path only, with no file name.
<?xml version="1.0" encoding="utf-8"?> <SiPolicy xmlns="urn:schemas-microsoft-com:sipolicy"> <VersionEx>10.0.0.0</VersionEx> <PlatformID>{2E07F7E4-194C-4D20-B7C9-6F44A6C5A234}</PlatformID> <Rules> <Rule> <Option>Enabled:Unsigned System Integrity Policy</Option> </Rule> <Rule> <Option>Enabled:Audit Mode</Option> </Rule> <Rule> <Option>Enabled:Advanced Boot Options Menu</Option> </Rule> <Rule> <Option>Required:Enforce Store Applications</Option> </Rule> <Rule> <Option>Enabled:UMCI</Option> </Rule> </Rules> <!--EKUS--> <EKUs /> <!--File Rules--> <FileRules> <Allow ID="ID_ALLOW_A_1" FriendlyName="C:\Windows\* FileRule" MinimumFileVersion="0.0.0.0" FilePath="C:\Windows\*" /> <Allow ID="ID_ALLOW_A_2" FriendlyName="C:\Program Files\* FileRule" MinimumFileVersion="0.0.0.0" FilePath="C:\Program Files\*" /> <Allow ID="ID_ALLOW_A_3" FriendlyName="C:\Program Files (x86)\* FileRule" MinimumFileVersion="0.0.0.0" FilePath="C:\Program Files (x86)\*" /> </FileRules> <!--Signers--> <Signers /> <!--Driver Signing Scenarios--> <SigningScenarios> <SigningScenario Value="131" ID="ID_SIGNINGSCENARIO_DRIVERS_1" FriendlyName="Auto generated policy on 11-16-2019"> <ProductSigners /> </SigningScenario> <SigningScenario Value="12" ID="ID_SIGNINGSCENARIO_WINDOWS" FriendlyName="Auto generated policy on 11-16-2019"> <ProductSigners> <FileRulesRef> <FileRuleRef RuleID="ID_ALLOW_A_1" /> <FileRuleRef RuleID="ID_ALLOW_A_2" /> <FileRuleRef RuleID="ID_ALLOW_A_3" /> </FileRulesRef> </ProductSigners> </SigningScenario> </SigningScenarios> <UpdatePolicySigners /> <CiSigners /> <HvciOptions>0</HvciOptions> <PolicyTypeID>{A244370E-44C9-4C06-B551-F6016E563076}</PolicyTypeID> </SiPolicy>
This method allows unspecified files to run provided they are in the defined path. It also has the same Runtime FilePath Rule Protection as the first method. But it does not allow SYS, MSI or PowerShell files to run.
You can see that the policy has almost exactly the same format for the FileRules collection. But the Signing Scenarios section is different. This time there are no rules in the Drivers scenario; only in the Windows (user-mode) scenario.
When you apply this policy, all the SYS driver files are denied. If the policy is in Enforced mode, the system will be unbootable.
I have tried editing the XML manually, to add the same paths to the drivers signing scenario, but this also does not work.
This is curious because, in one of the Microsoft example policies, a wildcard is used for both kernel-mode and user-mode files. This is the Allow All policy at C:\Windows\schemas\CodeIntegrity\ExamplePolicies\AllowAll.xml.
<?xml version="1.0" encoding="utf-8"?> <SiPolicy xmlns="urn:schemas-microsoft-com:sipolicy"> <VersionEx>1.0.0.0</VersionEx> <PolicyTypeID>{A244370E-44C9-4C06-B551-F6016E563076}</PolicyTypeID> <PlatformID>{2E07F7E4-194C-4D20-B7C9-6F44A6C5A234}</PlatformID> <Rules> <Rule> <Option>Enabled:Unsigned System Integrity Policy</Option> </Rule> <Rule> <Option>Enabled:Advanced Boot Options Menu</Option> </Rule> <Rule> <Option>Enabled:UMCI</Option> </Rule> <Rule> <Option>Enabled:Update Policy No Reboot</Option> </Rule> </Rules> <!--EKUS--> <EKUs /> <!--File Rules--> <FileRules> <Allow ID="ID_ALLOW_A_1" FileName="*" /> <Allow ID="ID_ALLOW_A_2" FileName="*" /> </FileRules> <!--Signers--> <Signers /> <!--Driver Signing Scenarios--> <SigningScenarios> <SigningScenario Value="131" ID="ID_SIGNINGSCENARIO_DRIVERS_1" FriendlyName="Auto generated policy on 08-17-2015"> <ProductSigners> <FileRulesRef> <FileRuleRef RuleID="ID_ALLOW_A_1" /> </FileRulesRef> </ProductSigners> </SigningScenario> <SigningScenario Value="12" ID="ID_SIGNINGSCENARIO_WINDOWS" FriendlyName="Auto generated policy on 08-17-2015"> <ProductSigners> <FileRulesRef> <FileRuleRef RuleID="ID_ALLOW_A_2" /> </FileRulesRef> </ProductSigners> </SigningScenario> </SigningScenarios> <UpdatePolicySigners /> <CiSigners /> <HvciOptions>0</HvciOptions> <Settings> <Setting Provider="PolicyInfo" Key="Information" ValueName="Name"> <Value> <String>AllowAll</String> </Value> </Setting> <Setting Provider="PolicyInfo" Key="Information" ValueName="Id"> <Value> <String>041417</String> </Value> </Setting> </Settings> </SiPolicy>
I think this must be a feature or a defect in the handling of the FilePath rule. I can’t think of a reason why a wildcard should be permitted in the FileName, but not in the FilePath.
Whatever the reason, we need to find a way to add SYS files to a policy. The obvious way to do this is by certificate, since we only want to allow signed drivers in any event. To achieve this, we need to perform a scan of the C:\Windows folder, at the Publisher level. We can use Option 2 Required:WHQL, to ensure that drivers are Windows Hardware Quality Labs (WHQL) signed.
This might be an opportunity to use the new Base and Supplemental policies in Windows 10 1903. A base policy with Publisher signers would allow the system to boot. It would also allow utilities from the same publishers (e.g. Microsoft, Dell, HP, Lenovo) to run. Then, a supplemental policy using FilePath rules could allow all applications in Program Files and Windows, whether signed or not.
We would just be left to deal with MSI’s, PowerShell scripts, and files in user-writeable locations.