‹ Back to library
POWERSHELL
Next sector · 05
Research
Papers, write-ups and exploit notes.
Detection Script for BatShadow/Vampire Bot
PowerShell script for detecting and remediating BatShadow threat actor's Vampire Bot malware. Based on threat intelligence from Aryaka Threat Research Labs (October 2025). Scans for malicious files, suspicious processes, C2 connections, registry persistence, and provides automated remediation capabilities.
#Requires -RunAsAdministrator <# .SYNOPSIS Detection and remediation script for BatShadow/Vampire Bot malware .DESCRIPTION This script detects and attempts to remediate BatShadow threat actor's Vampire Bot malware Based on threat intelligence from Aryaka Threat Research Labs (October 2025) .NOTES Version: 1.0 Author: Security Operations Requires: Administrator privileges .LINK https://www.aryaka.com/blog/batshade-vampire-bot-social-engineering-malware/ #> # Configuration $LogPath = "$env:SystemRoot\Temp\BatShadow-Detection-$(Get-Date -Format 'yyyyMMdd-HHmmss').log" $QuarantinePath = "$env:SystemRoot\Temp\Quarantine-$(Get-Date -Format 'yyyyMMdd-HHmmss')" # Known IOCs based on threat intelligence $IOCs = @{ C2Domains = @( 'api3.samsungcareers.work', 'samsungcareers.work', 'samsung-work.com', 'marriott-careers.work' ) MaliciousIPs = @( '103.124.95.161' ) SuspiciousProcesses = @( 'XtraViewer', 'XVDesktop', 'microsoftedge', 'chrome' ) FileIndicators = @{ Extensions = @('.lnk', '.exe', '.zip') SuspiciousNames = @( '*job*description*.pdf.exe', '*job*description*.lnk', '*Marketing*Manager*.exe', '*Marriott*.lnk', '*Samsung*.lnk', 'XtraViewer*' ) } RegistryKeys = @( 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run', 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Run', 'HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce', 'HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce' ) } # Detection results $DetectionResults = @{ MaliciousFiles = @() SuspiciousProcesses = @() NetworkConnections = @() RegistryEntries = @() HostFileEntries = @() MutexObjects = @() ScreenshotFiles = @() } # Logging function function Write-Log { param( [string]$Message, [ValidateSet('Info','Warning','Error','Success')] [string]$Level = 'Info' ) $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' $logMessage = "[$timestamp] [$Level] $Message" Add-Content -Path $LogPath -Value $logMessage switch($Level) { 'Info' { Write-Host $logMessage -ForegroundColor Cyan } 'Warning' { Write-Host $logMessage -ForegroundColor Yellow } 'Error' { Write-Host $logMessage -ForegroundColor Red } 'Success' { Write-Host $logMessage -ForegroundColor Green } } } # Banner function Show-Banner { Write-Host "`n========================================" -ForegroundColor Cyan Write-Host " BatShadow/Vampire Bot Detector v1.0" -ForegroundColor Cyan Write-Host " Threat Intelligence: Aryaka Labs" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan } # Check 1: Scan for malicious files function Find-MaliciousFiles { Write-Log "Scanning for suspicious files..." -Level Info $searchPaths = @( $env:TEMP, $env:USERPROFILE + '\Downloads', $env:USERPROFILE + '\Desktop', $env:APPDATA, $env:LOCALAPPDATA, "$env:SystemRoot\System32", "$env:ProgramData" ) foreach ($path in $searchPaths) { if (Test-Path $path) { foreach ($pattern in $IOCs.FileIndicators.SuspiciousNames) { try { $files = Get-ChildItem -Path $path -Filter $pattern -Recurse -ErrorAction SilentlyContinue -Force foreach ($file in $files) { $DetectionResults.MaliciousFiles += [PSCustomObject]@{ Path = $file.FullName Name = $file.Name Size = $file.Length Created = $file.CreationTime Modified = $file.LastWriteTime Hash = (Get-FileHash -Path $file.FullName -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash } Write-Log "FOUND: Suspicious file - $($file.FullName)" -Level Warning } } catch { Write-Log "Error scanning $path : $_" -Level Error } } } } # Look for WEBP screenshot files (Vampire Bot behavior) try { $webpFiles = Get-ChildItem -Path $env:TEMP -Filter "*.webp" -Recurse -ErrorAction SilentlyContinue -Force | Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } if ($webpFiles) { $DetectionResults.ScreenshotFiles += $webpFiles Write-Log "FOUND: Recent WEBP files (possible screenshots) - Count: $($webpFiles.Count)" -Level Warning } } catch { Write-Log "Error scanning for WEBP files: $_" -Level Error } } # Check 2: Identify suspicious processes function Find-SuspiciousProcesses { Write-Log "Checking for suspicious running processes..." -Level Info $processes = Get-Process -ErrorAction SilentlyContinue foreach ($proc in $processes) { # Check against known suspicious process names foreach ($suspName in $IOCs.SuspiciousProcesses) { if ($proc.ProcessName -like "*$suspName*") { try { $procInfo = [PSCustomObject]@{ Name = $proc.ProcessName PID = $proc.Id Path = $proc.Path CommandLine = (Get-CimInstance Win32_Process -Filter "ProcessId = $($proc.Id)" -ErrorAction SilentlyContinue).CommandLine StartTime = $proc.StartTime } $DetectionResults.SuspiciousProcesses += $procInfo Write-Log "FOUND: Suspicious process - $($proc.ProcessName) (PID: $($proc.Id))" -Level Warning } catch {} } } # Check for Go-compiled executables (Vampire Bot is Go-based) if ($proc.Path) { try { $fileContent = [System.IO.File]::ReadAllText($proc.Path) if ($fileContent -match 'golang|Go build ID|runtime.main') { Write-Log "FOUND: Go-based executable - $($proc.Path)" -Level Warning $DetectionResults.SuspiciousProcesses += [PSCustomObject]@{ Name = $proc.ProcessName PID = $proc.Id Path = $proc.Path Reason = "Go-based executable" } } } catch {} } } } # Check 3: Network connections to C2 function Find-C2Connections { Write-Log "Checking network connections to known C2 servers..." -Level Info try { $connections = Get-NetTCPConnection -State Established -ErrorAction SilentlyContinue foreach ($conn in $connections) { # Check against known malicious IPs if ($IOCs.MaliciousIPs -contains $conn.RemoteAddress) { $DetectionResults.NetworkConnections += [PSCustomObject]@{ LocalAddress = $conn.LocalAddress LocalPort = $conn.LocalPort RemoteAddress = $conn.RemoteAddress RemotePort = $conn.RemotePort State = $conn.State OwningProcess = (Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue).ProcessName } Write-Log "FOUND: Connection to malicious IP - $($conn.RemoteAddress)" -Level Warning } } # Check DNS cache for C2 domains $dnsCache = Get-DnsClientCache -ErrorAction SilentlyContinue foreach ($entry in $dnsCache) { foreach ($domain in $IOCs.C2Domains) { if ($entry.Name -like "*$domain*") { Write-Log "FOUND: DNS cache entry for C2 domain - $($entry.Name)" -Level Warning $DetectionResults.NetworkConnections += [PSCustomObject]@{ Type = "DNS" Domain = $entry.Name IPAddress = $entry.Data } } } } } catch { Write-Log "Error checking network connections: $_" -Level Error } } # Check 4: Registry persistence function Find-RegistryPersistence { Write-Log "Scanning registry for persistence mechanisms..." -Level Info foreach ($regPath in $IOCs.RegistryKeys) { if (Test-Path $regPath) { try { $entries = Get-ItemProperty -Path $regPath -ErrorAction SilentlyContinue foreach ($prop in $entries.PSObject.Properties) { if ($prop.Name -notin @('PSPath','PSParentPath','PSChildName','PSDrive','PSProvider')) { # Check for suspicious patterns $value = $prop.Value if ($value -match 'samsung|marriott|job.*description|XtraViewer|\.lnk|powershell.*-enc|powershell.*-w hidden') { $DetectionResults.RegistryEntries += [PSCustomObject]@{ Path = $regPath Name = $prop.Name Value = $value } Write-Log "FOUND: Suspicious registry entry - $regPath\$($prop.Name)" -Level Warning } } } } catch { Write-Log "Error scanning registry path $regPath : $_" -Level Error } } } # Check scheduled tasks Write-Log "Checking scheduled tasks..." -Level Info try { $tasks = Get-ScheduledTask -ErrorAction SilentlyContinue | Where-Object { $_.TaskName -like "*samsung*" -or $_.TaskName -like "*marriott*" -or $_.TaskName -like "*XtraViewer*" } foreach ($task in $tasks) { Write-Log "FOUND: Suspicious scheduled task - $($task.TaskName)" -Level Warning $DetectionResults.RegistryEntries += [PSCustomObject]@{ Type = "ScheduledTask" Name = $task.TaskName Path = $task.TaskPath State = $task.State } } } catch { Write-Log "Error checking scheduled tasks: $_" -Level Error } } # Check 5: Host file manipulation function Check-HostsFile { Write-Log "Checking hosts file for suspicious entries..." -Level Info $hostsPath = "$env:SystemRoot\System32\drivers\etc\hosts" if (Test-Path $hostsPath) { $hostsContent = Get-Content $hostsPath foreach ($line in $hostsContent) { foreach ($domain in $IOCs.C2Domains) { if ($line -match $domain) { $DetectionResults.HostFileEntries += $line Write-Log "FOUND: Suspicious hosts file entry - $line" -Level Warning } } } } } # Check 6: PowerShell execution policy and recent commands function Check-PowerShellActivity { Write-Log "Checking PowerShell activity..." -Level Info # Check PowerShell history $historyPath = "$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt" if (Test-Path $historyPath) { $history = Get-Content $historyPath -Tail 100 $suspiciousPatterns = @( 'Invoke-WebRequest.*samsung', 'Invoke-WebRequest.*marriott', 'IEX.*DownloadString', '-enc.*', '-w hidden', 'XtraViewer', 'Start-Process.*-WindowStyle Hidden' ) foreach ($cmd in $history) { foreach ($pattern in $suspiciousPatterns) { if ($cmd -match $pattern) { Write-Log "FOUND: Suspicious PowerShell command in history" -Level Warning } } } } } # Remediation function function Start-Remediation { param([bool]$AutoRemove = $false) if (-not $AutoRemove) { Write-Host "`n[?] Do you want to attempt automatic remediation? (Y/N): " -NoNewline -ForegroundColor Yellow $response = Read-Host if ($response -ne 'Y') { Write-Log "Remediation cancelled by user" -Level Info return } } Write-Log "Starting remediation process..." -Level Info # Create quarantine directory if (-not (Test-Path $QuarantinePath)) { New-Item -ItemType Directory -Path $QuarantinePath -Force | Out-Null } # Kill suspicious processes foreach ($proc in $DetectionResults.SuspiciousProcesses) { try { Write-Log "Terminating process: $($proc.Name) (PID: $($proc.PID))" -Level Info Stop-Process -Id $proc.PID -Force -ErrorAction Stop Write-Log "Successfully terminated process $($proc.PID)" -Level Success } catch { Write-Log "Failed to terminate process $($proc.PID): $_" -Level Error } } # Quarantine malicious files foreach ($file in $DetectionResults.MaliciousFiles) { try { $destPath = Join-Path $QuarantinePath $file.Name Write-Log "Quarantining file: $($file.Path)" -Level Info Move-Item -Path $file.Path -Destination $destPath -Force -ErrorAction Stop Write-Log "Successfully quarantined: $($file.Name)" -Level Success } catch { Write-Log "Failed to quarantine $($file.Path): $_" -Level Error } } # Remove registry persistence foreach ($regEntry in $DetectionResults.RegistryEntries) { try { if ($regEntry.Type -eq "ScheduledTask") { Write-Log "Removing scheduled task: $($regEntry.Name)" -Level Info Unregister-ScheduledTask -TaskName $regEntry.Name -Confirm:$false -ErrorAction Stop } else { Write-Log "Removing registry entry: $($regEntry.Path)\$($regEntry.Name)" -Level Info Remove-ItemProperty -Path $regEntry.Path -Name $regEntry.Name -Force -ErrorAction Stop } Write-Log "Successfully removed persistence mechanism" -Level Success } catch { Write-Log "Failed to remove persistence: $_" -Level Error } } # Block C2 domains via hosts file Write-Log "Blocking C2 domains..." -Level Info $hostsPath = "$env:SystemRoot\System32\drivers\etc\hosts" $hostsBlock = "`n# BatShadow C2 Domains - Blocked by Security Script $(Get-Date)`n" foreach ($domain in $IOCs.C2Domains) { $hostsBlock += "127.0.0.1 $domain`n" $hostsBlock += "::1 $domain`n" } try { Add-Content -Path $hostsPath -Value $hostsBlock -Force Write-Log "C2 domains blocked in hosts file" -Level Success } catch { Write-Log "Failed to update hosts file: $_" -Level Error } # Clear DNS cache try { Clear-DnsClientCache -ErrorAction Stop Write-Log "DNS cache cleared" -Level Success } catch { Write-Log "Failed to clear DNS cache: $_" -Level Error } # Firewall rules to block malicious IPs foreach ($ip in $IOCs.MaliciousIPs) { try { $ruleName = "Block BatShadow C2 - $ip" New-NetFirewallRule -DisplayName $ruleName -Direction Outbound -Action Block -RemoteAddress $ip -ErrorAction Stop | Out-Null Write-Log "Firewall rule created to block $ip" -Level Success } catch { Write-Log "Failed to create firewall rule for $ip : $_" -Level Error } } } # Generate report function Show-Report { Write-Host "`n========================================" -ForegroundColor Cyan Write-Host " DETECTION SUMMARY" -ForegroundColor Cyan Write-Host "========================================`n" -ForegroundColor Cyan Write-Host "Malicious Files Found: " -NoNewline Write-Host $DetectionResults.MaliciousFiles.Count -ForegroundColor $(if($DetectionResults.MaliciousFiles.Count -gt 0){'Red'}else{'Green'}) Write-Host "Suspicious Processes: " -NoNewline Write-Host $DetectionResults.SuspiciousProcesses.Count -ForegroundColor $(if($DetectionResults.SuspiciousProcesses.Count -gt 0){'Red'}else{'Green'}) Write-Host "C2 Network Connections: " -NoNewline Write-Host $DetectionResults.NetworkConnections.Count -ForegroundColor $(if($DetectionResults.NetworkConnections.Count -gt 0){'Red'}else{'Green'}) Write-Host "Registry Persistence: " -NoNewline Write-Host $DetectionResults.RegistryEntries.Count -ForegroundColor $(if($DetectionResults.RegistryEntries.Count -gt 0){'Red'}else{'Green'}) Write-Host "Screenshot Files (WEBP): " -NoNewline Write-Host $DetectionResults.ScreenshotFiles.Count -ForegroundColor $(if($DetectionResults.ScreenshotFiles.Count -gt 0){'Yellow'}else{'Green'}) Write-Host "`nDetailed log saved to: $LogPath" -ForegroundColor Cyan $totalThreats = $DetectionResults.MaliciousFiles.Count + $DetectionResults.SuspiciousProcesses.Count + $DetectionResults.NetworkConnections.Count + $DetectionResults.RegistryEntries.Count if ($totalThreats -gt 0) { Write-Host "`n[!] THREATS DETECTED - Immediate action recommended!" -ForegroundColor Red return $true } else { Write-Host "`n[+] No BatShadow/Vampire Bot indicators detected" -ForegroundColor Green return $false } } # Main execution function Main { Show-Banner Write-Log "Starting BatShadow/Vampire Bot detection scan..." -Level Info Write-Log "Log file: $LogPath" -Level Info # Run all detection checks Find-MaliciousFiles Find-SuspiciousProcesses Find-C2Connections Find-RegistryPersistence Check-HostsFile Check-PowerShellActivity # Show results $threatsFound = Show-Report # Offer remediation if threats found if ($threatsFound) { Write-Host "`n" Start-Remediation Write-Host "`n========================================" -ForegroundColor Green Write-Host " RECOMMENDED NEXT STEPS" -ForegroundColor Green Write-Host "========================================" -ForegroundColor Green Write-Host "1. Change all passwords (especially email/cloud accounts)" Write-Host "2. Review recent login activity for unauthorized access" Write-Host "3. Scan with updated antivirus/EDR solution" Write-Host "4. Monitor for any suspicious network activity" Write-Host "5. Review and restore from clean backup if necessary" Write-Host "6. Consider forensic analysis for sensitive systems" Write-Host "7. Report incident to security team/authorities`n" } Write-Log "Scan completed" -Level Success } # Execute Main
