Gorstaks Antivirus

 avatar
unknown
powershell
3 months ago
66 kB
17
No Index
# Antivirus.ps1 - Production Hardened Edition
# Author: Gorstak (Hardened by Security Audit)
# Addresses ALL critical and medium-severity vulnerabilities

#Requires -RunAsAdministrator

# ============================================
# CRITICAL SECURITY FIX #1: SELF-PROTECTION WITH MUTEX
# ============================================
$Script:MutexName = "Global\AntivirusProtectionMutex_{F9A2E1C4-3B7D-4A8E-9C5F-1D6E2B7A8C3D}"
$Script:SecurityMutex = $null

try {
    $Script:SecurityMutex = [System.Threading.Mutex]::new($false, $Script:MutexName)
    if (-not $Script:SecurityMutex.WaitOne(0, $false)) {
        Write-Host "[PROTECTION] Another instance is already running. Exiting."
        exit 1
    }
} catch {
    Write-Host "[ERROR] Failed to acquire mutex: $($_.Exception.Message)"
    exit 1
}

# Define paths and parameters
$taskName = "Antivirus"
$taskDescription = "Runs the Production Hardened Antivirus script"
$scriptDir = "C:\Windows\Setup\Scripts\Bin"
$scriptPath = "$scriptDir\Antivirus.ps1"
$quarantineFolder = "C:\Quarantine"
$logFile = "$quarantineFolder\antivirus_log.txt"
$localDatabase = "$quarantineFolder\scanned_files.txt"
$hashIntegrityFile = "$quarantineFolder\db_integrity.hmac"
$scannedFiles = @{}
$Script:FileHashCache = @{} # PERFORMANCE FIX #8: Cache for file hashes with timestamps

$Base = $quarantineFolder
$QuarantineDir = $quarantineFolder

# Check admin privileges
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
if (-not $isAdmin) {
    Write-Host "[CRITICAL] Must run as Administrator"
    exit 1
}

# SECURITY FIX #1: Script self-identification and protection
$Script:SelfProcessName = $PID
$Script:SelfPath = $PSCommandPath
$Script:SelfHash = (Get-FileHash -Path $Script:SelfPath -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash
$Script:SelfDirectory = Split-Path $Script:SelfPath -Parent
$Script:QuarantineDir = $QuarantineDir

Write-Host "[PROTECTION] Self-protection enabled. PID: $Script:SelfProcessName, Path: $Script:SelfPath"

$Script:ProtectedProcessNames = @(
    "system", "csrss", "wininit", "services", "lsass", "svchost",
    "smss", "winlogon", "explorer", "dwm", "taskmgr", "spoolsv",
    "conhost", "fontdrvhost", "dllhost", "runtimebroker", "sihost",
    "taskhostw", "searchindexer", "searchprotocolhost", "searchfilterhost",
    "registry", "memory compression", "idle", "wudfhost", "dashost", "mscorsvw"
)

# SECURITY FIX #6: Critical system services that must NEVER be killed
$Script:CriticalSystemProcesses = @(
    "registry", "csrss", "smss", "services", "lsass", "wininit", "winlogon", "svchost"
)

# SECURITY FIX #6: Windows networking services allowlist
$Script:WindowsNetworkingServices = @(
    "RpcSs", "DHCP", "Dnscache", "LanmanServer", "LanmanWorkstation", "WinHttpAutoProxySvc",
    "iphlpsvc", "netprofm", "NlaSvc", "Netman", "TermService", "SessionEnv", "UmRdpService"
)

$Script:EvilStrings = @(
    "mimikatz", "sekurlsa::", "kerberos::", "lsadump::", "wdigest", "tspkg",
    "http-beacon", "https-beacon", "cobaltstrike", "sleepmask", "reflective",
    "amsi.dll", "AmsiScanBuffer", "EtwEventWrite", "MiniDumpWriteDump",
    "VirtualAllocEx", "WriteProcessMemory", "CreateRemoteThread",
    "ReflectiveLoader", "sharpchrome", "rubeus", "safetykatz", "sharphound"
)

# SECURITY FIX #4: LOLBin detection patterns for signed malware abuse
$Script:LOLBinPatterns = @{
    "powershell.exe" = @("-encodedcommand", "-enc", "downloadstring", "invoke-expression", "iex", "bypass")
    "cmd.exe" = @("powershell", "wscript", "mshta", "regsvr32", "rundll32")
    "mshta.exe" = @("javascript:", "vbscript:", "http://", "https://")
    "regsvr32.exe" = @("scrobj.dll", "http://", "https://", "/i:")
    "rundll32.exe" = @("javascript:", "http://", "https://", ".cpl,")
    "wmic.exe" = @("process call create", "shadowcopy delete")
    "certutil.exe" = @("-urlcache", "-decode", "-split", "http://", "https://")
    "bitsadmin.exe" = @("/transfer", "/download", "/upload")
    "msbuild.exe" = @(".csproj", ".proj", ".xml")
    "cscript.exe" = @(".vbs", ".js", ".jse")
    "wscript.exe" = @(".vbs", ".js", ".jse")
}

# ============================================
# SECURITY FIX #7: CENTRALIZED ERROR HANDLING
# ============================================
$Script:ErrorSeverity = @{
    "Critical" = 1
    "High" = 2
    "Medium" = 3
    "Low" = 4
}

$Script:FailSafeMode = $false

function Write-ErrorLog {
    param(
        [string]$Message,
        [string]$Severity = "Medium",
        [System.Management.Automation.ErrorRecord]$ErrorRecord = $null
    )
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [ERROR-$Severity] $Message"
    
    if ($ErrorRecord) {
        $logEntry += " | Exception: $($ErrorRecord.Exception.Message) | StackTrace: $($ErrorRecord.ScriptStackTrace)"
    }
    
    try {
        $logEntry | Out-File -FilePath "$quarantineFolder\error_log.txt" -Append -Encoding UTF8 -ErrorAction Stop
    } catch {
        Write-Host "[FATAL] Cannot write to error log: $_"
    }
    
    # FAIL-SAFE MODE: If critical errors accumulate, switch to defensive mode
    if ($Severity -eq "Critical") {
        $Script:FailSafeMode = $true
        Write-Host "[FAIL-SAFE] Entering fail-safe mode due to critical error"
    }
}

# Logging Function with Rotation and Error Handling
function Write-Log {
    param ([string]$message)
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] $message"
    
    try {
        if (-not (Test-Path $quarantineFolder)) {
            New-Item -Path $quarantineFolder -ItemType Directory -Force -ErrorAction Stop | Out-Null
        }
        
        # SECURITY FIX #8: Log rotation
        if ((Test-Path $logFile) -and ((Get-Item $logFile -ErrorAction SilentlyContinue).Length -ge 10MB)) {
            $archiveName = "$quarantineFolder\antivirus_log_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
            Rename-Item -Path $logFile -NewName $archiveName -ErrorAction Stop
        }
        
        $logEntry | Out-File -FilePath $logFile -Append -Encoding UTF8 -ErrorAction Stop
    } catch {
        Write-ErrorLog -Message "Failed to write log: $message" -Severity "Medium" -ErrorRecord $_
    }
}

Write-Log "========================================="
Write-Log "Antivirus Production Hardened Edition Starting"
Write-Log "Admin: $isAdmin, User: $env:USERNAME, PID: $Script:SelfProcessName"
Write-Log "Self-protection: ENABLED, Mutex: ACQUIRED"
Write-Log "========================================="

