XMLOps/New-HashLevelRules.psm1
Function New-HashLevelRules { <# .SYNOPSIS Creates new Hash level rules in an XML file For each hash data, it creates 2 Hash rules, one for Authenticode SHA2-256 and one for SHA1 hash It also adds the FileRulesRef for each hash to the ProductSigners node of the correct signing scenario (Kernel/User mode) .PARAMETER Hashes The Hashes to be used for creating the rules, they are the output of the BuildSignerAndHashObjects Method .PARAMETER XmlFilePath The path to the XML file to be modified .INPUTS System.Collections.Generic.List[WDACConfig.HashCreator] System.IO.FileInfo .OUTPUTS System.Void #> [CmdletBinding()] [OutputType([System.Void])] Param( [Parameter(Mandatory = $true)][System.Collections.Generic.List[WDACConfig.HashCreator]]$Hashes, [Parameter(Mandatory = $true)][System.IO.FileInfo]$XmlFilePath ) Begin { . "$([WDACConfig.GlobalVars]::ModuleRootPath)\CoreExt\PSDefaultParameterValues.ps1" [WDACConfig.VerboseLogger]::Write("New-HashLevelRules: There are $($Hashes.Count) Hash rules to be added to the XML file") # Load the XML file [System.Xml.XmlDocument]$Xml = Get-Content -Path $XmlFilePath # Define the namespace manager [System.Xml.XmlNamespaceManager]$Ns = New-Object -TypeName System.Xml.XmlNamespaceManager -ArgumentList $Xml.NameTable $Ns.AddNamespace('ns', 'urn:schemas-microsoft-com:sipolicy') # Find the ProductSigners Nodes [System.Xml.XmlElement]$UMCI_ProductSigners_Node = $Xml.SelectSingleNode('//ns:SigningScenarios/ns:SigningScenario[@Value="12"]/ns:ProductSigners', $Ns) [System.Xml.XmlElement]$KMCI_ProductSigners_Node = $Xml.SelectSingleNode('//ns:SigningScenarios/ns:SigningScenario[@Value="131"]/ns:ProductSigners', $Ns) } Process { # Find the FileRules node [System.Xml.XmlElement]$FileRulesNode = $Xml.SelectSingleNode('//ns:FileRules', $Ns) # Loop through each hash and create a new rule for it Foreach ($Hash in $Hashes) { [System.String]$Guid = [System.Guid]::NewGuid().ToString().replace('-', '').ToUpper() # Create a unique ID for the rule [System.String]$HashSHA256RuleID = "ID_ALLOW_A_$Guid" [System.String]$HashSHA1RuleID = "ID_ALLOW_B_$Guid" # Create new Allow Hash rule for Authenticode SHA256D [System.Xml.XmlElement]$NewAuth256HashNode = $Xml.CreateElement('Allow', $FileRulesNode.NamespaceURI) $NewAuth256HashNode.SetAttribute('ID', $HashSHA256RuleID) $NewAuth256HashNode.SetAttribute('FriendlyName', "$($Hash.FileName) Hash Sha256") $NewAuth256HashNode.SetAttribute('Hash', $Hash.AuthenticodeSHA256) # Add the new node to the FileRules node [System.Void]$FileRulesNode.AppendChild($NewAuth256HashNode) # Create new Allow Hash rule for Authenticode SHA1 [System.Xml.XmlElement]$NewAuth1HashNode = $Xml.CreateElement('Allow', $FileRulesNode.NamespaceURI) $NewAuth1HashNode.SetAttribute('ID', $HashSHA1RuleID) $NewAuth1HashNode.SetAttribute('FriendlyName', "$($Hash.FileName) Hash Sha1") $NewAuth1HashNode.SetAttribute('Hash', $Hash.AuthenticodeSHA1) # Add the new node to the FileRules node [System.Void]$FileRulesNode.AppendChild($NewAuth1HashNode) # For User-Mode files if ($Hash.SiSigningScenario -eq '1') { # Check if FileRulesRef node exists, if not, create it $UMCI_Temp_FileRulesRefNode = $UMCI_ProductSigners_Node.SelectSingleNode('ns:FileRulesRef', $Ns) if ($Null -eq $UMCI_Temp_FileRulesRefNode) { [System.Xml.XmlElement]$UMCI_Temp_FileRulesRefNode = $Xml.CreateElement('FileRulesRef', $Ns.LookupNamespace('ns')) [System.Void]$UMCI_ProductSigners_Node.AppendChild($UMCI_Temp_FileRulesRefNode) } # Create FileRuleRef for Authenticode SHA256 Hash inside the <FileRulesRef> -> <ProductSigners> -> <SigningScenario Value="12"> [System.Xml.XmlElement]$NewUMCIFileRuleRefNode = $Xml.CreateElement('FileRuleRef', $UMCI_Temp_FileRulesRefNode.NamespaceURI) $NewUMCIFileRuleRefNode.SetAttribute('RuleID', $HashSHA256RuleID) [System.Void]$UMCI_Temp_FileRulesRefNode.AppendChild($NewUMCIFileRuleRefNode) # Create FileRuleRef for Authenticode SHA1 Hash inside the <FileRulesRef> -> <ProductSigners> -> <SigningScenario Value="12"> [System.Xml.XmlElement]$NewUMCIFileRuleRefNode = $Xml.CreateElement('FileRuleRef', $UMCI_Temp_FileRulesRefNode.NamespaceURI) $NewUMCIFileRuleRefNode.SetAttribute('RuleID', $HashSHA1RuleID) [System.Void]$UMCI_Temp_FileRulesRefNode.AppendChild($NewUMCIFileRuleRefNode) } # For Kernel-Mode files elseif ($Hash.SiSigningScenario -eq '0') { # Display a warning if a hash rule for a kernel-mode file is being created and the file is not an MSI # Since MDE does not record the Signing information events (Id 8038) for MSI files so we must create Hash based rules for them if (-NOT $Hash.FileName.EndsWith('.msi')) { Write-Warning -Message "Creating Hash rule for Kernel-Mode file: $($Hash.FileName). Kernel-Mode file should be signed!" } # Check if FileRulesRef node exists, if not, create it $KMCI_Temp_FileRulesRefNode = $KMCI_ProductSigners_Node.SelectSingleNode('ns:FileRulesRef', $Ns) if ($Null -eq $KMCI_Temp_FileRulesRefNode) { [System.Xml.XmlElement]$KMCI_Temp_FileRulesRefNode = $Xml.CreateElement('FileRulesRef', $Ns.LookupNamespace('ns')) [System.Void]$KMCI_ProductSigners_Node.AppendChild($KMCI_Temp_FileRulesRefNode) } # Create FileRuleRef for Authenticode SHA256 Hash inside the <FileRulesRef> -> <ProductSigners> -> <SigningScenario Value="131"> [System.Xml.XmlElement]$NewKMCIFileRuleRefNode = $Xml.CreateElement('FileRuleRef', $KMCI_Temp_FileRulesRefNode.NamespaceURI) $NewKMCIFileRuleRefNode.SetAttribute('RuleID', $HashSHA256RuleID) [System.Void]$KMCI_Temp_FileRulesRefNode.AppendChild($NewKMCIFileRuleRefNode) # Create FileRuleRef for Authenticode SHA1 Hash inside the <FileRulesRef> -> <ProductSigners> -> <SigningScenario Value="131"> [System.Xml.XmlElement]$NewKMCIFileRuleRefNode = $Xml.CreateElement('FileRuleRef', $KMCI_Temp_FileRulesRefNode.NamespaceURI) $NewKMCIFileRuleRefNode.SetAttribute('RuleID', $HashSHA1RuleID) [System.Void]$KMCI_Temp_FileRulesRefNode.AppendChild($NewKMCIFileRuleRefNode) } } } End { $Xml.Save($XmlFilePath) } } Export-ModuleMember -Function 'New-HashLevelRules' |