WDACSimulation/Get-SignerInfo.psm1
# Defining the Signer class from the WDACConfig Namespace if it doesn't already exist if (-NOT ('WDACConfig.Signer' -as [System.Type]) ) { Add-Type -Path "$ModuleRootPath\C#\Signer.cs" } Function Get-SignerInfo { <# .SYNOPSIS Function that takes an XML file path as input and returns an array of Signer objects The output contains as much info as possible about the signer .INPUTS System.IO.FileInfo .OUTPUTS WDACConfig.Signer[] .PARAMETER XmlFilePath The XML file path that the user selected for WDAC simulation. .PARAMETER SignedFilePath The signed file path that the user selected for WDAC simulation This is used for cross-referencing some of the signers' properties with the file's properties #> [CmdletBinding()] [OutputType([WDACConfig.Signer[]])] param( [Parameter(Mandatory = $true)][System.IO.FileInfo]$XmlFilePath, [parameter(Mandatory = $true)][System.IO.FileInfo]$SignedFilePath ) begin { # Detecting if Verbose switch is used $PSBoundParameters.Verbose.IsPresent ? ([System.Boolean]$Verbose = $true) : ([System.Boolean]$Verbose = $false) | Out-Null # Importing the $PSDefaultParameterValues to the current session, prior to everything else . "$ModuleRootPath\CoreExt\PSDefaultParameterValues.ps1" # Importing the required sub-modules Write-Verbose -Message 'Importing the required sub-modules' Import-Module -FullyQualifiedName "$ModuleRootPath\WDACSimulation\Convert-HexToOID.psm1" -Force # Load the XML file [System.Xml.XmlDocument]$Xml = Get-Content -LiteralPath $XmlFilePath } process { # Select the Signer nodes [System.Object[]]$Signers = $Xml.SiPolicy.Signers.Signer # Get User Mode Signers IDs [System.String[]]$UMSigners = ($Xml.SiPolicy.SigningScenarios.SigningScenario | Where-Object -FilterScript { $_.value -eq '12' }).ProductSigners.AllowedSigners.AllowedSigner.SignerId # Get Kernel Mode Signers IDs [System.String[]]$KMSigners = ($Xml.SiPolicy.SigningScenarios.SigningScenario | Where-Object -FilterScript { $_.value -eq '131' }).ProductSigners.AllowedSigners.AllowedSigner.SignerId # Get UpdatePolicySigners IDs [System.String[]]$UPSigners = $Xml.SiPolicy.UpdatePolicySigners.UpdatePolicySigner.SignerId # Get SupplementalPolicySigners IDs [System.String[]]$SPSigners = $Xml.SiPolicy.SupplementalPolicySigners.SupplementalPolicySigner.SignerId # Get all of the File Attrib IDs in the <FileRules> node [System.String[]]$FileAttribIDs = $Xml.SiPolicy.FileRules.FileAttrib.ID # Select the EKU nodes if they exist if ($Xml.SiPolicy.EKUs.EKU) { # Create a hashtable to store the correlation between the EKU IDs and their values [System.Collections.Hashtable]$EKUAndValuesCorrelation = @{} # Add the EKU IDs and their values to the hashtable $Xml.SiPolicy.EKUs.EKU | ForEach-Object -Process { $EKUAndValuesCorrelation.Add($_.ID, $_.Value) } } # Create an empty array to store the output [WDACConfig.Signer[]]$Output = @() # Loop through each Signer node and extract the information foreach ($Signer in $Signers) { # Replacing Wellknown root IDs with their corresponding TBS values and Names (Common Names) if ($Signer.CertRoot.Value -in ('03', '04', '05', '06', '07', '09', '0A', '0E', '0G', '0H', '0I')) { switch ($Signer.CertRoot.Value) { '03' { $Signer.CertRoot.Value = 'D67576F5521D1CCAB52E9215E0F9F743' $Signer.Name = 'Microsoft Authenticode(tm) Root Authority' break } '04' { $Signer.CertRoot.Value = '8B3C3087B7056F5EC5DDBA91A1B901F0' $Signer.Name = 'Microsoft Root Authority' break } '05' { $Signer.CertRoot.Value = '391BE92883D52509155BFEAE27B9BD340170B76B' $Signer.Name = 'Microsoft Root Certificate Authority' break } '06' { $Signer.CertRoot.Value = '121AF4B922A74247EA49DF50DE37609CC1451A1FE06B2CB7E1E079B492BD8195' $Signer.Name = 'Microsoft Code Signing PCA 2010' break } '07' { $Signer.CertRoot.Value = 'F6F717A43AD9ABDDC8CEFDDE1C505462535E7D1307E630F9544A2D14FE8BF26E' $Signer.Name = 'Microsoft Code Signing PCA 2011' break } '09' { $Signer.CertRoot.Value = '09CBAFBD98E81B4D6BAAAB32B8B2F5D7' $Signer.Name = 'Microsoft Test Root Authority' break } '0A' { $Signer.CertRoot.Value = '7A4D9890B0F9006A6F77472D50D83CA54975FCC2B7EA0563490134E19B78782A' $Signer.Name = 'Microsoft Testing Root Certificate Authority 2010' break } '0E' { $Signer.CertRoot.Value = 'ED55F82E1444F79CA9DCE826846FDC4E0EA3859E3D26EFEF412D2FFF0C7C8E6C' $Signer.Name = 'Microsoft Development Root Certificate Authority 2014' break } '0G' { $Signer.CertRoot.Value = '68D221D720E975DB5CD14B24F2970F86A5B8605A2A1BC784A17B83F7CF500A70EB177CE228273B8540A800178F23EAC8' $Signer.Name = 'Microsoft ECC Testing Root Certificate Authority 2017' break } '0H' { $Signer.CertRoot.Value = '214592CB01B59104195F80AF2886DBF85771AF42A3821D104BF18F415158C49CBC233511672CD6C432351AC9228E3E75' $Signer.Name = 'Microsoft ECC Development Root Certificate Authority 2018' break } '0I' { $Signer.CertRoot.Value = '32991981BF1575A1A5303BB93A381723EA346B9EC130FDB596A75BA1D7CE0B0A06570BB985D25841E23BE944E8FF118F' $Signer.Name = 'Microsoft ECC Product Root Certificate Authority 2018' break } } } # Check if the Signer has an EKU if ($Signer.CertEKU) { # Flag indicating the signer has an EKU [System.Boolean]$HasEKU = $true # an array to store the EKU OIDs of the signer (in case the signer has multiple EKUs) [System.String[]]$EKUOIDs = @() # Loop through each EKU ID (hex value) and convert it to an OID $EKUAndValuesCorrelation[$Signer.CertEKU.ID] | ForEach-Object -Process { $EKUOIDs += Convert-HexToOID -Hex $_ } # Get the EKU OIDs of the file's signer certificate (Leaf certificate) [System.String[]]$FileEKUOIDs = (Get-AuthenticodeSignature -LiteralPath $SignedFilePath).SignerCertificate.EnhancedKeyUsageList.ObjectId # Check if the array of EKU OIDs of the file's signer certificate contains all the EKU OIDs of the signer defined in the WDAC policy if (-NOT ($EKUOIDs | Where-Object -FilterScript { $FileEKUOIDs -notcontains $_ })) { # Set the flag to indicate that the EKUs match [System.Boolean]$EKUsMatch = $true } else { # Set the flag to indicate that the EKUs don't match [System.Boolean]$EKUsMatch = $false } } else { [System.Boolean]$HasEKU = $false [System.String[]]$EKUOIDs = '0' [System.Boolean]$EKUsMatch = $false } # Determine the scope of the signer if ($Signer.ID -in $UMSigners) { [System.String]$SignerScope = 'UserMode' } elseif ($Signer.ID -in $KMSigners) { [System.String]$SignerScope = 'KernelMode' } elseif ($Signer.ID -in $UPSigners) { [System.String]$SignerScope = 'UpdatePolicy' } elseif ($Signer.ID -in $SPSigners) { [System.String]$SignerScope = 'SupplementalPolicy' } else { Write-Warning -Message "The signer with the ID $($Signer.ID) is not associated with any signing scenarios, Update policy signers or Supplemental policy signers defined in the WDAC policy. The policy XML file might be corrupted." } # Determine whether the signer has a FileAttribRef, if it points to a file then it uses FilePublisher level if ($Signer.FileAttribRef.RuleID) { # If the signer has FilaAttrib(s) but there is no file rule in the policy XML file that points to it, then display a warning # Using a loop here for when there are multiple FileAttribRef nodes assigned to a single signer $Signer.FileAttribRef.RuleID | ForEach-Object -Process { if ($_ -notin $FileAttribIDs) { Write-Warning -Message "The signer with ID $($Signer.ID) has a file attribute but is not allowed in any of the file rules defined in the WDAC policy. The policy XML file may be corrupted." } } # Flag indicating the signer has a FileAttribRef [System.Boolean]$HasFileAttrib = $true # an array to store the FileAttribRef IDs of the signer [System.String[]]$SignerFileAttributeIDs = $Signer.FileAttribRef.RuleID } else { # Flag indicating the signer has no FileAttribRef [System.Boolean]$HasFileAttrib = $false } # If the signer has no FileAttribRef, then set it to N/A # The value doesn't matter if $HasFileAttrib is false if ([System.String]::IsNullOrWhiteSpace($SignerFileAttributeIDs)) { $SignerFileAttributeIDs = 'N/A' } # Create a new instance of the Signer class in the WDACConfig Namespace [WDACConfig.Signer]$SignerObj = New-Object -TypeName 'WDACConfig.Signer' -ArgumentList ($Signer.ID, $Signer.Name, $Signer.CertRoot.Value, $Signer.CertPublisher.Value, $HasEKU, $EKUOIDs, $EKUsMatch, $SignerScope, $HasFileAttrib, $SignerFileAttributeIDs) # Add the Signer object to the output array if it doesn't already exist with another ID, typically for files that are allowed in both User and Kernel mode signing scenarios so they have 2 identical signers with different IDs # Commenting it because it causes slight inaccuracies in the detected level of an allowed file # if (-NOT ($Output | Where-Object { ($_.Name -eq $SignerObj.Name) -and ($_.CertRoot -eq $SignerObj.CertRoot) -and ($_.CertPublisher -eq $SignerObj.CertPublisher) -and ($_.HasEKU -eq $SignerObj.HasEKU) -and ($_.EKUOIDs -eq $SignerObj.EKUOIDs) -and ($_.EKUsMatch -eq $SignerObj.EKUsMatch) })) { $Output += $SignerObj # } } } end { # Return the output array return $Output } } Export-ModuleMember -Function 'Get-SignerInfo' # SIG # Begin signature block # MIILkgYJKoZIhvcNAQcCoIILgzCCC38CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAP+pjPzvVUQY5b # 3HRpT3t7bvdZmW3bIjI/3QNA29gn7aCCB9AwggfMMIIFtKADAgECAhMeAAAABI80 # LDQz/68TAAAAAAAEMA0GCSqGSIb3DQEBDQUAME8xEzARBgoJkiaJk/IsZAEZFgNj # b20xIjAgBgoJkiaJk/IsZAEZFhJIT1RDQUtFWC1DQS1Eb21haW4xFDASBgNVBAMT # C0hPVENBS0VYLUNBMCAXDTIzMTIyNzExMjkyOVoYDzIyMDgxMTEyMTEyOTI5WjB5 # MQswCQYDVQQGEwJVSzEeMBwGA1UEAxMVSG90Q2FrZVggQ29kZSBTaWduaW5nMSMw # IQYJKoZIhvcNAQkBFhRob3RjYWtleEBvdXRsb29rLmNvbTElMCMGCSqGSIb3DQEJ # ARYWU3B5bmV0Z2lybEBvdXRsb29rLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP # ADCCAgoCggIBAKb1BJzTrpu1ERiwr7ivp0UuJ1GmNmmZ65eckLpGSF+2r22+7Tgm # pEifj9NhPw0X60F9HhdSM+2XeuikmaNMvq8XRDUFoenv9P1ZU1wli5WTKHJ5ayDW # k2NP22G9IPRnIpizkHkQnCwctx0AFJx1qvvd+EFlG6ihM0fKGG+DwMaFqsKCGh+M # rb1bKKtY7UEnEVAsVi7KYGkkH+ukhyFUAdUbh/3ZjO0xWPYpkf/1ldvGes6pjK6P # US2PHbe6ukiupqYYG3I5Ad0e20uQfZbz9vMSTiwslLhmsST0XAesEvi+SJYz2xAQ # x2O4n/PxMRxZ3m5Q0WQxLTGFGjB2Bl+B+QPBzbpwb9JC77zgA8J2ncP2biEguSRJ # e56Ezx6YpSoRv4d1jS3tpRL+ZFm8yv6We+hodE++0tLsfpUq42Guy3MrGQ2kTIRo # 7TGLOLpayR8tYmnF0XEHaBiVl7u/Szr7kmOe/CfRG8IZl6UX+/66OqZeyJ12Q3m2 # fe7ZWnpWT5sVp2sJmiuGb3atFXBWKcwNumNuy4JecjQE+7NF8rfIv94NxbBV/WSM # pKf6Yv9OgzkjY1nRdIS1FBHa88RR55+7Ikh4FIGPBTAibiCEJMc79+b8cdsQGOo4 # ymgbKjGeoRNjtegZ7XE/3TUywBBFMf8NfcjF8REs/HIl7u2RHwRaUTJdAgMBAAGj # ggJzMIICbzA8BgkrBgEEAYI3FQcELzAtBiUrBgEEAYI3FQiG7sUghM++I4HxhQSF # hqV1htyhDXuG5sF2wOlDAgFkAgEIMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA4GA1Ud # DwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBsGCSsGAQQBgjcVCgQOMAwwCgYIKwYB # BQUHAwMwHQYDVR0OBBYEFOlnnQDHNUpYoPqECFP6JAqGDFM6MB8GA1UdIwQYMBaA # FICT0Mhz5MfqMIi7Xax90DRKYJLSMIHUBgNVHR8EgcwwgckwgcaggcOggcCGgb1s # ZGFwOi8vL0NOPUhPVENBS0VYLUNBLENOPUhvdENha2VYLENOPUNEUCxDTj1QdWJs # aWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9u # LERDPU5vbkV4aXN0ZW50RG9tYWluLERDPWNvbT9jZXJ0aWZpY2F0ZVJldm9jYXRp # b25MaXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwgccG # CCsGAQUFBwEBBIG6MIG3MIG0BggrBgEFBQcwAoaBp2xkYXA6Ly8vQ049SE9UQ0FL # RVgtQ0EsQ049QUlBLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZp # Y2VzLENOPUNvbmZpZ3VyYXRpb24sREM9Tm9uRXhpc3RlbnREb21haW4sREM9Y29t # P2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0 # aG9yaXR5MA0GCSqGSIb3DQEBDQUAA4ICAQA7JI76Ixy113wNjiJmJmPKfnn7brVI # IyA3ZudXCheqWTYPyYnwzhCSzKJLejGNAsMlXwoYgXQBBmMiSI4Zv4UhTNc4Umqx # pZSpqV+3FRFQHOG/X6NMHuFa2z7T2pdj+QJuH5TgPayKAJc+Kbg4C7edL6YoePRu # HoEhoRffiabEP/yDtZWMa6WFqBsfgiLMlo7DfuhRJ0eRqvJ6+czOVU2bxvESMQVo # bvFTNDlEcUzBM7QxbnsDyGpoJZTx6M3cUkEazuliPAw3IW1vJn8SR1jFBukKcjWn # aau+/BE9w77GFz1RbIfH3hJ/CUA0wCavxWcbAHz1YoPTAz6EKjIc5PcHpDO+n8Fh # t3ULwVjWPMoZzU589IXi+2Ol0IUWAdoQJr/Llhub3SNKZ3LlMUPNt+tXAs/vcUl0 # 7+Dp5FpUARE2gMYA/XxfU9T6Q3pX3/NRP/ojO9m0JrKv/KMc9sCGmV9sDygCOosU # 5yGS4Ze/DJw6QR7xT9lMiWsfgL96Qcw4lfu1+5iLr0dnDFsGowGTKPGI0EvzK7H+ # DuFRg+Fyhn40dOUl8fVDqYHuZJRoWJxCsyobVkrX4rA6xUTswl7xYPYWz88WZDoY # gI8AwuRkzJyUEA07IYtsbFCYrcUzIHME4uf8jsJhCmb0va1G2WrWuyasv3K/G8Nn # f60MsDbDH1mLtzGCAxgwggMUAgEBMGYwTzETMBEGCgmSJomT8ixkARkWA2NvbTEi # MCAGCgmSJomT8ixkARkWEkhPVENBS0VYLUNBLURvbWFpbjEUMBIGA1UEAxMLSE9U # Q0FLRVgtQ0ECEx4AAAAEjzQsNDP/rxMAAAAAAAQwDQYJYIZIAWUDBAIBBQCggYQw # GAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGC # NwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQx # IgQg3CErKHrxpE83whS3yWZxfEkPx91yRkHQts6r8Bub3ZgwDQYJKoZIhvcNAQEB # BQAEggIABDJ0k2Tn1YdLkRhqL+WjZhEdAPU1fxSUfZE3I/711zmZrF68V3m8ygdh # f+HnFZ7h2M4Mc0PpMqP6KvECC34o+TVMjsxfFxflLGe+xwhM530Z0KFjoj8eIQgW # D+LTk0OdPI6ucDrYjEoOelfLCTQoXvuNXGnQLnFaaLZ7729p9uJ62qeebDjkNe1N # f97s5hE4911GfcGs+uuQ66jIThyPYuchgvN9O13D6PSfItN8oBuVr7eH7aWT2N3q # lF5L59CxoE9ItTjEwdHEQUQlBCMazekogVPlR53eAGBOat+lFIfQXvz8iAcLj16y # DnBi0t5kOUm+WKywiM3CDSUQ6Dy11igLXeD3oa4iYbDQ3LTo2xeH1Vi7BewIScMY # rBTLcR2JmnyzfjxRNAvHpjnSHYlN1eIgf7bVvy/D+KHJ1v8eQfSofpMBaAKN+ixf # pe9odfMrHpIbftOLc0iWSeXQckmFgrZ2BB+RQpobv1Bm0k6Inoem7orJGDnF+d/Z # GvSm1g3FXA0kDhXZQCCgIjhZPu/zohwl705aaausLRrevgRDms9CljUWHsjhHAGR # alhVz0D2fn8bQAEpAa/ImwYbbDvwfYEvN4QGy5iIiOxrui3Yp399/NZzraef4oGZ # z6HaPlGhTZl9LLAbDDD0cHKbP7RW2CyLdmisXlbMc3rfZSSs8RQ= # SIG # End signature block |