Skip to content

Commit c974c7b

Browse files
authored
Update fix.ps1
1 parent 451a43d commit c974c7b

1 file changed

Lines changed: 49 additions & 113 deletions

File tree

fix.ps1

Lines changed: 49 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,13 @@
1616
.NOTES
1717
Author : Pacific Northwest Computers
1818
Contact : jon@pnwcomputers.com | 360-624-7379
19-
Version : 2.4.0
19+
Version : 2.2
2020
Updated : May 2026 -- added ClickOnce cache purge, VBScript staging files,
2121
SILENTCONNECT delivery artifacts, Defender exclusion removal,
2222
new process aliases, updated firewall block list
2323
#>
2424

2525
#Requires -RunAsAdministrator
26-
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '', Scope='Function', Target='Log-Removed')]
27-
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '', Scope='Function', Target='Log-Failed')]
28-
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '', Scope='Function', Target='Log-NotFound')]
29-
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Scope='Variable', Target='clickOnceClean')]
30-
param()
3126
# Set UTF-8 output encoding so box-drawing characters render correctly
3227
# Works whether launched via RUN_ME.bat (chcp 65001) or directly from PowerShell
3328
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
@@ -43,20 +38,12 @@ $RemovedItems = [System.Collections.Generic.List[string]]::new()
4338
$FailedItems = [System.Collections.Generic.List[string]]::new()
4439
$NotFoundItems = [System.Collections.Generic.List[string]]::new()
4540

46-
# Hoisted from Step 9 -- guarantee these are defined even if Step 9
47-
# aborts mid-flight (terminating errors bypass SilentlyContinue and would
48-
# otherwise leave the summary block reading $null -> phantom "failure" status).
49-
$script:Issues = 0
50-
$script:VerifyResults = [System.Collections.Generic.List[string]]::new()
51-
$script:clickOnceClean = $true
52-
5341
function Write-Log {
5442
param([string]$Msg, [string]$Color = "White")
5543
$entry = "[$(Get-Date -Format 'HH:mm:ss')] $Msg"
5644
Write-Host $entry -ForegroundColor $Color
5745
$ActionLog.Add($entry)
5846
}
59-
6047
function Log-Removed { param([string]$I); $RemovedItems.Add(" [REMOVED] $I") }
6148
function Log-Failed { param([string]$I); $FailedItems.Add(" [FAILED] $I") }
6249
function Log-NotFound { param([string]$I); $NotFoundItems.Add(" [NOT FOUND] $I") }
@@ -78,39 +65,25 @@ function Remove-LockedPath {
7865
}
7966

