Recently, I've had a user not being able to install his setup created with Advanced Installer on a machine where the Code Integrity (Device Guard) policy was enabled.
In today's article, since I familiarized myself with the topic, I will try to explain what this policy is and how to configure it as such you will be able to install the setup created with Advanced Installer there.
Device Guard is a policy that allows organizations to lock down devices in a way that provides advanced malware protection against new and unknown malware variants by blocking anything other than trusted apps—which are apps that are signed by specific software vendors, the Windows Store, or even your own organization.
Now, the issue our users encountered is the fact that some resources from the project (such as temporary fles, custom actions, etc.) are signed with our own certificate, while the resources from the setup (e.g. the customer files) are signed with his own certificate.
As previously mentioned, the solution would be to add both our certificate and the user's certificate to the policy, so that the setup becomes "trustworthy".
Turning on this policy is quite easy as you'll see in the following steps. However, it's the configuration which is a bit more complicated at it requires some PowerShell knowledge.
Here's how to enable the policy:
1. open the Group Policy Editor
2. navigate to "Computer Configuration" --> "Administrative Templates" --> "System" --> "Device Guard"
If you double click on the policy, you will see that it can be easily enabled:
However, it requires as input the path to the configuration file (as I previously explained).
Below we'll be discussing how to create a Device Guard policy. As previously mentioned, for this we will need PowerShell for which I will try to explain each cmdlet.
Note: Of course, for this, please use a Virtual Machine
Note: Open a PowerShell window, create a "temp" folder (or whatever name you want) under C:\ and navigate there in PowerShell.
1. first of all, we need to scan a reference system to create an XML policy file. To do so, we will use the "New-CIPolicy" cmdlet.
Code: Select all
New-CIPolicy -FilePath ".\policysys32.xml" -Level Publisher -UserPEs -ScanPath "c:\windows\system32"
Explanation:
We restricted New-CIPolicy to scanning only the system32 folder. This should capture most files that Windows needs to boot and run. We will scan the Program Files folder separately, which will generate a second XML file, policyprogfiles.xml, that we can merge with policysys32.xml.The New-CIPolicy cmdlet creates a new Code Integrity (CI) policy, which is a set of rules that define what code is allowed to run on a system. The -FilePath parameter specifies the path to the file where the policy will be saved. The -Level parameter specifies the level of the policy, which can be either "Publisher" or "System". The "Publisher" level allows code from trusted publishers to run, while the "System" level allows only code that is signed by Microsoft to run. The -UserPEs parameter specifies that the policy should apply to user-mode Portable Executable (PE) files, which are executable files that run in user mode, rather than kernel mode. The -ScanPath parameter specifies the path to a directory that will be scanned for executables to include in the policy.
2. we will repeat step 1), this time for the Program Files folder
Code: Select all
New-CIPolicy -FilePath ".\policyprogfiles.xml" -Level Publisher -UserPEs -ScanPath "c:\program files" -NoScript
Code: Select all
Merge-CIPolicy -PolicyPaths ".\policysys32.xml", ".\policyprogfiles.xml" -OutputFilePath ".\policyfinal.xml"
When a Code Integrity (CI) policy is created in audit mode, it is used to monitor and log any violations of the policy, but it does NOT block the execution of code that violates the policy. This is useful for testing and debugging purposes, as it allows you to see what code would be blocked if the policy were enforced.
Code: Select all
Set-RuleOption -FilePath ".\policyfinal.xml" -Option 3 -Delete
Code: Select all
ConvertFrom-CIPolicy ".\policyfinal.xml" ".\DeviceGuardPolicy.bin"
Let's see how this looks like in practice, shall we?
Let's click "Apply" then "Ok"
Note: We must reboot the machine in order for the policy to take effect.
After the reboot, let's try to launch the setup created with Advanced Installer (which should be signed). Upon launching the MSI, this should be the encountered message:
Now about the "fix", as mentioned at the start of this article, we should add the certificates to be "trusted" by the policy. To do so, considering the points above (1 to 4), we would have a point 3.5 (between 3 and 4) where we would do that.
Code: Select all
Add-SignerRule -FilePath ".\policyfinal.xml" -CertificatePath "C:\Users\Catalin\Desktop\MyKey.pfx" -Kernel -User -Update
We would need to do that for both the certificate you are using to sign the setup and our certificate.This cmdlet allows you to specify a code signing certificate and specify that any code signed with that certificate is allowed to run on the system. This can be useful for allowing code from a trusted publisher to run, while still blocking code that is not signed or is signed by an untrusted publisher.
We then need to reconvert the XML file to BIN, add it to the policy and reboot the machine once again.
After the reboot, you should now be able to install the setup created with Advanced Installer.
Hope this helps!
Best regards and a Merry Christmas,
Catalin