Core/Invoke-WDACSimulation.psm1

Function Invoke-WDACSimulation {
    [CmdletBinding()]
    Param(
        [ArgumentCompleter([WDACConfig.ArgCompleter.XmlFilePathsPicker])]
        [Alias('X')][Parameter(Mandatory = $true)][string]$XmlFilePath,
        [ArgumentCompleter([WDACConfig.ArgCompleter.FolderPicker])]
        [Alias('D')][Parameter(Mandatory = $false)][string[]]$FolderPath,
        [ArgumentCompleter([WDACConfig.ArgCompleter.MultipleAnyFilePathsPicker])]
        [Alias('F')][Parameter(Mandatory = $false)][string[]]$FilePath,
        [Alias('C')][Parameter(Mandatory = $false)][switch]$CSVOutput,
        [Alias('N')][Parameter(Mandatory = $false)][switch]$NoCatalogScanning,
        [ArgumentCompleter([WDACConfig.ArgCompleter.FolderPicker])]
        [Alias('Cat')][Parameter(Mandatory = $false)][string[]]$CatRootPath,
        [Alias('CPU')][Parameter(Mandatory = $false)][System.UInt32]$ThreadsCount = 2,
        [Alias('S')][Parameter(Mandatory = $false)][switch]$SkipVersionCheck
    )
    [WDACConfig.LoggerInitializer]::Initialize($VerbosePreference, $DebugPreference, $Host)
    if (-NOT $SkipVersionCheck) { Update-WDACConfigPSModule -InvocationStatement $MyInvocation.Statement }
    $FinalSimulationResults = [WDACConfig.InvokeWDACSimulation]::Invoke($FilePath, $FolderPath, $XmlFilePath, $NoCatalogScanning, $CSVOutput, $CatRootPath, $ThreadsCount)

    # Change the color of the Table header to SkyBlue
    $PSStyle.Formatting.TableHeader = "$($PSStyle.Foreground.FromRGB(135,206,235))"

    if ($FinalSimulationResults.Count -gt 10000) {
        # If the result is too big and the user forgot to use CSV Output then output everything to CSV instead of trying to display on the console
        if (!$CSVOutput) {
            $FinalSimulationResults.Values | Sort-Object -Property IsAuthorized -Descending | Export-Csv -LiteralPath (Join-Path -Path ([WDACConfig.GlobalVars]::UserConfigDir) -ChildPath "WDAC Simulation Output $(Get-Date -Format "MM-dd-yyyy 'at' HH-mm-ss").csv") -Force
        }
        Return "The number of files is too many to display on the console. Saving the results in a CSV file in '$((Join-Path -Path ([WDACConfig.GlobalVars]::UserConfigDir) -ChildPath "WDAC Simulation Output $(Get-Date -Format "MM-dd-yyyy 'at' HH-mm-ss").csv"))'"
    }

    # Return the final main output array as a table
    Return $FinalSimulationResults.Values | Select-Object -Property 'Path',
    @{
        Label      = 'Source'
        Expression =
        { switch ($_.Source) {
                { $_ -eq 'Signer' } { $Color = "$($PSStyle.Foreground.FromRGB(152,255,152))" }
                { $_ -eq 'Hash' } { $Color = "$($PSStyle.Foreground.FromRGB(255,255,49))" }
                { $_ -eq 'Unsigned' } { $Color = "$($PSStyle.Foreground.FromRGB(255,20,147))" }
            }
            "$Color$($_.Source)$($PSStyle.Reset)"
        }
    },
    @{
        Label      = 'IsAuthorized'
        Expression =
        {
            switch ($_.IsAuthorized) {
                { $_ -eq $true } { $Color = "$($PSStyle.Foreground.FromRGB(255,0,255))"; break }
                { $_ -eq $false } { $Color = "$($PSStyle.Foreground.FromRGB(255,165,0))$($PSStyle.Blink)"; break }
            }
            "$Color$($_.IsAuthorized)$($PSStyle.Reset)"
        }
    },
    @{
        Label      = 'MatchCriteria'
        Expression = {
            # If the MatchCriteria starts with 'UnknownError', truncate it to 50 characters. The full string will be displayed in the CSV output file. If it does not then just display it as it is
            $_.MatchCriteria -match 'UnknownError' ? $_.MatchCriteria.Substring(0, 50) + '...' : "$($_.MatchCriteria)"
        }
    },
    @{
        Label      = 'SpecificFileName'
        Expression = {
            $_.SpecificFileNameLevelMatchCriteria
        }
    } | Sort-Object -Property IsAuthorized | Format-Table

    <#
.SYNOPSIS
    Simulates the deployment of the WDAC policy. It can produce a very detailed CSV file that contains the output of the simulation.
    On the console, it can display a table that shows the file path, source, MatchCriteria, and whether the file is allowed or not.
    The console results are color coded for easier reading.
 
    Properties explanation:
 
    FilePath: The name of the file gathered from its full path. (the actual long path of the file is not displayed in the console output, only in the CSV file)
    Source: The source of the file's MatchCriteria, e.g., 'Signer' (For signed files only), 'Hash' (For signed and unsigned files), 'Unsigned' (For unsigned files only)
    MatchCriteria: The reason the file is allowed or not. For files authorized by FilePublisher level, it will show the specific file name level that the file is authorized by. (https://learn.microsoft.com/en-us/windows/security/application-security/application-control/app-control-for-business/design/select-types-of-rules-to-create#table-3--specificfilenamelevel-options)
    IsAuthorized: A boolean value that indicates whether the file is allowed or not.
.LINK
    https://github.com/HotCakeX/Harden-Windows-Security/wiki/Invoke-WDACSimulation
.DESCRIPTION
    Simulates the deployment of an App Control policy by analyzing a folder (recursively) or files and checking which of the detected files are allowed by a user selected policy xml file
.PARAMETER FolderPath
    Browse for a folders to include in the simulation
.PARAMETER FilePath
    Browse for files to include in the simulation
.PARAMETER XmlFilePath
    Browse for the App Control policy XML file
.PARAMETER NoCatalogScanning
    Bypass the scanning of the security catalogs on the system
.PARAMETER CatRootPath
    Provide path(s) to directories where security catalog .cat files are located. If not provided, the default path is C:\Windows\System32\CatRoot
.PARAMETER CSVOutput
    Exports the output to a CSV file. The CSV output is saved in the WDACConfig folder: C:\Program Files\WDACConfig
.PARAMETER ThreadsCount
    The number of the concurrent/parallel tasks to use when performing App Control Simulation.
    By default it uses 2 parallel tasks. Minimum allowed value is 1.
.PARAMETER SkipVersionCheck
    Bypass the online version check
.INPUTS
    System.IO.FileInfo[]
    System.IO.DirectoryInfo[]
    System.Management.Automation.SwitchParameter
.OUTPUTS
    System.Collections.Generic.List[WDACConfig.SimulationOutput]
.EXAMPLE
    Invoke-WDACSimulation -FolderPath 'C:\Windows\System32' -XmlFilePath 'C:\Users\HotCakeX\Desktop\Policy.xml'
    This example will simulate the deployment of the policy.xml file against the C:\Windows\System32 folder
.NOTES
    WDAC templates such as 'Default Windows' and 'Allow Microsoft' don't have CertPublisher element in their Signers because they don't target a leaf certificate,
    thus they weren't created using FilePublisher level, they were created using Publisher or Root certificate levels to allow Microsoft's wellknown certificates.
#>

}