Shared/Test-ECCSignedFiles.psm1
Function Test-ECCSignedFiles { <# .SYNOPSIS This function gets list of directories or files Then it checks if the files are WDAC compliant If they are, it checks if they are signed with ECC If they are, it returns an array of them if -Process parameter is not used With -Progress parameter, the function creates Hash level rules for each ECC file puts them in a separate XML policy file and returns the path to it .PARAMETER Directory The directories to process .PARAMETER File The files to process .PARAMETER Process Indicates that instead of returning list of ECC Signed files, the function will create Hash Level rules for them .PARAMETER ECCSignedFilesTempPolicy The path to the temporary policy file where the Hash Level rules will be stored. .INPUTS System.IO.DirectoryInfo[] System.IO.FileInfo[] .OUTPUTS System.String[] System.IO.FileInfo .NOTES The OID of the ECC algorithm for public keys is '1.2.840.10045.2.1' #> Param ( [ValidateScript({ [System.IO.Directory]::Exists($_) })] [Parameter(Mandatory = $false)][System.IO.DirectoryInfo[]]$Directory, [Parameter(Mandatory = $false)][System.IO.FileInfo[]]$File, [Parameter(Mandatory = $false)][System.Management.Automation.SwitchParameter]$Process, [Parameter(Mandatory = $true)][System.IO.FileInfo]$ECCSignedFilesTempPolicy ) Begin { Write-Verbose -Message 'Test-ECCSignedFiles: Importing the required sub-modules' Import-Module -Force -FullyQualifiedName @( "$([WDACConfig.GlobalVars]::ModuleRootPath)\Shared\Get-KernelModeDrivers.psm1", "$([WDACConfig.GlobalVars]::ModuleRootPath)\XMLOps\New-HashLevelRules.psm1", "$([WDACConfig.GlobalVars]::ModuleRootPath)\XMLOps\Clear-CiPolicy_Semantic.psm1" ) -Verbose:$false # Get the compliant WDAC files from the File and Directory parameters and add them to the HashSet $WDACSupportedFiles = [System.Collections.Generic.HashSet[System.String]]@([WDACConfig.FileUtility]::GetFilesFast($Directory, $File, $null)) } Process { Write-Verbose -Message "Test-ECCSignedFiles: Processing $($WDACSupportedFiles.Count) WDAC compliant files to check for ECC signatures." # The check for existence is mainly for the files detected in audit logs that no longer exist on the disk # Audit logs or MDE data simply don't have the data related to the file's signature algorithm, so only local files can be checked $ECCSignedFiles = [System.Collections.Generic.HashSet[System.String]]@( foreach ($Path in $WDACSupportedFiles) { if (([System.IO.FileInfo]$Path).Exists -eq $true) { $AuthResult = Get-AuthenticodeSignature -LiteralPath $Path if ($AuthResult.Status -ieq 'Valid') { if (($AuthResult.SignerCertificate.PublicKey.Oid.Value).Contains('1.2.840.10045.2.1')) { # Write-Verbose -Message "Test-ECCSignedFiles: The file '$Path' is signed with ECC algorithm. Will create Hash Level rules for it." $Path } } } } ) } End { if (-NOT $Process) { Return ($ECCSignedFiles.Count -gt 0 ? $ECCSignedFiles : $null) } else { if (($null -ne $ECCSignedFiles) -and ($ECCSignedFiles.Count -gt 0)) { $CompleteHashes = New-Object -TypeName 'System.Collections.Generic.List[WDACConfig.HashCreator]' foreach ($ECCSignedFile in $ECCSignedFiles) { [WDACConfig.AuthenticodePageHashes]$HashOutput = [WDACConfig.AuthPageHash]::GetCiFileHashes($ECCSignedFile) $CompleteHashes.Add([WDACConfig.HashCreator]::New( $HashOutput.SHA256Authenticode, $HashOutput.SHA1Authenticode, ([System.IO.FileInfo]$ECCSignedFile).Name, # Check if the file is kernel-mode or user-mode -- Don't need the verbose output of the cmdlet when using it in embedded mode ($null -eq (Get-KernelModeDrivers -File $ECCSignedFile 4>$null)) ? 1 : 0 ) ) } Copy-Item -LiteralPath 'C:\Windows\schemas\CodeIntegrity\ExamplePolicies\AllowAll.xml' -Destination $ECCSignedFilesTempPolicy -Force Clear-CiPolicy_Semantic -Path $ECCSignedFilesTempPolicy New-HashLevelRules -Hashes $CompleteHashes -XmlFilePath $ECCSignedFilesTempPolicy Return $ECCSignedFilesTempPolicy } else { Write-Verbose -Message 'Test-ECCSignedFiles: No ECC signed files found. Exiting the function.' Return $null } } } } Export-ModuleMember -Function 'Test-ECCSignedFiles' |