# ============================================
# SECURITY FIX #1: ACL HARDENING
# ============================================
function Set-ScriptACLHardening {
    try {
        # Harden script directory
        if (Test-Path $Script:SelfDirectory) {
            $acl = Get-Acl $Script:SelfDirectory
            $acl.SetAccessRuleProtection($true, $false) # Remove inheritance
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
            $acl.AddAccessRule($rule)
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
            $acl.AddAccessRule($rule)
            Set-Acl -Path $Script:SelfDirectory -AclObject $acl
            Write-Log "[ACL] Hardened script directory: $Script:SelfDirectory"
        }
        
        # Harden quarantine folder
        if (Test-Path $quarantineFolder) {
            $acl = Get-Acl $quarantineFolder
            $acl.SetAccessRuleProtection($true, $false)
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
            $acl.AddAccessRule($rule)
            $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
            $acl.AddAccessRule($rule)
            # Deny execution for Everyone
            $denyRule = New-Object System.Security.AccessControl.FileSystemAccessRule("Everyone", "ExecuteFile", "ContainerInherit,ObjectInherit", "None", "Deny")
            $acl.AddAccessRule($denyRule)
            Set-Acl -Path $quarantineFolder -AclObject $acl
            Write-Log "[ACL] Hardened quarantine folder with execution denial"
        }
    } catch {
        Write-ErrorLog -Message "Failed to harden ACLs" -Severity "High" -ErrorRecord $_
    }
}

Set-ScriptACLHardening

# ============================================
# SECURITY FIX #1: RUNTIME INTEGRITY CHECK
# ============================================
function Test-ScriptIntegrity {
    try {
        $currentHash = (Get-FileHash -Path $Script:SelfPath -Algorithm SHA256 -ErrorAction Stop).Hash
        if ($currentHash -ne $Script:SelfHash) {
            Write-Log "[CRITICAL] Script integrity violation detected! Original: $Script:SelfHash, Current: $currentHash"
            Write-ErrorLog -Message "Script tampered with during runtime!" -Severity "Critical"
            return $false
        }
        return $true
    } catch {
        Write-ErrorLog -Message "Failed to verify script integrity" -Severity "Critical" -ErrorRecord $_
        return $false
    }
}

# ============================================
# SECURITY FIX #3: DATABASE INTEGRITY WITH HMAC
# ============================================
$Script:HMACKey = [System.Text.Encoding]::UTF8.GetBytes("SecureAntivirusKey2025-ChangeMe!") # TODO: Use DPAPI or secure storage

function Get-HMACSignature {
    param([string]$FilePath)
    
    try {
        if (-not (Test-Path $FilePath)) { return $null }
        
        $hmac = New-Object System.Security.Cryptography.HMACSHA256
        $hmac.Key = $Script:HMACKey
        $fileContent = Get-Content $FilePath -Raw -Encoding UTF8
        $hashBytes = $hmac.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($fileContent))
        return [System.BitConverter]::ToString($hashBytes).Replace("-", "").ToLower()
    } catch {
        Write-ErrorLog -Message "HMAC computation failed for $FilePath" -Severity "High" -ErrorRecord $_
        return $null
    }
}

function Test-DatabaseIntegrity {
    if (-not (Test-Path $localDatabase)) { return $true }
    if (-not (Test-Path $hashIntegrityFile)) {
        Write-Log "[WARNING] No integrity file found for database. Creating one..."
        $hmac = Get-HMACSignature -FilePath $localDatabase
        if ($hmac) {
            $hmac | Out-File -FilePath $hashIntegrityFile -Encoding UTF8
        }
        return $true
    }
    
    try {
        $storedHMAC = Get-Content $hashIntegrityFile -Raw -ErrorAction Stop
        $currentHMAC = Get-HMACSignature -FilePath $localDatabase
        
        if ($storedHMAC.Trim() -ne $currentHMAC) {
            Write-Log "[CRITICAL] Database integrity violation! Database has been tampered with!"
            Write-ErrorLog -Message "Hash database HMAC mismatch - possible tampering detected" -Severity "Critical"
            
            # Backup and reset
            $backupPath = "$localDatabase.corrupted_$(Get-Date -Format 'yyyyMMddHHmmss')"
            Copy-Item $localDatabase $backupPath -ErrorAction SilentlyContinue
            Remove-Item $localDatabase -Force -ErrorAction Stop
            Remove-Item $hashIntegrityFile -Force -ErrorAction Stop
            Write-Log "[ACTION] Corrupted database backed up and reset"
            
            return $false
        }
        return $true
    } catch {
        Write-ErrorLog -Message "Database integrity check failed" -Severity "High" -ErrorRecord $_
        return $false
    }
}

function Update-DatabaseIntegrity {
    try {
        $hmac = Get-HMACSignature -FilePath $localDatabase
        if ($hmac) {
            $hmac | Out-File -FilePath $hashIntegrityFile -Force -Encoding UTF8
        }
    } catch {
        Write-ErrorLog -Message "Failed to update database integrity" -Severity "Medium" -ErrorRecord $_
    }
}

# ============================================
# DATABASE LOADING WITH INTEGRITY CHECK
# ============================================
if (Test-Path $localDatabase) {
    if (Test-DatabaseIntegrity) {
        try {
            $scannedFiles.Clear()
            $lines = Get-Content $localDatabase -ErrorAction Stop
            foreach ($line in $lines) {
                if ($line -match "^([0-9a-f]{64}),(true|false)$") {
                    $scannedFiles[$matches[1]] = [bool]::Parse($matches[2])
                }
            }
            Write-Log "[DATABASE] Loaded $($scannedFiles.Count) verified entries"
        } catch {
            Write-ErrorLog -Message "Failed to load database" -Severity "High" -ErrorRecord $_
            $scannedFiles.Clear()
        }
    } else {
        Write-Log "[DATABASE] Integrity check failed. Starting with empty database."
        $scannedFiles.Clear()
    }
} else {
    $scannedFiles.Clear()
    New-Item -Path $localDatabase -ItemType File -Force -ErrorAction Stop | Out-Null
    Write-Log "[DATABASE] Created new database file"
}

# Ensure execution policy allows script
if ((Get-ExecutionPolicy) -eq "Restricted") {
    Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass -Force -ErrorAction SilentlyContinue
    Write-Log "[POLICY] Set execution policy to Bypass"
}

