Core/ConvertTo-WDACPolicy.psm1
Function ConvertTo-WDACPolicy { [CmdletBinding( DefaultParameterSetName = 'In-Place Upgrade' )] param( [ValidateScript({ Test-CiPolicy -XmlFile $_ })] [Parameter(Mandatory = $false, ParameterSetName = 'In-Place Upgrade')] [System.IO.FileInfo]$PolicyToAddLogsTo, [ValidateScript({ Test-CiPolicy -XmlFile $_ })] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy File Association')] [System.IO.FileInfo]$BasePolicyFile, [ArgumentCompleter({ param($CommandName, $parameterName, $wordToComplete, $CommandAst, $fakeBoundParameters) [System.String[]]$PolicyGUIDs = ((&'C:\Windows\System32\CiTool.exe' -lp -json | ConvertFrom-Json).Policies | Where-Object -FilterScript { ($_.IsSystemPolicy -ne 'True') -and ($_.PolicyID -eq $_.BasePolicyID) }).PolicyID $Existing = $CommandAst.FindAll({ $args[0] -is [System.Management.Automation.Language.StringConstantExpressionAst] }, $false).Value $PolicyGUIDs | Where-Object -FilterScript { $_ -notin $Existing } | ForEach-Object -Process { "'{0}'" -f $_ } })] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy GUID Association')] [System.Guid]$BasePolicyGUID, [ArgumentCompleter({ param($CommandName, $parameterName, $wordToComplete, $CommandAst, $fakeBoundParameters) [System.String[]]$Policies = ((&'C:\Windows\System32\CiTool.exe' -lp -json | ConvertFrom-Json).Policies | Where-Object -FilterScript { ($_.FriendlyName) -and ($_.PolicyID -eq $_.BasePolicyID) }).FriendlyName $Existing = $CommandAst.FindAll({ $args[0] -is [System.Management.Automation.Language.StringConstantExpressionAst] }, $false).Value $Policies | Where-Object -FilterScript { $_ -notin $Existing } | ForEach-Object -Process { "'{0}'" -f $_ } })] [Parameter(Mandatory = $false, ParameterSetName = 'In-Place Upgrade')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy GUID Association')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy File Association')] [System.String[]]$FilterByPolicyNames, [Parameter(Mandatory = $false, ParameterSetName = 'In-Place Upgrade')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy GUID Association')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy File Association')] [System.UInt64]$MinutesAgo, [Parameter(Mandatory = $false, ParameterSetName = 'In-Place Upgrade')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy GUID Association')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy File Association')] [System.UInt64]$HoursAgo, [Parameter(Mandatory = $false, ParameterSetName = 'In-Place Upgrade')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy GUID Association')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy File Association')] [System.UInt64]$DaysAgo, [Parameter(Mandatory = $false, ParameterSetName = 'In-Place Upgrade')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy GUID Association')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy File Association')] [System.Management.Automation.SwitchParameter]$KernelModeOnly, [ValidateSet('Audit', 'Blocked')] [Parameter(Mandatory = $false, ParameterSetName = 'In-Place Upgrade')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy GUID Association')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy File Association')] [System.String]$LogType = 'Audit', [Parameter(Mandatory = $false, ParameterSetName = 'In-Place Upgrade')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy GUID Association')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy File Association')] [System.Management.Automation.SwitchParameter]$Deploy, [Parameter(Mandatory = $false, ParameterSetName = 'In-Place Upgrade')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy GUID Association')] [Parameter(Mandatory = $false, ParameterSetName = 'Base-Policy File Association')] [System.Management.Automation.SwitchParameter]$ExtremeVisibility, [Parameter(Mandatory = $false)][System.Management.Automation.SwitchParameter]$SkipVersionCheck ) 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 'ConvertTo-WDACPolicy: Importing the required sub-modules' Import-Module -FullyQualifiedName "$ModuleRootPath\Shared\Update-self.psm1" -Force Import-Module -FullyQualifiedName "$ModuleRootPath\Shared\Write-ColorfulText.psm1" -Force Import-Module -FullyQualifiedName "$ModuleRootPath\Shared\Receive-CodeIntegrityLogs.psm1" -Force Import-Module -FullyQualifiedName "$ModuleRootPath\Shared\Edit-CiPolicyRuleOptions.psm1" -Force Import-Module -FullyQualifiedName "$ModuleRootPath\Shared\New-AppxPackageCiPolicy.psm1" -Force Import-Module -FullyQualifiedName "$ModuleRootPath\Shared\New-EmptyPolicy.psm1" -Force Import-Module -FullyQualifiedName "$ModuleRootPath\Shared\Get-RuleRefs.psm1" -Force Import-Module -FullyQualifiedName "$ModuleRootPath\Shared\Get-FileRules.psm1" -Force # if -SkipVersionCheck wasn't passed, run the updater if (-NOT $SkipVersionCheck) { Update-self -InvocationStatement $MyInvocation.Statement } if ($MinutesAgo -or $HoursAgo -or $DaysAgo) { # Convert MinutesAgo, HoursAgo, and DaysAgo to DateTime objects [System.DateTime]$CurrentDateTime = Get-Date [System.DateTime]$StartTime = $CurrentDateTime.AddMinutes(-$MinutesAgo) -as [System.DateTime] [System.DateTime]$StartTime = $StartTime.AddHours(-$HoursAgo) -as [System.DateTime] [System.DateTime]$StartTime = $StartTime.AddDays(-$DaysAgo) -as [System.DateTime] } # To store the logs that user selects using GUI [PSCustomObject[]]$SelectedLogs = @() # The paths to the policy files to be merged together to produce the final Supplemental policy [System.String[]]$PolicyFilesToMerge = @() # Initializing some flags [System.Boolean]$HasKernelFiles = $false [System.Boolean]$HasNormalFiles = $false # Save the current date in a variable as string [System.String]$CurrentDate = $(Get-Date -Format "MM-dd-yyyy 'at' HH-mm-ss") # Initialize the flag indicating whether the cmdlet should exit [System.Boolean]$ShouldExit = $false } Process { [PSCustomObject[]]$EventsToDisplay = Receive-CodeIntegrityLogs -PostProcessing OnlyExisting -PolicyName:$FilterByPolicyNames -Date:$StartTime -Type:$LogType | Select-Object -Property @{ Label = 'File Name' Expression = { # Can't use Get-Item or Get-ChildItem because the file might not exist on the disk # Can't use Split-Path -LiteralPath with -Leaf parameter because not supported [System.String]$TempPath = Split-Path -LiteralPath $_.'File Name' $_.'File Name'.Replace($TempPath, '').TrimStart('\') } }, 'TimeCreated', 'PolicyName', 'ProductName', 'FileVersion', 'OriginalFileName', 'FileDescription', 'InternalName', 'PackageFamilyName', @{ Label = 'Full Path' Expression = { $_.'File Name' } }, 'Validated Signing Level', 'Requested Signing Level', 'SI Signing Scenario', 'UserId', 'Publishers', 'SHA256 Hash', 'SHA256 Flat Hash', 'SHA1 Hash', 'SHA1 Flat Hash', 'PolicyGUID', 'PolicyHash', 'ActivityId', 'Process Name', 'UserWriteable', 'PolicyID', 'Status', 'USN', 'SignerInfo' # If the KernelModeOnly switch is used, then filter the events by the 'Requested Signing Level' property if ($KernelModeOnly) { $EventsToDisplay = $EventsToDisplay | Where-Object -FilterScript { $_.'SI Signing Scenario' -eq 'Kernel-Mode' } } # Sort the events by TimeCreated in descending order [PSCustomObject[]]$EventsToDisplay = $EventsToDisplay | Sort-Object -Property TimeCreated -Descending if (($null -eq $EventsToDisplay) -and ($EventsToDisplay.Count -eq 0)) { Write-ColorfulText -Color HotPink -InputText 'No logs were found to display. Exiting...' $ShouldExit = $true return } #Region Out-GridView properties visibility settings # If the ExtremeVisibility switch is used, then display all the properties of the logs without any filtering if (-NOT $ExtremeVisibility) { [System.String[]]$PropertiesToDisplay = @('File Name', 'TimeCreated', 'PolicyName', 'ProductName', 'FileVersion', 'OriginalFileName', 'FileDescription', 'InternalName', 'PackageFamilyName', 'Full Path', 'SI Signing Scenario', 'UserId', 'Publishers') # Create a PSPropertySet object that contains the names of the properties to be visible # Used for Out-GridView display # https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.pspropertyset # https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pscustomobject#using-defaultpropertyset-the-long-way $Visible = [System.Management.Automation.PSPropertySet]::new( 'DefaultDisplayPropertySet', # the name of the property set $PropertiesToDisplay # the names of the properties to be visible ) # Add the PSPropertySet object to the PSStandardMembers member set of each element of the $EventsToDisplay array foreach ($Element in $EventsToDisplay) { $Element | Add-Member -MemberType 'MemberSet' -Name 'PSStandardMembers' -Value $Visible } } #Endregion Out-GridView properties visibility settings <# Will enable this section once this issue has been fixed: https://github.com/PowerShell/GraphicalTools/issues/235 if ($AlternateDisplay) { if (-NOT (Get-InstalledModule -Name Microsoft.PowerShell.ConsoleGuiTools -ErrorAction SilentlyContinue)) { Write-Verbose -Message 'ConvertTo-WDACPolicy: Installing the Microsoft.PowerShell.ConsoleGuiTools module' Install-Module -Name Microsoft.PowerShell.ConsoleGuiTools -Force } # Display the logs in a console grid view using outside module $SelectedLogs = $EventsToDisplay | Out-ConsoleGridView -Title "$($EventsToDisplay.count) $LogType Code Integrity Logs" -OutputMode Multiple } #> # Display the logs in a grid view using the build-in cmdlet $SelectedLogs = $EventsToDisplay | Out-GridView -OutputMode Multiple -Title "$($EventsToDisplay.count) $LogType Code Integrity Logs" Write-Verbose -Message "ConvertTo-WDACPolicy: Selected logs count: $($SelectedLogs.count)" if (!$BasePolicyGUID -and !$BasePolicyFile -and !$PolicyToAddLogsTo) { Write-ColorfulText -Color HotPink -InputText 'A more specific parameter was not provided to define what to do with the selected logs. Exiting...' $ShouldExit = $true return } # If the user has selected any logs, then create a WDAC policy for them, otherwise return if ($null -eq $SelectedLogs) { $ShouldExit = $true return } Write-Verbose -Message 'ConvertTo-WDACPolicy: Creating a temporary folder to store the symbolic links to the files and WDAC polices' [System.IO.DirectoryInfo]$SymLinksStorage = New-Item -Path ($UserTempDirectoryPath + 'SymLinkStorage' + $(New-Guid)) -ItemType Directory -Force # The path to the TEMP Supplemental WDAC Policy file [System.IO.FileInfo]$WDACPolicyPathTemp = (Join-Path -Path $SymLinksStorage -ChildPath 'TEMP CiPolicy From Logs.xml') # The path to the final Supplemental WDAC Policy file [System.IO.FileInfo]$WDACPolicyPath = (Join-Path -Path $SymLinksStorage -ChildPath "CiPolicy From Logs $CurrentDate.xml") # The path to the Kernel protected file hashes WDAC Policy file [System.IO.FileInfo]$WDACPolicyKernelProtectedPath = (Join-Path -Path $SymLinksStorage -ChildPath "Kernel Protected Files Hashes $CurrentDate.xml") #Region Kernel-protected-files-automatic-detection-and-allow-rule-creation # This part takes care of Kernel protected files such as the main executable of the games installed through Xbox app # For these files, only Kernel can get their hashes, it passes them to event viewer and we take them from event viewer logs # Any other attempts such as "Get-FileHash" or "Get-AuthenticodeSignature" fail and ConfigCI Module cmdlets totally ignore these files and do not create allow rules for them Write-Verbose -Message 'ConvertTo-WDACPolicy: Checking for Kernel protected files in the selected logs' # Storing the logs of the kernel protected files [PSCustomObject[]]$KernelProtectedFileLogs = @() # Looping through every file with .exe and .dll extensions to check if they are kernel protected regardless of whether the file exists or not foreach ($Log in $SelectedLogs | Where-Object -FilterScript { [System.IO.Path]::GetExtension($_.'Full Path') -in @('.exe', '.dll') }) { try { # Testing each file to find the protected ones Get-FileHash -Path $Log.'Full Path' -ErrorAction Stop | Out-Null } # If the file is protected, it will throw an exception and the module will continue to the next one # Making sure only the right file is captured by narrowing down the error type. # E.g., when get-filehash can't get a file's hash because its open by another program, the exception is different: System.IO.IOException catch [System.UnauthorizedAccessException] { $KernelProtectedFileLogs += $Log } catch { Write-Verbose -Message "ConvertTo-WDACPolicy: An unexpected error occurred while checking the file: $($Log.'Full Path')" } } # Only proceed if any kernel protected file(s) were found in any of the selected logs if (($null -ne $KernelProtectedFileLogs) -and ($KernelProtectedFileLogs.count -gt 0)) { Write-Verbose -Message 'ConvertTo-WDACPolicy: The following Kernel protected files were detected, creating allow rules for them:' $KernelProtectedFileLogs | ForEach-Object -Process { Write-Verbose -Message $($_.'File Name') } # Check if any of the kernel-protected files can be allowed by FamilyPackageName [PSCustomObject]$AppxOutput = New-AppxPackageCiPolicy -Logs $KernelProtectedFileLogs -directoryPath $SymLinksStorage if ($null -ne $AppxOutput.PolicyPath) { # Add the path of the Appx package policy file to the array of policy files to merge $PolicyFilesToMerge += $AppxOutput.PolicyPath # Set the flag indicating that there are kernel-protected files in the selected logs [System.Boolean]$HasKernelFiles = $true } # If the New-AppxPackageCiPolicy function returned remaining logs then create allow rules for them using Hash level if (($null -ne $AppxOutput.RemainingLogs) -and ($AppxOutput.RemainingLogs.count -gt 0)) { # Put the Rules and RulesRefs in an empty policy file by extracting the hashes from the logs Write-Verbose -Message "ConvertTo-WDACPolicy: $($AppxOutput.RemainingLogs.count) Kernel protected files were found in the selected logs that did not have the PackageFamilyName property or the app is not installed on the system, creating allow rules for them using Hash level" New-EmptyPolicy -RulesContent (Get-FileRules -HashesArray $AppxOutput.RemainingLogs) -RuleRefsContent (Get-RuleRefs -HashesArray $AppxOutput.RemainingLogs) | Out-File -FilePath $WDACPolicyKernelProtectedPath -Force # Add the path of the Kernel protected files Hashes policy file to the array of policy files to merge $PolicyFilesToMerge += $WDACPolicyKernelProtectedPath # Set the flag indicating that there are kernel-protected files in the selected logs [System.Boolean]$HasKernelFiles = $true } else { Write-Verbose -Message 'ConvertTo-WDACPolicy: All kernel protected files were allowed using their PackageFamilyName property' } } else { Write-Verbose -Message 'ConvertTo-WDACPolicy: No Kernel protected files were found in any of the selected logs' } [System.UInt64]$LogCountBeforeRemovingKernelProtectedFiles = $SelectedLogs.Count # Remove the logs of the Kernel protected files from the selected logs since they cannot be scanned with New-CIPolicy cmdlet [PSCustomObject[]]$SelectedLogs = $SelectedLogs | Where-Object -FilterScript { $KernelProtectedFileLogs -notcontains $_ } Write-Verbose -Message "ConvertTo-WDACPolicy: The number of logs before removing the Kernel protected files: $LogCountBeforeRemovingKernelProtectedFiles and after: $($SelectedLogs.Count). There were $($KernelProtectedFileLogs.Count) Kernel protected files." #Endregion Kernel-protected-files-automatic-detection-and-allow-rule-creation # If there are still logs after removing the kernel protected files, then scan them if (($null -ne $SelectedLogs) -and ($SelectedLogs.Count -gt 0)) { #Region Main Policy Creation Write-Verbose -Message 'ConvertTo-WDACPolicy: Creating symbolic links to the non-kernel-protected files in the logs' Foreach ($File in $SelectedLogs) { New-Item -ItemType SymbolicLink -Path "$SymLinksStorage\$($File.'File Name')" -Target $File.'Full Path' -Force | Out-Null } # Creating a hash table to dynamically add parameters based on user input and pass them to New-Cipolicy cmdlet [System.Collections.Hashtable]$CiPolicyScanHashTable = @{ FilePath = $WDACPolicyPathTemp ScanPath = $SymLinksStorage Level = 'WHQLFilePublisher' MultiplePolicyFormat = $true UserWriteablePaths = $true AllowFileNameFallbacks = $true } # Only scan UserPEs if the KernelModeOnly switch is not used if (!$KernelModeOnly) { $CiPolicyScanHashTable['UserPEs'] = $true } # Set the Fallback property to 'None' if the KernelModeOnly switch is used, otherwise set it to 'FilePublisher' and 'Hash' $CiPolicyScanHashTable['Fallback'] = $KernelModeOnly ? 'None' : ('FilePublisher', 'Hash') Write-Verbose -Message 'ConvertTo-WDACPolicy: Scanning the files in the selected event logs with the following parameters:' if ($Verbose) { $CiPolicyScanHashTable } New-CIPolicy @CiPolicyScanHashTable # Add the path of the TEMP WDAC Policy file as the 1st element to the policy files to merge array [System.String[]]$PolicyFilesToMerge = @($WDACPolicyPathTemp) + $PolicyFilesToMerge # Set the flag indicating that there are normal files in the selected logs [System.Boolean]$HasNormalFiles = $true #Endregion Main Policy Creation } # If there are only kernel-protected files in the selected logs if (($HasKernelFiles -eq $true) -and ($HasNormalFiles -eq $false)) { Write-Verbose -Message 'ConvertTo-WDACPolicy: There are only kernel-protected files in the selected logs' Merge-CIPolicy -PolicyPaths $PolicyFilesToMerge -OutputFilePath $WDACPolicyPath | Out-Null } # If there are only normal files in the selected logs elseif (($HasKernelFiles -eq $false) -and ($HasNormalFiles -eq $true)) { Write-Verbose -Message 'ConvertTo-WDACPolicy: There are only normal files in the selected logs' # Using merge on a single policy takes care of any possible orphaned rules or file attributes Merge-CIPolicy -PolicyPaths $WDACPolicyPathTemp -OutputFilePath $WDACPolicyPath | Out-Null } # If there are both kernel-protected and normal files in the selected logs elseif (($HasKernelFiles -eq $true) -and ($HasNormalFiles -eq $true)) { Write-Verbose -Message 'ConvertTo-WDACPolicy: There are both kernel-protected and normal files in the selected logs' Merge-CIPolicy -PolicyPaths $PolicyFilesToMerge -OutputFilePath $WDACPolicyPath | Out-Null } # If there are no files in the selected logs else { Write-ColorfulText -Color HotPink -InputText 'No logs were selected to create a WDAC policy from. Exiting...' $ShouldExit = $true return } #Region Base To Supplemental Policy Association and Deployment # If -BasePolicyFile parameter was used then associate the supplemental policy with the user input base policy if ($null -ne $BasePolicyFile) { # Objectify the user input base policy file to extract its Base policy ID $InputXMLObj = [System.Xml.XmlDocument](Get-Content -Path $BasePolicyFile) [System.String]$SupplementalPolicyID = Set-CIPolicyIdInfo -FilePath $WDACPolicyPath -PolicyName "Supplemental Policy from event logs - $(Get-Date -Format 'MM-dd-yyyy')" -SupplementsBasePolicyID $InputXMLObj.SiPolicy.BasePolicyID -ResetPolicyID [System.String]$SupplementalPolicyID = $SupplementalPolicyID.Substring(11) # Configure policy rule options Edit-CiPolicyRuleOptions -Action Supplemental -XMLFile $WDACPolicyPath Write-Verbose -Message 'ConvertTo-WDACPolicy: Copying the policy file to the current directory' Copy-Item -Path $WDACPolicyPath -Destination '.\' -Force if ($Deploy) { ConvertFrom-CIPolicy -XmlFilePath $WDACPolicyPath -BinaryFilePath "$SupplementalPolicyID.cip" | Out-Null Write-Verbose -Message 'ConvertTo-WDACPolicy: Deploying the Supplemental policy' &'C:\Windows\System32\CiTool.exe' --update-policy "$SupplementalPolicyID.cip" -json | Out-Null } } # If -BasePolicyGUID parameter was used then use it by setting it as the Base policy ID in the supplemental policy elseif ($null -ne $BasePolicyGUID) { [System.String]$SupplementalPolicyID = Set-CIPolicyIdInfo -FilePath $WDACPolicyPath -PolicyName "Supplemental Policy from event logs - $(Get-Date -Format 'MM-dd-yyyy')" -SupplementsBasePolicyID $BasePolicyGUID -ResetPolicyID [System.String]$SupplementalPolicyID = $SupplementalPolicyID.Substring(11) # Configure policy rule options Edit-CiPolicyRuleOptions -Action Supplemental -XMLFile $WDACPolicyPath Write-Verbose -Message 'ConvertTo-WDACPolicy: Copying the policy file to the current directory' Copy-Item -Path $WDACPolicyPath -Destination '.\' -Force if ($Deploy) { ConvertFrom-CIPolicy -XmlFilePath $WDACPolicyPath -BinaryFilePath "$SupplementalPolicyID.cip" | Out-Null Write-Verbose -Message 'ConvertTo-WDACPolicy: Deploying the Supplemental policy' &'C:\Windows\System32\CiTool.exe' --update-policy "$SupplementalPolicyID.cip" -json | Out-Null } } # If -PolicyToAddLogsTo parameter was used then merge the supplemental policy with the user input policy elseif ($null -ne $PolicyToAddLogsTo) { # Objectify the user input policy file to extract its policy ID $InputXMLObj = [System.Xml.XmlDocument](Get-Content -Path $PolicyToAddLogsTo) Set-CIPolicyIdInfo -FilePath $WDACPolicyPath -PolicyName "Supplemental Policy from event logs - $(Get-Date -Format 'MM-dd-yyyy')" -ResetPolicyID | Out-Null # Remove all policy rule option prior to merging the policies since we don't need to add/remove any policy rule options to/from the user input policy Edit-CiPolicyRuleOptions -Action RemoveAll -XMLFile $WDACPolicyPath Merge-CIPolicy -PolicyPaths "$PolicyToAddLogsTo", "$WDACPolicyPath" -OutputFilePath "$PolicyToAddLogsTo" | Out-Null # Set HVCI to Strict Set-HVCIOptions -Strict -FilePath "$PolicyToAddLogsTo" if ($Deploy) { ConvertFrom-CIPolicy -XmlFilePath $PolicyToAddLogsTo -BinaryFilePath "$($InputXMLObj.SiPolicy.PolicyID).cip" | Out-Null Write-Verbose -Message 'ConvertTo-WDACPolicy: Deploying the policy that user selected to add the logs to' &'C:\Windows\System32\CiTool.exe' --update-policy "$($InputXMLObj.SiPolicy.PolicyID).cip" -json | Out-Null } } #Endregion Base To Supplemental Policy Association and Deployment } End { if ($ShouldExit -eq $true) { return } Write-Verbose -Message 'ConvertTo-WDACPolicy: Removing the temporary folder and its content' Remove-Item -Path $SymLinksStorage -Recurse -Force } <# .SYNOPSIS Displays the Code Integrity logs in a GUI and allows the user to select the logs to convert to a Supplemental WDAC policy It's a multi-purpose cmdlet that offers a wide range of functionalities that can either be used separately or mixed together for very detailed and specific tasks .DESCRIPTION You can filter the logs by the policy name and the time You can add the logs to an existing WDAC policy or create a new one .PARAMETER FilterByPolicyNames The names of the policies to filter the logs by. Supports auto-completion, press TAB key to view the list of the deployed base policy names to choose from. It will not display the policies that are already selected on the command line. You can manually enter the name of the policies that are no longer available on the system. .PARAMETER PolicyToAddLogsTo The policy to add the selected logs to, it can either be a base or supplemental policy. .PARAMETER BasePolicyFile The base policy file to associate the supplemental policy with .PARAMETER BasePolicyGUID The GUID of the base policy to associate the supplemental policy with .PARAMETER MinutesAgo The number of minutes ago from the current time to filter the logs by .PARAMETER HoursAgo The number of hours ago from the current time to filter the logs by .PARAMETER DaysAgo The number of days ago from the current time to filter the logs by .PARAMETER KernelModeOnly If used, will filter the logs by including only the Kernel-Mode logs .PARAMETER LogType The type of logs to display: Audit or Blocked .PARAMETER Deploy If used, will deploy the policy on the system .PARAMETER ExtremeVisibility If used, will display all the properties of the logs without any filtering. .PARAMETER SkipVersionCheck Can be used with any parameter to bypass the online version check - only to be used in rare cases .NOTES The biggest specified time unit is used for filtering the logs if more than one time unit is specified. .EXAMPLE ConvertTo-WDACPolicy -PolicyToAddLogsTo "C:\Users\Admin\AllowMicrosoftPlusBlockRules.xml" -Verbose This example will display the Code Integrity logs in a GUI and allow the user to select the logs to add to the specified policy file. .EXAMPLE ConvertTo-WDACPolicy -Verbose -BasePolicyGUID '{ACE9058C-8A24-47F4-86F0-A33FAB5073E3}' This example will display the Code Integrity logs in a GUI and allow the user to select the logs to create a new supplemental policy and associate it with the specified base policy GUID. .EXAMPLE ConvertTo-WDACPolicy -BasePolicyFile "C:\Users\Admin\AllowMicrosoftPlusBlockRules.xml" This example will display the Code Integrity logs in a GUI and allow the user to select the logs to create a new supplemental policy and associate it with the specified base policy file. .EXAMPLE ConvertTo-WDACPolicy This example will display the Code Integrity logs in a GUI and takes no further action. .EXAMPLE ConvertTo-WDACPolicy -FilterByPolicyNames 'VerifiedAndReputableDesktopFlightSupplemental','WindowsE_Lockdown_Flight_Policy_Supplemental' -Verbose This example will filter the Code Integrity logs by the specified policy names and display them in a GUI. It will also display verbose messages on the console. .EXAMPLE ConvertTo-WDACPolicy -FilterByPolicyNames 'Microsoft Windows Driver Policy - Enforced' -MinutesAgo 10 This example will filter the Code Integrity logs by the specified policy name and the number of minutes ago from the current time and display them in a GUI. So, it will display the logs that are 10 minutes old and are associated with the specified policy name. #> } # Importing argument completer ScriptBlocks . "$ModuleRootPath\Resources\ArgumentCompleters.ps1" Register-ArgumentCompleter -CommandName 'ConvertTo-WDACPolicy' -ParameterName 'PolicyToAddLogsTo' -ScriptBlock $ArgumentCompleterXmlFilePathsPicker Register-ArgumentCompleter -CommandName 'ConvertTo-WDACPolicy' -ParameterName 'BasePolicyFile' -ScriptBlock $ArgumentCompleterXmlFilePathsPicker # SIG # Begin signature block # MIILkgYJKoZIhvcNAQcCoIILgzCCC38CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA9SHYe+D0CXNIZ # iFfH8Ckg7DPkaa+PYCAsK67xbL1SQ6CCB9AwggfMMIIFtKADAgECAhMeAAAABI80 # 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 # IgQgQhBFpsh5/S5fGDp2nOpQ7g0YxihUShIyhtjy25SedZIwDQYJKoZIhvcNAQEB # BQAEggIAom8Eb8pcgTHFPUqJwyQ4SSZhmDOO2LaHzLdnNFa4nLrXqzFvHyCcZOse # oOZVPHjzsYn5qSjREARnMFBy5oFav/ko0A3bMCcszYZRZmZnjq0H2DBlisFflXZW # Py18CPdyzHz5q47rjuWH9d82zNcmF+r1QjbOGdIYMqge6iZHWor3oMLPymgbCUGe # Hol/t2WeQo2kIffRarPWgltB8sLr82NNiNCQPhBNDe8UVXe/A2dyXYJnDQ1ItmEp # B7dFJCtbvlQvRRvkGEZHC/vDA66D4LFlNCRN9my3cGC8ljcg3Vdw4ey+IY+RCkCf # m4XoelbCXzKNTsOm4rky6YYBUHJVcro7GbNo/IgfXQMmIl7fo5LEPytBlAeNyWwl # aYuyqpJU1iDuep4oghNzADYI6psFwXwN813S4if/dT3ulz2k1lOGxdplXqIhg2hk # +akF6t2QwvlmdhR2THxA1gPDE566vdAUyic3SVd5l3tgeCMS2du77Q6Ih09CGijr # 54BPUazcTPItMwycUs81Vts2rsrsc+SLag7lZEweTw/nYK2ehgmdqslsGhZMBy4e # ZeI0xx81wOqfrHe/moYsVL2BKviYj2T4lR4ca8xPkgC8en5yAVUZsl71MtooFNun # hOpD5DQ3ZJ2pVnsdY2FPR8Od0iE4gqwPq0+8l55W/BPQrt+xJq4= # SIG # End signature block |