Gorstaks Anti Malware

 avatar
unknown
powershell
3 months ago
20 kB
15
No Index
# PowerShell Malware Detection Script
# Runs autonomously with zero user input
# Requires Administrator privileges

# Ensure running as administrator
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Write-Error "This script requires Administrator privileges. Please run as Administrator."
    exit 1
}

# Create base directory for logs and quarantine
$Base = "$env:TEMP\MalwareDetection"
$QuarantineDir = "$Base\Quarantine"
if (-not (Test-Path $Base)) {
    New-Item -ItemType Directory -Path $Base -Force | Out-Null
}
if (-not (Test-Path $QuarantineDir)) {
    New-Item -ItemType Directory -Path $QuarantineDir -Force | Out-Null
}

# Logging function
function Log {
    param([string]$Message)
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] $Message"
    Write-Host $logEntry
    $logEntry | Out-File "$Base\main.log" -Append
}

Log "=== PowerShell Malware Detection Starting ==="
Log "[+] Log directory: $Base"
Log "[+] Quarantine directory: $QuarantineDir"

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

# ============================================
# ============================================
function Check-FileHash {
    param(
        [string]$FilePath,
        [string]$ProcessName,
        [int]$ProcessId
    )
    
    try {
        if (-not (Test-Path $FilePath)) {
            Log "[HASH] File not found for hash check: $FilePath"
            return $false
        }
        
        $hash = (Get-FileHash -Path $FilePath -Algorithm SHA256).Hash
        Log "[HASH] Checking hash for $ProcessName (PID: $ProcessId): $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) {
                Log "[HASH] CIRCL reports malicious: $ProcessName"
                $isMalicious = $true
            }
        } catch {
            Log "[HASH] CIRCL lookup failed or no result"
        }
        
        # 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) {
                Log "[HASH] Cymru reports malicious: $ProcessName"
                $isMalicious = $true
            }
        } catch {
            Log "[HASH] Cymru lookup failed or no result"
        }
        
        # 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") {
                Log "[HASH] MalwareBazaar reports known malware: $ProcessName"
                $isMalicious = $true
            }
        } catch {
            Log "[HASH] MalwareBazaar lookup failed or no result"
        }
        
        return $isMalicious
        
    } catch {
        Log "[HASH] Error during hash check: $_"
        return $false
    }
}

# ============================================
# ============================================
function Kill-Threat {
    param(
        [int]$ProcessId,
        [string]$ProcessName,
        [string]$Reason
    )
    
    try {
        if (Get-Process -Id $ProcessId -ErrorAction SilentlyContinue) {
            Log "[KILL] Terminating process: $ProcessName (PID: $ProcessId) - Reason: $Reason"
            Stop-Process -Id $ProcessId -Force -ErrorAction Stop
            Log "[KILL] Successfully terminated PID: $ProcessId"
            return $true
        } else {
            Log "[KILL] Process already terminated: PID $ProcessId"
            return $false
        }
    } catch {
        Log "[KILL] Failed to terminate PID $ProcessId : $_"
        return $false
    }
}

# ============================================
# ============================================
function Quarantine-File {
    param(
        [string]$FilePath,
        [string]$ProcessName,
        [int]$ProcessId,
        [string]$DetectionReason
    )
    
    try {
        if (-not (Test-Path $FilePath)) {
            Log "[QUARANTINE] File not found, cannot quarantine: $FilePath"
            return $false
        }
        
        $timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
        $fileName = [System.IO.Path]::GetFileName($FilePath)
        $quarantinePath = Join-Path $QuarantineDir "${timestamp}_${ProcessName}_${ProcessId}_${fileName}"
        
        # Copy file to quarantine
        Copy-Item -Path $FilePath -Destination $quarantinePath -Force -ErrorAction Stop
        
        # Log quarantine details
        $quarantineInfo = @{
            Timestamp = $timestamp
            OriginalPath = $FilePath
            QuarantinePath = $quarantinePath
            ProcessName = $ProcessName
            ProcessId = $ProcessId
            DetectionReason = $DetectionReason
        } | ConvertTo-Json -Compress
        
        $quarantineInfo | Out-File "$QuarantineDir\quarantine.log" -Append
        Log "[QUARANTINE] File quarantined: $FilePath -> $quarantinePath"
        
        # Try to delete original file
        try {
            Remove-Item -Path $FilePath -Force -ErrorAction Stop
            Log "[QUARANTINE] Original file deleted: $FilePath"
        } catch {
            Log "[QUARANTINE] Could not delete original file (may be in use): $FilePath"
        }
        
        return $true
        
    } catch {
        Log "[QUARANTINE] Failed to quarantine file: $_"
        return $false
    }
}

