HI folks, in this post, I continue my blog series about Application Control for Business and take a closer look at how to work with signed policies. In the previous post, I showed you how to create and apply a policy for fully managed devices. Application control for business is one of the best preventive measures against ransomware.
However, as you have seen, policies can easily applied and removed with privileged local administrator rights again. While unsigned policies are fine for testing and lab environments, signed policies are required for secure production environments. Otherwise it could be an other potential attack surface, if your policies not protected against tampering.
For this reason, before you apply policies, you should sign them with a code signature certificate. While doing this provides the highest level of protection, it makes it extremely difficult to remove a policy from your devices again.
You must consider the possible danger with using signed policies in your environment and I can only suggest this, if you know what are you doing. If someone delete a sign policy from the EFI partition of your windows machine after it was already applied successfully, you get trouble to start the windows. Each attempt to boot without a signed policy after it has been applied, will be failed until a proper signed replacement policy is manually applied.

Use signed policies to protect App Control for Business against tampering | Microsoft Learn
Before you attempt to deploy a signed policy, you should first deploy an unsigned version of the policy to uncover any issues with the policy rules.
Previous Blog Posts:
- Mastering App Control for Business | Part 1: Introduction & Key Concept
- Mastering App Control for Business | Part 2: Policy Templates & Rule Options
- Mastering App Control for Business | Part 3: Application ID Tagging Policies & managed Installer
- Mastering App Control for Business | Part 4: How to create a “starter base policy” for lightly managed devices
- Mastering App Control for Business | Part 5: Create a base policy for fully managed devices
Requirements
First, you need code signing certificate to be able to sign App Control for Business policies. Getting one is possible on various ways:
- issue one certificate from your internal enterprise private key infrastructure
- purchase a code signing certificate from one of the Microsoft Trusted Root Program participants
- use a self-signed certificate (for testing only)
Second, all your device must have UEFI and secure boot enabled.
Third, for the signing, you need the SignTool.exe tool on your workstation, which is part of the Windows Software Development Kit (SDK). After you installed the SDK, you find the binary in the \Bin folder of the Windows SDK installation. For example: C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe

Note: If you want to create a self-signed code signing certificate for testing, you can use the following PowerShell code:
# Parameters
$certName = "CodeSigningCertTest"
$certPath = "Cert:\CurrentUser\My"
$validYears = 1
# Create self-signed certificate
$cert = New-SelfSignedCertificate `
-Subject "CN=$certName" `
-Type CodeSigningCert `
-CertStoreLocation $certPath `
-KeyUsage DigitalSignature `
-KeyExportPolicy Exportable `
-NotAfter (Get-Date).AddYears($validYears)
-HashAlgorithm "SHA256" `
-KeyLength 4096
# Export the certificate and private key as PFX
$pfxPath = "$env:USERPROFILE\Desktop\$certName.pfx"
$certPassword = Read-Host -Prompt "Enter a password for the PFX-Container" -AsSecureString
Export-PfxCertificate `
-Cert $cert `
-FilePath $pfxPath `
-Password $certPassword
# Export certificate as CRT (DER-Format)
$crtPath = "$env:USERPROFILE\Desktop\$certName.crt"
Export-Certificate `
-Cert $cert `
-FilePath $crtPath
Write-Host "Certificate was created and exported with private key to: $pfxPath"
Write-Host "Certificate was exported to: $crtPath"
Once, we have the code signing certificate in the User Certificate store on your development system and you haven’t uses the script snippet above for a self-signed certificate, you have to export the certificate and PFX-container. It is important to keep these 2 files in a safe place, such as a hardware security module, so if you development system crashed or deleted, you will be able to continue using the same certificate to sign further Application Control for Business policies.
The PFX-Container is very important because it contains the public and private key of the certificate. Anyone who has access to this PFX-Container can disable your deployed and signed Application Control for Business policies.
All device on which signed policies are applied must trust the code signing certificate (trusted publisher – machine store).

Signing the policy
Preparation
As I mentioned above, you need a code signing certificate for signing. Because I don’t have purchased one and I don’t implemented a private key infrastructure in my lab environment yet, I decided to create my own self-signed certificate for this testing only.

