-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUninstall-WebrootAndEnableDefender.ps1
More file actions
307 lines (260 loc) · 14 KB
/
Uninstall-WebrootAndEnableDefender.ps1
File metadata and controls
307 lines (260 loc) · 14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
<#
.SYNOPSIS
This script automates the uninstallation of Webroot SecureAnywhere, performs a thorough cleanup, and enables Microsoft Defender Antivirus.
.DESCRIPTION
Designed for maximum compatibility and reliability for unattended execution by combining a staged approach with a forceful, deep-cleaning mechanism.
1. Sets the PowerShell Execution Policy to Bypass for the current process.
2. Attempts a standard uninstallation using WRSA.exe.
3. Performs a two-stage cleanup:
a. Stage 1: A "gentle" attempt to remove leftover folders.
b. Stage 2 (Forceful): If Stage 1 fails, it stops services, terminates processes, and performs a deep-level registry and file system purge.
4. Conditionally removes WMI entries ONLY if the full cleanup is successful.
5. Dynamically uses the correct WMI namespace (SecurityCenter/SecurityCenter2) for the OS.
6. Enables and starts Microsoft Defender services.
.EXAMPLE
.\Uninstall-WebrootAndEnableDefender.ps1
Run from an elevated PowerShell terminal. A reboot is recommended to finalize cleanup.
#>
# Set the execution policy for the current process to ensure the script can run in restricted environments.
try {
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force -ErrorAction Stop
} catch {
# If this fails, there's a bigger issue like a Group Policy override. We'll warn but continue.
Write-Warning "Failed to set execution policy. The script may be blocked from running. Error: $_"
}
# Set ErrorActionPreference to stop on unhandled errors for the rest of the script.
$ErrorActionPreference = "Stop"
#region Helper Functions
function Write-Log {
param (
[Parameter(Mandatory=$true)]
[string]$Message,
[ValidateSet("INFO","WARNING","ERROR")]
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "$timestamp [$Level] $Message"
Write-Host $logMessage
}
function Stop-WebrootProcesses {
Write-Log "Stopping Webroot user-mode processes..."
$processesToStop = @("WRSA", "WRSAUI", "WRCoreService", "WRSkyClient")
foreach ($procName in $processesToStop) {
try {
if (Get-Process -Name $procName -ErrorAction SilentlyContinue) {
Write-Log "Stopping process: $procName..."
Stop-Process -Name $procName -Force -ErrorAction Stop
Write-Log "Process '$procName' stopped."
} else {
Write-Log "Process '$procName' not found."
}
} catch {
Write-Log "Error stopping '$procName': $_" "WARNING"
}
}
}
function Remove-WebrootServices {
Write-Log "Attempting to stop and remove Webroot kernel services..."
$serviceNames = @("WRSVC", "WRCoreService", "WRSkyClient", "WRkrn", "WRBoot", "wrUrlFlt")
foreach ($serviceName in $serviceNames) {
try {
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if ($service) {
if ($service.Status -eq 'Running') {
Write-Log "Stopping service '$serviceName'..."
Stop-Service -Name $serviceName -Force -ErrorAction Stop
}
Write-Log "Deleting service '$serviceName' via sc.exe..."
sc.exe delete $serviceName
} else {
Write-Log "Service '$serviceName' not found."
}
} catch {
Write-Log "Could not stop or delete service '$serviceName'. It may already be gone or protected. Details: $_" "WARNING"
}
}
}
function Remove-WebrootRegistry {
Write-Log "Performing deep-level registry cleanup..."
$regKeysToRemove = @(
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\WRUNINST",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WRUNINST",
"HKLM:\SOFTWARE\WOW6432Node\WRData", "HKLM:\SOFTWARE\WOW6432Node\WRCore", "HKLM:\SOFTWARE\WOW6432Node\WRMIDData", "HKLM:\SOFTWARE\WOW6432Node\webroot",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WRUNINST", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WRUNINST",
"HKLM:\SOFTWARE\WRData", "HKLM:\SOFTWARE\WRMIDData", "HKLM:\SOFTWARE\WRCore", "HKLM:\SOFTWARE\webroot",
"HKLM:\SYSTEM\ControlSet001\services\WRSVC", "HKLM:\SYSTEM\ControlSet001\services\WRkrn", "HKLM:\SYSTEM\ControlSet001\services\WRBoot",
"HKLM:\SYSTEM\ControlSet001\services\WRCore", "HKLM:\SYSTEM\ControlSet001\services\WRCoreService", "HKLM:\SYSTEM\ControlSet001\services\wrUrlFlt",
"HKLM:\SYSTEM\CurrentControlSet\services\WRSVC", "HKLM:\SYSTEM\CurrentControlSet\services\WRkrn", "HKLM:\SYSTEM\CurrentControlSet\services\WRBoot",
"HKLM:\SYSTEM\CurrentControlSet\services\WRCore", "HKLM:\SYSTEM\CurrentControlSet\services\WRCoreService", "HKLM:\SYSTEM\CurrentControlSet\services\wrUrlFlt"
)
foreach ($key in $regKeysToRemove) {
if (Test-Path $key) {
Write-Log "Removing registry key: $key"
try { Remove-Item -Path $key -Recurse -Force -ErrorAction Stop }
catch { Write-Log "Failed to remove registry key '$key'. Details: $_" "WARNING" }
}
}
$regStartupPaths = @("HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run")
foreach ($path in $regStartupPaths) {
if (Test-Path $path) {
try {
if (Get-ItemProperty -Path $path -Name "WRSVC" -ErrorAction SilentlyContinue) {
Write-Log "Removing WRSVC startup item from $path"
Remove-ItemProperty -Path $path -Name "WRSVC" -Force -ErrorAction Stop
}
} catch { Write-Log "Failed to remove startup item from '$path'. Details: $_" "WARNING" }
}
}
}
function Start-ServiceWithCheck {
param ([string]$ServiceName, [int]$TimeoutSeconds = 30)
try {
if (!(Get-Service -Name $ServiceName -ErrorAction SilentlyContinue)) {
Write-Log "Service '$ServiceName' not found. Cannot start it." "WARNING"
return
}
Write-Log "Starting service '$ServiceName'..."
Start-Service -Name $ServiceName -ErrorAction Stop
$elapsed = 0
while ($elapsed -lt $TimeoutSeconds) {
if ((Get-Service -Name $ServiceName).Status -eq 'Running') {
Write-Log "Service '$ServiceName' is running."
return
}
Start-Sleep -Seconds 1; $elapsed++
}
throw "Service '$ServiceName' failed to start within $TimeoutSeconds seconds."
} catch {
Write-Log "Error starting '$ServiceName': $_" "ERROR"
}
}
function Remove-FolderWithRetry {
param(
[string[]]$Folders,
[int]$MaxRetries = 5,
[int]$RetryDelaySeconds = 60
)
$expandedFolders = $Folders | ForEach-Object { [System.Environment]::ExpandEnvironmentVariables($_) }
for ($attempt = 1; $attempt -le $MaxRetries; $attempt++) {
$foldersThatExist = $expandedFolders | Where-Object { Test-Path $_ }
if ($foldersThatExist.Count -eq 0) {
if ($attempt -eq 1) {
Write-Log "Cleanup check complete. No Webroot folders were found."
} else {
Write-Log "All targeted folders were successfully removed."
}
return $true
}
Write-Log "Attempt ${attempt}/${MaxRetries}: Found folders to delete: $($foldersThatExist -join ', ')"
foreach ($folder in $foldersThatExist) {
try {
Remove-Item -Path $folder -Recurse -Force -ErrorAction Stop
Write-Log "Successfully deleted: $folder"
} catch {
Write-Log "Error deleting '$folder': $_" "ERROR"
}
}
$remainingFolders = $expandedFolders | Where-Object { Test-Path $_ }
if ($remainingFolders.Count -eq 0) {
Write-Log "All targeted folders were successfully removed."
return $true
}
Write-Log "Folders still remaining after attempt ${attempt}: $($remainingFolders -join ', ')" "WARNING"
if ($attempt -lt $MaxRetries) {
Write-Log "Retrying in $RetryDelaySeconds seconds..."
Start-Sleep -Seconds $RetryDelaySeconds
}
}
Write-Log "Failed to delete all folders after $MaxRetries attempts." "ERROR"
return $false
}
#endregion Helper Functions
#region WMI Functions
function Remove-WebrootSecurityCenter {
param ([string]$OSVersion)
$majorVersion = [int]($OSVersion.Split('.')[0]); $minorVersion = [int]($OSVersion.Split('.')[1])
$namespace = if ($majorVersion -eq 6 -and $minorVersion -eq 1) { "root\SecurityCenter" } else { "root\SecurityCenter2" }
Write-Log "Using WMI namespace '$namespace' for this OS version."
try {
if (-not (Get-WmiObject -Namespace "root" -Class "__Namespace" | Where-Object {$_.Name -eq $namespace.Split('\')[1]})) {
Write-Log "WMI namespace '$namespace' does not exist. This is expected on some systems." "INFO"; return
}
$webrootProducts = Get-WmiObject -Namespace $namespace -Class "AntiVirusProduct" -ErrorAction SilentlyContinue | Where-Object { $_.displayName -like "*Webroot*" }
if (!$webrootProducts) { Write-Log "No Webroot WMI entries found in '$namespace'."; return }
foreach ($product in $webrootProducts) {
Write-Log "Removing WMI entry: $($product.displayName)"
try { $product.Delete(); Write-Log "Successfully removed WMI entry: $($product.displayName)" }
catch { Write-Log "Failed to remove WMI entry '$($product.displayName)': $_" "ERROR" }
}
} catch { Write-Log "Could not manage WMI entries in '$namespace'. Details: $_" "WARNING" }
}
#endregion WMI Functions
#region Main Script
# --- Initialize ---
$cleanupSuccessful = $false
$OS = Get-WmiObject -Class Win32_OperatingSystem
$OSVersion = $OS.Version
Write-Log "Detected Operating System: $($OS.Caption) (Version: $OSVersion)"
# --- Define Paths ---
$foldersToDelete = @(
"%ProgramData%\WRData", "%ProgramData%\WRCore", "%ProgramFiles%\Webroot",
"%ProgramFiles(x86)%\Webroot", "%ProgramData%\Microsoft\Windows\Start Menu\Programs\Webroot SecureAnywhere"
)
$exePaths = @("C:\Program Files (x86)\Webroot\WRSA.exe", "C:\Program Files\Webroot\WRSA.exe")
# --- Stage 0: Standard Uninstall ---
$webrootExePath = $exePaths | Where-Object { Test-Path $_ } | Select-Object -First 1
if ($webrootExePath) {
Write-Log "Webroot detected at '$webrootExePath', initiating uninstallation..."
try {
$process = Start-Process -FilePath $webrootExePath -ArgumentList "-uninstall" -Wait -PassThru -ErrorAction Stop
Write-Log "Uninstaller exit code: $($process.ExitCode)"
} catch { Write-Log "Uninstallation command failed to run: $_" "ERROR" }
Write-Log "Waiting up to 5 minutes for uninstaller to complete..."
$maxWait = 300; $elapsed = 0
while ((Test-Path $webrootExePath) -and ($elapsed -lt $maxWait)) { Start-Sleep -Seconds 10; $elapsed += 10 }
if (Test-Path $webrootExePath) {
Write-Log "Uninstaller did not complete after 5 minutes. Proceeding to forceful cleanup." "WARNING"
} else { Write-Log "Uninstaller appears to have completed successfully." }
} else { Write-Log "Webroot not detected, proceeding directly to cleanup." }
# --- Stage 1: Gentle Cleanup Attempt ---
Write-Log "--- Starting Stage 1: Gentle Cleanup ---"
$cleanupSuccessful = Remove-FolderWithRetry -Folders $foldersToDelete -MaxRetries 1 -RetryDelaySeconds 0
# --- Stage 2: Forceful Cleanup Attempt ---
if (-not $cleanupSuccessful) {
Write-Log "--- Gentle cleanup failed. Escalating to Stage 2: Forceful Cleanup ---"
Stop-WebrootProcesses
Remove-WebrootServices
Remove-WebrootRegistry
Write-Log "Pausing for 10 seconds to allow services and registry changes to apply..."
Start-Sleep -Seconds 10
$cleanupSuccessful = Remove-FolderWithRetry -Folders $foldersToDelete
}
# --- Configure MS Defender ---
Write-Log "--- Configuring Microsoft Defender ---"
if (Get-Command -Name "Set-MpPreference" -ErrorAction SilentlyContinue) {
Write-Log "Modern Defender module found. Using Set-MpPreference..."
try { Set-MpPreference -DisableRealtimeMonitoring $false -ErrorAction Stop; Set-MpPreference -DisableIOAVProtection $false -ErrorAction Stop }
catch { Write-Log "Error using Set-MpPreference. This may resolve after a reboot. Details: $_" "WARNING" }
} else { Write-Log "Modern Defender module not found. Relying on registry edits." }
$regPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender"
try {
if (-not (Test-Path $regPath)) { New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft" -Name "Windows Defender" -Force -ErrorAction Stop | Out-Null }
Set-ItemProperty -Path $regPath -Name "DisableAntiSpyware" -Value 0 -Type DWORD -Force -ErrorAction Stop
$rtRegPath = Join-Path -Path $regPath -ChildPath "Real-Time Protection"
if (-not (Test-Path $rtRegPath)) { New-Item -Path $regPath -Name "Real-Time Protection" -Force -ErrorAction Stop | Out-Null }
Set-ItemProperty -Path $rtRegPath -Name "DisableBehaviorMonitoring" -Value 0 -Type DWORD -Force -ErrorAction Stop
Set-ItemProperty -Path $rtRegPath -Name "DisableOnAccessProtection" -Value 0 -Type DWORD -Force -ErrorAction Stop
Set-ItemProperty -Path $rtRegPath -Name "DisableScanOnRealtimeEnable" -Value 0 -Type DWORD -Force -ErrorAction Stop
Write-Log "Defender registry policies updated successfully."
} catch { Write-Log "Registry update error: $_" "ERROR" }
Start-ServiceWithCheck -ServiceName "WinDefend"
Start-ServiceWithCheck -ServiceName "WdNisSvc"
# --- Conditional WMI Cleanup ---
if ($cleanupSuccessful) {
Write-Log "--- Cleanup successful. Proceeding with WMI removal. ---"
Remove-WebrootSecurityCenter -OSVersion $OSVersion
} else {
Write-Log "--- Cleanup FAILED. Skipping WMI removal to avoid system misconfiguration. ---" "ERROR"
}
Write-Log "Script completed. A reboot is strongly recommended to finalize the removal of all components." "WARNING"
#endregion Main Script