# ============================================
# FILELESS MALWARE DETECTION
# ============================================
function Detect-FilelessMalware {
    # Monitor for common fileless techniques
    $filelessIndicators = @{
        "PowerShellWithoutFile" = {
            Get-Process -Name powershell -ErrorAction SilentlyContinue |
            Where-Object {
                $_.MainWindowTitle -match "encodedcommand|enc|iex|invoke-expression" -or
                $_.Modules | Where-Object { 
                    $_.ModuleName -eq "" -or $_.FileName -eq ""
                }
            }
        }
        "WMIEventSubscriptions" = {
            Get-WmiObject -Namespace root\Subscription -Class __EventFilter -ErrorAction SilentlyContinue |
            Where-Object { $_.Query -match "powershell|vbscript|javascript" }
        }
        "RegistryScripts" = {
            $suspiciousKeys = @(
                "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
                "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
            )
            $results = @()
            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 {
                            $results += $_
                        }
                    }
                }
            }
            return $results
        }
    }
    
    $detections = @()
    foreach ($indicator in $filelessIndicators.Keys) {
        $results = & $filelessIndicators[$indicator]
        if ($results) {
            $detections += [PSCustomObject]@{
                Indicator = $indicator
                Details = $results
            }
            Log "[ALERT] Fileless malware detected: $indicator"
            
            if ($indicator -eq "PowerShellWithoutFile") {
                foreach ($proc in $results) {
                    # Check hash if file path exists
                    if ($proc.Path) {
                        $hashMalicious = Check-FileHash -FilePath $proc.Path -ProcessName $proc.Name -ProcessId $proc.Id
                        if ($hashMalicious) {
                            Quarantine-File -FilePath $proc.Path -ProcessName $proc.Name -ProcessId $proc.Id -DetectionReason "Malicious hash + Fileless PowerShell"
                        }
                    }
                    Kill-Threat -ProcessId $proc.Id -ProcessName $proc.Name -Reason "Fileless PowerShell execution"
                }
            }
            elseif ($indicator -eq "WMIEventSubscriptions") {
                foreach ($subscription in $results) {
                    try {
                        Log "[ACTION] Removing malicious WMI event filter: $($subscription.Name)"
                        Remove-WmiObject -InputObject $subscription -ErrorAction Stop
                        
                        # Also remove associated consumers and bindings
                        $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
                            Log "[ACTION] Removed associated WMI consumer: $($consumer.Name)"
                        }
                        foreach ($binding in $bindings) {
                            Remove-WmiObject -InputObject $binding -ErrorAction SilentlyContinue
                            Log "[ACTION] Removed WMI binding"
                        }
                    } catch {
                        Log "[ERROR] Failed to remove WMI subscription: $_"
                    }
                }
            }
            elseif ($indicator -eq "RegistryScripts") {
                foreach ($regEntry in $results) {
                    try {
                        $keyPath = $regEntry.PSPath
                        $valueName = $regEntry.Name
                        Log "[ACTION] Removing malicious registry entry: $keyPath\$valueName"
                        Remove-ItemProperty -Path $keyPath -Name $valueName -Force -ErrorAction Stop
                    } catch {
                        Log "[ERROR] Failed to remove registry entry: $_"
                    }
                }
            }
        }
    }
    
    return $detections
}

