-
Notifications
You must be signed in to change notification settings - Fork 0
About Code Integrity Policy Signing
A Code Integrity policy, also known as Application Control for Business policy, is a binary file containing the rules that define which applications, files or drivers are allowed to run on the operating system. They can be cryptographically signed which adds extra benefits and protections against tampering. You can find more information about that here.
To sign a Code Integrity policy, you need a code signing certificate whose specifications is detailed in this article. You could use SignTool.exe from the Windows SDK to sign the policy but this article explores how to do it without the SignTool.exe program.
The operating system requires a specific OID for the content of the certificate. The OID is 1.3.6.1.4.1.311.79.1 and is specific to Code Integrity policies. The following C# code demonstrates the signing process:
byte[] fileContent = File.ReadAllBytes(filePath);
const string contentTypeOid = "1.3.6.1.4.1.311.79.1";
ContentInfo contentInfo = new(new Oid(contentTypeOid), fileContent);
SignedCms signedCms = new(contentInfo, false);
CmsSigner signer = new(signingCertificate);
signer.DigestAlgorithm = new Oid("Certificate's Hashing algorithm OID");
signer.IncludeOption = X509IncludeOption.EndCertOnly;
signer.SignerIdentifierType = SubjectIdentifierType.IssuerAndSerialNumber;
signedCms.ComputeSignature(signer, false);
byte[] signedBytes = signedCms.Encode();
File.Delete(filePath);
File.WriteAllBytes(filePath, signedBytes);The C# code above successfully signs the Code Integrity file, but the resulting file will not be recognized by the operating system after deployment. The reason is that the signed CIP file's certificate uses Cryptographic Message Syntax (CMS) version 3 while the operating system expects version 1.
.NET marks each individual signer as v3 if they use SubjectIdentifierType.SubjectKeyIdentifier, otherwise v1.
Additionally, .NET also marks the whole document as v3 if the document content type isn't 1.2.840.113549.1.7.1, or if any signer is v3, otherwise v1.
If we look at RFC5652, we see this part:
IF ((certificates is present) AND
(any certificates with a type of other are present)) OR
((crls is present) AND
(any crls with a type of other are present))
THEN version MUST be 5
ELSE
IF (certificates is present) AND
(any version 2 attribute certificates are present)
THEN version MUST be 4
ELSE
IF ((certificates is present) AND
(any version 1 attribute certificates are present)) OR
(any SignerInfo structures are version 3) OR
(encapContentInfo eContentType is other than id-data)
THEN version MUST be 3
ELSE version MUST be 1
With the important bits being:
(encapContentInfo eContentType is other than id-data)
Which makes it clear that if we use custom content type OID, the document should be marked as v3.
Since the version value of the CMS is outside the signed portion of the data block, we can find the 02 01 03 and replace it with 02 01 01 in order to make the CIP file usable by the operating system. The CMS version number is really just telling a reader "this uses a feature from the future". For example, if the reader only knows about CMS v3 but it sees SignedData.version == 5, it can just say: "nope, I won't know how to read that, let's stop now."
The strange thing about this requirement is that custom encapsulated data types seem to have come in version 3, so the OS is basically saying "I only understand v1, but I also understand that you are using a custom encapsulated data type, which is a V3 feature."
App Control Studio implements this workaround in its signing process so it can produce CIP files that are both signed and usable by the operating system.
Keep in mind that if you deploy a signed CIP file with CMS V3 certificate, the system will reject it and boot failure might occur.
If you prefer to use the SignTool.exe program, you can download it from NuGet or the Windows SDK.
The following command can be used to sign a CIP file with SignTool.exe:
$"sign /v /n \"{certCN}\" /p7 . /p7co 1.3.6.1.4.1.311.79.1 /fd certHash \"{ciPath.Name}\"";-
/nspecifies the certificate's common name (CN) in the certificate store, we supply it viacertCNvariable. -
/p7specifies the file should be signed using PKCS #7. -
/p7cospecifies the content type OID for the signed content. -
/fdspecifies the file digest algorithm to use, which should match the certificate's hashing algorithm. -
/venables verbose output. -
ciPath.Namevariable is the path to the CIP file to be signed.
Welcome to the Windows Security Studio Wiki. This documentation provides comprehensive guides, tools, and resources for hardening Windows systems using enterprise-grade security controls.
- Create AppControl Policy
- Create Supplemental Policy
- System Information
- Configure Policy Rule Options
- Policy Editor
- Simulation
- Allow New Apps
- Build New Certificate
- Create Policy From Event Logs
- Create Policy From MDE Advanced Hunting
- Create Deny Policy
- Merge App Control Policies
- Deploy App Control Policy
- Get Code Integrity Hashes
- Get Secure Policy Settings
- Update
- Sidebar
- Validate Policies
- View File Certificates
- Microsoft Graph
-
Protect
- Microsoft Security Baselines
- Microsoft Security Baselines Overrides
- Microsoft 365 Apps Security Baseline
- Microsoft Defender
- Attack Surface Reduction
- BitLocker
- Device Guard
- TLS Security
- Lock Screen
- User Account Control
- Windows Firewall
- Optional Windows Features
- Windows Networking
- Miscellaneous Configurations
- Windows Update
- Edge Browser
- Certificate Checking
- Country IP Blocking
- Non Admin Measures
- Group Policy Editor
- Manage Installed Apps
- File Reputation
- Audit Policies
- Cryptographic Bill of Materials
- Intune
- Configuration Service Provider (CSP)
- Introduction
- How To Generate Audit Logs via App Control Policies
- How To Create an App Control Supplemental Policy
- How to Create an App Control Deny Policy
- The Strength of Signed App Control Policies
- How To Upload App Control Policies To Intune Using App Control Studio
- How To Create and Maintain Strict Kernel‐Mode App Control Policy
- App Control Notes
- How to use Windows Server to Create App Control Code Signing Certificate
- Fast and Automatic Microsoft Recommended Driver Block Rules updates
- App Control policy for BYOVD Kernel mode only protection
- EKUs in App Control for Business Policies
- App Control Rule Levels Comparison and Guide
- Script Enforcement and PowerShell Constrained Language Mode in App Control Policies
- How to Use Microsoft Defender for Endpoint Advanced Hunting With App Control
- App Control Frequently Asked Questions (FAQs)
- System Integrity Policy Transformations | XML to CIP and Back
- About Code Integrity Policy Signing
- DISM API in Packaged Apps and the Mechanics of Child Process Identity
- How To Install Microsoft Store Apps Completely Offline
- Create Bootable USB flash drive with no 3rd party tools
- Event Viewer
- Group Policy
- How to compact your OS and free up extra space
- Hyper V
- Git GitHub Desktop and Mandatory ASLR
- Signed and Verified commits with GitHub desktop
- About TLS, DNS, Encryption and OPSEC concepts
- Things to do when clean installing Windows
- Comparison of security benchmarks
- BitLocker, TPM and Pluton | What Are They and How Do They Work
- How to Detect Changes in User and Local Machine Certificate Stores in Real Time Using PowerShell
- Cloning Personal and Enterprise Repositories Using GitHub Desktop
- Only a Small Portion of The Windows OS Security Apparatus
- Rethinking Trust: Advanced Security Measures for High‐Stakes Systems
- Clean Source principle, Azure and Privileged Access Workstations
- How to Securely Connect to Azure VMs and Use RDP
- Basic PowerShell tricks and notes
- Basic PowerShell tricks and notes Part 2
- Basic PowerShell tricks and notes Part 3
- Basic PowerShell tricks and notes Part 4
- Basic PowerShell tricks and notes Part 5
- How To Access All Stream Outputs From Thread Jobs In PowerShell In Real Time
- PowerShell Best Practices To Follow When Coding
- How To Asynchronously Access All Stream Outputs From Background Jobs In PowerShell
- Powershell Dynamic Parameters and How to Add Them to the Get‐Help Syntax
- RunSpaces In PowerShell
- How To Use Reflection And Prevent Using Internal & Private C# Methods in PowerShell