The next steps are based on the policy file which I created in the previous post: Mastering App Control for Business | Part 5: Create a base policy for fully managed devices – ctrlshiftenter.cloud
Preparation-Steps (cmdline)
Microsoft recommends to enable the rule options 9 – Enabled:Advanced Boot Options Menu and 0 – Enabled:Boot Audit on Failure to leave troubleshooting options available. If you haven’t enabled these options, failures could prevent your system from booting, leaving you with no chance to fix the problems.
If you unsure whether the options are set to enable, you can execute the following commands to enable both rule options:
Set-RuleOption -FilePath C:\temp\MyBigBusiness_v10.0.5.1.xml -Option 9
Set-RuleOption -FilePath C:\temp\MyBigBusiness_v10.0.5.1.xml -Option 10
Next, we have to remove the rule option 6 – Enabled:Unsigned System Integrity Policy to enforce the signing requirement.
Set-RuleOption -FilePath C:\temp\MyBigBusiness_v10.0.5.1.xml -Option 6 -Delete
If your Application Control for Business policy doesn’t already include an <UpdatePolicySigner> rule for our signing certificate (it shouldn’t, we created the policy from scratch) you must add it.

You can user the Add-SignerRule command to create an <UpdatePolicySigner> rule from our code signing certificate.
Note: If your policy doesn't allow Supplemental policies, you should omit the -Supplemental switch from the following command:
Add-SignerRule -FilePath C:\temp\MyBigBusinessFromWizard_v10.0.5.1.xml -CertificatePath $env:Userprofile\Desktop\CodeSigningCertTest.crt -Update -Supplemental
Add-SignerRule (ConfigCI) | Microsoft Learn
Afterwards, you will notice a <UpdatePolicySigner> entry with a reference to the signing certificate.


Now, we increase the policy version from 10.0.5.1 to 10.0.5.2.
Set-CIPolicyVersion -FilePath C:\temp\MyBigBusiness_v10.0.5.1.xml -Version 10.0.5.2
Rename-Item -Path C:\temp\MyBigBusiness_v10.0.5.1.xml -NewName C:\temp\MyBigBusiness_v10.0.5.2.xml
Preparations-Steps (App Control Wizard)
The same procedure can be done with the App Control Wizard.



Afterwards, you have to add a signer rule via commandline.
Note: If your policy doesn't allow Supplemental policies, you should omit the -Supplemental switch from the following command:
Add-SignerRule -FilePath C:\temp\MyBigBusinessFromWizard_v10.0.5.2.xml -CertificatePath $env:Userprofile\Desktop\CodeSigningCertTest.crt -Update -Supplemental
Add-SignerRule (ConfigCI) | Microsoft Learn
Afterwards, you will notice a <UpdatePolicySigner> entry with a reference to the signing certificate.


