Private/Test-TakeControlCrashHistory.ps1

function Test-TakeControlCrashHistory {
    <#
    .SYNOPSIS
        Detects application crashes and access violations in Take Control binaries.
     
    .DESCRIPTION
        Checks Windows Event Logs and crash dumps for evidence of Take Control
        runtime failures, including access violations in BASupSrvCnfg.exe and BASupSrvc.exe.
    #>

    [CmdletBinding()]
    param(
        [hashtable]$Config,
        [int]$LookbackDays = 7,
        [switch]$Silent
    )
    
    $crashDetected = $false
    $crashDetails = @()
    
    # 1. Check Application Event Log for Application Errors
    if (-not $Silent) { Write-TakeControlLog -Message "Scanning for Take Control crashes (Last $LookbackDays days)..." -Level Info -LogPath $Config.LogPath }
    
    try {
        $appErrors = Get-WinEvent -FilterHashtable @{
            LogName   = 'Application'
            ProviderName = 'Application Error', 'Windows Error Reporting'
            StartTime = (Get-Date).AddDays(-$LookbackDays)
        } -ErrorAction SilentlyContinue | Where-Object { 
            $_.Message -match 'BASupSrv(c|Cnfg)\.exe' 
        }
        
        if ($appErrors) {
            $crashDetected = $true
            foreach ($event in $appErrors | Select-Object -First 5) {
                $detail = [PSCustomObject]@{
                    Timestamp   = $event.TimeCreated
                    Source      = $event.ProviderName
                    EventID     = $event.Id
                    Message     = $event.Message
                    Type        = 'EventLog'
                }
                $crashDetails += $detail
                
                # Parse access violation details
                if ($event.Message -match 'exception code (0x[0-9a-fA-F]+)') {
                    $exCode = $matches[1]
                    if ($exCode -eq '0xc0000005') {
                        if (-not $Silent) { 
                            Write-TakeControlLog -Message "CRASH DETECTED: Access Violation ($exCode) at $($event.TimeCreated)" -Level Warning -LogPath $Config.LogPath 
                        }
                    }
                }
                
                if ($event.Message -match 'BASupSrvCnfg\.exe') {
                    if (-not $Silent) { 
                        Write-TakeControlLog -Message "DETECTION: BASupSrvCnfg.exe (Configuration Tool) crashed. This binary manages agent settings." -Level Warning -LogPath $Config.LogPath 
                    }
                }
            }
        }
    }
    catch {
        if (-not $Silent) { Write-TakeControlLog -Message "WARNING: Could not access Application Event Log: $_" -Level Warning -LogPath $Config.LogPath }
    }
    
    # 2. Check for Crash Dumps
    try {
        $dumpPath = Join-Path $env:LOCALAPPDATA 'CrashDumps'
        if (Test-Path $dumpPath) {
            $dumps = Get-ChildItem $dumpPath -Filter "BASupSrv*.dmp" -ErrorAction SilentlyContinue |
                     Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-$LookbackDays) }
            
            if ($dumps) {
                $crashDetected = $true
                foreach ($dump in $dumps) {
                    $crashDetails += [PSCustomObject]@{
                        Timestamp = $dump.LastWriteTime
                        Source    = 'CrashDump'
                        EventID   = 0
                        Message   = "Crash dump found: $($dump.Name) ($([math]::Round($dump.Length/1KB, 2)) KB)"
                        Type      = 'DumpFile'
                    }
                }
                if (-not $Silent) { 
                    Write-TakeControlLog -Message "CRASH DUMP DETECTED: Found $($dumps.Count) dump file(s) in $dumpPath" -Level Warning -LogPath $Config.LogPath 
                }
            }
        }
    }
    catch {
        if (-not $Silent) { Write-TakeControlLog -Message "WARNING: Could not check crash dumps: $_" -Level Warning -LogPath $Config.LogPath }
    }
    
    # 3. Validate Critical Binaries
    $binaries = @(
        (Join-Path $Config.AgentInstallPath 'BASupSrvc.exe'),
        (Join-Path $Config.AgentInstallPath 'BASupSrvCnfg.exe')
    )
    
    foreach ($binPath in $binaries) {
        if (Test-Path $binPath) {
            $fileInfo = Get-Item $binPath
            
            # Check for suspiciously small file size (corruption indicator)
            if ($fileInfo.Length -lt 50KB) {
                $crashDetected = $true
                if (-not $Silent) { 
                    Write-TakeControlLog -Message "CORRUPTION SUSPECTED: $($fileInfo.Name) is only $([math]::Round($fileInfo.Length/1KB, 2)) KB (expected >50KB)" -Level Warning -LogPath $Config.LogPath 
                }
            }
            
            # Validate signature
            try {
                $sig = Get-AuthenticodeSignature $binPath -ErrorAction Stop
                if ($sig.Status -ne 'Valid') {
                    $crashDetected = $true
                    if (-not $Silent) { 
                        Write-TakeControlLog -Message "SIGNATURE INVALID: $($fileInfo.Name) signature status is '$($sig.Status)'" -Level Warning -LogPath $Config.LogPath 
                    }
                }
            }
            catch {
                if (-not $Silent) { Write-TakeControlLog -Message "WARNING: Could not validate signature for $($fileInfo.Name): $_" -Level Warning -LogPath $Config.LogPath }
            }
        }
        else {
            # Binary missing entirely
            if ($binPath -like '*BASupSrvc.exe') {
                # BASupSrvc.exe is critical and already checked elsewhere
                continue
            }
            if (-not $Silent) { 
                Write-TakeControlLog -Message "MISSING BINARY: $([System.IO.Path]::GetFileName($binPath)) not found" -Level Warning -LogPath $Config.LogPath 
            }
        }
    }
    
    return [PSCustomObject]@{
        CrashDetected = $crashDetected
        CrashCount    = $crashDetails.Count
        Details       = $crashDetails
    }
}