# ============================================
# MEMORY SCANNER
# ============================================
Log "[+] Starting PowerShell memory scanner"
Start-Job -ScriptBlock {
    $log = "$using:Base\ps_memory_hits.log"
    $QuarantineDir = $using:QuarantineDir
    $Base = $using:Base
    
    ${function:Check-FileHash} = ${using:function:Check-FileHash}
    ${function:Kill-Threat} = ${using:function:Kill-Threat}
    ${function:Quarantine-File} = ${using:function:Quarantine-File}
    ${function:Log} = ${using:function:Log}
    $ApiConfig = $using:ApiConfig
    
    $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 {
            $_.WorkingSet64 -gt 100MB -or $_.Name -match 'powershell|wscript|cscript|mshta|rundll32|regsvr32|msbuild|cmstp|excel|word|outlook'
        } | ForEach-Object {
            $hit = $false
            try {
                $_.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 → $($_.Name) ($($_.Id))" | Out-File $log -Append
                
                if ($_.Path) {
                    $hashMalicious = Check-FileHash -FilePath $_.Path -ProcessName $_.Name -ProcessId $_.Id
                    if ($hashMalicious) {
                        Quarantine-File -FilePath $_.Path -ProcessName $_.Name -ProcessId $_.Id -DetectionReason "Malicious strings in memory"
                    }
                }
                Kill-Threat -ProcessId $_.Id -ProcessName $_.Name -Reason "Malicious strings in memory"
            }
        }
    }
} | Out-Null

# ============================================
# REFLECTIVE PAYLOAD DETECTOR
# ============================================
Log "[+] Starting reflective payload detector"
Start-Job -ScriptBlock {
    $log = "$using:Base\manual_map_hits.log"
    $QuarantineDir = $using:QuarantineDir
    $Base = $using:Base
    
    ${function:Check-FileHash} = ${using:function:Check-FileHash}
    ${function:Kill-Threat} = ${using:function:Kill-Threat}
    ${function:Quarantine-File} = ${using:function:Quarantine-File}
    ${function:Log} = ${using:function:Log}
    $ApiConfig = $using:ApiConfig
    
    while ($true) {
        Start-Sleep -Seconds 2
        Get-Process | Where-Object { $_.WorkingSet64 -gt 40MB } | ForEach-Object {
            $p = $_
            $sus = $false
            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 }
            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) {
                        Quarantine-File -FilePath $p.Path -ProcessName $p.Name -ProcessId $p.Id -DetectionReason "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)
            # Check for process hollowing indicators
            $procPath = $Process.Path
            $modules = Get-Process -Id $Process.Id -Module -ErrorAction SilentlyContinue
            return ($modules -and $procPath -and ($modules[0].FileName -ne $procPath))
        }
        "CredentialAccess" = {
            param($Process)
            # Check for credential dumping tools
            $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")
        }
        "LateralMovement" = {
            param($Process)
            # Detect lateral movement attempts
            $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)
        }
    }
    
    Start-Job -ScriptBlock {
        $behaviors = $using:suspiciousBehaviors
        $logFile = "$using:Base\behavior_detections.log"
        $Base = $using:Base
        $QuarantineDir = $using:QuarantineDir
        
        ${function:Check-FileHash} = ${using:function:Check-FileHash}
        ${function:Kill-Threat} = ${using:function:Kill-Threat}
        ${function:Quarantine-File} = ${using:function:Quarantine-File}
        ${function:Log} = ${using:function:Log}
        $ApiConfig = $using:ApiConfig
        
        while ($true) {
            Start-Sleep -Seconds 5
            Get-Process | ForEach-Object {
                $process = $_
                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) {
                                        Quarantine-File -FilePath $process.Path -ProcessName $process.Name -ProcessId $process.Id -DetectionReason "Suspicious behavior: $behavior"
                                    }
                                }
                                Kill-Threat -ProcessId $process.Id -ProcessName $process.Name -Reason "Suspicious behavior: $behavior"
                            }
                        }
                    } catch {
                        # Silently continue on errors
                    }
                }
            }
        }
    } | Out-Null
}

Log "[+] Starting behavior monitor"
Start-BehaviorMonitor

# ============================================
# MAIN MONITORING LOOP
# ============================================
Log "[+] All detection modules active"
Log "[+] Monitoring for threats... (Press Ctrl+C to stop)"

try {
    while ($true) {
        # Run fileless malware detection every 10 seconds
        Start-Sleep -Seconds 10
        Detect-FilelessMalware | Out-Null
    }
} finally {
    # Cleanup on exit
    Log "=== Stopping detection modules ==="
    Get-Job | Stop-Job
    Get-Job | Remove-Job
    Log "=== Detection stopped ==="
}
Editor is loading...
Leave a Comment