Convert to binary and sign the policy with SignTool.exe
If you haven’t imported the certificate, public and private key into the current user`s personal certificate store, you have to do this first.

Afterwards, we have to convert the policy .xml file to a binary .cip file.
$PolicyID = Set-CIPolicyIdInfo -FilePath "C:\temp\MyBigBusinessFromWizard_v10.0.5.2.xml" -ResetPolicyID
$PolicyID = $PolicyID.Substring(11)
$PolicyBIN = "C:\temp\" + $PolicyID + ".cip"
ConvertFrom-CIPolicy -XmlFilePath "C:\temp\MyBigBusinessFromWizard_v10.0.5.2.xml" -BinaryFilePath $PolicyBIN

Next, we have to sign the policy binary file with our code signing certificate. To do this, we use the SignTool.exe with the following parameter set:
"C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe " sign -v -n "CodeSigningCertTest" -p7 . -p7co 1.3.6.1.4.1.311.79.1 -fd sha256 "C:\temp\{fe1dbc91-5bb7-45f5-9164-299bdff9694d}.cip"
What this command does:
It digitally signs a Application Control for Business policy file using our code signing certificate.
CIP-File
: This is the file you want to sign — usually a.cip
file (your policy).
sign
: This tellssigntool
to sign a file.-v
: Shows detailed output while signing (verbose mode).-n "CodeSigningCertTest"
: Uses a certificate from the user’s personal certification store with the subject name “CodeSigningCertTest”.-p7 .
: Saves the signature in PKCS #7 format in the current folder.-p7co 1.3.6.1.4.1.311.79.1
: Adds a special identifier (OID) that tells Windows this signature is for a Application Control for Business policy.-fd sha256
: Uses SHA256 as the hashing algorithm.

If the command runs successfully, you notice an additional policy file with .p7 file extension in your working dir. You have to rename it to {GUID}.cip

Verify the signed policy
You can use certutil.exe or PowerShell to verify the signed file. Review the output to confirm the signature algorithm as described in the Warning at the top of this article.
certutil.exe -asn “C:\temp\done{fe1dbc91-5bb7-45f5-9164-299bdff9694d}.cip.p7” returns you the signed file.
If you run the following PowerShell commands, you get some additional information about the signature.
$CIPolicyBin = "C:\temp\done\{fe1dbc91-5bb7-45f5-9164-299bdff9694d}.cip"
Add-Type -AssemblyName 'System.Security'
$SignedCryptoMsgSyntax = New-Object -TypeName System.Security.Cryptography.Pkcs.SignedCms
$SignedCryptoMsgSyntax.Decode([System.IO.File]::ReadAllBytes($CIPolicyBin))
$SignedCryptoMsgSyntax.Certificates | Format-List -Property *

Apply the signed policy via CiTool
Since Windows 11 22H2 it is very easy to apply policies locally via CiTool.
CiTool --update-policy "C:\temp\done\{fe1dbc91-5bb7-45f5-9164-299bdff9694d}.cip"
After you have applied the signed policy, you can validate the applying via CiTool.
CiTool --list-policies

As you can see in the screenshot above, our signed policy ist currently enforced. Because we are using UEFI secure boot, the anti-tampering protection of the signed policy takes effect and starts protecting Application Control for Business policies against any tampering. Finally, we need to reboot the device one more time and hope there won’t be any boot failures 😛 .
Applying signed policies without restarting the system after the deployment, is the same as deploying unsigned policies. At this point, signed policies can be easily removed just like an unsigned policy.
What happens if someone tries to delete a signed policy from file system?
Signed Application Control for Business policies are built to protect themselves. Even against malicious administrators with full access to the operating system. Let’s look at what happens if someone tries to remove a deployed signed policy by force.
Deleting the policy from the windows file system
If someone deletes the .cip
policy file from the following locations:
For multi-policy format (common with multiple active policies):
C:\Windows\System32\CodeIntegrity\CiPolicies\Active\{PolicyId}.cip
For single-policy format:
C:\Windows\System32\CodeIntegrity\SiPolicy.p7b
and restarts the system, nothing will happen.
- The policy will still be active.
- Enforcement will still be shown in System Information (msinfo32.exe).
This is by design. It protects against rogue admins trying to bypass security after the device has booted.
Deleting the policy from the EFI Partition
If someone goes one step further and deletes the policy file from the EFI system partition:
\EFI\Microsoft\Boot\CiPolicies\Active
nothing will happen immediately. But after the next reboot, the system will fail to boot. This is a built-in protection of signed policies + Secure Boot.

Once the EFI copy is gone, Secure Boot detects the missing signature and prevents the OS from starting.


To recover from this situation, someone would need to:
- Enter the UEFI firmware settings,
- and disable Secure Boot manually.
And now we come to one of my favorite topic, which I tell all administrators and customers over and over again: Protect the UEFI/BIOS with a password.
If you have done your homework, there are no additional attack surfaces, if someone could delete the policies from EFI partition.
Why attackers would fail?
- UEFI is password protected (recommended):
- An attacker cannot enter the UEFI settings without the firmware password.
- Combined with BitLocker and other protections, the device becomes extremely secure. Even against physical attacks.
- UEFI isn’t protected with a password:
- The attacker may disable Secure Boot or flash the firmware.
- But since the disk is BitLocker-protected, a recovery key is required to boot.
- They’ll need 48-digit recovery keys for the OS drive and any other encrypted drives.
Remove a signed policy
Removing a signed Application Control for Business policy is not as simple as deleting a file. Windows protects these policies – especially when they are signed and enforced.
But don’t worry – there is a clear step-by-step process to remove a signed policy safely.
Create a Replacement Policy
Before you can remove a signed policy, you need to replace it with a special policy that allows unsigned policies again.
Make sure the new replacement policy:
- Has Rule Option 6 enabled:
Enabled: Unsigned System Integrity Policy
- Uses the same Policy ID (GUID) as the old one
- Has a higher or equal version number than the old policy
- Contains the
<UpdatePolicySigners>
section with the same code signature certificate thumbprint. - Is signed with a certificate that was listed in the
<UpdatePolicySigners>
of the original policy
Stop the old Policy from being re-deployed
If the old signed policy was deployed using:
- Group Policy (GPO)
- Intune
- or another method
You must disable or unlink that deployment first, so it doesn’t come back after reboot.
Deploy the Replacement Policy
Now deploy your replacement policy using the same method you used before. For example via GPO, Intune or locally via CiTool.
Restart the device!
Remove the Replacement Policy
Use the CiTool.exe
command to remove the now unsigned policy:
CiTool.exe --remove-policy "{YourPolicyId-GUID}"
Restart the device!
Delete the policy files from disk
Now that the policy is inactive, you can delete the remaining policy files from the system.
For multi-policy format (common with multiple active policies):
<EFI Partition>\Microsoft\Boot\CiPolicies\Active\{PolicyId}.cip
C:\Windows\System32\CodeIntegrity\CiPolicies\Active\{PolicyId}.cip
For single-policy format:
<EFI Partition>\Microsoft\Boot\SiPolicy.p7b
C:\Windows\System32\CodeIntegrity\SiPolicy.p7b
Restart the device!