Gorstaks Antivirus
unknown
powershell
2 months ago
105 kB
7
No Index
# Antivirus.ps1
# Author: Gorstak
$Config = @{
BaseDirectory = "C:\ProgramData\Antivirus"
QuarantineDirectory = "C:\ProgramData\Antivirus\Quarantine"
BackupDirectory = "C:\ProgramData\Antivirus\Backup"
LogFile = "C:\ProgramData\Antivirus\av.log"
BlockedLogFile = "C:\ProgramData\Antivirus\blocked.log"
DatabaseFile = "C:\ProgramData\Antivirus\known_files.db"
MaxDatabaseEntries = 50000
MaxLogSizeMB = 10
MemoryScanIntervalSec = 8
MemoryScanMaxSizeMB = 150
ProcessTimeoutSeconds = 30
DatabaseCleanupDays = 30
EnableMemoryScanning = $true
EnableRealtimeMonitor = $true
EnableThreatIntel = $true
EnableAlerts = $true
AutoQuarantine = $true
MalwareBazaarApiKey = ""
CirclHashLookupUrl = "https://hashlookup.circl.lu/lookup/sha256"
CymruApiUrl = "https://api.malwarehash.cymru.com/v1/hash"
MalwareBazaarApiUrl = "https://mb-api.abuse.ch/api/v1/"
CymruDetectionThreshold = 60
SuspiciousFileSizeKB = 3072
}
$BehaviorConfig = @{
EnableBehaviorKill = $true
EnableAutoBlockC2 = $true
DeepScanIntervalHours = 6
ThreatIntelUpdateDays = 7
}
$KeyScramblerConfig = @{
EnableKeyScrambler = $true
FloodChance = 0.5
BeforeKeyChance = 0.75
AfterKeyChance = 0.75
MinFakeChars = 1
MaxFakeChars = 6
}
$RulesDirectory = Join-Path $Config.BaseDirectory "rules"
$KnownFilesCache = @{}
$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
$AllowedSIDs = @('S-1-2-0', 'S-1-5-20')
$RiskyPaths = @('\temp\', '\downloads\', '\appdata\local\temp\', '\public\', '\windows\temp\', '\appdata\roaming\', '\desktop\')
# Monitor only specific extensions
$MonitoredExtensions = @('.com', '.exe', '.exif', '.dll', '.winmd')
# Executable extensions for special handling
$ExecutableExtensions = @(
'.exe', '.dll', '.sys', '.ocx', '.scr', '.com', '.cpl', '.msi', '.drv', '.winmd',
'.ps1', '.bat', '.cmd', '.vbs', '.js', '.hta', '.jse', '.wsf', '.wsh', '.psc1',
'.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.bzip', '.bzip2', '.xz', '.tgz',
'.tbz', '.taz', '.tpz', '.z', '.lzh', '.lha', '.arc', '.arj', '.cab', '.iso', '.img',
'.doc', '.docx', '.docm', '.docb', '.dot', '.dotx', '.dotm', '.xls', '.xlsx', '.xlsm',
'.xlsb', '.xlt', '.xltx', '.xltm', '.xlam', '.xla', '.xlm', '.xll', '.xlw', '.ppt',
'.pptx', '.pptm', '.pps', '.ppsx', '.ppsm', '.pot', '.potx', '.potm', '.ppa', '.ppam',
'.rtf', '.odt', '.ods', '.mdb', '.accdb', '.accde', '.accda', '.accdr', '.accdt',
'.htm', '.html', '.mht', '.mhtml', '.xml', '.xsl', '.xps', '.svg',
'.reg', '.inf', '.ini', '.cfg', '.config', '.manifest', '.lnk', '.url',
'.chm', '.hta', '.msp', '.msu', '.apk', '.crx', '.xpi', '.eml', '.msg'
)
$ProtectedProcesses = @(
'System', 'Idle', 'Registry', 'smss', 'csrss', 'wininit', 'services', 'lsass',
'svchost', 'winlogon', 'explorer', 'dwm', 'SearchUI', 'SearchIndexer', 'fontdrvhost',
'RuntimeBroker', 'sihost', 'taskhostw'
)
$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',
'invoke-mimikatz', 'invoke-bloodhound', 'powersploit', 'empire'
)
New-Item -ItemType Directory -Path $Config.BaseDirectory, $Config.QuarantineDirectory, $Config.BackupDirectory, $RulesDirectory -Force -ErrorAction SilentlyContinue | Out-Null
function Write-Log {
param([string]$Message)
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$logLine = "$timestamp | $Message"
try {
$logLine | Out-File -FilePath $Config.LogFile -Append -Encoding UTF8
} catch {
Write-Host "[LOG ERROR] $_"
}
Write-Host $logLine
if (Test-Path $Config.LogFile) {
$logSize = (Get-Item $Config.LogFile -ErrorAction SilentlyContinue).Length
if ($logSize -ge ($Config.MaxLogSizeMB * 1MB)) {
$archiveName = "$($Config.BaseDirectory)\av_log_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
try {
Rename-Item -Path $Config.LogFile -NewName $archiveName -ErrorAction SilentlyContinue
} catch {}
}
}
}
Write-Log "=== Antivirus Starting ==="
Write-Log "Admin: $IsAdmin | User: $env:USERNAME | SID: $([Security.Principal.WindowsIdentity]::GetCurrent().User.Value)"
function Load-Database {
if (Test-Path $Config.DatabaseFile) {
try {
$lines = Get-Content $Config.DatabaseFile -ErrorAction Stop
$count = 0
foreach ($line in $lines) {
if ($line -match '^([0-9a-f]{64}),(true|false),(.+)$') {
$hash = $matches[1]
$safe = [bool]::Parse($matches[2])
$timestamp = $matches[3]
try {
$entryDate = [datetime]::Parse($timestamp)
if ($entryDate -lt (Get-Date).AddDays(-$Config.DatabaseCleanupDays)) {
continue
}
} catch {}
$KnownFilesCache[$hash] = $safe
$count++
if ($count -ge $Config.MaxDatabaseEntries) {
break
}
}
}
Write-Log "Loaded $count entries from database"
} catch {
Write-Log "Failed to load database: $_"
$KnownFilesCache.Clear()
}
} else {
New-Item -Path $Config.DatabaseFile -ItemType File -Force -ErrorAction SilentlyContinue | Out-Null
Write-Log "Created new database file"
}
}
function Save-ToDatabase {
param(
[string]$Hash,
[bool]$IsSafe
)
if (-not $Hash) { return }
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$entry = "$Hash,$IsSafe,$timestamp"
try {
$entry | Out-File -FilePath $Config.DatabaseFile -Append -Encoding UTF8
$KnownFilesCache[$Hash] = $IsSafe
} catch {
Write-Log "Failed to save to database: $_"
}
if ($KnownFilesCache.Count -gt $Config.MaxDatabaseEntries) {
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
}
Load-Database
function Test-ShouldExclude {
param([string]$FilePath)
$lower = $FilePath.ToLower()
# Exclude antivirus's own folder to prevent self-quarantine
$avFolderLower = $Config.BaseDirectory.ToLower()
if ($lower -like "$avFolderLower\*" -or $lower -eq $avFolderLower) { return $true }
if ($lower -like '*\assembly\*') { return $true }
if ($lower -like '*\winsxs\*') { return $true }
if ($lower -like '*\microsoft.net\*') { return $true }
if ($lower -like '*\windows\system32\config\*') { return $true }
if ($lower -like '*ctfmon*' -or $lower -like '*msctf.dll' -or $lower -like '*msutb.dll') {
return $true
}
return $false
}
function Get-FileHashSafe {
param([string]$FilePath)
if (-not (Test-Path $FilePath)) { return $null }
try {
return (Get-FileHash -Path $FilePath -Algorithm SHA256 -ErrorAction Stop).Hash.ToLower()
} catch {
return $null
}
}
function Get-FileSignatureInfo {
param([string]$FilePath)
if (-not (Test-Path $FilePath)) { return $null }
try {
$signature = Get-AuthenticodeSignature -FilePath $FilePath -ErrorAction Stop
$hash = Get-FileHashSafe -FilePath $FilePath
return [PSCustomObject]@{
Hash = $hash
Status = $signature.Status
StatusMessage = $signature.StatusMessage
SignerName = $signature.SignerCertificate.Subject
}
} catch {
return $null
}
}
function Test-CirclHashLookup {
param([string]$SHA256)
if (-not $SHA256) { return $false }
try {
$url = "$($Config.CirclHashLookupUrl)/$SHA256"
$response = Invoke-RestMethod -Uri $url -TimeoutSec 8 -ErrorAction Stop
if ($response) {
Write-Log "CIRCL known-good match: $SHA256"
return $true
}
} catch {}
return $false
}
function Test-CymruMalwareHash {
param([string]$SHA256)
if (-not $SHA256) { return $false }
try {
$url = "$($Config.CymruApiUrl)/$SHA256"
$response = Invoke-RestMethod -Uri $url -TimeoutSec 8 -ErrorAction Stop
if ($response.detections -ge $Config.CymruDetectionThreshold) {
Write-Log "CYMRU malware match: $SHA256 (detections: $($response.detections))"
return $true
}
} catch {}
return $false
}
function Test-MalwareBazaarHash {
param([string]$SHA256)
if (-not $SHA256) { return $false }
try {
$body = @{
query = 'get_info'
hash = $SHA256
}
if ($Config.MalwareBazaarApiKey) {
$body.api_key = $Config.MalwareBazaarApiKey
}
$response = Invoke-RestMethod -Uri $Config.MalwareBazaarApiUrl -Method Post -Body $body -TimeoutSec 10 -ErrorAction Stop
if ($response.query_status -eq 'ok' -or ($response.data -and $response.data.Count -gt 0)) {
Write-Log "MalwareBazaar match: $SHA256"
return $true
}
} catch {}
return $false
}
function Test-SuspiciousUnsignedDll {
param([string]$FilePath)
$extension = [IO.Path]::GetExtension($FilePath).ToLower()
if ($extension -notin @('.dll', '.winmd')) { return $false }
try {
$signature = Get-AuthenticodeSignature -FilePath $FilePath -ErrorAction Stop
if ($signature.Status -eq 'Valid') { return $false }
} catch {}
$fileInfo = Get-Item $FilePath -ErrorAction SilentlyContinue
if (-not $fileInfo) { return $false }
$fileSizeKB = $fileInfo.Length / 1KB
$pathLower = $FilePath.ToLower()
foreach ($riskyPath in $RiskyPaths) {
if ($pathLower -like "*$riskyPath*" -and $fileSizeKB -lt $Config.SuspiciousFileSizeKB) {
return $true
}
}
if ($pathLower -like '*\appdata\roaming\*' -and $fileSizeKB -lt 800 -and $fileInfo.Name -match '^[a-z0-9]{4,12}\.(dll|winmd)$') {
return $true
}
return $false
}
function Test-FileLocked {
param([string]$FilePath)
try {
$stream = [IO.File]::Open($FilePath, 'Open', 'ReadWrite', 'None')
$stream.Close()
return $false
} catch {
return $true
}
}
function Stop-ProcessesUsingFile {
param([string]$FilePath)
$fileName = [IO.Path]::GetFileName($FilePath)
try {
Get-Process | Where-Object {
try {
$_.Modules.FileName -contains $FilePath
} catch {
$false
}
} | ForEach-Object {
if ($ProtectedProcesses -notcontains $_.Name) {
Write-Log "Stopping process $($_.Name) (PID: $($_.Id)) using file: $FilePath"
try {
$_.CloseMainWindow() | Out-Null
Start-Sleep -Milliseconds 500
if (-not $_.HasExited) {
Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue
}
} catch {}
}
}
} catch {
try {
taskkill /F /FI "MODULES eq $fileName" 2>&1 | Out-Null
} catch {}
}
}
function Set-FileOwnership {
param([string]$FilePath)
try {
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 "Set ownership and permissions for: $FilePath"
return $true
} catch {
Write-Log "Failed to set ownership: $_"
return $false
}
}
function Move-ToQuarantine {
param(
[string]$FilePath,
[string]$Reason
)
if (-not (Test-Path $FilePath)) {
Write-Log "Cannot quarantine - file not found: $FilePath"
return
}
if (Test-FileLocked -FilePath $FilePath) {
Stop-ProcessesUsingFile -FilePath $FilePath
Start-Sleep -Milliseconds 500
}
$fileName = [IO.Path]::GetFileName($FilePath)
$timestamp = Get-Date -Format 'yyyyMMdd_HHmmss'
$backupPath = Join-Path $Config.BackupDirectory "${fileName}_${timestamp}.bak"
$quarantinePath = Join-Path $Config.QuarantineDirectory "${fileName}_${timestamp}"
try {
Copy-Item -Path $FilePath -Destination $backupPath -Force -ErrorAction Stop
Move-Item -Path $FilePath -Destination $quarantinePath -Force -ErrorAction Stop
Write-Log "QUARANTINED [$Reason]: $FilePath -> $quarantinePath"
Send-ThreatAlert -Severity "HIGH" -Message "File quarantined: $Reason" -Details $FilePath
} catch {
Write-Log "Quarantine failed for $FilePath : $_"
if (Set-FileOwnership -FilePath $FilePath) {
try {
Copy-Item -Path $FilePath -Destination $backupPath -Force -ErrorAction Stop
Move-Item -Path $FilePath -Destination $quarantinePath -Force -ErrorAction Stop
Write-Log "QUARANTINED (after ownership fix) [$Reason]: $FilePath"
} catch {
Write-Log "Quarantine still failed after ownership fix: $_"
}
}
}
}
function Block-FileExecution {
param(
[string]$FilePath,
[int]$ProcessId,
[string]$Type
)
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$blockEntry = "$timestamp | BLOCKED $Type | $FilePath | PID $ProcessId"
try {
$blockEntry | Out-File -FilePath $Config.BlockedLogFile -Append -Encoding UTF8
} catch {}
Write-Log "BLOCKED $Type | $FilePath | PID $ProcessId"
try {
$process = Get-Process -Id $ProcessId -ErrorAction SilentlyContinue
if ($process -and ($ProtectedProcesses -notcontains $process.ProcessName)) {
Stop-Process -Id $ProcessId -Force -ErrorAction SilentlyContinue
Write-Log "Killed process PID $ProcessId"
}
} catch {}
if (Test-Path $FilePath) {
Move-ToQuarantine -FilePath $FilePath -Reason "Real-time $Type block"
}
}
$global:EmailConfig = $null
$global:WebhookUrl = $null
function Send-ThreatAlert {
param(
[string]$Severity,
[string]$Message,
[string]$Details
)
if (-not $Config.EnableAlerts) { return }
$severityUpper = $Severity.ToUpper()
$entryType = switch ($severityUpper) {
"CRITICAL" { [System.Diagnostics.EventLogEntryType]::Error }
"HIGH" { [System.Diagnostics.EventLogEntryType]::Warning }
"MEDIUM" { [System.Diagnostics.EventLogEntryType]::Warning }
default { [System.Diagnostics.EventLogEntryType]::Information }
}
try {
if (-not [System.Diagnostics.EventLog]::SourceExists("Antivirus")) {
New-EventLog -LogName Application -Source "Antivirus" -ErrorAction SilentlyContinue
}
Write-EventLog -LogName Application -Source "Antivirus" `
-EventId 1001 -Message "$Message - $Details" `
-EntryType $entryType -ErrorAction SilentlyContinue
} catch {}
if ($global:EmailConfig) {
try {
Send-MailMessage @global:EmailConfig `
-Subject "[$severityUpper] Antivirus Alert" `
-Body "$Message`n`nDetails: $Details" `
-ErrorAction SilentlyContinue
} catch {
Write-Log "Email alert failed: $_"
}
}
if ($global:WebhookUrl) {
try {
$payload = @{
severity = $severityUpper
message = $Message
details = $Details
timestamp = Get-Date -Format 'o'
hostname = $env:COMPUTERNAME
} | ConvertTo-Json
Invoke-WebRequest -Uri $global:WebhookUrl -Method Post -Body $payload -ContentType 'application/json' -ErrorAction SilentlyContinue | Out-Null
} catch {
Write-Log "Webhook alert failed: $_"
}
}
}
function Update-ThreatIntelligence {
if (-not $Config.EnableThreatIntel) { return }
Write-Log "Updating threat intelligence feeds..."
$yaraRules = @(
"https://raw.githubusercontent.com/Neo23x0/signature-base/master/yara/gen_campaign_uac.yar",
"https://raw.githubusercontent.com/Neo23x0/signature-base/master/yara/gen_malware_set.yar",
"https://raw.githubusercontent.com/Yara-Rules/rules/master/malware/Malware.yar"
)
$hashLists = @(
"https://raw.githubusercontent.com/davidonzo/Threat-Intel/master/lists/latest-hashes.txt"
)
foreach ($url in $yaraRules) {
$fileName = Split-Path $url -Leaf
$outputPath = Join-Path $RulesDirectory $fileName
try {
Invoke-WebRequest -Uri $url -OutFile $outputPath -UseBasicParsing -TimeoutSec 15 -ErrorAction Stop
Write-Log "Downloaded YARA rule: $fileName"
} catch {
Write-Log "Failed to download YARA rule $fileName : $_"
}
}
foreach ($url in $hashLists) {
$fileName = Split-Path $url -Leaf
$outputPath = Join-Path $Config.BaseDirectory $fileName
try {
Invoke-WebRequest -Uri $url -OutFile $outputPath -UseBasicParsing -TimeoutSec 15 -ErrorAction Stop
Write-Log "Downloaded hash list: $fileName"
} catch {
Write-Log "Failed to download hash list $fileName : $_"
}
}
}
function Invoke-ThreatAnalysis {
param([string]$FilePath)
if (-not (Test-Path $FilePath -PathType Leaf)) { return }
if (Test-ShouldExclude -FilePath $FilePath) { return }
$extension = [IO.Path]::GetExtension($FilePath).ToLower()
if ($MonitoredExtensions -notcontains $extension) { return }
$fileHash = Get-FileHashSafe -FilePath $FilePath
if (-not $fileHash) { return }
if ($KnownFilesCache.ContainsKey($fileHash)) {
if (-not $KnownFilesCache[$fileHash]) {
Move-ToQuarantine -FilePath $FilePath -Reason "Previously identified threat"
}
return
}
if (Test-CirclHashLookup -SHA256 $fileHash) {
Save-ToDatabase -Hash $fileHash -IsSafe $true
Write-Log "ALLOWED (CIRCL known-good): $FilePath"
return
}
if (Test-CymruMalwareHash -SHA256 $fileHash) {
Save-ToDatabase -Hash $fileHash -IsSafe $false
Move-ToQuarantine -FilePath $FilePath -Reason "Cymru MHR malware match (>=$($Config.CymruDetectionThreshold)% detection)"
return
}
if (Test-MalwareBazaarHash -SHA256 $fileHash) {
Save-ToDatabase -Hash $fileHash -IsSafe $false
Move-ToQuarantine -FilePath $FilePath -Reason "MalwareBazaar malware match"
return
}
if (Test-SuspiciousUnsignedDll -FilePath $FilePath) {
Save-ToDatabase -Hash $fileHash -IsSafe $false
Move-ToQuarantine -FilePath $FilePath -Reason "Suspicious unsigned DLL/WINMD in risky location"
return
}
$signatureInfo = Get-FileSignatureInfo -FilePath $FilePath
if ($signatureInfo) {
$isSafe = ($signatureInfo.Status -eq 'Valid')
Save-ToDatabase -Hash $fileHash -IsSafe $isSafe
if ($isSafe) {
Write-Log "ALLOWED (digitally signed): $FilePath"
} else {
Write-Log "ALLOWED (unsigned but no threat indicators): $FilePath"
}
}
}
function Initialize-Yara {
param(
[string]$BaseDir = $Config.BaseDirectory
)
$yaraExe = Join-Path $BaseDir "yara64.exe"
$yaraRuleMem = Join-Path $BaseDir "mem.yar"
Write-Log "Initializing YARA components..."
if (-not (Test-Path $yaraExe)) {
Write-Log "yara64.exe not found - attempting download"
try {
$releaseUrl = "https://api.github.com/repos/VirusTotal/yara/releases/latest"
$release = Invoke-RestMethod -Uri $releaseUrl -Headers @{"Accept"="application/vnd.github.v3+json"} -TimeoutSec 12
$asset = $release.assets | Where-Object { $_.name -match 'yara.*win64\.zip' } | Select-Object -First 1
if ($asset) {
$zipUrl = $asset.browser_download_url
$tempZip = Join-Path $BaseDir "yara-latest-win64.zip"
Write-Log "Downloading YARA from: $zipUrl"
Invoke-WebRequest -Uri $zipUrl -OutFile $tempZip -TimeoutSec 30 -UseBasicParsing
Expand-Archive -Path $tempZip -DestinationPath $BaseDir -Force
Get-ChildItem $BaseDir -Filter "*yara*64.exe" | ForEach-Object {
if ($_.Name -ne "yara64.exe") {
Rename-Item $_.FullName (Join-Path $BaseDir "yara64.exe") -Force -ErrorAction SilentlyContinue
}
}
Remove-Item $tempZip -Force -ErrorAction SilentlyContinue
if (Test-Path $yaraExe) {
Write-Log "Successfully downloaded and extracted yara64.exe"
} else {
Write-Log "ERROR: yara64.exe still not found after extraction"
}
} else {
Write-Log "Could not find win64 zip asset in latest release"
}
}
catch {
Write-Log "Failed to auto-download YARA: $_"
Write-Log "You must manually place yara64.exe into $BaseDir"
Write-Log "Download from: https://github.com/VirusTotal/yara/releases/latest"
}
}
else {
Write-Log "yara64.exe already exists"
}
if (-not (Test-Path $yaraRuleMem)) {
Write-Log "Downloading memory YARA rules..."
$ruleUrls = @(
"https://raw.githubusercontent.com/Neo23x0/signature-base/master/yara/generic_anomalies.yar",
"https://raw.githubusercontent.com/Neo23x0/signature-base/master/yara/thor-webshells.yar"
)
$combinedRules = @()
foreach ($url in $ruleUrls) {
try {
$content = Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 12 | Select-Object -ExpandProperty Content
$combinedRules += $content
Write-Log "Downloaded rule set: $(Split-Path $url -Leaf)"
}
catch {
Write-Log "Failed to download $url : $_"
}
}
if ($combinedRules.Count -gt 0) {
$combinedRules -join "`n`n" | Out-File -FilePath $yaraRuleMem -Encoding utf8 -Force
Write-Log "Created combined memory rule file: $yaraRuleMem"
}
else {
Write-Log "No memory rules could be downloaded"
}
}
else {
Write-Log "Memory YARA rules already exist"
}
if (Test-Path $yaraExe) {
Write-Log "YARA setup complete - ready to use"
return $true
}
else {
Write-Log "YARA executable missing - memory YARA scanning will be DISABLED"
return $false
}
}
$yaraReady = Initialize-Yara
function Invoke-MemoryScan {
if (-not $Config.EnableMemoryScanning) { return }
$maxBytes = $Config.MemoryScanMaxSizeMB * 1MB
$logFile = Join-Path $Config.BaseDirectory "memory_hits.log"
Get-Process -EA 0 | Where-Object {
$_.WorkingSet64 -lt $maxBytes -and $ProtectedProcesses -notcontains $_.Name
} | ForEach-Object {
$process = $_
$suspicious = $false
$reasons = @()
try {
if (-not $process.Path -or $process.Path -eq '') {
$suspicious = $true
$reasons += "NoPath"
}
} catch {}
try {
$emptyModules = $process.Modules | Where-Object {
$_.FileName -eq '' -or $_.ModuleName -eq ''
}
if ($emptyModules) {
$suspicious = $true
$reasons += "EmptyModule"
}
} catch {}
try {
foreach ($module in $process.Modules) {
foreach ($evilString in $EvilStrings) {
if ($module.ModuleName -match $evilString -or ($module.FileName -and $module.FileName -match $evilString)) {
$suspicious = $true
$reasons += "EvilString($evilString)"
break
}
}
if ($suspicious) { break }
}
} catch {}
if ($suspicious) {
$reasonString = $reasons -join '; '
$logEntry = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | MEMORY HIT [$reasonString] -> $($process.Name) (PID: $($process.Id)) Path: '$($process.Path)' WS: $([math]::Round($process.WorkingSet64/1MB, 2))MB"
Write-Log "MEMORY: $reasonString -> $($process.Name) (PID: $($process.Id))"
try { $logEntry | Out-File -FilePath $logFile -Append -Encoding UTF8 } catch {}
try { Stop-Process -Id $process.Id -Force -EA 0 } catch {}
}
}
}
function Invoke-YaraMemoryScan {
$yaraExePath = Join-Path $Config.BaseDirectory "yara64.exe"
$yaraRulePath = Join-Path $Config.BaseDirectory "mem.yar"
if (-not (Test-Path $yaraExePath) -or -not (Test-Path $yaraRulePath)) { return }
$logFile = Join-Path $Config.BaseDirectory "yara_memory_hits.log"
Get-Process -EA 0 | Where-Object {
$_.WorkingSet64 -gt 100MB -or $_.Name -match 'powershell|wscript|cscript|mshta|rundll32|regsvr32|msbuild|cmstp'
} | ForEach-Object {
$process = $_
try {
$result = & $yaraExePath -w $yaraRulePath -p $process.Id 2>$null
if ($LASTEXITCODE -eq 0 -and $result) {
$logEntry = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | YARA HIT -> $($process.Name) (PID: $($process.Id))"
Write-Log "YARA: Hit on $($process.Name) (PID: $($process.Id))"
try { $logEntry | Out-File -FilePath $logFile -Append -Encoding UTF8 } catch {}
if ($ProtectedProcesses -notcontains $process.Name) {
Stop-Process -Id $process.Id -Force -EA 0
}
}
} catch {}
}
}
function Find-FilelessIndicators {
$detections = @()
try {
$suspiciousPowerShell = Get-Process -Name powershell, pwsh -ErrorAction SilentlyContinue | Where-Object {
$_.MainWindowTitle -match 'encodedcommand|enc|iex|invoke-expression'
}
if ($suspiciousPowerShell) {
$detections += [PSCustomObject]@{
Type = "FilelessPowerShell"
Details = $suspiciousPowerShell | Select-Object Name, Id, MainWindowTitle
}
Write-Log "Fileless indicator detected: PowerShell without file"
}
} catch {}
try {
$wmiEvents = Get-WmiObject -Namespace root\Subscription -Class __EventFilter -ErrorAction SilentlyContinue |
Where-Object { $_.Query -match 'powershell|vbscript|javascript' }
if ($wmiEvents) {
$detections += [PSCustomObject]@{
Type = "WMIEventSubscription"
Details = $wmiEvents | Select-Object Name, Query
}
Write-Log "Fileless indicator detected: WMI event subscriptions"
}
} catch {}
try {
$registryKeys = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run',
'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run'
)
foreach ($key in $registryKeys) {
if (Test-Path $key) {
$props = Get-ItemProperty -Path $key -ErrorAction SilentlyContinue
if ($props) {
$props.PSObject.Properties | Where-Object {
$_.MemberType -eq 'NoteProperty' -and $_.Value -match 'powershell.*-enc|mshta|regsvr32.*scrobj'
} | ForEach-Object {
$detections += [PSCustomObject]@{
Type = "RegistryScript"
Details = "$key -> $($_.Name): $($_.Value)"
}
Write-Log "Fileless indicator detected: Registry script in $key"
}
}
}
}
} catch {}
return $detections
}
function Find-PersistenceMechanisms {
$suspiciousItems = @()
$locations = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run',
'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run',
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run',
'C:\Windows\System32\Tasks',
'C:\Windows\Tasks',
"$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup",
'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup'
)
foreach ($location in $locations) {
try {
if ($location -match '^HK') {
if (Test-Path $location) {
$props = Get-ItemProperty -Path $location -ErrorAction SilentlyContinue
if ($props) {
$props.PSObject.Properties | Where-Object {
$_.MemberType -eq 'NoteProperty' -and $_.Value -match '\.(exe|dll|ps1|vbs|js|bat|cmd)$'
} | ForEach-Object {
$suspiciousItems += [PSCustomObject]@{
Location = $location
Name = $_.Name
Value = $_.Value
Type = 'Registry'
}
}
}
}
} else {
if (Test-Path $location) {
Get-ChildItem -Path $location -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.Extension -match '\.(exe|dll|lnk|ps1|vbs|js|bat|cmd)$' } |
ForEach-Object {
$suspiciousItems += [PSCustomObject]@{
Location = $location
Name = $_.Name
Value = $_.FullName
Type = 'FileSystem'
}
}
}
}
} catch {
Write-Log "Error checking persistence location $location : $_"
}
}
return $suspiciousItems
}
function Test-ProcessHollowing {
param($Process)
try {
$processPath = $Process.Path
if (-not $processPath) { return $false }
$modules = $Process.Modules
if ($modules -and $modules.Count -gt 0) {
return ($modules[0].FileName -ne $processPath)
}
} catch {}
return $false
}
function Test-CredentialAccessBehavior {
param($Process)
try {
$commandLine = (Get-CimInstance Win32_Process -Filter "ProcessId=$($Process.Id)" -ErrorAction SilentlyContinue).CommandLine
if ($commandLine -match 'mimikatz|procdump|sekurlsa|lsadump|credential|password') {
return $true
}
} catch {}
if ($Process.ProcessName -match 'vaultcmd|cred') {
return $true
}
return $false
}
function Test-LateralMovementBehavior {
param($Process)
try {
$connections = Get-NetTCPConnection -OwningProcess $Process.Id -ErrorAction SilentlyContinue
$externalConnections = $connections | Where-Object {
$_.RemoteAddress -notmatch '^(127\.|192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)|^(::1|fe80:)' -and
$_.RemoteAddress -ne '0.0.0.0' -and $_.RemoteAddress -ne '::'
}
return (($externalConnections | Measure-Object).Count -gt 10)
} catch {}
return $false
}
function Test-C2Communication {
param($Connection)
$suspiciousPorts = @(4444, 5555, 6666, 7777, 8080, 8443, 9001, 1337, 31337)
if ($Connection.RemotePort -in $suspiciousPorts) {
try {
$hostname = [System.Net.Dns]::GetHostEntry($Connection.RemoteAddress).HostName
$c2Domains = @('pastebin', 'ddns.net', 'no-ip.org', 'duckdns.org', 'bit.ly', 'tinyurl')
foreach ($domain in $c2Domains) {
if ($hostname -like "*$domain*") {
return $true
}
}
} catch {}
}
return $false
}
function Invoke-ProcessAndNetworkScan {
Get-Process | ForEach-Object {
$process = $_
try {
$exePath = $process.MainModule.FileName
if ($exePath -and (Test-Path $exePath)) {
Invoke-ThreatAnalysis -FilePath $exePath
}
} catch {}
if ($BehaviorConfig.EnableBehaviorKill -and ($ProtectedProcesses -notcontains $process.Name)) {
try {
if (Test-ProcessHollowing -Process $process) {
Write-Log "BEHAVIOR: Process hollowing detected - $($process.Name) (PID: $($process.Id))"
Send-ThreatAlert -Severity "HIGH" -Message "Process hollowing detected" -Details "$($process.Name) PID: $($process.Id)"
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
}
elseif (Test-CredentialAccessBehavior -Process $process) {
Write-Log "BEHAVIOR: Credential access detected - $($process.Name) (PID: $($process.Id))"
Send-ThreatAlert -Severity "HIGH" -Message "Credential access behavior" -Details "$($process.Name) PID: $($process.Id)"
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
}
elseif (Test-LateralMovementBehavior -Process $process) {
Write-Log "BEHAVIOR: Lateral movement detected - $($process.Name) (PID: $($process.Id))"
Send-ThreatAlert -Severity "MEDIUM" -Message "Lateral movement behavior" -Details "$($process.Name) PID: $($process.Id)"
}
} catch {}
}
}
if ($BehaviorConfig.EnableAutoBlockC2) {
Get-NetTCPConnection -ErrorAction SilentlyContinue | Where-Object {
$_.State -in @('Established', 'Listen')
} | ForEach-Object {
$connection = $_
try {
$process = Get-Process -Id $connection.OwningProcess -ErrorAction SilentlyContinue
if ($process -and (Test-C2Communication -Connection $connection)) {
Write-Log "NETWORK: Suspicious C2 connection - $($process.Name) (PID: $($process.Id)) -> $($connection.RemoteAddress):$($connection.RemotePort)"
Send-ThreatAlert -Severity "HIGH" -Message "C2 communication detected" -Details "$($process.Name) -> $($connection.RemoteAddress):$($connection.RemotePort)"
if ($ProtectedProcesses -notcontains $process.Name) {
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
}
try {
$ruleName = "Block_C2_$($connection.RemoteAddress)"
New-NetFirewallRule -DisplayName $ruleName `
-Direction Outbound `
-Protocol TCP `
-RemoteAddress $connection.RemoteAddress `
-Action Block `
-Enabled True `
-ErrorAction SilentlyContinue | Out-Null
Write-Log "Created firewall rule to block: $($connection.RemoteAddress)"
} catch {}
}
} catch { }
}
}
}
# ===================== Additional Detection Functions =====================
function Stop-ThreatProcess {
param([int]$ProcessId, [string]$ProcessName)
if ($ProcessId -eq $PID) { return }
if ($ProtectedProcesses -contains $ProcessName -or $ProtectedProcesses -contains ($ProcessName -replace '\.exe$','')) { return }
try {
$proc = Get-Process -Id $ProcessId -EA 0
if ($proc.Path -like 'C:\Windows\*' -or $proc.Path -like 'C:\Program Files*') { return }
Stop-Process -Id $ProcessId -Force -EA 0
Write-Log "Terminated threat: $ProcessName (PID: $ProcessId)"
} catch {}
}
function Invoke-LOLBinDetection {
$LOLBins = @{
"certutil" = "-decode|-urlcache|-verifyctl|-encode"
"bitsadmin" = "transfer|addfile|/download"
"mshta" = "http://|https://|javascript:|vbscript:"
"regsvr32" = "scrobj\.dll|/s|http://|https://"
"rundll32" = "javascript:|http://|shell32\.dll,Control_RunDLL"
"wmic" = "process call create|/node:|format:.*http|xsl:http"
"powershell" = "-enc\s|-encodedcommand|downloadstring|iex\s|invoke-expression|-nop|-w\s*hidden|bypass"
"msiexec" = "/quiet|/q.*http"
"cscript" = "http://|https://"
"wscript" = "http://|https://"
}
foreach ($proc in Get-WmiObject Win32_Process -EA 0) {
if ($proc.ProcessId -eq $PID -or -not $proc.CommandLine) { continue }
$name = $proc.Name -replace '\.exe$',''
$cmd = $proc.CommandLine.ToLower()
foreach ($lolbin in $LOLBins.Keys) {
if ($name -eq $lolbin -and $cmd -match $LOLBins[$lolbin]) {
Write-Log "LOLBin attack: $($proc.Name) PID:$($proc.ProcessId)"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $proc.Name
break
}
}
}
}
function Invoke-ProcessAnomalyDetection {
$systemBinaries = @("svchost.exe", "lsass.exe", "csrss.exe", "smss.exe", "wininit.exe", "services.exe")
$officeApps = "winword|excel|powerpnt|outlook|msaccess"
$scriptEngines = "powershell|cmd|wscript|cscript|mshta"
foreach ($proc in Get-WmiObject Win32_Process -EA 0) {
if ($proc.ProcessId -eq $PID) { continue }
$cmd = $proc.CommandLine
$path = $proc.ExecutablePath
$parent = Get-WmiObject Win32_Process -Filter "ProcessId=$($proc.ParentProcessId)" -EA 0
# Office apps spawning script engines (macro attack)
if ($parent.Name -match $officeApps -and $proc.Name -match $scriptEngines) {
Write-Log "Macro attack: $($parent.Name) spawned $($proc.Name)"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $proc.Name
continue
}
# System binaries from wrong location
if ($proc.Name -in $systemBinaries -and $path -and $path -notmatch "Windows\\System32") {
Write-Log "Masquerading: Fake $($proc.Name) at $path"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $proc.Name
continue
}
# Suspicious command line patterns
if ($cmd -and ($cmd -match "-enc\s.*bypass" -or $cmd -match "DownloadString|DownloadFile" -or $cmd -match "FromBase64String.*Invoke")) {
Write-Log "Suspicious process: $($proc.Name)"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $proc.Name
}
}
}
function Invoke-AMSIBypassDetection {
$pattern = "AmsiScanBuffer|amsiInitFailed|AmsiUtils|AmsiContext|Patch.*Amsi|Disable.*Amsi|bypass.*amsi"
foreach ($proc in Get-CimInstance Win32_Process -EA 0) {
if ($proc.ProcessId -eq $PID -or $proc.Name -notmatch "powershell|pwsh|wscript|cscript") { continue }
$cmd = $proc.CommandLine
if (-not $cmd) { continue }
if ($cmd -match $pattern) {
Write-Log "AMSI bypass attempt: $($proc.Name) PID:$($proc.ProcessId)"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $proc.Name
continue
}
# Check encoded commands
if ($cmd -match "-enc\s+([A-Za-z0-9+/=]+)") {
try {
$decoded = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($Matches[1]))
if ($decoded -match $pattern) {
Write-Log "Encoded AMSI bypass: $($proc.Name)"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $proc.Name
}
} catch {}
}
}
}
function Invoke-CredentialDumpDetection {
$toolPattern = "mimikatz|sekurlsa|pwdump|gsecdump|procdump|nanodump|lsassy|lazagne|hashdump"
$lsassProc = Get-Process lsass -EA 0
foreach ($proc in Get-WmiObject Win32_Process -EA 0) {
if ($proc.ProcessId -eq $PID) { continue }
$cmd = $proc.CommandLine
$name = $proc.Name
# Known tools
if ($name -match $toolPattern -or $cmd -match $toolPattern) {
Write-Log "Credential tool: $name"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $name
continue
}
# LSASS access
if ($lsassProc -and $cmd -match "lsass" -and $proc.ProcessId -ne $lsassProc.Id) {
Write-Log "LSASS access: $name"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $name
continue
}
# Memory/registry dumps
if ($cmd -match "MiniDump|comsvcs\.dll.*#24|reg\s+(save|export).*(sam|security|system)") {
Write-Log "Credential dump: $name"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $name
}
}
}
function Invoke-WMIPersistenceDetection {
try {
$ns = "root\subscription"
$filters = Get-CimInstance -Namespace $ns -ClassName __EventFilter -EA 0
$consumers = Get-CimInstance -Namespace $ns -ClassName CommandLineEventConsumer -EA 0
$bindings = Get-CimInstance -Namespace $ns -ClassName __FilterToConsumerBinding -EA 0
foreach ($filter in $filters) {
if ($filter.Name -match "microsoft|SCM Event") { continue }
if ($filter.Query -match "ProcessStartTrace|powershell|cmd") {
Write-Log "Malicious WMI filter: $($filter.Name)"
Send-ThreatAlert -Severity "HIGH" -Message "WMI persistence detected" -Details $filter.Name
$bindings | Where-Object { $_.Filter -like "*$($filter.Name)*" } | ForEach-Object { Remove-CimInstance $_ -EA 0 }
Remove-CimInstance $filter -EA 0
}
}
foreach ($consumer in $consumers) {
if ($consumer.CommandLineTemplate -match "powershell|cmd|-enc|http") {
Write-Log "Malicious WMI consumer: $($consumer.Name)"
Send-ThreatAlert -Severity "HIGH" -Message "WMI persistence detected" -Details $consumer.Name
$bindings | Where-Object { $_.Consumer -like "*$($consumer.Name)*" } | ForEach-Object { Remove-CimInstance $_ -EA 0 }
Remove-CimInstance $consumer -EA 0
}
}
} catch {}
}
function Invoke-ScheduledTaskDetection {
$whitelist = @("Antivirus", "GoogleUpdate", "MicrosoftEdge", "OneDrive", "Adobe")
$badExes = "powershell|cmd\.exe|wscript|cscript|mshta|certutil|bitsadmin"
$badArgs = "-enc|http://|https://|bypass|hidden|downloadstring"
try {
foreach ($task in Get-ScheduledTask -EA 0 | Where-Object { $_.State -eq "Ready" -and $_.TaskPath -notmatch "\\Microsoft\\" }) {
if ($whitelist | Where-Object { $task.TaskName -match $_ }) { continue }
$exe = $task.Actions[0].Execute
$args = $task.Actions[0].Arguments
if ($exe -match $badExes -and $args -match $badArgs) {
Write-Log "Malicious task: $($task.TaskName)"
Send-ThreatAlert -Severity "HIGH" -Message "Malicious scheduled task" -Details $task.TaskName
Unregister-ScheduledTask -TaskName $task.TaskName -TaskPath $task.TaskPath -Confirm:$false -EA 0
}
}
} catch {}
}
function Invoke-RegistryPersistenceDetection {
$runKeys = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
)
$badPattern = "powershell.*-enc|cmd.*/c.*powershell|http://|https://|wscript|cscript|mshta"
foreach ($key in $runKeys) {
if (-not (Test-Path $key)) { continue }
try {
$props = Get-ItemProperty -Path $key -EA 0
foreach ($prop in $props.PSObject.Properties) {
if ($prop.Name -match "^PS" -or -not $prop.Value) { continue }
if ($prop.Value -match $badPattern) {
Write-Log "Registry persistence: $key\$($prop.Name)"
Send-ThreatAlert -Severity "HIGH" -Message "Registry persistence" -Details "$key\$($prop.Name)"
# Try to quarantine the executable
$exePath = ($prop.Value -split ' ')[0] -replace '"',''
if ($exePath -and (Test-Path $exePath) -and $exePath -notmatch "Windows|Program Files") {
Move-ToQuarantine -FilePath $exePath -Reason "Registry persistence executable"
}
if ($key -like "HKCU:*") {
Remove-ItemProperty -Path $key -Name $prop.Name -EA 0
}
}
}
} catch {}
}
}
function Invoke-DLLHijackingDetection {
$badLocations = "\\Temp\\|\\Downloads\\|\\Desktop\\|\\AppData\\"
foreach ($proc in Get-Process -EA 0) {
if ($proc.Id -eq $PID) { continue }
try {
foreach ($mod in $proc.Modules) {
if ($mod.FileName -match $badLocations -and $mod.FileName -like "*.dll") {
$sig = Get-AuthenticodeSignature $mod.FileName -EA 0
if ($sig.Status -ne "Valid") {
Write-Log "Suspicious DLL: $($proc.ProcessName) loaded $($mod.FileName)"
Stop-ThreatProcess -ProcessId $proc.Id -ProcessName $proc.ProcessName
break
}
}
}
} catch {}
}
}
function Invoke-TokenManipulationDetection {
foreach ($proc in Get-Process -EA 0 | Where-Object { $_.Path }) {
try {
$owner = (Get-CimInstance Win32_Process -Filter "ProcessId=$($proc.Id)" -EA 0).GetOwner()
if ($owner.Domain -eq "NT AUTHORITY" -and $proc.Path -notmatch "^C:\\Windows") {
Write-Log "Token manipulation: $($proc.ProcessName) as SYSTEM from $($proc.Path)"
Stop-ThreatProcess -ProcessId $proc.Id -ProcessName $proc.ProcessName
}
} catch {}
}
}
function Invoke-ProcessHollowingDetection {
$systemProcs = @("svchost.exe", "explorer.exe", "lsass.exe", "csrss.exe", "services.exe")
foreach ($proc in Get-CimInstance Win32_Process -EA 0) {
if ($proc.ProcessId -eq $PID) { continue }
try {
$procObj = Get-Process -Id $proc.ProcessId -EA 0
# Path mismatch
if ($procObj.Path -and $proc.ExecutablePath -and $procObj.Path -ne $proc.ExecutablePath) {
Write-Log "Process hollowing: $($proc.Name)"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $proc.Name
continue
}
# System process from wrong location
if ($proc.Name -in $systemProcs -and $proc.ExecutablePath -and $proc.ExecutablePath -notmatch "Windows\\System32") {
Write-Log "Fake system process: $($proc.Name)"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $proc.Name
}
} catch {}
}
}
function Invoke-RansomwareDetection {
$encryptedExts = @(".encrypted", ".locked", ".crypto", ".crypt", ".locky", ".cerber", ".zepto")
$shadowDelete = "vssadmin.*delete|wbadmin.*delete|shadowcopy.*delete|recoveryenabled.*no"
# Check shadow deletion commands
foreach ($proc in Get-WmiObject Win32_Process -EA 0) {
if ($proc.ProcessId -eq $PID) { continue }
if ($proc.CommandLine -match $shadowDelete) {
Write-Log "Ransomware (shadow delete): $($proc.Name)"
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $proc.Name
}
}
# Check recently encrypted files
$userDirs = @("$env:USERPROFILE\Documents", "$env:USERPROFILE\Desktop")
$recentEncrypted = 0
foreach ($dir in $userDirs) {
if (-not (Test-Path $dir)) { continue }
Get-ChildItem $dir -Recurse -File -EA 0 | Where-Object { (Get-Date) - $_.LastWriteTime -lt [TimeSpan]::FromMinutes(5) } | ForEach-Object {
if ($encryptedExts -contains $_.Extension.ToLower()) { $recentEncrypted++ }
if ($_.Name -match "readme|decrypt|how_to|ransom") { Write-Log "Ransom note: $($_.FullName)" }
}
}
if ($recentEncrypted -gt 10) {
Write-Log "RANSOMWARE ALERT: $recentEncrypted files encrypted!"
Send-ThreatAlert -Severity "CRITICAL" -Message "Ransomware detected" -Details "$recentEncrypted files encrypted"
}
}
function Invoke-NetworkAnomalyDetection {
$badPorts = @(4444, 5555, 31337, 6666, 12345, 54321)
$scriptProcs = "cmd|powershell|wscript|cscript|mshta|rundll32"
Get-NetTCPConnection -State Established -EA 0 | Where-Object { $_.RemoteAddress -notmatch "^(127\.|192\.168\.|10\.)" } | ForEach-Object {
$proc = Get-Process -Id $_.OwningProcess -EA 0
$ip = $_.RemoteAddress
$port = $_.RemotePort
$isThreat = ($port -in $badPorts) -or ($proc.ProcessName -match $scriptProcs) -or ($proc.Path -and $proc.Path -notmatch "Windows|Program Files")
if ($isThreat) {
Write-Log "Network threat: $($proc.ProcessName) -> $ip`:$port"
$ruleName = "AV_Block_$ip"
if (-not (Get-NetFirewallRule -DisplayName $ruleName -EA 0)) {
New-NetFirewallRule -DisplayName $ruleName -Direction Outbound -RemoteAddress $ip -Action Block -EA 0 | Out-Null
}
if ($proc.ProcessName -match $scriptProcs) {
Stop-ThreatProcess -ProcessId $proc.Id -ProcessName $proc.ProcessName
}
}
}
}
# ===================== KeyScrambler Anti-Keylogger Protection =====================
$KeyScramblerSource = @"
using System;
using System.Runtime.InteropServices;
using System.Threading;
public class KeyScrambler
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
[StructLayout(LayoutKind.Sequential)]
public struct KBDLLHOOKSTRUCT
{
public uint vkCode;
public uint scanCode;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
public uint type;
public INPUTUNION u;
}
[StructLayout(LayoutKind.Explicit)]
public struct INPUTUNION
{
[FieldOffset(0)] public KEYBDINPUT ki;
}
[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
private const uint INPUT_KEYBOARD = 1;
private const uint KEYEVENTF_UNICODE = 0x0004;
private const uint KEYEVENTF_KEYUP = 0x0002;
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, IntPtr lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")] private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")] private static extern bool GetMessage(out MSG msg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
[DllImport("user32.dll")] private static extern bool TranslateMessage(ref MSG msg);
[DllImport("user32.dll")] private static extern IntPtr DispatchMessage(ref MSG msg);
[DllImport("user32.dll")] private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
[DllImport("user32.dll")] private static extern IntPtr GetMessageExtraInfo();
[DllImport("user32.dll")] private static extern short GetKeyState(int nVirtKey);
[DllImport("kernel32.dll")] private static extern IntPtr GetModuleHandle(string lpModuleName);
[StructLayout(LayoutKind.Sequential)]
public struct MSG { public IntPtr hwnd; public uint message; public IntPtr wParam; public IntPtr lParam; public uint time; public POINT pt; }
[StructLayout(LayoutKind.Sequential)]
public struct POINT { public int x; public int y; }
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr _hookID = IntPtr.Zero;
private static LowLevelKeyboardProc _proc;
private static Random _rnd = new Random();
private static double _floodChance = 0.5;
private static double _beforeKeyChance = 0.75;
private static double _afterKeyChance = 0.75;
private static int _minFakeChars = 1;
private static int _maxFakeChars = 6;
public static void Configure(double floodChance, double beforeChance, double afterChance, int minChars, int maxChars)
{
_floodChance = floodChance;
_beforeKeyChance = beforeChance;
_afterKeyChance = afterChance;
_minFakeChars = minChars;
_maxFakeChars = maxChars;
}
public static void Start()
{
if (_hookID != IntPtr.Zero) return;
_proc = HookCallback;
_hookID = SetWindowsHookEx(WH_KEYBOARD_LL,
Marshal.GetFunctionPointerForDelegate(_proc),
GetModuleHandle(null), 0);
if (_hookID == IntPtr.Zero)
throw new Exception("KeyScrambler hook failed: " + Marshal.GetLastWin32Error());
MSG msg;
while (GetMessage(out msg, IntPtr.Zero, 0, 0))
{
TranslateMessage(ref msg);
DispatchMessage(ref msg);
}
}
public static void Stop()
{
if (_hookID != IntPtr.Zero)
{
UnhookWindowsHookEx(_hookID);
_hookID = IntPtr.Zero;
}
}
public static bool IsRunning()
{
return _hookID != IntPtr.Zero;
}
private static bool ModifiersDown()
{
return (GetKeyState(0x10) & 0x8000) != 0 || // Shift
(GetKeyState(0x11) & 0x8000) != 0 || // Ctrl
(GetKeyState(0x12) & 0x8000) != 0; // Alt
}
private static void InjectFakeChar(char c)
{
var inputs = new INPUT[2];
inputs[0].type = INPUT_KEYBOARD;
inputs[0].u.ki.wVk = 0;
inputs[0].u.ki.wScan = (ushort)c;
inputs[0].u.ki.dwFlags = KEYEVENTF_UNICODE;
inputs[0].u.ki.dwExtraInfo = GetMessageExtraInfo();
inputs[1] = inputs[0];
inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
SendInput(2, inputs, Marshal.SizeOf(typeof(INPUT)));
Thread.Sleep(_rnd.Next(1, 7));
}
private static void Flood()
{
if (_rnd.NextDouble() < _floodChance) return;
int count = _rnd.Next(_minFakeChars, _maxFakeChars + 1);
for (int i = 0; i < count; i++)
InjectFakeChar((char)_rnd.Next('A', 'Z' + 1));
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
KBDLLHOOKSTRUCT k = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
if ((k.flags & 0x10) != 0) return CallNextHookEx(_hookID, nCode, wParam, lParam);
if (ModifiersDown()) return CallNextHookEx(_hookID, nCode, wParam, lParam);
if (k.vkCode >= 65 && k.vkCode <= 90)
{
if (_rnd.NextDouble() < _beforeKeyChance) Flood();
var ret = CallNextHookEx(_hookID, nCode, wParam, lParam);
if (_rnd.NextDouble() < _afterKeyChance) Flood();
return ret;
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
}
"@
$Script:KeyScramblerRunspace = $null
$Script:KeyScramblerPowerShell = $null
function Start-KeyScrambler {
if (-not $KeyScramblerConfig.EnableKeyScrambler) {
Write-Log "KeyScrambler is disabled in configuration"
return
}
Write-Log "Initializing KeyScrambler anti-keylogger protection..."
try {
if (-not ([System.Management.Automation.PSTypeName]'KeyScrambler').Type) {
Add-Type -TypeDefinition $KeyScramblerSource -Language CSharp -ErrorAction Stop
Write-Log "KeyScrambler compiled successfully"
}
[KeyScrambler]::Configure(
$KeyScramblerConfig.FloodChance,
$KeyScramblerConfig.BeforeKeyChance,
$KeyScramblerConfig.AfterKeyChance,
$KeyScramblerConfig.MinFakeChars,
$KeyScramblerConfig.MaxFakeChars
)
# Use runspace (thread) instead of job (separate process)
$Script:KeyScramblerRunspace = [runspacefactory]::CreateRunspace()
$Script:KeyScramblerRunspace.ApartmentState = "STA"
$Script:KeyScramblerRunspace.ThreadOptions = "ReuseThread"
$Script:KeyScramblerRunspace.Open()
$Script:KeyScramblerPowerShell = [powershell]::Create()
$Script:KeyScramblerPowerShell.Runspace = $Script:KeyScramblerRunspace
$null = $Script:KeyScramblerPowerShell.AddScript({
param($Source, $FloodChance, $BeforeChance, $AfterChance, $MinChars, $MaxChars)
Add-Type -TypeDefinition $Source -Language CSharp -ErrorAction Stop
[KeyScrambler]::Configure($FloodChance, $BeforeChance, $AfterChance, $MinChars, $MaxChars)
[KeyScrambler]::Start()
}).AddArgument($KeyScramblerSource).AddArgument($KeyScramblerConfig.FloodChance).AddArgument($KeyScramblerConfig.BeforeKeyChance).AddArgument($KeyScramblerConfig.AfterKeyChance).AddArgument($KeyScramblerConfig.MinFakeChars).AddArgument($KeyScramblerConfig.MaxFakeChars)
$null = $Script:KeyScramblerPowerShell.BeginInvoke()
Write-Log "KeyScrambler ACTIVE - anti-keylogger protection enabled (runspace thread)"
Write-Log " -> You see only your real typing"
Write-Log " -> Keyloggers receive garbage mixed with your keystrokes"
}
catch {
Write-Log "KeyScrambler initialization failed: $_"
}
}
function Stop-KeyScrambler {
try {
if ($Script:KeyScramblerPowerShell) {
$Script:KeyScramblerPowerShell.Stop()
$Script:KeyScramblerPowerShell.Dispose()
$Script:KeyScramblerPowerShell = $null
}
if ($Script:KeyScramblerRunspace) {
$Script:KeyScramblerRunspace.Close()
$Script:KeyScramblerRunspace.Dispose()
$Script:KeyScramblerRunspace = $null
}
Write-Log "KeyScrambler stopped"
} catch {}
}
# ===================== Niche/Specialized Detection Functions =====================
# NeuroBehaviorMonitor state variables
$Script:NBM_LastRun = [DateTime]::MinValue
$Script:NBM_TickInterval = 2
$Script:NBM_FocusHistory = @{}
$Script:NBM_LastBrightness = -1
$Script:NBM_FlashScore = 0
$Script:NBM_LastCursorPos = @{X=0; Y=0}
$Script:NBM_CursorFirstSeen = [DateTime]::MinValue
$Script:NBM_CursorJitterCount = 0
$Script:NBM_LastAvgR = -1
$Script:NBM_LastAvgG = -1
$Script:NBM_LastAvgB = -1
$Script:NBM_DistortScore = 0
$Script:NBM_TopmostAllowlist = @("explorer", "taskmgr", "devenv", "code", "chrome", "firefox", "msedge")
$Script:NBM_Reported = @{}
function Test-NBMShouldReport {
param([string]$Key)
if ($Script:NBM_Reported.ContainsKey($Key)) { return $false }
$Script:NBM_Reported[$Key] = [DateTime]::UtcNow
return $true
}
function Invoke-NeuroBehaviorMonitor {
$now = Get-Date
if ($Script:NBM_LastRun -ne [DateTime]::MinValue -and ($now - $Script:NBM_LastRun).TotalSeconds -lt $Script:NBM_TickInterval) { return }
$Script:NBM_LastRun = $now
try {
Add-Type -AssemblyName System.Windows.Forms -EA 0
Add-Type -AssemblyName System.Drawing -EA 0
if (-not ([System.Management.Automation.PSTypeName]'NeuroWin32').Type) {
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class NeuroWin32 {
[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint pid);
[DllImport("user32.dll")] public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
public const int GWL_EXSTYLE = -20;
public const int WS_EX_TOPMOST = 0x00000008;
}
"@ -EA 0
}
$hWnd = [NeuroWin32]::GetForegroundWindow()
if ($hWnd -eq [IntPtr]::Zero) { return }
$fpid = 0
[NeuroWin32]::GetWindowThreadProcessId($hWnd, [ref]$fpid) | Out-Null
if ($fpid -eq 0 -or $fpid -eq $PID) { return }
$proc = Get-Process -Id $fpid -EA 0
$procName = if ($proc) { $proc.ProcessName } else { "unknown" }
# Screen sample for flash/color detection
$bmp = [System.Drawing.Bitmap]::new(64,64)
$g = [System.Drawing.Graphics]::FromImage($bmp)
$g.CopyFromScreen(0,0,0,0,$bmp.Size)
$g.Dispose()
$sumBright = 0; $sumR = 0; $sumG = 0; $sumB = 0; $samples = 0
for ($x=0; $x -lt 64; $x+=4) {
for ($y=0; $y -lt 64; $y+=4) {
$c = $bmp.GetPixel($x,$y)
$sumR += $c.R; $sumG += $c.G; $sumB += $c.B
$sumBright += $c.R + $c.G + $c.B
$samples++
}
}
$bmp.Dispose()
$n = [Math]::Max(1, $samples)
$avgR = $sumR/$n; $avgG = $sumG/$n; $avgB = $sumB/$n
# Focus steal detection
if (-not $Script:NBM_FocusHistory.ContainsKey($fpid)) { $Script:NBM_FocusHistory[$fpid] = @{Count=0; FirstSeen=[DateTime]::UtcNow} }
$fe = $Script:NBM_FocusHistory[$fpid]
$fe.Count++
$elapsed = ([DateTime]::UtcNow - $fe.FirstSeen).TotalSeconds
if ($elapsed -gt 10) { $fe.Count = 1; $fe.FirstSeen = [DateTime]::UtcNow }
if ($elapsed -lt 10 -and $fe.Count -gt 8) {
if (Test-NBMShouldReport -Key "Focus:$procName") {
Write-Log "NeuroBehavior: Focus abuse by $procName"
Send-ThreatAlert -Severity "MEDIUM" -Message "Focus abuse detected" -Details $procName
}
$fe.Count = 0
}
$Script:NBM_FocusHistory[$fpid] = $fe
# Flash detection
if ($Script:NBM_LastBrightness -ge 0) {
$delta = [Math]::Abs($sumBright - $Script:NBM_LastBrightness)
if ($delta -gt 40000) { $Script:NBM_FlashScore++ } else { $Script:NBM_FlashScore = [Math]::Max(0, $Script:NBM_FlashScore - 1) }
if ($Script:NBM_FlashScore -ge 6) {
if (Test-NBMShouldReport -Key "Flash:$procName") {
Write-Log "NeuroBehavior: Flash stimulus from $procName"
Send-ThreatAlert -Severity "HIGH" -Message "Flash stimulus detected" -Details $procName
Stop-ThreatProcess -ProcessId $fpid -ProcessName $procName
}
$Script:NBM_FlashScore = 0
}
}
$Script:NBM_LastBrightness = $sumBright
# Topmost abuse
$exStyle = [NeuroWin32]::GetWindowLong($hWnd, [NeuroWin32]::GWL_EXSTYLE)
if (([int]$exStyle -band [NeuroWin32]::WS_EX_TOPMOST) -ne 0 -and $Script:NBM_TopmostAllowlist -notcontains $procName.ToLower()) {
if (Test-NBMShouldReport -Key "Topmost:$procName") {
Write-Log "NeuroBehavior: Topmost abuse by $procName"
}
}
# Color distortion
if ($Script:NBM_LastAvgR -ge 0) {
$dR = [Math]::Abs($avgR - $Script:NBM_LastAvgR)
$dG = [Math]::Abs($avgG - $Script:NBM_LastAvgG)
$dB = [Math]::Abs($avgB - $Script:NBM_LastAvgB)
$maxD = [Math]::Max($dR, [Math]::Max($dG, $dB))
if ($maxD -gt 70) { $Script:NBM_DistortScore++ } else { $Script:NBM_DistortScore = [Math]::Max(0, $Script:NBM_DistortScore - 1) }
if ($Script:NBM_DistortScore -ge 5) {
if (Test-NBMShouldReport -Key "Distort:$procName") {
Write-Log "NeuroBehavior: Screen distortion by $procName"
}
$Script:NBM_DistortScore = 0
}
}
$Script:NBM_LastAvgR = $avgR; $Script:NBM_LastAvgG = $avgG; $Script:NBM_LastAvgB = $avgB
} catch {}
}
# PrivacyForge - Identity spoofing
$Script:PrivacyForgeIdentity = $null
$Script:PrivacyForgeDataCollected = 0
$Script:PrivacyForgeLastRotation = Get-Date
function Invoke-PrivacyForgeGenerateIdentity {
$firstNames = @("John", "Jane", "Michael", "Sarah", "David", "Emily", "James", "Jessica")
$lastNames = @("Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis")
$domains = @("gmail.com", "yahoo.com", "outlook.com", "protonmail.com")
$userAgents = @(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0"
)
$firstName = Get-Random -InputObject $firstNames
$lastName = Get-Random -InputObject $lastNames
return @{
name = "$firstName $lastName"
email = "$firstName$lastName$(Get-Random -Min 100 -Max 9999)@$(Get-Random -InputObject $domains)"
user_agent = Get-Random -InputObject $userAgents
device_id = [Guid]::NewGuid().ToString()
mac_address = "{0:X2}-{1:X2}-{2:X2}-{3:X2}-{4:X2}-{5:X2}" -f (1..6 | ForEach-Object { Get-Random -Min 0 -Max 256 })
}
}
function Invoke-PrivacyForgeSpoofing {
try {
$timeSinceRotation = (Get-Date) - $Script:PrivacyForgeLastRotation
$shouldRotate = ($timeSinceRotation.TotalSeconds -ge 3600) -or ($Script:PrivacyForgeDataCollected -ge 50) -or (-not $Script:PrivacyForgeIdentity)
if ($shouldRotate) {
$Script:PrivacyForgeIdentity = Invoke-PrivacyForgeGenerateIdentity
$Script:PrivacyForgeDataCollected = 0
$Script:PrivacyForgeLastRotation = Get-Date
Write-Log "PrivacyForge: Identity rotated - $($Script:PrivacyForgeIdentity.name)"
}
$Script:PrivacyForgeDataCollected += Get-Random -Min 1 -Max 5
} catch {}
}
# ELF DLL Unloader
$Script:ElfDLLProcessed = @{}
function Invoke-ElfDLLUnloader {
try {
if (-not ([System.Management.Automation.PSTypeName]'DLLUnloaderLite').Type) {
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class DLLUnloaderLite {
[DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(int access, bool inherit, int pid);
[DllImport("kernel32.dll")] public static extern IntPtr GetProcAddress(IntPtr mod, string name);
[DllImport("kernel32.dll")] public static extern IntPtr GetModuleHandle(string name);
[DllImport("kernel32.dll")] public static extern IntPtr CreateRemoteThread(IntPtr proc, IntPtr attr, uint stack, IntPtr start, IntPtr param, uint flags, IntPtr id);
[DllImport("kernel32.dll")] public static extern uint WaitForSingleObject(IntPtr handle, uint ms);
[DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr handle);
}
"@ -EA 0
}
$targets = @('chrome', 'msedge', 'firefox', 'brave', 'opera')
$whitelist = @('ntdll.dll', 'kernel32.dll', 'user32.dll', 'gdi32.dll')
foreach ($procName in $targets) {
foreach ($proc in Get-Process -Name $procName -EA 0) {
try {
$hProc = [DLLUnloaderLite]::OpenProcess(0x1F0FFF, $false, $proc.Id)
if ($hProc -eq [IntPtr]::Zero) { continue }
$freeLib = [DLLUnloaderLite]::GetProcAddress([DLLUnloaderLite]::GetModuleHandle("kernel32.dll"), "FreeLibrary")
foreach ($mod in $proc.Modules) {
$name = [IO.Path]::GetFileName($mod.FileName).ToLower()
$key = "$($proc.Id):$($mod.FileName)"
if ($whitelist -contains $name -or $Script:ElfDLLProcessed.ContainsKey($key)) { continue }
if ($name -like '*_elf.dll') {
Write-Log "ELF Unloader: Unloading $name from $procName"
$thread = [DLLUnloaderLite]::CreateRemoteThread($hProc, [IntPtr]::Zero, 0, $freeLib, $mod.BaseAddress, 0, [IntPtr]::Zero)
if ($thread -ne [IntPtr]::Zero) {
[DLLUnloaderLite]::WaitForSingleObject($thread, 5000) | Out-Null
[DLLUnloaderLite]::CloseHandle($thread) | Out-Null
}
$Script:ElfDLLProcessed[$key] = Get-Date
}
}
[DLLUnloaderLite]::CloseHandle($hProc) | Out-Null
} catch {}
}
}
} catch {}
}
# Rootkit Detection (simplified)
function Invoke-RootkitDetection {
try {
# Hidden process detection
$procList = Get-Process | Select-Object -ExpandProperty Id
$perfProcs = Get-Counter "\Process(*)\ID Process" -EA 0 | Select-Object -ExpandProperty CounterSamples |
Where-Object { $_.CookedValue -gt 0 } | ForEach-Object { [int]$_.CookedValue }
$hidden = $perfProcs | Where-Object { $_ -notin $procList }
foreach ($pid in $hidden) {
Write-Log "ROOTKIT: Hidden process PID $pid"
Send-ThreatAlert -Severity "CRITICAL" -Message "Hidden process detected" -Details "PID: $pid"
}
# Suspicious drivers
Get-WindowsDriver -Online -EA 0 | Where-Object { $_.ProviderName -notmatch "Microsoft" -and $_.ClassName -eq "System" } | ForEach-Object {
$driverPath = $_.OriginalFileName
if ($driverPath -and (Test-Path $driverPath)) {
$sig = Get-AuthenticodeSignature $driverPath -EA 0
if ($sig.Status -ne "Valid") {
Write-Log "ROOTKIT: Unsigned driver $($_.DriverName)"
Send-ThreatAlert -Severity "HIGH" -Message "Suspicious driver" -Details $_.DriverName
}
}
}
# Suspicious modules in system processes
@("lsass", "csrss", "winlogon", "services") | ForEach-Object {
$proc = Get-Process -Name $_ -EA 0
if ($proc) {
$proc.Modules | Where-Object { $_.FileName -notmatch "^C:\\Windows" } | ForEach-Object {
Write-Log "ROOTKIT: Suspicious module $($_.ModuleName) in $($proc.ProcessName)"
}
}
}
} catch {}
}
# Attack Tools Detection
function Invoke-AttackToolsDetection {
$attackTools = @(
"mimikatz", "sekurlsa", "lazagne", "procdump", "pwdump", "gsecdump",
"hydra", "hashcat", "john", "ncrack", "medusa",
"metasploit", "msfconsole", "msfvenom", "cobaltstrike", "beacon",
"bloodhound", "sharphound", "empire", "powersploit",
"nmap", "masscan", "sqlmap", "burpsuite",
"xmrig", "ccminer", "minerd"
)
$pattern = $attackTools -join "|"
foreach ($proc in Get-WmiObject Win32_Process -EA 0) {
$name = $proc.Name.ToLower()
$cmd = if ($proc.CommandLine) { $proc.CommandLine.ToLower() } else { "" }
$path = if ($proc.ExecutablePath) { $proc.ExecutablePath.ToLower() } else { "" }
if ($name -match $pattern -or $cmd -match $pattern -or $path -match $pattern) {
Write-Log "Attack tool: $($proc.Name)"
Send-ThreatAlert -Severity "CRITICAL" -Message "Attack tool detected" -Details $proc.Name
Stop-ThreatProcess -ProcessId $proc.ProcessId -ProcessName $proc.Name
if ($proc.ExecutablePath -and (Test-Path $proc.ExecutablePath)) {
Move-ToQuarantine -FilePath $proc.ExecutablePath -Reason "Attack tool"
}
}
}
}
# Beacon Detection
function Invoke-BeaconDetection {
$connections = Get-NetTCPConnection -State Established -EA 0 | Where-Object {
$_.RemoteAddress -notmatch "^(127\.|192\.168\.|10\.)"
} | Select-Object -First 200
$groups = $connections | Group-Object OwningProcess, RemoteAddress
foreach ($g in $groups) {
if ($g.Count -lt 3) { continue }
$procId = ($g.Name -split ',')[0].Trim()
$ip = ($g.Name -split ',')[1].Trim()
$proc = Get-Process -Id $procId -EA 0
if ($proc -and $g.Count -gt 5) {
Write-Log "Beacon pattern: $($proc.ProcessName) -> $ip ($($g.Count) connections)"
Send-ThreatAlert -Severity "HIGH" -Message "Beacon detected" -Details "$($proc.ProcessName) -> $ip"
# Block IP
$rule = "AV_Beacon_$ip"
if (-not (Get-NetFirewallRule -DisplayName $rule -EA 0)) {
New-NetFirewallRule -DisplayName $rule -Direction Outbound -RemoteAddress $ip -Action Block -EA 0 | Out-Null
}
Stop-ThreatProcess -ProcessId $proc.Id -ProcessName $proc.ProcessName
}
}
}
# USB Monitoring
$Script:KnownUSBDevices = @{}
function Invoke-USBMonitoring {
try {
$drives = Get-WmiObject Win32_LogicalDisk -Filter "DriveType=2" -EA 0
foreach ($drive in $drives) {
$id = $drive.DeviceID
if ($Script:KnownUSBDevices.ContainsKey($id)) { continue }
$Script:KnownUSBDevices[$id] = Get-Date
Write-Log "USB: New device $id"
# Scan for autorun and suspicious files
$autorun = Join-Path $id "autorun.inf"
if (Test-Path $autorun) {
Write-Log "USB: Autorun detected on $id"
Remove-Item $autorun -Force -EA 0
}
Get-ChildItem "$id\" -Include *.exe,*.dll,*.scr,*.bat,*.vbs,*.ps1 -Recurse -EA 0 | ForEach-Object {
$sig = Get-AuthenticodeSignature $_.FullName -EA 0
if ($sig.Status -ne "Valid") {
Write-Log "USB: Unsigned executable $($_.FullName)"
Move-ToQuarantine -FilePath $_.FullName -Reason "Unsigned USB executable"
}
}
}
} catch {}
}
# GFocus - User-initiated connection whitelist firewall
# Browsers: whitelist based on address bar + 30 sec grace for dependencies
# Other apps: only allowed connections when they have foreground focus
$Script:GFocus_BrowserAllowedIPs = @{} # IP -> expiry time (browser whitelist)
$Script:GFocus_BrowserBlockedIPs = @{} # IP -> rule name (browser blocks)
$Script:GFocus_AppBlockedProcs = @{} # ProcessId -> @{RuleName; IPs} (app blocks)
$Script:GFocus_LastAddressBar = ""
$Script:GFocus_LastForegroundPid = 0
$Script:GFocus_GracePeriod = 30
$Script:GFocus_Browsers = "chrome|msedge|firefox|brave|opera|iexplore|vivaldi|waterfox"
$Script:GFocus_ControlledApps = "powershell|pwsh|cmd|WindowsTerminal|python|node|curl|wget|git|ssh|telnet|ftp|wscript|cscript|mshta"
function Invoke-GFocus {
try {
if (-not ([System.Management.Automation.PSTypeName]'GFocusUI').Type) {
Add-Type @"
using System;
using System.Runtime.InteropServices;
using System.Text;
public class GFocusUI {
[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint pid);
[DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
}
"@ -EA 0
}
Add-Type -AssemblyName UIAutomationClient -EA 0
Add-Type -AssemblyName UIAutomationTypes -EA 0
$hWnd = [GFocusUI]::GetForegroundWindow()
$fgPid = 0
[GFocusUI]::GetWindowThreadProcessId($hWnd, [ref]$fgPid) | Out-Null
if ($fgPid -eq 0) { return }
$fgProc = Get-Process -Id $fgPid -EA 0
if (-not $fgProc) { return }
$now = Get-Date
$isBrowser = $fgProc.ProcessName -match $Script:GFocus_Browsers
$isControlledApp = $fgProc.ProcessName -match $Script:GFocus_ControlledApps
# ==================== BROWSER ADDRESS BAR DETECTION ====================
# Only read address bar when browser is in foreground
if ($isBrowser) {
# Detect if browser just regained focus (was doing something else before)
$lastWasBrowser = $false
try {
$lastProc = Get-Process -Id $Script:GFocus_LastForegroundPid -EA 0
if ($lastProc -and $lastProc.ProcessName -match $Script:GFocus_Browsers) {
$lastWasBrowser = $true
}
} catch {}
$browserRegainedFocus = (-not $lastWasBrowser -and $Script:GFocus_LastForegroundPid -ne 0)
$userInput = $null
# Get address bar content
try {
$auto = [System.Windows.Automation.AutomationElement]::FromHandle($hWnd)
$editCondition = [System.Windows.Automation.PropertyCondition]::new(
[System.Windows.Automation.AutomationElement]::ControlTypeProperty,
[System.Windows.Automation.ControlType]::Edit
)
$edits = $auto.FindAll([System.Windows.Automation.TreeScope]::Descendants, $editCondition)
foreach ($edit in $edits) {
try {
$valuePattern = $edit.GetCurrentPattern([System.Windows.Automation.ValuePattern]::Pattern)
$value = $valuePattern.Current.Value
if ($value -match "^https?://|^www\.|^\w+\.\w+") {
$userInput = $value
break
}
} catch {}
}
} catch {}
# Process navigation OR refresh when browser regains focus
$shouldProcess = $userInput -and (($userInput -ne $Script:GFocus_LastAddressBar) -or $browserRegainedFocus)
if ($shouldProcess) {
$Script:GFocus_LastAddressBar = $userInput
$hostname = $null
if ($userInput -match "https?://([^/:]+)") { $hostname = $Matches[1] }
elseif ($userInput -match "^www\.([^/:]+)") { $hostname = "www." + $Matches[1] }
elseif ($userInput -match "^([a-zA-Z0-9][-a-zA-Z0-9]*\.)+[a-zA-Z]{2,}") { $hostname = $Matches[0] }
if ($hostname) {
if ($browserRegainedFocus) {
Write-Log "GFocus: Browser regained focus on $hostname - refreshing whitelist"
} else {
Write-Log "GFocus: Browser navigated to $hostname"
}
try {
$ips = [System.Net.Dns]::GetHostAddresses($hostname) | ForEach-Object { $_.IPAddressToString }
$expiry = $now.AddSeconds($Script:GFocus_GracePeriod)
foreach ($ip in $ips) {
$Script:GFocus_BrowserAllowedIPs[$ip] = $expiry
# Unblock if previously blocked
if ($Script:GFocus_BrowserBlockedIPs.ContainsKey($ip)) {
Remove-NetFirewallRule -DisplayName $Script:GFocus_BrowserBlockedIPs[$ip] -EA 0
$Script:GFocus_BrowserBlockedIPs.Remove($ip)
Write-Log "GFocus: Unblocked $ip (user returned)"
}
}
} catch {}
}
}
}
# ==================== BROWSER CONNECTION MONITORING ====================
# Always monitor ALL browser processes (they spawn multiple child processes)
$browserProcs = Get-Process -EA 0 | Where-Object { $_.ProcessName -match $Script:GFocus_Browsers } | Select-Object -ExpandProperty Id
$browserConns = Get-NetTCPConnection -State Established -EA 0 | Where-Object { $_.OwningProcess -in $browserProcs }
foreach ($conn in $browserConns) {
$ip = $conn.RemoteAddress
if ($ip -match "^(127\.|10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.|::1|fe80)") { continue }
if ($Script:GFocus_BrowserAllowedIPs.ContainsKey($ip)) {
$Script:GFocus_BrowserAllowedIPs[$ip] = $now.AddSeconds($Script:GFocus_GracePeriod)
} elseif (-not $Script:GFocus_BrowserBlockedIPs.ContainsKey($ip)) {
# Block non-user-initiated browser connection
$ruleName = "GFocus_Browser_$($ip -replace '[.:]','_')"
New-NetFirewallRule -DisplayName $ruleName -Direction Outbound -RemoteAddress $ip -Action Block -EA 0 | Out-Null
$Script:GFocus_BrowserBlockedIPs[$ip] = $ruleName
Write-Log "GFocus: Blocked browser connection to $ip (not user-initiated)"
}
}
# Cleanup expired browser IPs
$expired = @($Script:GFocus_BrowserAllowedIPs.Keys | Where-Object { $Script:GFocus_BrowserAllowedIPs[$_] -lt $now })
foreach ($ip in $expired) { $Script:GFocus_BrowserAllowedIPs.Remove($ip) }
# ==================== CONTROLLED APP HANDLING ====================
# Apps like PowerShell only get network access when in foreground
# Get all controlled app processes
$controlledProcs = Get-Process -EA 0 | Where-Object { $_.ProcessName -match $Script:GFocus_ControlledApps }
foreach ($appProc in $controlledProcs) {
$appPid = $appProc.Id
$appName = $appProc.ProcessName
$hasForeground = ($appPid -eq $fgPid)
# Get this app's connections
$appConns = Get-NetTCPConnection -State Established -EA 0 | Where-Object { $_.OwningProcess -eq $appPid }
$appIPs = @($appConns | ForEach-Object { $_.RemoteAddress } | Where-Object { $_ -notmatch "^(127\.|10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.|::1|fe80)" } | Select-Object -Unique)
if ($hasForeground) {
# App has foreground - allow its connections, remove any blocks
if ($Script:GFocus_AppBlockedProcs.ContainsKey($appPid)) {
$blockInfo = $Script:GFocus_AppBlockedProcs[$appPid]
foreach ($ruleName in $blockInfo.RuleNames) {
Remove-NetFirewallRule -DisplayName $ruleName -EA 0
}
$Script:GFocus_AppBlockedProcs.Remove($appPid)
Write-Log "GFocus: $appName gained foreground - unblocked connections"
}
} else {
# App lost foreground - block its external connections
if ($appIPs.Count -gt 0 -and -not $Script:GFocus_AppBlockedProcs.ContainsKey($appPid)) {
$ruleNames = @()
foreach ($ip in $appIPs) {
$ruleName = "GFocus_App_${appName}_$($ip -replace '[.:]','_')"
New-NetFirewallRule -DisplayName $ruleName -Direction Outbound -RemoteAddress $ip -Action Block -EA 0 | Out-Null
$ruleNames += $ruleName
}
$Script:GFocus_AppBlockedProcs[$appPid] = @{ RuleNames = $ruleNames; IPs = $appIPs }
Write-Log "GFocus: $appName lost foreground - blocked $($appIPs.Count) connection(s)"
}
}
}
# Cleanup rules for processes that no longer exist
$deadPids = @($Script:GFocus_AppBlockedProcs.Keys | Where-Object { -not (Get-Process -Id $_ -EA 0) })
foreach ($deadPid in $deadPids) {
$blockInfo = $Script:GFocus_AppBlockedProcs[$deadPid]
foreach ($ruleName in $blockInfo.RuleNames) {
Remove-NetFirewallRule -DisplayName $ruleName -EA 0
}
$Script:GFocus_AppBlockedProcs.Remove($deadPid)
}
$Script:GFocus_LastForegroundPid = $fgPid
} catch {}
}
# Script Content Scanner
function Invoke-ScriptContentScan {
$badPatterns = @(
"Invoke-Mimikatz", "Invoke-BloodHound", "Invoke-Kerberoast",
"AmsiScanBuffer", "amsiInitFailed", "VirtualAlloc.*PAGE_EXECUTE",
"CreateRemoteThread", "WriteProcessMemory", "ReflectiveLoader"
)
$pattern = $badPatterns -join "|"
$scriptDirs = @("$env:TEMP", "$env:APPDATA", "$env:USERPROFILE\Downloads")
foreach ($dir in $scriptDirs) {
if (-not (Test-Path $dir)) { continue }
Get-ChildItem $dir -Include *.ps1,*.vbs,*.js,*.bat,*.cmd -Recurse -EA 0 | ForEach-Object {
try {
$content = Get-Content $_.FullName -Raw -EA 0
if ($content -match $pattern) {
Write-Log "Malicious script: $($_.FullName)"
Move-ToQuarantine -FilePath $_.FullName -Reason "Malicious script content"
}
} catch {}
}
}
}
# Startup Persistence Detection
function Invoke-StartupPersistenceDetection {
$startupPaths = @(
"$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup",
"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup"
)
foreach ($path in $startupPaths) {
if (-not (Test-Path $path)) { continue }
Get-ChildItem $path -EA 0 | ForEach-Object {
$file = $_
if ($file.Extension -match "\.(exe|dll|vbs|js|bat|cmd|ps1|scr)$") {
$targetPath = if ($file.Extension -eq ".lnk") {
$shell = New-Object -ComObject WScript.Shell
$shell.CreateShortcut($file.FullName).TargetPath
} else { $file.FullName }
if ($targetPath -and (Test-Path $targetPath)) {
$sig = Get-AuthenticodeSignature $targetPath -EA 0
if ($sig.Status -ne "Valid") {
Write-Log "Startup persistence: Unsigned $($file.Name)"
Move-ToQuarantine -FilePath $file.FullName -Reason "Unsigned startup item"
}
}
}
}
}
}
# Driver Watcher
function Invoke-DriverWatcher {
$badDriverNames = @("bfs", "unionfs", "rootkit", "stealth", "hide")
$pattern = $badDriverNames -join "|"
Get-WindowsDriver -Online -EA 0 | Where-Object { $_.DriverName -match $pattern } | ForEach-Object {
Write-Log "Suspicious driver: $($_.DriverName)"
Send-ThreatAlert -Severity "HIGH" -Message "Suspicious driver" -Details $_.DriverName
# Try to stop and disable
try {
Stop-Service -Name $_.DriverName -Force -EA 0
Set-Service -Name $_.DriverName -StartupType Disabled -EA 0
Write-Log "Driver disabled: $($_.DriverName)"
} catch {}
}
}
Write-Log "Performing full system scan - all drives, all folders, monitored extensions only"
# Suspicious extensions (subset for double-extension detection)
$suspiciousExtensions = @('.com', '.exe', '.exif', '.dll', '.winmd')
# Function to detect multiple/suspicious extensions (e.g., file.pdf.exe, file.dll.exe.dll)
function Test-SuspiciousExtension {
param([string]$FileName)
# Check for multiple extensions
$parts = $FileName -split '\.'
if ($parts.Count -gt 2) {
# Has multiple extensions - check if any are executable
for ($i = 1; $i -lt $parts.Count - 1; $i++) {
$ext = ".$($parts[$i])".ToLower()
if ($suspiciousExtensions -contains $ext) {
return $true # Hidden executable extension
}
}
}
# Check for unicode tricks or excessive spaces
if ($FileName -match '\s{2,}\.' -or $FileName -match '[\u200B-\u200D\uFEFF]') {
return $true
}
return $false
}
# Get ALL drives - local, removable, and network
$allDrives = Get-WmiObject Win32_LogicalDisk -ErrorAction SilentlyContinue | Where-Object {
$_.DriveType -in @(2, 3, 4) # 2=Removable, 3=Local, 4=Network
} | Select-Object -ExpandProperty DeviceID
Write-Log "Found drives to scan: $($allDrives -join ', ')"
foreach ($drive in $allDrives) {
Write-Log "Scanning drive: $drive"
try {
# Scan only files with monitored extensions
Get-ChildItem -Path "$drive\" -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $MonitoredExtensions -contains $_.Extension.ToLower() } | ForEach-Object {
$file = $_
$fileName = $file.Name
$filePath = $file.FullName
$ext = $file.Extension.ToLower()
# Skip Windows core system files to avoid breaking the OS
if ($filePath -match "\\Windows\\System32\\|\\Windows\\SysWOW64\\|\\Windows\\WinSxS\\|\\Windows\\assembly\\") {
# But still check for suspicious names even in system folders
if (Test-SuspiciousExtension -FileName $fileName) {
Write-Log "SUSPICIOUS: Multiple extension in system folder: $filePath"
Send-ThreatAlert -Severity "CRITICAL" -Message "Suspicious file in system folder" -Details $filePath
}
return
}
# Check for multiple/suspicious extensions (e.g., pdf.exe, doc.scr)
if (Test-SuspiciousExtension -FileName $fileName) {
Write-Log "THREAT: Multiple/suspicious extension detected: $filePath"
Send-ThreatAlert -Severity "HIGH" -Message "Suspicious multiple extension" -Details $filePath
Move-ToQuarantine -FilePath $filePath -Reason "Multiple/suspicious extension: $fileName"
return
}
# Full threat analysis for ALL files
Invoke-ThreatAnalysis -FilePath $filePath
# Check for unsigned DLLs
if ($ext -in @('.dll', '.winmd')) {
try {
$sig = Get-AuthenticodeSignature $filePath -ErrorAction SilentlyContinue
if ($sig.Status -ne 'Valid') {
Write-Log "Unsigned DLL: $filePath"
Move-ToQuarantine -FilePath $filePath -Reason "Unsigned DLL"
}
} catch {}
}
}
} catch {
Write-Log "Error scanning drive $drive : $_"
}
}
Write-Log "Full system scan completed"
# Monitor ALL accessible drives for real-time protection
$monitorFolders = @()
foreach ($drive in $allDrives) {
$monitorFolders += "$drive\"
}
if ($Config.EnableRealtimeMonitor) {
Write-Log "Setting up real-time file monitoring"
foreach ($folder in $monitorFolders) {
if (-not (Test-Path $folder)) { continue }
try {
$watcher = New-Object IO.FileSystemWatcher $folder, '*.*' -Property @{
IncludeSubdirectories = $true
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
Register-ObjectEvent $watcher Created -Action {
$filePath = $Event.SourceEventArgs.FullPath
$ext = [IO.Path]::GetExtension($filePath).ToLower()
if ($using:MonitoredExtensions -contains $ext) {
Start-Sleep -Milliseconds 800
Invoke-ThreatAnalysis -FilePath $filePath
}
} | Out-Null
$watcher.EnableRaisingEvents = $true
Write-Log "File watcher active for: $folder"
} catch {
Write-Log "Failed to create file watcher for $folder : $_"
}
}
}
Write-Log "Registering WMI real-time execution monitors"
try {
Register-WmiEvent -Query "SELECT * FROM Win32_ProcessStartTrace" -Action {
$event = $Event.SourceEventArgs.NewEvent
$filePath = $event.ProcessName
$processId = $event.ProcessId
try {
$ownerSid = (Get-CimInstance Win32_Process -Filter "ProcessId=$processId" -ErrorAction SilentlyContinue |
Invoke-CimMethod -MethodName GetOwnerSid).Sid
} catch {
$ownerSid = "Unknown"
}
if ($AllowedSIDs -contains $ownerSid) {
try {
$signature = Get-AuthenticodeSignature -FilePath $filePath -ErrorAction Stop
if ($signature.Status -eq 'Valid') {
return
}
} catch {}
}
Block-FileExecution -FilePath $filePath -ProcessId $processId -Type "EXE"
} | Out-Null
Write-Log "WMI process start monitor registered"
} catch {
Write-Log "Failed to register WMI process start monitor: $_"
}
try {
Register-WmiEvent -Query "SELECT * FROM Win32_ModuleLoadTrace" -Action {
$event = $Event.SourceEventArgs.NewEvent
$filePath = $event.ImageName
$processId = $event.ProcessId
if (-not (Test-Path $filePath)) { return }
try {
$ownerSid = (Get-CimInstance Win32_Process -Filter "ProcessId=$processId" -ErrorAction SilentlyContinue |
Invoke-CimMethod -MethodName GetOwnerSid).Sid
} catch {
$ownerSid = "Unknown"
}
if ($AllowedSIDs -contains $ownerSid) {
try {
$signature = Get-AuthenticodeSignature -FilePath $filePath -ErrorAction Stop
if ($signature.Status -eq 'Valid') {
return
}
} catch {}
}
Block-FileExecution -FilePath $filePath -ProcessId $processId -Type "DLL"
} | Out-Null
Write-Log "WMI module load monitor registered"
} catch {
Write-Log "Failed to register WMI module load monitor: $_"
}
if ($Config.EnableMemoryScanning) {
Write-Log "Memory scanning enabled (runs in main loop)"
}
if ($KeyScramblerConfig.EnableKeyScrambler) {
Start-KeyScrambler
}
$Script:LastDeepScan = [DateTime]::MinValue
function Invoke-DeepScan {
if (-not $IsAdmin -or -not $Config.EnableThreatIntel) { return }
$now = Get-Date
$intervalSeconds = 60 * 60 * $BehaviorConfig.DeepScanIntervalHours
if ($Script:LastDeepScan -ne [DateTime]::MinValue -and ($now - $Script:LastDeepScan).TotalSeconds -lt $intervalSeconds) {
return
}
$Script:LastDeepScan = $now
Write-Log "Running deep scan..."
try {
$persistence = Find-PersistenceMechanisms
if ($persistence -and $persistence.Count -gt 0) {
$outputFile = Join-Path $Config.BaseDirectory "persistence_scan.csv"
$persistence | Export-Csv -Path $outputFile -NoTypeInformation
Write-Log "Persistence scan found $($persistence.Count) items -> $outputFile"
Send-ThreatAlert -Severity "MEDIUM" -Message "Persistence mechanisms detected" -Details "Found $($persistence.Count) items"
}
} catch {
Write-Log "Persistence scan error: $_"
}
try {
$fileless = Find-FilelessIndicators
if ($fileless -and $fileless.Count -gt 0) {
$outputFile = Join-Path $Config.BaseDirectory "fileless_detections.xml"
$fileless | Export-Clixml -Path $outputFile
Write-Log "Fileless indicators found: $($fileless.Count) -> $outputFile"
Send-ThreatAlert -Severity "HIGH" -Message "Fileless malware indicators" -Details "Found $($fileless.Count) indicators"
}
} catch {
Write-Log "Fileless scan error: $_"
}
}
if ($IsAdmin -and $Config.EnableThreatIntel) {
$lastUpdateFile = Join-Path $Config.BaseDirectory "last_update.txt"
$currentTime = Get-Date
$shouldUpdate = $false
if (-not (Test-Path $lastUpdateFile)) {
$shouldUpdate = $true
} else {
try {
$lastUpdate = (Get-Item $lastUpdateFile).LastWriteTime
if ($lastUpdate -lt $currentTime.AddDays(-$BehaviorConfig.ThreatIntelUpdateDays)) {
$shouldUpdate = $true
}
} catch {
$shouldUpdate = $true
}
}
if ($shouldUpdate) {
Update-ThreatIntelligence
$currentTime | Out-File -FilePath $lastUpdateFile
}
Write-Log "Deep scanner initialized (runs every $($BehaviorConfig.DeepScanIntervalHours) hours)"
}
Write-Log "All monitoring systems active"
Write-Host "`nAntivirus is now running" -ForegroundColor Green
Write-Host "Press [Ctrl+C] to stop" -ForegroundColor Yellow
try {
while ($true) {
try {
# Core threat detection
Invoke-ProcessAndNetworkScan
Start-Sleep -Seconds 5
Invoke-LOLBinDetection
Start-Sleep -Seconds 5
Invoke-ProcessAnomalyDetection
Start-Sleep -Seconds 5
Invoke-AMSIBypassDetection
Start-Sleep -Seconds 5
Invoke-CredentialDumpDetection
Start-Sleep -Seconds 5
Invoke-RansomwareDetection
Start-Sleep -Seconds 5
Invoke-ProcessHollowingDetection
Start-Sleep -Seconds 5
Invoke-NetworkAnomalyDetection
Start-Sleep -Seconds 5
Invoke-DLLHijackingDetection
Start-Sleep -Seconds 5
Invoke-TokenManipulationDetection
Start-Sleep -Seconds 5
Invoke-WMIPersistenceDetection
Start-Sleep -Seconds 5
Invoke-ScheduledTaskDetection
Start-Sleep -Seconds 5
Invoke-RegistryPersistenceDetection
Start-Sleep -Seconds 5
# Niche/specialized detections
Invoke-NeuroBehaviorMonitor
Start-Sleep -Seconds 5
Invoke-PrivacyForgeSpoofing
Start-Sleep -Seconds 5
Invoke-ElfDLLUnloader
Start-Sleep -Seconds 5
Invoke-RootkitDetection
Start-Sleep -Seconds 5
Invoke-AttackToolsDetection
Start-Sleep -Seconds 5
Invoke-BeaconDetection
Start-Sleep -Seconds 5
Invoke-USBMonitoring
Start-Sleep -Seconds 5
Invoke-GFocus
Start-Sleep -Seconds 5
Invoke-ScriptContentScan
Start-Sleep -Seconds 5
Invoke-StartupPersistenceDetection
Start-Sleep -Seconds 5
Invoke-DriverWatcher
Start-Sleep -Seconds 5
# Memory scanning (previously in separate jobs)
Invoke-MemoryScan
Start-Sleep -Seconds 5
Invoke-YaraMemoryScan
Start-Sleep -Seconds 5
# Deep scan (runs periodically based on interval)
Invoke-DeepScan
Start-Sleep -Seconds 5
Write-Log "Scan cycle completed"
} catch {
Write-Log "Scan cycle error: $_"
}
}
} catch {
Write-Log "Main loop terminated: $($_.Exception.Message)"
Write-Host "`nAntivirus stopped. Check log file: $($Config.LogFile)" -ForegroundColor Red
}
Editor is loading...
Leave a Comment