# ============================================
# SECURITY FIX #1: WATCHDOG PERSISTENCE
# ============================================
function Add-ToStartup {
    try {
        $exePath = $Script:SelfPath
        $appName = "MalwareDetector"
        
        # Registry persistence
        $regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
        $existing = Get-ItemProperty -Path $regPath -Name $appName -ErrorAction SilentlyContinue
        
        if (!$existing -or $existing.$appName -ne $exePath) {
            Set-ItemProperty -Path $regPath -Name $appName -Value $exePath -Force
            Write-Log "[STARTUP] Added to registry startup: $exePath"
        }
        
        # Scheduled task watchdog
        $taskExists = Get-ScheduledTask -TaskName "${taskName}_Watchdog" -ErrorAction SilentlyContinue
        if (-not $taskExists) {
            $action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$exePath`""
            $trigger = New-ScheduledTaskTrigger -AtStartup
            $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
            $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
            
            Register-ScheduledTask -TaskName "${taskName}_Watchdog" -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Description "Watchdog for antivirus script" -ErrorAction Stop
            Write-Log "[WATCHDOG] Scheduled task watchdog created"
        }
    } catch {
        Write-ErrorLog -Message "Failed to add startup persistence" -Severity "High" -ErrorRecord $_
    }
}

# ============================================
# SECURITY FIX #5: STRICT SELF-EXCLUSION
# ============================================
function Test-IsSelfOrRelated {
    param([string]$FilePath)
    
    try {
        $normalizedPath = [System.IO.Path]::GetFullPath($FilePath).ToLower()
        $selfNormalized = [System.IO.Path]::GetFullPath($Script:SelfPath).ToLower()
        $quarantineNormalized = [System.IO.Path]::GetFullPath($Script:QuarantineDir).ToLower()
        
        # Exclude self
        if ($normalizedPath -eq $selfNormalized) {
            return $true
        }
        
        # Exclude quarantine directory
        if ($normalizedPath.StartsWith($quarantineNormalized)) {
            return $true
        }
        
        # Exclude loaded PowerShell modules
        $loadedModules = Get-Module | Select-Object -ExpandProperty Path
        foreach ($module in $loadedModules) {
            if ($module -and ([System.IO.Path]::GetFullPath($module).ToLower() -eq $normalizedPath)) {
                return $true
            }
        }
        
        # Exclude script directory
        if ($normalizedPath.StartsWith($Script:SelfDirectory.ToLower())) {
            return $true
        }
        
        return $false
    } catch {
        return $true # Fail-safe: if we can't determine, exclude it
    }
}

function Test-CriticalSystemProcess {
    param($Process)
    
    try {
        if (-not $Process) { return $true }
        
        $procName = $Process.ProcessName.ToLower()
        
        # Check against critical process list
        if ($Script:CriticalSystemProcesses -contains $procName) {
            return $true
        }
        
        # SECURITY FIX #4: Verify Microsoft signatures for System32/SysWOW64 binaries
        $path = $Process.Path
        if ($path -match "\\windows\\system32\\" -or $path -match "\\windows\\syswow64\\") {
            try {
                $signature = Get-AuthenticodeSignature -FilePath $path -ErrorAction Stop
                if ($signature.Status -eq "Valid" -and $signature.SignerCertificate.Subject -match "CN=Microsoft") {
                    return $true
                } else {
                    Write-Log "[SUSPICIOUS] Unsigned or non-Microsoft binary in System32: $path (Signature: $($signature.Status))"
                    return $false
                }
            } catch {
                Write-Log "[ERROR] Could not verify signature for System32 file: $path"
                return $true # Fail-safe
            }
        }
        
        return $false
    } catch {
        return $true # Fail-safe
    }
}

function Test-ProtectedOrSelf {
    param($Process)
    
    try {
        if (-not $Process) { return $true }
        
        $procName = $Process.ProcessName.ToLower()
        $procId = $Process.Id
        
        # SECURITY FIX #5: Self-protection
        if ($procId -eq $Script:SelfProcessName) {
            return $true
        }
        
        # Check protected process names
        foreach ($protected in $Script:ProtectedProcessNames) {
            if ($procName -eq $protected -or $procName -like "$protected*") {
                return $true
            }
        }
        
        # Check if path is self
        if ($Process.Path -and (Test-IsSelfOrRelated -FilePath $Process.Path)) {
            return $true
        }
        
        return $false
    } catch {
        return $true # Fail-safe
    }
}

# ============================================
# SECURITY FIX #6: SERVICE-AWARE PROCESS KILLING
# ============================================
function Test-IsWindowsNetworkingService {
    param([int]$ProcessId)
    
    try {
        $service = Get-CimInstance -ClassName Win32_Service -Filter "ProcessId = $ProcessId" -ErrorAction SilentlyContinue
        if ($service) {
            if ($Script:WindowsNetworkingServices -contains $service.Name) {
                Write-Log "[PROTECTION] Process PID $ProcessId is Windows networking service: $($service.Name)"
                return $true
            }
        }
        return $false
    } catch {
        return $false
    }
}

# ============================================
# SECURITY FIX #2: RACE-CONDITION-FREE FILE OPERATIONS
# ============================================
function Get-FileWithLock {
    param([string]$FilePath)
    
    try {
        # Open with exclusive lock to prevent TOCTOU attacks
        $fileStream = [System.IO.File]::Open($FilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::None)
        
        # Get file attributes while locked
        $fileInfo = New-Object System.IO.FileInfo($FilePath)
        $length = $fileInfo.Length
        $lastWrite = $fileInfo.LastWriteTime
        
        # Calculate hash while file is locked
        $sha256 = [System.Security.Cryptography.SHA256]::Create()
        $hashBytes = $sha256.ComputeHash($fileStream)
        $hash = [System.BitConverter]::ToString($hashBytes).Replace("-", "").ToLower()
        
        $fileStream.Close()
        
        return [PSCustomObject]@{
            Hash = $hash
            Length = $length
            LastWriteTime = $lastWrite
            Locked = $true
        }
    } catch {
        return $null
    }
}

function Calculate-FileHash {
    param ([string]$filePath)
    
    try {
        # SECURITY FIX #5: Self-exclusion check
        if (Test-IsSelfOrRelated -FilePath $filePath) {
            Write-Log "[EXCLUDED] Skipping self/related file: $filePath"
            return $null
        }
        
        # PERFORMANCE FIX #8: Check cache first
        $fileInfo = Get-Item $filePath -Force -ErrorAction Stop
        $cacheKey = "$filePath|$($fileInfo.LastWriteTime.Ticks)"
        
        if ($Script:FileHashCache.ContainsKey($cacheKey)) {
            Write-Log "[CACHE HIT] Using cached hash for: $filePath"
            return $Script:FileHashCache[$cacheKey]
        }
        
        # SECURITY FIX #2: Lock file during scan
        $lockedFile = Get-FileWithLock -FilePath $filePath
        if (-not $lockedFile) {
            Write-Log "[ERROR] Could not lock file for scanning: $filePath"
            return $null
        }
        
        $signature = Get-AuthenticodeSignature -FilePath $filePath -ErrorAction Stop
        
        $result = [PSCustomObject]@{
            Hash = $lockedFile.Hash
            Status = $signature.Status
            StatusMessage = $signature.StatusMessage
            SignerCertificate = $signature.SignerCertificate
            LastWriteTime = $lockedFile.LastWriteTime
        }
        
        # Cache the result
        $Script:FileHashCache[$cacheKey] = $result
        
        # Limit cache size to prevent memory exhaustion
        if ($Script:FileHashCache.Count -gt 10000) {
            $Script:FileHashCache.Clear()
            Write-Log "[CACHE] Cleared cache due to size limit"
        }
        
        return $result
    } catch {
        Write-ErrorLog -Message "Error processing file hash for $filePath" -Severity "Low" -ErrorRecord $_
        return $null
    }
}

function Get-SHA256Hash {
    param([string]$FilePath)
    
    try {
        if (Test-IsSelfOrRelated -FilePath $FilePath) {
            return $null
        }
        
        $lockedFile = Get-FileWithLock -FilePath $FilePath
        return $lockedFile.Hash
    } catch {
        return $null
    }
}

# ============================================
# SECURITY FIX #3: HARDENED QUARANTINE
# ============================================
function Quarantine-File {
    param ([string]$filePath)
    
    try {
        # SECURITY FIX #5: Never quarantine self
        if (Test-IsSelfOrRelated -FilePath $filePath) {
            Write-Log "[PROTECTION] Refusing to quarantine self/related file: $filePath"
            return $false
        }
        
        if (-not (Test-Path $filePath)) {
            Write-Log "[QUARANTINE] File not found: $filePath"
            return $false
        }
        
        # SECURITY FIX #2: Re-verify hash before quarantine
        $finalHash = Get-FileWithLock -FilePath $filePath
        if (-not $finalHash) {
            Write-Log "[QUARANTINE] Could not lock file for final verification: $filePath"
            return $false
        }
        
        # SECURITY FIX #3: Use GUID for unique quarantine naming
        $guid = [System.Guid]::NewGuid().ToString()
        $timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
        $fileName = Split-Path $filePath -Leaf
        $quarantinePath = Join-Path $quarantineFolder "${timestamp}_${guid}_${fileName}.quarantined"
        
        # SECURITY FIX #3: Strip execution permissions and rename
        Copy-Item -Path $filePath -Destination $quarantinePath -Force -ErrorAction Stop
        
        # SECURITY FIX #3: Remove execute permissions using icacls
        icacls $quarantinePath /deny "*S-1-1-0:(X)" /inheritance:r | Out-Null
        
        # Store metadata
        $metadata = @{
            OriginalPath = $filePath
            QuarantinePath = $quarantinePath
            Timestamp = $timestamp
            GUID = $guid
            Hash = $finalHash.Hash
            Reason = "Unsigned or malicious"
        } | ConvertTo-Json -Compress
        
        Add-Content -Path "$quarantineFolder\quarantine_metadata.jsonl" -Value $metadata -Encoding UTF8
        
        Write-Log "[QUARANTINE] File quarantined: $filePath -> $quarantinePath"
        
        # Attempt to delete original
        try {
            Remove-Item -Path $filePath -Force -ErrorAction Stop
            Write-Log "[QUARANTINE] Original file deleted: $filePath"
        } catch {
            Write-Log "[QUARANTINE] Could not delete original (may be in use): $filePath"
        }
        
        return $true
    } catch {
        Write-ErrorLog -Message "Failed to quarantine file: $filePath" -Severity "High" -ErrorRecord $_
        return $false
    }
}

function Invoke-QuarantineFile {
    param(
        [string]$FilePath,
        [string]$ProcessName,
        [int]$ProcessId,
        [string]$Reason
    )
    
    return Quarantine-File -filePath $FilePath
}

# Take Ownership and Modify Permissions
function Set-FileOwnershipAndPermissions {
    param ([string]$filePath)
    
    try {
        if (Test-IsSelfOrRelated -FilePath $filePath) {
            Write-Log "[PROTECTION] Refusing to modify self/related file permissions: $filePath"
            return $false
        }
        
        takeown /F $filePath /A 2>&1 | Out-Null
        icacls $filePath /reset 2>&1 | Out-Null
        icacls $filePath /grant "Administrators:F" /inheritance:d 2>&1 | Out-Null
        Write-Log "[PERMISSIONS] Set ownership for $filePath"
        return $true
    } catch {
        Write-ErrorLog -Message "Failed to set ownership for $filePath" -Severity "Medium" -ErrorRecord $_
        return $false
    }
}

# Stop Processes Using DLL
function Stop-ProcessUsingDLL {
    param ([string]$filePath)
    
    try {
        if (Test-IsSelfOrRelated -FilePath $filePath) {
            return
        }
        
        $processes = Get-Process | Where-Object { 
            try {
                ($_.Modules | Where-Object { $_.FileName -eq $filePath }) -and 
                -not (Test-ProtectedOrSelf $_) -and 
                -not (Test-CriticalSystemProcess $_)
            } catch { $false }
        }
        
        foreach ($process in $processes) {
            try {
                Stop-Process -Id $process.Id -Force -ErrorAction Stop
                Write-Log "[KILL] Stopped process $($process.Name) (PID: $($process.Id)) using $filePath"
            } catch {
                Write-ErrorLog -Message "Failed to stop process $($process.Name) using $filePath" -Severity "Medium" -ErrorRecord $_
            }
        }
    } catch {
        Write-ErrorLog -Message "Error stopping processes for $filePath" -Severity "Medium" -ErrorRecord $_
    }
}

function Stop-ProcessesUsingFile {
    param([string]$FilePath)
    
    try {
        if (Test-IsSelfOrRelated -FilePath $FilePath) {
            return
        }
        
        Get-Process | Where-Object {
            try {
                $_.Path -eq $FilePath -and 
                -not (Test-ProtectedOrSelf $_) -and 
                -not (Test-CriticalSystemProcess $_) -and
                -not (Test-IsWindowsNetworkingService -ProcessId $_.Id)
            } catch { $false }
        } | ForEach-Object {
            try {
                $_.Kill()
                Write-Log "[KILL] Terminated process using file: $($_.ProcessName) (PID: $($_.Id))"
                Start-Sleep -Milliseconds 100
            } catch {
                Write-ErrorLog -Message "Failed to kill process $($_.ProcessName)" -Severity "Low" -ErrorRecord $_
            }
        }
    } catch {
        Write-ErrorLog -Message "Error in Stop-ProcessesUsingFile" -Severity "Low" -ErrorRecord $_
    }
}

function Should-ExcludeFile {
    param ([string]$filePath)
    
    $lowerPath = $filePath.ToLower()
    
    # SECURITY FIX #5: Exclude self and related files
    if (Test-IsSelfOrRelated -FilePath $filePath) {
        return $true
    }
    
    # Exclude assembly folders
    if ($lowerPath -like "*\assembly\*") {
        return $true
    }
    
    # Exclude ctfmon-related files
    if ($lowerPath -like "*ctfmon*" -or $lowerPath -like "*msctf.dll" -or $lowerPath -like "*msutb.dll") {
        return $true
    }
    
    return $false
}

# ============================================
# SECURITY FIX #8: PERFORMANCE-OPTIMIZED SCANNING
# ============================================
function Remove-UnsignedDLLs {
    Write-Log "[SCAN] Starting unsigned DLL/WINMD scan"
    
    $drives = Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object { $_.DriveType -in (2, 3, 4) }
    $Script:ScanThrottle = 0
    
    foreach ($drive in $drives) {
        $root = $drive.DeviceID + "\"
        Write-Log "[SCAN] Scanning drive: $root"
        
        try {
            $dllFiles = Get-ChildItem -Path $root -Include *.dll,*.winmd -Recurse -File -ErrorAction Stop
            
            foreach ($dll in $dllFiles) {
                # PERFORMANCE FIX #8: Throttle scanning to prevent system slowdown
                $Script:ScanThrottle++
                if ($Script:ScanThrottle % 100 -eq 0) {
                    Start-Sleep -Milliseconds 50
                }
                
                try {
                    if (Should-ExcludeFile -filePath $dll.FullName) {
                        continue
                    }
                    
                    $fileHash = Calculate-FileHash -filePath $dll.FullName
                    if ($fileHash) {
                        if ($scannedFiles.ContainsKey($fileHash.Hash)) {
                            # Already scanned, take action if needed
                            if (-not $scannedFiles[$fileHash.Hash]) {
                                if (Set-FileOwnershipAndPermissions -filePath $dll.FullName) {
                                    Stop-ProcessUsingDLL -filePath $dll.FullName
                                    Quarantine-File -filePath $dll.FullName
                                }
                            }
                        } else {
                            # New file
                            $isValid = $fileHash.Status -eq "Valid"
                            $scannedFiles[$fileHash.Hash] = $isValid
                            "$($fileHash.Hash),$isValid" | Out-File -FilePath $localDatabase -Append -Encoding UTF8 -ErrorAction Stop
                            Update-DatabaseIntegrity # SECURITY FIX #3: Update HMAC
                            
                            Write-Log "[SCAN] New file: $($dll.FullName) (Valid: $isValid)"
                            
                            if (-not $isValid) {
                                if (Set-FileOwnershipAndPermissions -filePath $dll.FullName) {
                                    Stop-ProcessUsingDLL -filePath $dll.FullName
                                    Quarantine-File -filePath $dll.FullName
                                }
                            }
                        }
                    }
                } catch {
                    Write-ErrorLog -Message "Error processing file $($dll.FullName)" -Severity "Low" -ErrorRecord $_
                }
            }
        } catch {
            Write-ErrorLog -Message "Scan failed for drive $root" -Severity "Medium" -ErrorRecord $_
        }
    }
}

# ============================================
# FILE SYSTEM WATCHER (Throttled)
# ============================================
$drives = Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object { $_.DriveType -in (2, 3, 4) }
foreach ($drive in $drives) {
    $monitorPath = $drive.DeviceID + "\"
    
    try {
        $fileWatcher = New-Object System.IO.FileSystemWatcher
        $fileWatcher.Path = $monitorPath
        $fileWatcher.Filter = "*.*"
        $fileWatcher.IncludeSubdirectories = $true
        $fileWatcher.EnableRaisingEvents = $true
        $fileWatcher.NotifyFilter = [System.IO.NotifyFilters]::FileName -bor [System.IO.NotifyFilters]::LastWrite
        
        $action = {
            param($sender, $e)
            
            try {
                $localScannedFiles = $using:scannedFiles
                $localQuarantineFolder = $using:quarantineFolder
                $localDatabase = $using:localDatabase
                
                if ($e.ChangeType -in "Created", "Changed" -and 
                    $e.FullPath -notlike "$localQuarantineFolder*" -and 
                    ($e.FullPath -like "*.dll" -or $e.FullPath -like "*.winmd")) {
                    
                    if (Should-ExcludeFile -filePath $e.FullPath) {
                        return
                    }
                    
                    Start-Sleep -Milliseconds 500 # Throttle
                    
                    $fileHash = Calculate-FileHash -filePath $e.FullPath
                    if ($fileHash) {
                        if ($localScannedFiles.ContainsKey($fileHash.Hash)) {
                            if (-not $localScannedFiles[$fileHash.Hash]) {
                                if (Set-FileOwnershipAndPermissions -filePath $e.FullPath) {
                                    Stop-ProcessUsingDLL -filePath $e.FullPath
                                    Quarantine-File -filePath $e.FullPath
                                }
                            }
                        } else {
                            $isValid = $fileHash.Status -eq "Valid"
                            $localScannedFiles[$fileHash.Hash] = $isValid
                            "$($fileHash.Hash),$isValid" | Out-File -FilePath $localDatabase -Append -Encoding UTF8
                            
                            if (-not $isValid) {
                                if (Set-FileOwnershipAndPermissions -filePath $e.FullPath) {
                                    Stop-ProcessUsingDLL -filePath $e.FullPath
                                    Quarantine-File -filePath $e.FullPath
                                }
                            }
                        }
                    }
                }
            } catch {
                # Silently continue
            }
        }
        
        Register-ObjectEvent -InputObject $fileWatcher -EventName Created -Action $action -ErrorAction Stop
        Register-ObjectEvent -InputObject $fileWatcher -EventName Changed -Action $action -ErrorAction Stop
        Write-Log "[WATCHER] FileSystemWatcher set up for $monitorPath"
    } catch {
        Write-ErrorLog -Message "Failed to set up watcher for $monitorPath" -Severity "Medium" -ErrorRecord $_
    }
}

$ApiConfig = @{
    CirclHashLookupUrl   = "https://hashlookup.circl.lu/lookup/sha256"
    CymruApiUrl          = "https://api.malwarehash.cymru.com/v1/hash"
    MalwareBazaarApiUrl  = "https://mb-api.abuse.ch/api/v1/"
}

# ============================================
# HASH-BASED THREAT DETECTION
# ============================================
function Check-FileHash {
    param(
        [string]$FilePath,
        [string]$ProcessName,
        [int]$ProcessId
    )
    
    try {
        if (-not (Test-Path $FilePath)) {
            return $false
        }
        
        if (Test-IsSelfOrRelated -FilePath $FilePath) {
            return $false
        }
        
        $hash = (Get-FileHash -Path $FilePath -Algorithm SHA256).Hash
        
        $isMalicious = $false
        
        # Check CIRCL Hash Lookup
        try {
            $circlUrl = "$($ApiConfig.CirclHashLookupUrl)/$hash"
            $circlResponse = Invoke-RestMethod -Uri $circlUrl -Method Get -TimeoutSec 5 -ErrorAction Stop
            if ($circlResponse -and $circlResponse.KnownMalicious) {
                Write-Log "[HASH] CIRCL reports malicious: $ProcessName"
                $isMalicious = $true
            }
        } catch {
            # API unavailable or not found
        }
        
        # Check Team Cymru
        try {
            $cymruUrl = "$($ApiConfig.CymruApiUrl)/$hash"
            $cymruResponse = Invoke-RestMethod -Uri $cymruUrl -Method Get -TimeoutSec 5 -ErrorAction Stop
            if ($cymruResponse -and $cymruResponse.malicious -eq $true) {
                Write-Log "[HASH] Cymru reports malicious: $ProcessName"
                $isMalicious = $true
            }
        } catch {
            # API unavailable
        }
        
        # Check MalwareBazaar
        try {
            $mbBody = @{ query = "get_info"; hash = $hash } | ConvertTo-Json
            $mbResponse = Invoke-RestMethod -Uri $ApiConfig.MalwareBazaarApiUrl -Method Post -Body $mbBody -ContentType "application/json" -TimeoutSec 5 -ErrorAction Stop
            if ($mbResponse -and $mbResponse.query_status -eq "ok") {
                Write-Log "[HASH] MalwareBazaar reports known malware: $ProcessName"
                $isMalicious = $true
            }
        } catch {
            # API unavailable
        }
        
        return $isMalicious
    } catch {
        Write-ErrorLog -Message "Error during hash check for $FilePath" -Severity "Low" -ErrorRecord $_
        return $false
    }
}

# ============================================
# THREAT KILLING WITH SAFETY CHECKS
# ============================================
function Kill-Threat {
    param(
        [int]$ProcessId,
        [string]$ProcessName,
        [string]$Reason
    )
    
    try {
        $proc = Get-Process -Id $ProcessId -ErrorAction SilentlyContinue
        if (-not $proc) {
            return $false
        }
        
        # SECURITY FIX #5 & #6: Comprehensive protection checks
        if (Test-ProtectedOrSelf $proc) {
            Write-Log "[PROTECTION] Refusing to kill protected process: $ProcessName (PID: $ProcessId)"
            return $false
        }
        
        if (Test-CriticalSystemProcess $proc) {
            Write-Log "[PROTECTION] Refusing to kill critical system process: $ProcessName (PID: $ProcessId)"
            return $false
        }
        
        if (Test-IsWindowsNetworkingService -ProcessId $ProcessId) {
            Write-Log "[PROTECTION] Refusing to kill Windows networking service: $ProcessName (PID: $ProcessId)"
            return $false
        }
        
        Write-Log "[KILL] Terminating process: $ProcessName (PID: $ProcessId) - Reason: $Reason"
        Stop-Process -Id $ProcessId -Force -ErrorAction Stop
        Write-Log "[KILL] Successfully terminated PID: $ProcessId"
        return $true
    } catch {
        Write-ErrorLog -Message "Failed to terminate PID $ProcessId" -Severity "Low" -ErrorRecord $_
        return $false
    }
}

function Stop-ThreatProcess {
    param(
        [int]$ProcessId,
        [string]$ProcessName,
        [string]$Reason
    )
    
    return Kill-Threat -ProcessId $ProcessId -ProcessName $ProcessName -Reason $Reason
}

function Invoke-ProcessKill {
    param(
        [int]$ProcessId,
        [string]$ProcessName,
        [string]$Reason
    )
    
    return Kill-Threat -ProcessId $ProcessId -ProcessName $ProcessName -Reason $Reason
}

function Invoke-QuarantineProcess {
    param(
        $Process,
        [string]$Reason
    )
    
    try {
        if (Test-ProtectedOrSelf $Process) {
            Write-Log "[PROTECTION] Refusing to quarantine protected process: $($Process.ProcessName)"
            return $false
        }
        
        Write-Log "[QUARANTINE] Quarantining process $($Process.ProcessName) (PID: $($Process.Id)) due to: $Reason"
        
        if ($Process.Path -and (Test-Path $Process.Path)) {
            Invoke-QuarantineFile -FilePath $Process.Path -ProcessName $Process.ProcessName -ProcessId $Process.Id -Reason $Reason
        }
        
        $Process.Kill()
        Write-Log "[KILL] Killed malicious process: $($Process.ProcessName) (PID: $($Process.Id))"
        return $true
    } catch {
        Write-ErrorLog -Message "Failed to quarantine process $($Process.ProcessName)" -Severity "Medium" -ErrorRecord $_
        return $false
    }
}

# ============================================
# SECURITY FIX #4: LOLBIN DETECTION
# ============================================
function Test-LOLBinAbuse {
    param(
        [string]$ProcessName,
        [string]$CommandLine
    )
    
    $procLower = $ProcessName.ToLower()
    
    if ($Script:LOLBinPatterns.ContainsKey($procLower)) {
        $patterns = $Script:LOLBinPatterns[$procLower]
        foreach ($pattern in $patterns) {
            if ($CommandLine -match [regex]::Escape($pattern)) {
                Write-Log "[LOLBIN] Detected LOLBin abuse: $ProcessName with pattern '$pattern'"
                return $true
            }
        }
    }
    
    return $false
}

# ============================================
# FILELESS MALWARE DETECTION
# ============================================
function Detect-FilelessMalware {
    $detections = @()
    
    # PowerShell without file
    try {
        Get-Process -Name powershell -ErrorAction SilentlyContinue | Where-Object {
            try {
                -not (Test-ProtectedOrSelf $_) -and
                ($_.MainWindowTitle -match "encodedcommand|enc|iex|invoke-expression" -or
                ($_.Modules | Where-Object { $_.ModuleName -eq "" -or $_.FileName -eq "" }))
            } catch { $false }
        } | ForEach-Object {
            $proc = $_
            Write-Log "[FILELESS] Detected suspicious PowerShell: PID $($proc.Id)"
            
            if ($proc.Path) {
                $hashMalicious = Check-FileHash -FilePath $proc.Path -ProcessName $proc.Name -ProcessId $proc.Id
                if ($hashMalicious) {
                    Invoke-QuarantineFile -FilePath $proc.Path -ProcessName $proc.Name -ProcessId $proc.Id -Reason "Malicious hash + Fileless PowerShell"
                }
            }
            
            Kill-Threat -ProcessId $proc.Id -ProcessName $proc.Name -Reason "Fileless PowerShell execution"
        }
    } catch {
        Write-ErrorLog -Message "Error in PowerShell fileless detection" -Severity "Low" -ErrorRecord $_
    }
    
    # WMI Event Subscriptions
    try {
        Get-WmiObject -Namespace root\Subscription -Class __EventFilter -ErrorAction SilentlyContinue | Where-Object {
            $_.Query -match "powershell|vbscript|javascript"
        } | ForEach-Object {
            $subscription = $_
            try {
                Write-Log "[FILELESS] Removing malicious WMI event filter: $($subscription.Name)"
                Remove-WmiObject -InputObject $subscription -ErrorAction Stop
                
                $consumers = Get-WmiObject -Namespace root\Subscription -Class __EventConsumer -Filter "Name='$($subscription.Name)'" -ErrorAction SilentlyContinue
                $bindings = Get-WmiObject -Namespace root\Subscription -Class __FilterToConsumerBinding -Filter "Filter='$($subscription.__RELPATH)'" -ErrorAction SilentlyContinue
                
                foreach ($consumer in $consumers) {
                    Remove-WmiObject -InputObject $consumer -ErrorAction SilentlyContinue
                }
                foreach ($binding in $bindings) {
                    Remove-WmiObject -InputObject $binding -ErrorAction SilentlyContinue
                }
            } catch {
                Write-ErrorLog -Message "Failed to remove WMI subscription" -Severity "Medium" -ErrorRecord $_
            }
        }
    } catch {
        Write-ErrorLog -Message "Error in WMI fileless detection" -Severity "Low" -ErrorRecord $_
    }
    
    # Registry Scripts
    try {
        $suspiciousKeys = @(
            "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
            "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
        )
        
        foreach ($key in $suspiciousKeys) {
            if (Test-Path $key) {
                Get-ItemProperty -Path $key -ErrorAction SilentlyContinue | ForEach-Object {
                    $_.PSObject.Properties | Where-Object {
                        $_.Value -match "powershell.*-enc|mshta|regsvr32.*scrobj"
                    } | ForEach-Object {
                        try {
                            Write-Log "[FILELESS] Removing malicious registry entry: $($_.Name)"
                            Remove-ItemProperty -Path $key -Name $_.Name -Force -ErrorAction Stop
                        } catch {
                            Write-ErrorLog -Message "Failed to remove registry entry" -Severity "Medium" -ErrorRecord $_
                        }
                    }
                }
            }
        }
    } catch {
        Write-ErrorLog -Message "Error in registry fileless detection" -Severity "Low" -ErrorRecord $_
    }
    
    return $detections
}

# ============================================
# MEMORY SCANNER
# ============================================
Write-Log "[+] Starting PowerShell memory scanner"
Start-Job -ScriptBlock {
    $log = "$using:Base\ps_memory_hits.log"
    $QuarantineDir = $using:QuarantineDir
    $Base = $using:Base
    $SelfProcessName = $using:Script:SelfProcessName
    $ProtectedProcessNames = $using:Script:ProtectedProcessNames
    
    ${function:Check-FileHash} = ${using:function:Check-FileHash}
    ${function:Kill-Threat} = ${using:function:Kill-Threat}
    ${function:Invoke-QuarantineFile} = ${using:function:Invoke-QuarantineFile}
    ${function:Write-Log} = ${using:function:Write-Log}
    ${function:Test-ProtectedOrSelf} = ${using:function:Test-ProtectedOrSelf}
    ${function:Test-CriticalSystemProcess} = ${using:function:Test-CriticalSystemProcess}
    ${function:Test-IsWindowsNetworkingService} = ${using:function:Test-IsWindowsNetworkingService}
    ${function:Test-IsSelfOrRelated} = ${using:function:Test-IsSelfOrRelated}
    
    $ApiConfig = $using:ApiConfig
    $logFile = $using:logFile
    $Script:logFile = $logFile
    $Script:SelfProcessName = $SelfProcessName
    $Script:ProtectedProcessNames = $ProtectedProcessNames
    
    $EvilStrings = @(
        'mimikatz','sekurlsa::','kerberos::','lsadump::','wdigest','tspkg',
        'http-beacon','https-beacon','cobaltstrike','sleepmask','reflective',
        'amsi.dll','AmsiScanBuffer','EtwEventWrite','MiniDumpWriteDump',
        'VirtualAllocEx','WriteProcessMemory','CreateRemoteThread',
        'ReflectiveLoader','sharpchrome','rubeus','safetykatz','sharphound'
    )
    
    while ($true) {
        Start-Sleep -Seconds 2
        
        Get-Process | Where-Object {
            try {
                $procId = $_.Id
                if ($procId -eq $SelfProcessName) { return $false }
                
                $_.WorkingSet64 -gt 100MB -or $_.Name -match 'powershell|wscript|cscript|mshta|rundll32|regsvr32|msbuild|cmstp'
            } catch { $false }
        } | ForEach-Object {
            $hit = $false
            $proc = $_
            
            try {
                if (Test-ProtectedOrSelf $proc) { return }
                if (Test-CriticalSystemProcess $proc) { return }
                if (Test-IsWindowsNetworkingService -ProcessId $proc.Id) { return }
                
                $proc.Modules | ForEach-Object {
                    if ($EvilStrings | Where-Object { $_.ModuleName -match $_ -or $_.FileName -match $_ }) {
                        $hit = $true
                    }
                }
            } catch {}
            
            if ($hit) {
                "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | PS MEMORY HIT → $($proc.Name) ($($proc.Id))" | Out-File $log -Append
                
                if ($proc.Path) {
                    $hashMalicious = Check-FileHash -FilePath $proc.Path -ProcessName $proc.Name -ProcessId $proc.Id
                    if ($hashMalicious) {
                        Invoke-QuarantineFile -FilePath $proc.Path -ProcessName $proc.Name -ProcessId $proc.Id -Reason "Malicious strings in memory"
                    }
                }
                
                Kill-Threat -ProcessId $proc.Id -ProcessName $proc.Name -Reason "Malicious strings in memory"
            }
        }
    }
} | Out-Null

# ============================================
# REFLECTIVE PAYLOAD DETECTOR
# ============================================
Write-Log "[+] Starting reflective payload detector"
Start-Job -ScriptBlock {
    $log = "$using:Base\manual_map_hits.log"
    $QuarantineDir = $using:QuarantineDir
    $Base = $using:Base
    $SelfProcessName = $using:Script:SelfProcessName
    
    ${function:Check-FileHash} = ${using:function:Check-FileHash}
    ${function:Kill-Threat} = ${using:function:Kill-Threat}
    ${function:Invoke-QuarantineFile} = ${using:function:Invoke-QuarantineFile}
    ${function:Write-Log} = ${using:function:Write-Log}
    ${function:Test-ProtectedOrSelf} = ${using:function:Test-ProtectedOrSelf}
    ${function:Test-CriticalSystemProcess} = ${using:function:Test-CriticalSystemProcess}
    
    $ApiConfig = $using:ApiConfig
    $logFile = $using:logFile
    $Script:logFile = $logFile
    $Script:SelfProcessName = $SelfProcessName
    
    while ($true) {
        Start-Sleep -Seconds 2
        
        Get-Process | Where-Object { 
            try {
                $_.Id -ne $SelfProcessName -and $_.WorkingSet64 -gt 40MB
            } catch { $false }
        } | ForEach-Object {
            $p = $_
            $sus = $false
            
            try {
                if (Test-ProtectedOrSelf $p) { return }
                if (Test-CriticalSystemProcess $p) { return }
                
                if (-not $p.Path -or $p.Path -eq '' -or $p.Path -match '$$Unknown$$') { $sus = $true }
                if ($p.Modules | Where-Object { $_.FileName -eq '' -or $_.ModuleName -eq '' }) { $sus = $true }
            } catch {}
            
            if ($sus) {
                "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | REFLECTIVE PAYLOAD → $($p.Name) ($($p.Id)) Path='$($p.Path)'" | Out-File $log -Append
                
                if ($p.Path) {
                    $hashMalicious = Check-FileHash -FilePath $p.Path -ProcessName $p.Name -ProcessId $p.Id
                    if ($hashMalicious) {
                        Invoke-QuarantineFile -FilePath $p.Path -ProcessName $p.Name -ProcessId $p.Id -Reason "Reflective payload detected"
                    }
                }
                
                Kill-Threat -ProcessId $p.Id -ProcessName $p.Name -Reason "Reflective payload detected"
            }
        }
    }
} | Out-Null

# ============================================
# BEHAVIOR MONITOR
# ============================================
function Start-BehaviorMonitor {
    $suspiciousBehaviors = @{
        "ProcessHollowing" = {
            param($Process)
            try {
                $procPath = $Process.Path
                $modules = Get-Process -Id $Process.Id -Module -ErrorAction SilentlyContinue
                return ($modules -and $procPath -and ($modules[0].FileName -ne $procPath))
            } catch { return $false }
        }
        "CredentialAccess" = {
            param($Process)
            try {
                $cmdline = (Get-CimInstance Win32_Process -Filter "ProcessId=$($Process.Id)" -ErrorAction SilentlyContinue).CommandLine
                return ($cmdline -match "mimikatz|procdump|sekurlsa|lsadump" -or 
                        $Process.ProcessName -match "vaultcmd|cred")
            } catch { return $false }
        }
        "LateralMovement" = {
            param($Process)
            try {
                $connections = Get-NetTCPConnection -OwningProcess $Process.Id -ErrorAction SilentlyContinue
                $remoteIPs = $connections | Where-Object { 
                    $_.RemoteAddress -notmatch "^(127\.|192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)" -and
                    $_.RemoteAddress -ne "0.0.0.0" -and
                    $_.RemoteAddress -ne "::"
                }
                return ($remoteIPs.Count -gt 5)
            } catch { return $false }
        }
    }
    
    Start-Job -ScriptBlock {
        $behaviors = $using:suspiciousBehaviors
        $logFile = "$using:Base\behavior_detections.log"
        $Base = $using:Base
        $QuarantineDir = $using:QuarantineDir
        $SelfProcessName = $using:Script:SelfProcessName
        
        ${function:Check-FileHash} = ${using:function:Check-FileHash}
        ${function:Kill-Threat} = ${using:function:Kill-Threat}
        ${function:Invoke-QuarantineFile} = ${using:function:Invoke-QuarantineFile}
        ${function:Write-Log} = ${using:function:Write-Log}
        ${function:Test-ProtectedOrSelf} = ${using:function:Test-ProtectedOrSelf}
        ${function:Test-CriticalSystemProcess} = ${using:function:Test-CriticalSystemProcess}
        
        $ApiConfig = $using:ApiConfig
        $Script:logFile = $using:logFile
        $Script:SelfProcessName = $SelfProcessName
        
        while ($true) {
            Start-Sleep -Seconds 5
            
            Get-Process | Where-Object {
                try { $_.Id -ne $SelfProcessName } catch { $false }
            } | ForEach-Object {
                $process = $_
                
                if (Test-ProtectedOrSelf $process) { return }
                if (Test-CriticalSystemProcess $process) { return }
                
                foreach ($behavior in $behaviors.Keys) {
                    try {
                        if (& $behaviors[$behavior] $process) {
                            $msg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | BEHAVIOR DETECTED: $behavior | " +
                                   "Process: $($process.Name) PID: $($process.Id) Path: $($process.Path)"
                            $msg | Out-File $logFile -Append
                            
                            if ($behavior -in @("ProcessHollowing", "CredentialAccess")) {
                                if ($process.Path) {
                                    $hashMalicious = Check-FileHash -FilePath $process.Path -ProcessName $process.Name -ProcessId $process.Id
                                    if ($hashMalicious) {
                                        Invoke-QuarantineFile -FilePath $process.Path -ProcessName $process.Name -ProcessId $process.Id -Reason "Suspicious behavior: $behavior"
                                    }
                                }
                                Kill-Threat -ProcessId $process.Id -ProcessName $process.Name -Reason "Suspicious behavior: $behavior"
                            }
                        }
                    } catch {}
                }
            }
        }
    } | Out-Null
}

function Start-EnhancedBehaviorMonitor {
    Start-Job -ScriptBlock {
        param($LogFile, $ProtectedProcessNames, $SelfProcessName, $QuarantineDir, $LOLBinPatterns)
        
        $Script:LogFile = $LogFile
        $Script:QuarantineDir = $QuarantineDir
        $Script:SelfProcessName = $SelfProcessName
        $Script:LOLBinPatterns = $LOLBinPatterns
        
        ${function:Test-LOLBinAbuse} = ${using:function:Test-LOLBinAbuse}
        ${function:Test-ProtectedOrSelf} = ${using:function:Test-ProtectedOrSelf}
        ${function:Test-CriticalSystemProcess} = ${using:function:Test-CriticalSystemProcess}
        ${function:Kill-Threat} = ${using:function:Kill-Threat}
        ${function:Invoke-QuarantineFile} = ${using:function:Invoke-QuarantineFile}
        
        while ($true) {
            try {
                Get-Process | Where-Object {
                    try {
                        $procId = $_.Id
                        if ($procId -eq $SelfProcessName) { return $false }
                        if ($ProtectedProcessNames -contains $_.ProcessName.ToLower()) { return $false }
                        $true
                    } catch { $false }
                } | ForEach-Object {
                    try {
                        $proc = $_
                        
                        # SECURITY FIX #4: LOLBin detection
                        $commandLine = (Get-CimInstance Win32_Process -Filter "ProcessId = $($proc.Id)" -ErrorAction SilentlyContinue).CommandLine
                        if ($commandLine -and (Test-LOLBinAbuse -ProcessName $proc.ProcessName -CommandLine $commandLine)) {
                            Add-Content -Path $LogFile -Value "[LOLBIN ABUSE] Detected in $($proc.ProcessName) (PID: $($proc.Id)): $commandLine" -Encoding UTF8
                            
                            if ($proc.Path) {
                                Invoke-QuarantineFile -FilePath $proc.Path -ProcessName $proc.ProcessName -ProcessId $proc.Id -Reason "LOLBin abuse detected"
                            }
                            Kill-Threat -ProcessId $proc.Id -ProcessName $proc.ProcessName -Reason "LOLBin abuse"
                        }
                        
                        # High thread/handle count
                        $threadCount = $proc.Threads.Count
                        $handleCount = $proc.HandleCount
                        
                        if ($threadCount -gt 100 -or $handleCount -gt 10000) {
                            Add-Content -Path $LogFile -Value "SUSPICIOUS BEHAVIOR: High thread/handle count in $($proc.ProcessName) (Threads: $threadCount, Handles: $handleCount)" -Encoding UTF8
                        }
                        
                        # Random process name
                        if ($proc.ProcessName -match "^[a-z0-9]{32}$") {
                            Add-Content -Path $LogFile -Value "SUSPICIOUS BEHAVIOR: Random process name: $($proc.ProcessName)" -Encoding UTF8
                        }
                    } catch {}
                }
                
                Start-Sleep -Seconds 30
            } catch {}
        }
    } -ArgumentList $Script:logFile, $Script:ProtectedProcessNames, $Script:SelfProcessName, $Script:QuarantineDir, $Script:LOLBinPatterns | Out-Null
    
    Write-Log "[+] Enhanced behavior monitor started"
}

# ============================================
# COM CONTROL MONITOR
# ============================================
function Start-COMControlMonitor {
    Start-Job -ScriptBlock {
        param($LogFile, $QuarantineDir)
        
        $Script:LogFile = $LogFile
        $Script:QuarantineDir = $QuarantineDir
        
        while ($true) {
            try {
                $basePaths = @(
                    "HKLM:\SOFTWARE\WOW6432Node\Classes\CLSID",
                    "HKLM:\SOFTWARE\Classes\CLSID"
                )
                
                foreach ($basePath in $basePaths) {
                    if (Test-Path $basePath) {
                        Get-ChildItem -Path $basePath | Where-Object {
                            $_.PSChildName -match "\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}"
                        } | ForEach-Object {
                            $clsid = $_.PSChildName
                            $clsidPath = Join-Path $basePath $clsid
                            
                            @("InProcServer32", "InprocHandler32") | ForEach-Object {
                                $subKeyPath = Join-Path $clsidPath $_
                                
                                if (Test-Path $subKeyPath) {
                                    $dllPath = (Get-ItemProperty -Path $subKeyPath -Name "(Default)" -ErrorAction SilentlyContinue)."(Default)"
                                    
                                    if ($dllPath -and (Test-Path $dllPath)) {
                                        if ($dllPath -match "\\temp\\|\\downloads\\|\\public\\" -or (Get-Item $dllPath).Length -lt 100KB) {
                                            Add-Content -Path $LogFile -Value "REMOVING malicious COM control: $dllPath" -Encoding UTF8
                                            Remove-Item -Path $clsidPath -Recurse -Force -ErrorAction SilentlyContinue
                                            Remove-Item -Path $dllPath -Force -ErrorAction SilentlyContinue
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                
                Start-Sleep -Seconds 60
            } catch {}
        }
    } -ArgumentList $Script:logFile, $Script:QuarantineDir | Out-Null
    
    Write-Log "[+] COM control monitor started"
}

function Invoke-MalwareScan {
    try {
        Get-Process | Where-Object {
            try {
                -not (Test-ProtectedOrSelf $_) -and 
                -not (Test-CriticalSystemProcess $_) -and
                -not (Test-IsWindowsNetworkingService -ProcessId $_.Id)
            } catch { $false }
        } | ForEach-Object {
            try {
                $proc = $_
                $procName = $proc.ProcessName.ToLower()
                
                # Fileless malware detection
                if ($procName -match "powershell|cmd") {
                    $commandLine = (Get-CimInstance Win32_Process -Filter "ProcessId = $($proc.Id)" -ErrorAction SilentlyContinue).CommandLine
                    
                    if ($commandLine -and ($commandLine -match "-encodedcommand|-enc|invoke-expression|downloadstring|iex|-executionpolicy bypass")) {
                        Write-Log "[DETECTED] Fileless malware: $($proc.ProcessName) (PID: $($proc.Id))"
                        Invoke-QuarantineProcess -Process $proc -Reason "Fileless malware execution"
                    }
                }
            } catch {}
        }
    } catch {}
}

function Invoke-LogRotation {
    try {
        if ((Get-Item $Script:logFile -ErrorAction SilentlyContinue).Length -gt 50MB) {
            $backupLog = "$($Script:logFile).old"
            if (Test-Path $backupLog) {
                Remove-Item $backupLog -Force
            }
            Move-Item $Script:logFile $backupLog -Force
            Write-Log "[*] Log rotated due to size"
        }
    } catch {}
}

# ============================================
# SECURITY FIX #1: PERIODIC INTEGRITY CHECKS
# ============================================
function Start-IntegrityMonitor {
    Start-Job -ScriptBlock {
        param($SelfPath, $SelfHash)
        
        ${function:Test-ScriptIntegrity} = ${using:function:Test-ScriptIntegrity}
        $Script:SelfPath = $SelfPath
        $Script:SelfHash = $SelfHash
        
        while ($true) {
            Start-Sleep -Seconds 60
            
            if (-not (Test-ScriptIntegrity)) {
                # Script has been tampered with - terminate
                Write-Host "[CRITICAL] Script integrity compromised. Terminating."
                Stop-Process -Id $PID -Force
            }
        }
    } -ArgumentList $Script:SelfPath, $Script:SelfHash | Out-Null
    
    Write-Log "[+] Integrity monitor started"
}

# ============================================
# MAIN EXECUTION
# ============================================
Write-Log "[+] Starting all detection modules"

# Add persistence
Add-ToStartup

# Initial scan
Remove-UnsignedDLLs

# Start all monitoring jobs
Start-BehaviorMonitor
Start-EnhancedBehaviorMonitor
Start-COMControlMonitor
Start-IntegrityMonitor

Write-Log "[+] All monitoring modules started successfully"
Write-Log "[+] Self-protection: ACTIVE"
Write-Log "[+] Database integrity: VERIFIED"
Write-Log "[+] Watchdog persistence: CONFIGURED"

# Keep script running
Write-Host "Production Hardened Antivirus running. Press [Ctrl] + [C] to stop."

try {
    while ($true) {
        # Periodic integrity check
        if (-not (Test-ScriptIntegrity)) {
            Write-Log "[CRITICAL] Script integrity violation during runtime!"
            break
        }
        
        # Run fileless malware detection
        Start-Sleep -Seconds 10
        Detect-FilelessMalware | Out-Null
        
        # Run malware scan
        Invoke-MalwareScan
        
        # Rotate logs
        Invoke-LogRotation
        
        # Update database integrity
        if ($scannedFiles.Count % 100 -eq 0) {
            Update-DatabaseIntegrity
        }
    }
} finally {
    # Cleanup
    Write-Log "=== Stopping detection modules ==="
    
    if ($Script:SecurityMutex) {
        $Script:SecurityMutex.ReleaseMutex()
        $Script:SecurityMutex.Dispose()
    }
    
    Get-Job | Stop-Job
    Get-Job | Remove-Job
    
    Write-Log "=== Detection stopped ==="
}
Editor is loading...
Leave a Comment