8067
# ── Banner ────────────────────────────────────────────────────────────────────
81-
# Pure-ASCII banner. Avoids UTF-8 box-drawing chars so this renders correctly
82-
# regardless of console codepage (some PowerShell 5.1 / Windows console host
83-
# combinations ignore chcp 65001 and decode output as cp1252, producing mojibake).
84-
$host.UI.RawUI.WindowTitle = "PNWC Remediation Tool v2.4.0"
85-
8668
Clear-Host
87-
Write-Host ""
88-
Write-Host " ###### ## ## ## ## ######" -ForegroundColor Cyan
89-
Write-Host " ## ## ### ## ## ## ## " -ForegroundColor Cyan
90-
Write-Host " ###### ###### ## ## ## ## " -ForegroundColor Cyan
91-
Write-Host " ## ## ### ######## ## " -ForegroundColor Cyan
92-
Write-Host " ## ## ## ## ## ######" -ForegroundColor Cyan
93-
Write-Host ""
94-
Write-Host " Pacific Northwest Computers" -ForegroundColor White
95-
Write-Host " Malware Remediation Toolkit" -ForegroundColor DarkGray
96-
Write-Host ""
9769
Write-Host ("=" * 70) -ForegroundColor DarkCyan
9870
Write-Host " PNWC Remediation Tool - JWrapper / ScreenConnect Intrusion " -ForegroundColor Cyan
9971
Write-Host " Pacific Northwest Computers | jon@pnwcomputers.com " -ForegroundColor Gray
100-
Write-Host " v2.4.0 -- SILENTCONNECT / Medusa IAB variant " -ForegroundColor DarkGray
72+
Write-Host " v2.2 -- SILENTCONNECT / Medusa IAB variant " -ForegroundColor DarkGray
10173
Write-Host ("=" * 70) -ForegroundColor DarkCyan
10274
Write-Host ""
10375
Write-Host " Started : $(Get-Date -Format 'dddd MMMM dd yyyy HH:mm:ss')" -ForegroundColor Gray
10476
Write-Host " Computer : $env:COMPUTERNAME" -ForegroundColor Gray
10577
Write-Host " Log file : $ReportFile" -ForegroundColor Gray
10678
Write-Host ""
107-
$ActionLog.Add("PNWC Remediation Tool v2.4.0 -- JWrapper/ScreenConnect (SILENTCONNECT)")
79+
$ActionLog.Add("PNWC Remediation Tool v2.2 -- JWrapper/ScreenConnect (SILENTCONNECT)")
10880
$ActionLog.Add("Started : $(Get-Date)")
10981
$ActionLog.Add("Computer: $env:COMPUTERNAME")
11082
$ActionLog.Add("OS : $((Get-WmiObject Win32_OperatingSystem).Caption)")
11183
$ActionLog.Add("Operator: $([Security.Principal.WindowsIdentity]::GetCurrent().Name)")
11284
$ActionLog.Add(("=" * 70))
11385

86+
11487
# ════════════════════════════════════════════════════════════
11588
# STEP 1 — KILL PROCESSES
11689
# ════════════════════════════════════════════════════════════
@@ -120,7 +93,7 @@ $BadProcs = @(
12093
"Remote Access Service", # space-variant alias (confirmed in ETL traces)
12194
"Remote_Access_Configure",
12295
"Remote_Access_Launcher",
123-
"Remote_AccessWinLauncher", # JWrapper Windows launcher component (v2.4.0 addition)
96+
"Remote_AccessWinLauncher", # JWrapper Windows launcher component (v2.2 addition)
12497
"SimpleService",
12598
"StopSimpleGatewayService",
12699
"ScreenConnect.WindowsClient",
@@ -206,7 +179,7 @@ foreach ($key in $RegKeys) {
206179
Log-Removed "Registry: $key"
207180
} catch {
208181
Write-Log " [!] Failed to remove: $key ($($_.Exception.Message))" "Red"
209-
$regPath = $key -replace "HKLM:\\","HKLM\\" -replace "HKCU:\\","HKCU\\"
182+
$regPath = $key -replace "HKLM:\\","HKLM\" -replace "HKCU:\\","HKCU\"
210183
reg.exe delete $regPath /f 2>&1 | Out-Null
211184
Log-Failed "Registry: $key"
212185
}
@@ -267,7 +240,7 @@ foreach ($path in $PrimaryPaths) {
267240
}
268241
}
269242

270-
# ClickOnce cache -- remove ScreenConnect entries per-user (v2.4.0 addition)
243+
# ClickOnce cache -- remove ScreenConnect entries per-user (v2.2 addition)
271244
Write-Log " [*] Scanning ClickOnce cache for ScreenConnect artifacts..." "Yellow"
272245
Get-ChildItem "C:\Users" -Directory -ErrorAction SilentlyContinue | ForEach-Object {
273246
$coPath = Join-Path $_.FullName "AppData\Local\Apps\2.0"
@@ -279,6 +252,7 @@ Get-ChildItem "C:\Users" -Directory -ErrorAction SilentlyContinue | ForEach-Obje
279252
$_.Name -like "*420d02d3849b7992*" -or # v25.x Core/Windows DLL
280253
$_.Name -like "*1eba6b14258ee2ac*" -or # v19.x 2025 payload
281254
$_.Name -like "*25b0fbb6ef7eb094*" -or # v17-18.x 2021-2024
255+
$_.Name -like "*4b14c015c87c1ad8*" -or # v18.x intermediate payload
282256
$_.Name -like "*b15b0581876c57b7*" # v15.x oldest observed
283257
} |
284258
ForEach-Object {
@@ -296,7 +270,7 @@ Get-ChildItem "C:\Users" -Directory -ErrorAction SilentlyContinue | ForEach-Obje
296270
}
297271
}
298272

