How to delete a single Applocker rule

  • Context:

A colleague of mine was working on Applocker rules and the installer he was working on was so badly designed that we thought it would easier to restore the worst and most dangerous default rule named “*” for the built-in administrators.

If you restore this evil rule, you cannot and should not leave it there. You also have to delete it after it has been used to install successfully that ugly software.

  • Problem:

I started looking around using my google fu but only found the following web page from Microsoft named delete-an-applocker-rule that tells you actually how to clear *all* the rules. It’s a dead end and really not what we want 😦

  • Solution:

Instead I wrote the following function. Before looking at its code, let me tell you the following:

If you specify the first parameter to indicate what type of rules you want to delete, a Exe, Script, Msi, Appx, Dll, it will be used in the dynamic parameters block to enumerate all rules names found for this type.

Let’s see this in action:

You may also notice in the body of the function that the XML representation of Applocker rules never touches the disk. The rule is removed from the XML and its result is directly merged/reimported.

The function specifies a ‘high’ ConfirmImpact and SupportsShouldProcess because it’s destructive. There’s no backup of the rules or the rule being removed.

Last but not least, the rule is deleted but the group policies (GPO) are not refreshed. You’ll see its impact once the GPO have been reapplied.

Here’s the function:

#Requires -RunAsAdministrator
#Requires -Version 3.0
#Requires -PSEdition Desktop
Function Remove-LocalApplockerPolicyRule {
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
Param(
[ValidateSet('Exe','Script','Msi','Appx','Dll')]
[Parameter(Mandatory)]
[String]$Type
)
DynamicParam {
$Dictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary
#region helper function
Function New-ParameterAttributCollection {
[CmdletBinding()]
Param(
[Switch]$Mandatory,
[Switch]$ValueFromPipeline,
[Switch]$ValueFromPipelineByPropertyName,
[String]$ParameterSetName,
[Parameter()]
[ValidateSet(
'Arguments','Count','Drive','EnumeratedArguments','Length','NotNull',
'NotNullOrEmpty','Pattern','Range','Script','Set','UserDrive'
)][string]$ValidateType,
[Parameter()]
$ValidationContent
)
Begin {
}Process {
$c = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
$a = New-Object System.Management.Automation.ParameterAttribute
if ($Mandatory) {
$a.Mandatory = $true
}
if ($ValueFromPipeline) {
$a.ValueFromPipeline = $true
}
if ($ValueFromPipelineByPropertyName) {
$a.ValueFromPipelineByPropertyName=$true
}
if ($ParameterSetName) {
$a.ParameterSetName = $ParameterSetName
}
$c.Add($a)
if ($ValidateType -and $ValidationContent) {
try {
$c.Add((New-Object "System.Management.Automation.Validate$($ValidateType)Attribute"(
$ValidationContent
)))
} catch {
Throw $_
}
}
$c
}
End {}
}
#endregion
try {
$LocalApplockerPolicyXml = [xml](Get-AppLockerPolicy -Local -Xml -ErrorAction Stop)
} catch {
Throw 'Failed to read the local Applocker policy into XML'
}
#region param Rule
$Dictionary.Add(
'Rule',
(New-Object System.Management.Automation.RuntimeDefinedParameter(
'Rule',
[string],
(New-ParameterAttributCollection -Mandatory -ValidateType Set -ValidationContent (
$LocalApplockerPolicyXml.SelectNodes("/AppLockerPolicy/RuleCollection[@Type='$($PSBoundParameters['Type'])']").ChildNodes| ForEach-Object { $_.Name }
))
))
)
$Dictionary
}
Begin {
}
Process {
Write-Verbose -Message "Dealing with Rule Collection type: $($PSBoundParameters['Type'])"
Write-Verbose -Message "Dealing with Rule Name: $($PSBoundParameters['Rule'])"
# Select node
$n = $LocalApplockerPolicyXml.SelectNodes("/AppLockerPolicy/RuleCollection[@Type='$($PSBoundParameters['Type'])']").ChildNodes |
Where { $_.Name -eq "$($PSBoundParameters['Rule'])" }
if ($pscmdlet.ShouldProcess("$($n.OuterXml)", 'Remove rule')) {
try {
# Remove rule from xml
$null = $LocalApplockerPolicyXml.SelectNodes("/AppLockerPolicy/RuleCollection[@Type='$($PSBoundParameters['Type'])']").RemoveChild($n)
# Re-apply/import all rules except the removed rule
[Microsoft.Security.ApplicationId.PolicyManagement.PolicyModel.AppLockerPolicy]::FromXml($LocalApplockerPolicyXml.outerXML) |
Set-AppLockerPolicy -ErrorAction Stop
Write-Verbose -Message 'Successfully removed rule, a group policies refresh is required to see the impact of the removed rule'
} catch {
Throw "Something went wrong while trying to remove the applocker rule: $($_.Exception.Message)"
}
}
}
End {
}
} # endof Remove-LocalApplockerPolicyRule
Export-ModuleMember -Function 'Remove-LocalApplockerPolicyRule'

1 thought on “How to delete a single Applocker rule

  1. Pingback: Dew Drop – August 5, 2019 (#3004) | Morning Dew

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.