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-
5341function 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-
6047function Log-Removed { param ([string ]$I ); $RemovedItems.Add (" [REMOVED] $I " ) }
6148function Log-Failed { param ([string ]$I ); $FailedItems.Add (" [FAILED] $I " ) }
6249function 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-
8668Clear-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 " "
9769Write-Host (" =" * 70 ) - ForegroundColor DarkCyan
9870Write-Host " PNWC Remediation Tool - JWrapper / ScreenConnect Intrusion " - ForegroundColor Cyan
9971Write-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
10173Write-Host (" =" * 70 ) - ForegroundColor DarkCyan
10274Write-Host " "
10375Write-Host " Started : $ ( Get-Date - Format ' dddd MMMM dd yyyy HH:mm:ss' ) " - ForegroundColor Gray
10476Write-Host " Computer : $env: COMPUTERNAME " - ForegroundColor Gray
10577Write-Host " Log file : $ReportFile " - ForegroundColor Gray
10678Write-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)
271244Write-Log " [*] Scanning ClickOnce cache for ScreenConnect artifacts..." " Yellow"
272245Get-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 {
491468Write-Log " "
492469Write-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
504472try {
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# ════════════════════════════════════════════════════════════
551491Write-Log " "
552492Write-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 = @{
567506foreach ($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
580520Get-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.
608542if ($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"
623557Write-Log " REMEDIATION COMPLETE" " Cyan"
624558Write-Log (" =" * 70 ) " DarkCyan"
625559Write-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}
639570Write-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
734665POST-REMEDIATION VERIFICATION RESULTS
735666$divider
736667
737- $ ( $script : VerifyResults | Out-String )
668+ $ ( $VerifyResults | Out-String )
738669$divider
739670REQUIRED 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