299-
# SILENTCONNECT variant staging files (v2.4.0 addition)
273+
# SILENTCONNECT variant staging files (v2.2 addition)
300274
$StagingFiles = @(
301275
"C:\Windows\Temp\FileR.txt", # C# payload staging file
302276
"C:\Temp\ScreenConnect.ClientSetup.msi", # MSI staging path
@@ -320,7 +294,7 @@ foreach ($f in $StagingFiles) {
320294
}
321295
}
322296

323-
# VBScript delivery files in common locations (v2.4.0 addition)
297+
# VBScript delivery files in common locations (v2.2 addition)
324298
$VbsPatterns = @(
325299
"$env:USERPROFILE\Downloads\E-INVITE.vbs",
326300
"$env:USERPROFILE\Downloads\Proposal-*.vbs",
@@ -394,6 +368,7 @@ $C2BlockIPs = @{
394368
"147.45.218.13" = "JWrapper C2 redundant relay"
395369
# instance-sis2tc
396370
"15.204.131.77" = "ScreenConnect C2 relay (instance-sis2tc) -- April 2026 campaign"
371+
"147.75.50.76" = "ScreenConnect C2 relay (instance-sis2tc) -- Feb 2025 IP rotation"
397372
"147.28.146.148" = "ScreenConnect C2 relay (instance-fc5xev) -- 2024 campaign wave"
398373
# instance-zayrhg (2023-2026)
399374
"15.204.48.24" = "ScreenConnect C2 relay (instance-zayrhg) -- Mar-Aug 2026"
@@ -414,6 +389,8 @@ $C2BlockIPs = @{
414389
"139.178.89.208" = "ScreenConnect C2 relay (instance-xbirmk) -- Jan 2023"
415390
"139.178.89.96" = "ScreenConnect C2 relay (instance-xbirmk) -- Oct 2023"
416391
"139.178.89.228" = "ScreenConnect C2 relay (instance-xbirmk) -- Sep 2024"
392+
# instance-wrnmil (2023)
393+
"147.28.129.152" = "ScreenConnect C2 relay (instance-wrnmil) -- Mar-Oct 2023"
417394
# SILENTCONNECT delivery
418395
"86.38.225.59" = "bumptobabeco.top -- SILENTCONNECT delivery server, Lithuania"
419396
}
@@ -427,7 +404,7 @@ foreach ($ip in $C2BlockIPs.Keys) {
427404
-RemoteAddress $ip `
428405
-Protocol Any `
429406
-Enabled True `
430-
-Description "PNWC Remediation v2.4.0 -- Block $($C2BlockIPs[$ip])" `
407+
-Description "PNWC Remediation v2.2 -- Block $($C2BlockIPs[$ip])" `
431408
-ErrorAction Stop | Out-Null
432409
Write-Log " [OK] Added outbound block rule for: $ip ($($C2BlockIPs[$ip]))" "Green"
433410
Log-Removed "Firewall block added for C2 IP: $ip"
@@ -491,57 +468,20 @@ try {
491468
Write-Log ""
492469
Write-Log "--- STEP 8: Removing Windows Defender Exclusions Added by Malware ---" "Cyan"
493470
# SILENTCONNECT adds an ExclusionExtension for .exe during delivery
494-
# to prevent Defender from scanning the ScreenConnect installer.
495-
#
496-
# If a third-party AV is the active endpoint protection, or the WinDefend
497-
# service is stopped/disabled, Get-MpPreference fails with HRESULT 0x800106BA
498-
# (WMI/MI provider failure). That's a "not applicable" condition, not a
499-
# remediation failure -- we log it gracefully and move on.
500-
501-
# Pre-check: is Defender actually reachable on this system?
502-
$defenderReachable = $false
503-
$defenderSkipReason = $null
471+
# to prevent Defender from scanning the ScreenConnect installer
504472
try {
505-
$winDefSvc = Get-Service -Name WinDefend -ErrorAction Stop
506-
if ($winDefSvc.Status -eq 'Running') {
507-
$defenderReachable = $true
473+
$currentExclusions = (Get-MpPreference -ErrorAction Stop).ExclusionExtension
474+
if ($currentExclusions -and $currentExclusions -contains ".exe") {
475+
Remove-MpPreference -ExclusionExtension ".exe" -ErrorAction Stop
476+
Write-Log " [OK] Removed Defender .exe extension exclusion (added by SILENTCONNECT during delivery)" "Green"
477+
Log-Removed "Windows Defender ExclusionExtension: .exe"
508478
} else {
509-
$defenderSkipReason = "WinDefend service status is '$($winDefSvc.Status)' (not Running)"
479+
Write-Log " [--] No .exe Defender exclusion found" "DarkGray"
480+
Log-NotFound "Defender .exe exclusion (not present)"
510481
}
511482
} catch {
512-
$defenderSkipReason = "WinDefend service not installed or inaccessible"
513-
}
514-
515-
if (-not $defenderReachable) {
516-
Write-Log " [--] Windows Defender not active on this system -- skipping" "DarkGray"
517-
Write-Log " Reason: $defenderSkipReason" "Gray"
518-
Write-Log " (Third-party AV present, or Defender disabled by policy.)" "Gray"
519-
Log-NotFound "Defender exclusion check (Defender not active: $defenderSkipReason)"
520-
} else {
521-
try {
522-
$currentExclusions = (Get-MpPreference -ErrorAction Stop).ExclusionExtension
523-
if ($currentExclusions -and $currentExclusions -contains ".exe") {
524-
Remove-MpPreference -ExclusionExtension ".exe" -ErrorAction Stop
525-
Write-Log " [OK] Removed Defender .exe extension exclusion (added by SILENTCONNECT during delivery)" "Green"
526-
Log-Removed "Windows Defender ExclusionExtension: .exe"
527-
} else {
528-
Write-Log " [--] No .exe Defender exclusion found" "DarkGray"
529-
Log-NotFound "Defender .exe exclusion (not present)"
530-
}
531-
} catch {
532-
$errMsg = $_.Exception.Message
533-
# 0x800106BA is the canonical Defender-unreachable signature; the
534-
# service may have stopped between our pre-check and the cmdlet call,
535-
# or tamper protection may be blocking the MI provider. Treat as N/A.
536-
if ($errMsg -match '0x800106BA') {
537-
Write-Log " [--] Defender MI provider unreachable (0x800106BA) -- skipping" "DarkGray"
538-
Write-Log " (Service stopped mid-run, or tamper protection blocking MI access.)" "Gray"
539-
Log-NotFound "Defender exclusion check (MI provider unreachable, 0x800106BA)"
540-
} else {
541-
Write-Log " [!] Could not check/remove Defender exclusions: $errMsg" "Red"
542-
Log-Failed "Defender exclusion removal"
543-
}
544-
}
483+
Write-Log " [!] Could not check/remove Defender exclusions: $($_.Exception.Message)" "Red"
484+
Log-Failed "Defender exclusion removal"
545485
}
546486

547487

@@ -550,9 +490,8 @@ if (-not $defenderReachable) {
550490
# ════════════════════════════════════════════════════════════
551491
Write-Log ""
552492
Write-Log "--- STEP 9: Post-Remediation Verification ---" "Cyan"
553-
# $script:Issues, $script:VerifyResults, $script:clickOnceClean are
554-
# initialized at the top of the script so this block remains safe even
555-
# if it gets re-entered or partially aborts.
493+
$Issues = 0
494+
$VerifyResults = [System.Collections.Generic.List[string]]::new()
556495

557496
$Checks = @{
558497
"Service: Remote Access Service" = { Get-Service "Remote Access Service" -ErrorAction SilentlyContinue }
@@ -567,37 +506,32 @@ $Checks = @{
567506
foreach ($check in $Checks.Keys) {
568507
$result = & $Checks[$check]
569508
if ($result) {
570-
$script:Issues++
509+
$Issues++
571510
Write-Log " [!] STILL PRESENT: $check" "Red"
572-
$script:VerifyResults.Add(" [STILL PRESENT] $check")
511+
$VerifyResults.Add(" [STILL PRESENT] $check")
573512
} else {
574513
Write-Log " [OK] Cleared: $check" "Green"
575-
$script:VerifyResults.Add(" [CLEAR] $check")
514+
$VerifyResults.Add(" [CLEAR] $check")
576515
}
577516
}
578517

579518
# Check if any ClickOnce campaign tokens remain
519+
$clickOnceClean = $true
580520
Get-ChildItem "C:\Users" -Directory -ErrorAction SilentlyContinue | ForEach-Object {
581521
$coPath = Join-Path $_.FullName "AppData\Local\Apps\2.0"
582522
if (Test-Path $coPath) {
583523
$remaining = Get-ChildItem -Path $coPath -Recurse -Directory -ErrorAction SilentlyContinue |
584-
Where-Object {
585-
$_.Name -like "*27fa83f1ad328157*" -or # v25.x April 2026 wave
586-
$_.Name -like "*420d02d3849b7992*" -or # v25.x Core/Windows DLL
587-
$_.Name -like "*1eba6b14258ee2ac*" -or # v19.x 2025 payload
588-
$_.Name -like "*25b0fbb6ef7eb094*" -or # v17-18.x 2021-2024
589-
$_.Name -like "*b15b0581876c57b7*" # v15.x oldest observed
590-
}
524+
Where-Object { $_.Name -like "*27fa83f1ad328157*" -or $_.Name -like "*420d02d3849b7992*" }
591525
if ($remaining) {
592-
$script:clickOnceClean = $false
593-
$script:Issues++
594-
$script:VerifyResults.Add(" [STILL PRESENT] ClickOnce campaign token dirs in: $coPath")
526+
$clickOnceClean = $false
527+
$Issues++
528+
$VerifyResults.Add(" [STILL PRESENT] ClickOnce campaign token dirs in: $coPath")
595529
Write-Log " [!] STILL PRESENT: ClickOnce campaign dirs in $coPath" "Red"
596530
}
597531
}
598532
}
599-
if ($script:clickOnceClean) {
600-
$script:VerifyResults.Add(" [CLEAR] ClickOnce cache (no campaign tokens found)")
533+
if ($clickOnceClean) {
534+
$VerifyResults.Add(" [CLEAR] ClickOnce cache (no campaign tokens found)")
601535
Write-Log " [OK] Cleared: ClickOnce cache" "Green"
602536
}
603537

@@ -607,10 +541,10 @@ if ($script:clickOnceClean) {
607541
# Verification is based on Step 7 outcome, not a re-query.
608542
if ($ps4104Hits.Count -gt 0) {
609543
# Step 7 found and cleared entries -- mark as clean based on successful wevtutil cl
610-
$script:VerifyResults.Add(" [CLEAR] PowerShell 4104 campaign entries (documented and log cleared in Step 7)")
544+
$VerifyResults.Add(" [CLEAR] PowerShell 4104 campaign entries (documented and log cleared in Step 7)")
611545
Write-Log " [OK] Cleared: PowerShell 4104 campaign entries (Step 7 documented and cleared $($ps4104Hits.Count) entries)" "Green"
612546
} else {
613-
$script:VerifyResults.Add(" [CLEAR] PowerShell 4104 campaign entries (none present)")
547+
$VerifyResults.Add(" [CLEAR] PowerShell 4104 campaign entries (none present)")
614548
Write-Log " [OK] Cleared: PowerShell 4104 campaign entries (none found)" "Green"
615549
}
616550

@@ -623,17 +557,14 @@ Write-Log ("=" * 70) "DarkCyan"
623557
Write-Log " REMEDIATION COMPLETE" "Cyan"
624558
Write-Log ("=" * 70) "DarkCyan"
625559
Write-Log ""
626-
# Snapshot the count and coerce defensively so this block can never
627-
# produce "STATUS : item(s) could not be removed." (blank number).
628-
$issueCount = [int]($script:Issues)
629-
if ($issueCount -le 0) {
560+
if ($Issues -eq 0) {
630561
Write-Log " STATUS : All verified indicators removed successfully." "Green"
631562
Write-Log " *** REBOOT THIS MACHINE NOW ***" "Yellow"
632563
Write-Log ""
633564
Write-Log " After rebooting, run system_check.ps1 to confirm clean." "White"
634565
Write-Log " Then change ALL passwords used on this machine." "White"
635566
} else {
636-
Write-Log " STATUS : $issueCount item(s) could not be removed." "Red"
567+
Write-Log " STATUS : $Issues item(s) could not be removed." "Red"
637568
Write-Log " Review output above. Reboot and re-run, or contact PNWC." "Yellow"
638569
}
639570
Write-Log ""
@@ -644,8 +575,8 @@ Write-Log ("=" * 70) "DarkCyan"
644575
# ════════════════════════════════════════════════════════════
645576
# SAVE REPORT FILE
646577
# ════════════════════════════════════════════════════════════
647-
$statusText = if ($issueCount -le 0) { "ALL DETECTED ITEMS REMOVED -- Reboot required to complete cleanup" }
648-
else { "INCOMPLETE -- $issueCount item(s) could not be removed, see details below" }
578+
$statusText = if ($Issues -eq 0) { "ALL DETECTED ITEMS REMOVED -- Reboot required to complete cleanup" }
579+
else { "INCOMPLETE -- $Issues item(s) could not be removed, see details below" }
649580

650581
$divider = "=" * 70
651582

@@ -657,7 +588,7 @@ $divider
657588
Prepared by : Pacific Northwest Computers
658589
Phone : 360-624-7379
659590
Email : jon@pnwcomputers.com
660-
Tool ver : 2.4.0
591+
Tool ver : 2.2
661592
$divider
662593
663594
##############################################################
@@ -734,7 +665,7 @@ $divider
734665
POST-REMEDIATION VERIFICATION RESULTS
735666
$divider
736667
737-
$($script:VerifyResults | Out-String)
668+
$($VerifyResults | Out-String)
738669
$divider
739670
REQUIRED NEXT STEPS
740671
$divider
@@ -773,6 +704,10 @@ $divider
773704
IP: 139.178.89.208
774705
IP: 139.178.89.96
775706
IP: 139.178.89.228
707+
# instance-wrnmil (2023)
708+
IP: 147.28.129.152
709+
# instance-sis2tc rotation
710+
IP: 147.75.50.76
776711
# SILENTCONNECT delivery infrastructure
777712
IP: 86.38.225.59
778713
# Dynamic DNS
@@ -782,6 +717,7 @@ $divider
782717
Domain: instance-zayrhg-relay.screenconnect.com
783718
Domain: instance-c7gab0-relay.screenconnect.com
784719
Domain: instance-xbirmk-relay.screenconnect.com
720+
Domain: instance-wrnmil-relay.screenconnect.com
785721
Domain: bumptobabeco.top
786722
Domain: imansport.ir
787723
Domain: solpru.com

0 commit comments

Comments
 (0)