win: enable PowerShell as TI runs #128 #412 #421

Refactor Windows scripts to run as TrustedInstaller using PowerShell
instead of batch files. This improves code reuse and enables more
complex logic for system modifications.

Key changes:

- Add function to run any PowerShell script as TrustedInstaller
- Refactor existing functions to use new TrustedInstaller capability
- Enable soft deletion of protected registry keys and files (#412).
- Resolve issues with renaming Defender files (#128).

Other supporting changes:

- Enhance service disabling to handle dependent services
- Use base64 encoding of 'privacy.sexy' to avoid Defender alerts (#421).
- Add comments to generated code for better documentation
This commit is contained in:
undergroundwires
2024-08-28 14:01:54 +02:00
parent dc5c87376b
commit 6b8f6aae81

View File

@@ -15073,14 +15073,14 @@ actions:
data: "1"
deleteOnRevert: 'true' # Missing by default since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
-
function: SetRegistryValueAsTrustedInstaller
# Without TrustedInstaller: ❌ Windows 10 Pro (≥ 22H2) | ❌ Windows 11 Pro (≥ 21H2)
function: SetRegistryValue
parameters:
keyPath: HKLM\Software\Microsoft\Windows Defender\SpyNet
valueName: DisableBlockAtFirstSeen
dataType: REG_DWORD
data: "1"
deleteOnRevert: 'true' # Missing by default since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
elevateToTrustedInstaller: 'true' # Without TrustedInstaller: ❌ Windows 10 Pro (≥ 22H2) | ❌ Windows 11 Pro (≥ 21H2)
-
name: Disable Defender Antivirus "Extended Cloud Check" feature
recommend: strict # Part of MAPS/SypNet/Cloud Protection that sends personal data to Microsoft
@@ -15342,8 +15342,7 @@ actions:
# Default value `2` is observed on Azure VMs (URN: MicrosoftWindowsDesktop:*)
default: "'2'" # Default: 2 (Advanced) | Remove-MpPreference -Force -MAPSReporting | Set-MpPreference -Force -MAPSReporting 2
-
function: SetRegistryValueAsTrustedInstaller
# Without TrustedInstaller: ❌ Windows 10 Pro (≥ 22H2) | ❌ Windows 11 Pro (≥ 21H2)
function: SetRegistryValue
parameters:
keyPath: HKLM\SOFTWARE\Microsoft\Windows Defender\Spynet
valueName: SpyNetReporting
@@ -15351,6 +15350,7 @@ actions:
data: "0"
# Default value `2` is observed on Azure VMs (URN: MicrosoftWindowsDesktop:*)
dataOnRevert: "2" # Default value: `2` on Windows 10 Pro (≥ 22H2) | `2` on Windows 11 Pro (≥ 23H2)
elevateToTrustedInstaller: 'true' # Without TrustedInstaller: ❌ Windows 10 Pro (≥ 22H2) | ❌ Windows 11 Pro (≥ 21H2)
-
function: SetRegistryValue
parameters:
@@ -15426,14 +15426,14 @@ actions:
data: "2"
deleteOnRevert: 'true' # Missing by default since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
-
function: SetRegistryValueAsTrustedInstaller
# Without TrustedInstaller: ❌ Windows 10 Pro (≥ 22H2) | ❌ Windows 11 Pro (≥ 21H2)
function: SetRegistryValue
parameters:
keyPath: HKLM\SOFTWARE\Microsoft\Windows Defender\Spynet
valueName: SubmitSamplesConsent
dataType: REG_DWORD
data: "2"
dataOnRevert: "1" # Default value: `1` on Windows 10 Pro (≥ 22H2) | `1` on Windows 11 Pro (≥ 23H2)
elevateToTrustedInstaller: 'true' # Without TrustedInstaller: ❌ Windows 10 Pro (≥ 22H2) | ❌ Windows 11 Pro (≥ 21H2)
-
name: Disable Defender Antivirus real-time security intelligence updates
recommend: strict # Part of MAPS/SypNet/Cloud Protection that sends personal data to Microsoft
@@ -15623,16 +15623,14 @@ actions:
data: '1'
deleteOnRevert: 'true' # Missing by default since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
-
function: SetRegistryValueAsTrustedInstaller
# Without TrustedInstaller:
# - ❌ Fails with "ERROR: Access is denied." on Windows 11 Pro (>= 23H2)
# - ❌ Fails with "ERROR: Access is denied." on Windows 10 Pro (>= 22H2)
function: SetRegistryValue
parameters:
keyPath: HKLM\SOFTWARE\Microsoft\Windows Defender\CoreService
valueName: DisableCoreService1DSTelemetry
dataType: REG_DWORD
data: '1'
dataOnRevert: '0' # 0 by default since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
dataOnRevert: '0' # `0` by default since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
elevateToTrustedInstaller: 'true' # Without TrustedInstaller: ❌ Windows 10 Pro (≥ 22H2) | ❌ Windows 11 Pro (≥ 23H2)
-
name: Disable Defender Antivirus remote experimentation and configurations
recommend: strict # No significant security gains
@@ -15686,16 +15684,14 @@ actions:
data: '1'
deleteOnRevert: 'true' # Missing by default since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
-
function: SetRegistryValueAsTrustedInstaller
# Without TrustedInstaller:
# - ❌ Fails with "ERROR: Access is denied." on Windows 11 Pro (>= 23H2)
# - ❌ Fails with "ERROR: Access is denied." on Windows 10 Pro (>= 22H2)
function: SetRegistryValue
parameters:
keyPath: HKLM\SOFTWARE\Microsoft\Windows Defender\CoreService
valueName: DisableCoreServiceECSIntegration
dataType: REG_DWORD
data: '1'
dataOnRevert: '0'
elevateToTrustedInstaller: 'true' # Without TrustedInstaller: ❌ Windows 10 Pro (≥ 22H2) | ❌ Windows 11 Pro (≥ 23H2)
-
category: Disable Defender Antivirus
docs: |-
@@ -15839,23 +15835,23 @@ actions:
[13]: https://web.archive.org/web/20240725111550/https://247tech.co.uk/intune-disables-tamper-protection-by-default/ "Intune disables Tamper Protection by default 247 TECH | 247tech.co.uk"
call:
-
function: SetRegistryValueAsTrustedInstaller
# Without TrustedInstaller: ✅ Windows 10 Pro (20H2) | ❌ Windows 10 Pro (≥ 22H2) | ❌ Windows 11 Pro (≥ 21H2)
function: SetRegistryValue
parameters:
keyPath: HKLM\SOFTWARE\Microsoft\Windows Defender\Features
valueName: "TamperProtection"
dataType: REG_DWORD
data: "4"
dataOnRevert: "1" # Default value: `1` on Windows 10 Pro (≥ 22H2) | `1` on Windows 11 Pro (≥ 23H2)
elevateToTrustedInstaller: 'true' # Without TrustedInstaller: ❌ Windows 10 Pro (≥ 22H2) | ❌ Windows 11 Pro (≥ 21H2)
-
function: SetRegistryValueAsTrustedInstaller
# Without TrustedInstaller: ✅ Windows 10 Pro (>= 20H2) | ✅ Windows 11 Pro (>= 23H2)
function: SetRegistryValue
parameters:
keyPath: HKLM\SOFTWARE\Microsoft\Windows Defender\Features
valueName: "TamperProtectionSource"
dataType: REG_DWORD
data: "2"
dataOnRevert: "5" # Default value: Missing on Windows 10 Pro (≥ 22H2) | `0` on Windows 11 Pro (≥ 23H2)
elevateToTrustedInstaller: 'true' # Without TrustedInstaller: ✅ Windows 10 Pro (>= 20H2) | ❌ Windows 11 Pro (>= 23H2)
-
name: Disable outdated Defender Antivirus # Deprecated since Windows 10 version 1903
docs:
@@ -17408,7 +17404,7 @@ actions:
# Windows Defender services are protected, requiring escalated methods to disable them:
# 1. Try `DisableService` first, as this is the standard method recommended for disabling services.
# 2. Try `DisableServiceInRegistry` if the first attempt fails due to access errors.
# 3. Try `DisableServiceInRegistryAsTrustedInstaller` as last effort.
# 3. Try `DisableServiceInRegistry` with `elevateToTrustedInstaller` option as last effort.
children:
-
name: Disable "Microsoft Defender Antivirus Service"
@@ -17427,17 +17423,19 @@ actions:
| Windows 11 (≥ 23H2) | 🟢 Running | Automatic |
call:
-
# Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
function: DisableServiceInRegistryAsTrustedInstaller
# Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
function: DisableServiceInRegistry
parameters:
serviceName: WinDefend # Check: (Get-Service -Name 'WinDefend').StartType
defaultStartupMode: Automatic # Allowed values: Boot | System | Automatic | Manual
# - # ❌ "Access is denied" when renaming file, cannot grant permissions (Attempted to perform an unauthorized operation) since Windows 10 22H2 and Windows 11 22H2
# function: SoftDeleteFiles
# parameters:
# fileGlob: '%PROGRAMFILES%\Windows Defender\MsMpEng.exe' # Found also in C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.2107.4-0 and \4.18.2103.7-0 ...
# grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
elevateToTrustedInstaller: 'true'
-
function: SoftDeleteFiles
parameters:
fileGlob: '%PROGRAMFILES%\Windows Defender\MsMpEng.exe' # Found also in C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.2107.4-0 and \4.18.2103.7-0 ...
# grantPermissions: false # ❌ Cannot grant permissions since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 22H2)
elevateToTrustedInstaller: 'true' # 🔒️ Protected on Windows 10 Pro (≥ 22H2) | 🔒️ Protected on Windows 11 Pro (≥ 22H2)
-
category: Disable Defender kernel-level drivers
children:
@@ -17457,13 +17455,14 @@ actions:
# Excluding:
# - `%SYSTEMROOT%\System32\drivers\wd\WdNisDrv.sys`: Missing on Windows since Windows 10 22H2 and Windows 11 22H2
-
# Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
function: DisableServiceInRegistryAsTrustedInstaller
# Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
function: DisableServiceInRegistry
parameters:
serviceName: WdNisDrv # Check: (Get-Service -Name 'WdNisDrv').StartType
defaultStartupMode: Manual # Allowed values: Boot | System | Automatic | Manual
waitForDependentServicesOnStop: 'true' # Or it fails, `Microsoft Defender Antivirus Network Inspection Service (WdNisSvc)` depends on this
elevateToTrustedInstaller: 'true'
-
function: SoftDeleteFiles
parameters:
@@ -17485,13 +17484,14 @@ actions:
# Excluding:
# - `%SYSTEMROOT%\System32\drivers\wd\WdFilter.sys`: Missing on Windows since Windows 10 22H2 and Windows 11 22H2
-
# Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
function: DisableServiceInRegistryAsTrustedInstaller
# Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
function: DisableServiceInRegistry
parameters:
serviceName: WdFilter # Check: (Get-Service -Name 'WdFilter').StartType
defaultStartupMode: Boot # Allowed values: Boot | System | Automatic | Manual
# notStoppable: true # See `sc queryex WdFilter`, tested since Windows 10 22H2, Windows 11 22H2.
elevateToTrustedInstaller: 'true'
-
function: SoftDeleteFiles
parameters:
@@ -17512,12 +17512,13 @@ actions:
# Excluding:
# - `%SYSTEMROOT%\System32\drivers\wd\WdBoot.sys`: Missing on Windows since Windows 10 22H2 and Windows 11 22H2
-
# Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
function: DisableServiceInRegistryAsTrustedInstaller
# Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
function: DisableServiceInRegistry
parameters:
serviceName: WdBoot # Check: (Get-Service -Name 'WdBoot').StartType
defaultStartupMode: Boot # Allowed values: Boot | System | Automatic | Manual
elevateToTrustedInstaller: 'true'
-
function: SoftDeleteFiles
parameters:
@@ -17537,17 +17538,19 @@ actions:
| Windows 11 (≥ 23H2) | 🔴 Stopped | Manual |
call:
-
# Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
function: DisableServiceInRegistryAsTrustedInstaller
# Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
function: DisableServiceInRegistry
parameters:
serviceName: WdNisSvc # Check: (Get-Service -Name 'WdNisSvc').StartType
defaultStartupMode: Manual # Allowed values: Boot | System | Automatic | Manual
# - # ❌ "Access is denied" when renaming file, cannot grant permissions (Attempted to perform an unauthorized operation) since Windows 10 22H2 and Windows 11 22H2
# function: SoftDeleteFiles
# parameters:
# fileGlob: '%PROGRAMFILES%\Windows Defender\NisSrv.exe' # Found also in C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.2107.4-0 and \4.18.2103.7-0 ...
# grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
elevateToTrustedInstaller: 'true'
-
function: SoftDeleteFiles
parameters:
fileGlob: '%PROGRAMFILES%\Windows Defender\NisSrv.exe' # Found also in C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.2107.4-0 and \4.18.2103.7-0 ...
# grantPermissions: false # ❌ Cannot grant permissions since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 22H2)
elevateToTrustedInstaller: 'true' # 🔒️ Protected on Windows 10 Pro (≥ 22H2) | 🔒️ Protected on Windows 11 Pro (≥ 22H2)
-
name: Disable Microsoft Defender Core Service
docs: |-
@@ -17570,10 +17573,13 @@ actions:
This process is also known as "Antimalware Core Service" [1] [2] [6].
It's typically located in the `%PROGRAMDATA%\Microsoft\Windows Defender\Platform\<version number>\`
folder [6].
It is found on modern versions of Windows [5].
It may be found on modern versions of Windows [5].
### Overview of default service statuses
According to tests, the availability of this service varies across different Windows versions,
depending on the installed Defender antivirus updates.
| OS Version | Status | Start type |
| ---------- | -------| ---------- |
| Windows 10 (≥ 22H2) | 🟢 Running | Automatic |
@@ -17587,14 +17593,15 @@ actions:
[6]: https://web.archive.org/web/20240724234556/https://www.file.net/process/mpdefendercoreservice.exe.html "MpDefenderCoreService.exe Windows process - What is it? | file.net"
call:
# -
# Commented out because it does not work due to permission errors.
# function: DisableServiceInRegistryAsTrustedInstaller
# # Commented out because it does not work due to permission errors.
# function: DisableServiceInRegistry
# parameters:
# # Note: Always get "Permission Denied", could not find a way., https://github.com/undergroundwires/privacy.sexy/issues/385
# # Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ❌ `DisableServiceInRegistryAsTrustedInstaller`
# # Windows 11 (23H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ❌ `DisableServiceInRegistryAsTrustedInstaller`
# # Windows 10 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ❌ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# # Windows 11 (23H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ❌ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# serviceName: MDCoreSvc # Check: (Get-Service -Name 'MDCoreSvc').StartType
# defaultStartupMode: Automatic
# elevateToTrustedInstaller: 'true'
-
function: TerminateAndBlockExecution
# Successfully disables Microsoft Defender Core Service
@@ -17604,14 +17611,12 @@ actions:
# It requires computer restart as it cannot terminate the process but can prevent its future execution.
parameters:
executableNameWithExtension: MpDefenderCoreService.exe
# -
# Commented out because it does not work due to permission errors.
# # Marked: SoftDeleteFilesAsTrustedInstaller
# # Something like SoftDeleteFiles | RunAsTrustedInstaller would solve the issue.
# function: SoftDeleteFiles
# parameters:
# fileGlob: '%PROGRAMDATA%\Microsoft\Windows Defender\Platform\*\MpDefenderCoreService.exe'
# grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
-
function: SoftDeleteFiles
parameters:
fileGlob: '%PROGRAMDATA%\Microsoft\Windows Defender\Platform\*\MpDefenderCoreService.exe'
# grantPermissions: false # ❌ Cannot grant permissions since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
elevateToTrustedInstaller: 'true' # 🔒️ Protected on Windows 10 Pro (≥ 22H2) | 🔒️ Protected on Windows 11 Pro (≥ 23H2)
-
function: ShowComputerRestartSuggestion
-
@@ -18015,9 +18020,9 @@ actions:
call:
-
function: DisableServiceInRegistry
# Windows 10 (22H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (23H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 10 (22H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (23H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
parameters:
serviceName: Sense # Check: (Get-Service -Name 'Sense').StartType
defaultStartupMode: Manual # Allowed values: Boot | System | Automatic | Manual
@@ -19141,12 +19146,13 @@ actions:
[4]: https://web.archive.org/web/20231013160458/https://learn.microsoft.com/en-us/microsoft-365/security/defender-endpoint/microsoft-defender-antivirus-compatibility?view=o365-worldwide#notes-about-protection-states
call:
-
# Windows 10 (22H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
function: DisableServiceInRegistryAsTrustedInstaller
# Windows 10 (22H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ❌ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
function: DisableServiceInRegistry
parameters:
serviceName: SecurityHealthService # Check: (Get-Service -Name 'SecurityHealthService').StartType
defaultStartupMode: Manual # Allowed values: Boot | System | Automatic | Manual
elevateToTrustedInstaller: 'true'
-
function: SoftDeleteFiles
parameters:
@@ -19333,14 +19339,14 @@ actions:
value: $True # Set: Set-MpPreference -Force -DisablePrivacyMode $True
default: $False # Default: False | Remove-MpPreference -Force -DisablePrivacyMode | Set-MpPreference -Force -DisablePrivacyMode $False
-
function: SetRegistryValueAsTrustedInstaller
# Without TrustedInstaller: ❌ Windows 10 Pro (>= 20H2) | ❌ Windows 11 Pro (>= 23H2)
function: SetRegistryValue
parameters:
keyPath: HKLM\SOFTWARE\Microsoft\Windows Defender\UX Configuration
valueName: "DisablePrivacyMode"
dataType: REG_DWORD
data: "1"
deleteOnRevert: 'true' # Missing by default since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
elevateToTrustedInstaller: 'true' # Without TrustedInstaller: ❌ Windows 10 Pro (>= 20H2) | ❌ Windows 11 Pro (>= 23H2)
-
category: Disable sections in "Windows Security"
docs: |-
@@ -20008,15 +20014,16 @@ actions:
[9]: https://web.archive.org/web/20231129203543/https://call4cloud.nl/2022/03/before-we-wipe/ "KB5011487 | KB5011493 | 2022-03 | Windows.old wipe Issue | call4cloud.nl"
call:
-
# Windows 10 (21H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 10 (22H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (21H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 11 (23H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistryAsTrustedInstaller`
# Windows 10 (21H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 10 (22H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (21H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (22H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
# Windows 11 (23H2): ❌ `DisableService` | ✅ `DisableServiceInRegistry` | ✅ `DisableServiceInRegistry` with `elevateToTrustedInstaller`
function: DisableServiceInRegistry
parameters:
serviceName: WaaSMedicSvc # Check: (Get-Service -Name 'WaaSMedicSvc').StartType
defaultStartupMode: Manual # Allowed values: Automatic | Manual
elevateToTrustedInstaller: 'true'
-
function: SoftDeleteFiles
parameters:
@@ -29857,13 +29864,7 @@ functions:
# Renames files matching a given glob pattern by appending a `.OLD` extension, effectively "soft deleting" them.
# It does not touch any of the folders.
# This allows for easier restoration and less immediate disruption compared to permanent deletion.
# 🤓 Implementation:
# 1. (with `grantPermissions`:) Elevate script privileges.
# 2. Iterate every file in the given directory, and for each file:
# - (with `grantPermissions`:) Grant permissions to file to be able to modify it.
# - Rename the file.
# - (with `grantPermissions`:) Restore permissions of the file to its original state
# 3. (with `grantPermissions`:) Remove elevated script privileges.
# Try `grantPermissions` to elevate privileges first then `elevateToTrustedInstaller` as last effort.´
parameters:
- name: fileGlob
- name: grantPermissions # Grants permission on the files found, and restores original permissions after modification.
@@ -29872,21 +29873,24 @@ functions:
optional: true
- name: beforeIteration # (Iteration callback) Code to run before iteration.
optional: true
- name: elevateToTrustedInstaller # See `RunPowerShellWithOptionalElevation`
optional: true
call:
-
function: Comment
parameters:
codeComment: >-
Soft delete files matching pattern
{{ with $grantPermissions }}(with additional permissions){{ end }}
: "{{ $fileGlob }}"
Soft delete files matching pattern: "{{ $fileGlob }}"
{{ with $grantPermissions }}with additional permissions{{ end }}
{{ with $elevateToTrustedInstaller }}as TrustedInstaller{{ end }}
revertCodeComment: >-
Restore files matching pattern
{{ with $grantPermissions }}(with additional permissions){{ end }}
: "{{ $fileGlob }}"
Restore files matching pattern: "{{ $fileGlob }}"
{{ with $grantPermissions }}with additional permissions{{ end }}
{{ with $elevateToTrustedInstaller }}as TrustedInstaller{{ end }}
-
function: IterateGlob
parameters:
elevateToTrustedInstaller: '{{ with $elevateToTrustedInstaller }}true{{ end }}'
pathGlob: '{{ $fileGlob }}'
revertPathGlob: '{{ $fileGlob }}.OLD'
recurse: '{{ with $recurse }}{{ . }}{{ end }}'
@@ -30218,22 +30222,33 @@ functions:
codeComment: '{{ with $codeComment }}{{ . }}{{ end }}'
revertCodeComment: '{{ with $codeComment }}{{ . }}{{ end }}'
-
name: RunInlineCodeAsTrustedInstaller
name: RunPowerShellWithOptionalElevation
parameters:
- name: code # Batchfile code to execute with TrustedInstaller privileges.
- name: revertCode # Optional batchfile code to revert changes. This code also runs with TrustedInstaller privileges.
optional: true
- name: elevateToTrustedInstaller # When set to true, executes the code with TrustedInstaller privileges.
optional: true
- name: minimumWindowsVersion # See `RunPowerShellWithWindowsVersionConstraints`
optional: true
- name: maximumWindowsVersion # See `RunPowerShellWithWindowsVersionConstraints`
optional: true
- name: setupCode # PowerShell code to execute before elevation.
optional: true
docs: |-
This function executes PowerShell code with TrustedInstaller privileges, which may be required for performing system-level tasks
that require the highest permission levels.
This function is designed to handle tasks that cannot be completed under normal user or administrator privileges,
This function executes PowerShell code with optional TrustedInstaller privileges, whic
may be required for performing system-level tasks that require the highest permission levels.
It is designed to handle tasks that cannot be completed under normal user or administrator privileges,
such as modifying protected registry keys or system files.
call:
function: RunPowerShellWithWindowsVersionConstraints
parameters:
minimumWindowsVersion: '{{ with $minimumWindowsVersion }}{{ . }}{{ end }}'
maximumWindowsVersion: '{{ with $maximumWindowsVersion }}{{ . }}{{ end }}'
# Issues and workarounds:
# privacy.sexy word triggering Defender (https://github.com/undergroundwires/privacy.sexy/issues/421)
# Using `cAByAGkAdgBhAGMAeQAuAHMAZQB4AHkA` base64 encoding of `privacy.sexy`
# PowerShell commands (`Unregister-ScheduledTask` and `Get-ScheduledTask`) sometimes fail to find existing tasks.
# Seen e.g. on Windows 11 when reverting scripts after executing them and reboot.
# They are seen to throw different exceptions:
@@ -30253,22 +30268,29 @@ functions:
# - ❌ Not using `Unregister-ScheduledTask $taskName -Confirm:$false` because it sometimes fails with `0x80070002`
# - ✅ Using `schtasks.exe /delete /tn "$taskName" /f` with additional `| Out-Null` or `2>&1 | Out-Null`
# to suppress errors.
code: |-
$command = @'
{{ $code }}
'@
setupCode: |-
{{ with $elevateToTrustedInstaller }}
function Invoke-AsTrustedInstaller {
param ( `
[Parameter(Mandatory=$true)] `
[string]$Script `
)
$trustedInstallerSid = [System.Security.Principal.SecurityIdentifier]::new('S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464')
$trustedInstallerName = $trustedInstallerSid.Translate([System.Security.Principal.NTAccount])
$streamOutFile = New-TemporaryFile
$batchFile = New-TemporaryFile
$scriptFile = New-TemporaryFile
try {
$batchFile = Rename-Item $batchFile "$($batchFile.BaseName).bat" -PassThru
"@echo off`r`n$command`r`nexit 0" | Out-File $batchFile -Encoding ASCII
$taskName = 'privacy.sexy invoke'
$scriptFile = Rename-Item `
-LiteralPath $scriptFile `
-NewName "$($scriptFile.BaseName).ps1" `
-PassThru
$Script | Out-File $scriptFile -Encoding UTF8
$taskName = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String(('cAByAGkAdgBhAGMAeQAuAHMAZQB4AHkA'))) + ' invoke'
schtasks.exe /delete /tn "$taskName" /f 2>&1 | Out-Null # Clean if something went wrong before, suppress any output
$scriptExecutionCommand = "powershell.exe -ExecutionPolicy Bypass -File '$scriptFile' *>&1 | Out-File -FilePath '$streamOutFile' -Encoding UTF8"
$taskAction = New-ScheduledTaskAction `
-Execute 'cmd.exe' `
-Argument "cmd /c `"$batchFile`" > $streamOutFile 2>&1"
-Execute 'powershell.exe' `
-Argument "-ExecutionPolicy Bypass -Command `"$scriptExecutionCommand`""
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask `
-TaskName $taskName `
@@ -30281,92 +30303,90 @@ functions:
($scheduleService = New-Object -ComObject Schedule.Service).Connect()
$scheduleService.GetFolder('\').GetTask($taskName).RunEx($null, 0, 0, $trustedInstallerName) | Out-Null
$timeOutLimit = (Get-Date).AddMinutes(5)
Write-Host "Running as $trustedInstallerName"
Write-Host "Running as `"$trustedInstallerName`""
while((Get-ScheduledTaskInfo $taskName).LastTaskResult -eq 267009) {
Start-Sleep -Milliseconds 200
if((Get-Date) -gt $timeOutLimit) {
Write-Warning "Skipping results, it took so long to execute script."
break;
break
}
}
if (($result = (Get-ScheduledTaskInfo $taskName).LastTaskResult) -ne 0) {
Write-Error "Failed to execute with exit code: $result."
}
} finally {
}
finally {
schtasks.exe /delete /tn "$taskName" /f | Out-Null # Outputs only errors
}
Get-Content $streamOutFile
} finally {
Remove-Item $streamOutFile, $batchFile
}
# Marked: refactor-with-variables
# `revertCode` is complete duplicate of `code`.
finally {
Remove-Item $streamOutFile, $scriptFile
}
}
{{ end }}{{ with $setupCode }}
{{ . }}
{{ end }}
code: |-
{{ with $elevateToTrustedInstaller }}
$command = @'
{{ end }}
{{ $code }}
{{ with $elevateToTrustedInstaller }}
'@
Invoke-AsTrustedInstaller "$command"
{{ end }}
revertCode: |-
{{ with $revertCode }}
{{ with $elevateToTrustedInstaller }}
$command = @'
{{ end }}
{{ . }}
{{ with $elevateToTrustedInstaller }}
'@
$trustedInstallerSid = [System.Security.Principal.SecurityIdentifier]::new('S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464')
$trustedInstallerName = $trustedInstallerSid.Translate([System.Security.Principal.NTAccount])
$streamOutFile = New-TemporaryFile
$batchFile = New-TemporaryFile
try {
$batchFile = Rename-Item $batchFile "$($batchFile.BaseName).bat" -PassThru
"@echo off`r`n$command`r`nexit 0" | Out-File $batchFile -Encoding ASCII
$taskName = 'privacy.sexy invoke'
schtasks.exe /delete /tn "$taskName" /f 2>&1 | Out-Null # Clean if something went wrong before, suppress any output
$taskAction = New-ScheduledTaskAction `
-Execute 'cmd.exe' `
-Argument "cmd /c `"$batchFile`" > $streamOutFile 2>&1"
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask `
-TaskName $taskName `
-Action $taskAction `
-Settings $settings `
-Force `
-ErrorAction Stop `
| Out-Null
try {
($scheduleService = New-Object -ComObject Schedule.Service).Connect()
$scheduleService.GetFolder('\').GetTask($taskName).RunEx($null, 0, 0, $trustedInstallerName) | Out-Null
$timeOutLimit = (Get-Date).AddMinutes(5)
Write-Host "Running as $trustedInstallerName"
while((Get-ScheduledTaskInfo $taskName).LastTaskResult -eq 267009) {
Start-Sleep -Milliseconds 200
if((Get-Date) -gt $timeOutLimit) {
Write-Warning "Skipping results, it took so long to execute script."
break;
}
}
if (($result = (Get-ScheduledTaskInfo $taskName).LastTaskResult) -ne 0) {
Write-Error "Failed to execute with exit code: $result."
}
} finally {
schtasks.exe /delete /tn "$taskName" /f | Out-Null # Outputs only errors
}
Get-Content $streamOutFile
} finally {
Remove-Item $streamOutFile, $batchFile
}
Invoke-AsTrustedInstaller "$command"
{{ end }}
{{ end }}
-
name: DisableServiceInRegistry
# 💡 Purpose:
# Disables a specified service via the registry.
# Use this method only if `DisableService` does not work.
parameters: # Ensure that this function has the same parameters as `DisableService` and `DisableServiceInRegistryAsTrustedInstaller` to simplify testing and interchangeability.
# Disables a specified service via the registry with optional TrustedInstaller privileges for higher access rights.
# Use this method only if `DisableService` fails due to permission issues.
parameters: # Ensure that this function has the 333same parameters as `DisableService` to simplify testing and interchangeability.
- name: serviceName
- name: defaultStartupMode # Allowed values: Boot | System | Automatic | Manual
- name: waitForDependentServicesOnStop # Set to `true` to stop the service and wait for all dependent services to stop as well.
optional: true # Set to `false` to stop the service immediately without waiting for dependents.
- name: elevateToTrustedInstaller # See `RunPowerShellWithOptionalElevation`
optional: true
- name: maximumWindowsVersion # See `RunPowerShellWithWindowsVersionConstraints`
optional: true
call:
function: RunPowerShellWithWindowsVersionConstraints
# Marked: refactor-with-revert-call, refactor-with-variables
# Implementation of those should share similar code: `DisableService`, `StopService`, `StartService`, `DisableServiceInRegistry`
-
function: Comment
parameters:
codeComment: >-
Disable the service `{{ $serviceName }}`
{{ with $elevateToTrustedInstaller }}using TrustedInstaller privileges{{ end }}
revertCodeComment: >-
Restore the service `{{ $serviceName }}`
{{ with $elevateToTrustedInstaller }}using TrustedInstaller privileges{{ end }}
-
function: RunPowerShellWithOptionalElevation
# Marked: refactor-with-revert-call, refactor-with-variables
# Implementation shares similar code: `DisableService`, `StopService`, `StartService`
# Marked refactor-with-if-syntax:
# {{ with }} is used awkwardly with commented out code.
# Stopping services:
# Some services are not stoppable (i.e. WdFilter) and attempting to stop it:
# - With `sc stop` returns `[SC] ControlService FAILED 1052: The requested control is not valid for this service.`.
# - With `Stop-Service` PowerShell cmdlet throws `CouldNotStopService,Microsoft.PowerShell.Commands.StopServiceCommand` error
parameters:
elevateToTrustedInstaller: '{{ with $elevateToTrustedInstaller }}true{{ end }}'
maximumWindowsVersion: '{{ with $maximumWindowsVersion }}{{ . }}{{ end }}'
code: |- # We do the registry way because GUI, "sc config" or "Set-Service" will not work
code: |-
$serviceQuery = '{{ $serviceName }}'
$stopWithDependencies={{ with $waitForDependentServicesOnStop }} $true # {{ end }} $false
# -- 1. Skip if service does not exist
$service = Get-Service -Name $serviceQuery -ErrorAction SilentlyContinue
if(!$service) {
@@ -30377,19 +30397,32 @@ functions:
Write-Host "Disabling service: `"$serviceName`"."
# -- 2. Stop if running
if ($service.Status -eq [System.ServiceProcess.ServiceControllerStatus]::Running) {
Write-Host "`"$serviceName`" is running, trying to stop it."
Write-Host "`"$serviceName`" is running, attempting to stop it."
try {
Stop-Service -Name "$serviceName" -Force -ErrorAction Stop
Write-Host "Stopping the service `"$serviceName`"."
$stopParams = @{ `
Name = $ServiceName
Force = $true
ErrorAction = 'Stop'
}
if (-not $stopWithDependencies) {
$stopParams['NoWait'] = $true
}
Stop-Service @stopParams
Write-Host "Stopped `"$serviceName`" successfully."
} catch {
Write-Warning "Could not stop `"$serviceName`", it will be stopped after reboot: $_"
if ($_.FullyQualifiedErrorId -eq 'CouldNotStopService,Microsoft.PowerShell.Commands.StopServiceCommand') {
Write-Warning "The service `"$serviceName`" does not accept a stop command and may need to be stopped manually or on reboot."
} else {
Write-Warning "Failed to stop service `"$ServiceName`". It will be stopped after reboot. Error: $($_.Exception.Message)"
}
}
} else {
Write-Host "`"$serviceName`" is not running, no need to stop."
}
# -- 3. Skip if service info is not found in registry
$registryKey = "HKLM:\SYSTEM\CurrentControlSet\Services\$serviceName"
if(!(Test-Path $registryKey)) {
if (-Not (Test-Path $registryKey)) {
Write-Host "`"$registryKey`" is not found in registry, cannot enable it."
Exit 0
}
@@ -30400,153 +30433,69 @@ functions:
}
# -- 5. Disable service
try {
Set-ItemProperty $registryKey -Name Start -Value 4 -Force -ErrorAction Stop
Write-Host "Disabled `"$serviceName`" successfully."
Set-ItemProperty `
-LiteralPath $registryKey `
-Name "Start" `
-Value 4 `
-ErrorAction Stop
Write-Host 'Successfully disabled the service. It will not start automatically on next boot.'
} catch {
Write-Error "Could not disable `"$serviceName`": $_"
Write-Error "Failed to disable the service. Error: $($_.Exception.Message)"
Exit 1
}
revertCode: |-
$serviceQuery = '{{ $serviceName }}'
$defaultStartupMode = '{{ $defaultStartupMode }}'
# -- 1. Skip if service does not exist
$service = Get-Service -Name $serviceQuery -ErrorAction SilentlyContinue
if(!$service) {
if (!$service) {
Write-Warning "Service query `"$serviceQuery`" did not yield and results, cannot enable it."
Exit 1
}
$serviceName = $service.Name
Write-Host "Enabling service: `"$serviceName`" with `"$defaultStartupMode`" start."
Write-Host "Restoring registry settings for service `"$serviceName`" to default startup mode `"$defaultStartupMode`"."
# -- 2. Skip if service info is not found in registry
$registryKey = "HKLM:\SYSTEM\CurrentControlSet\Services\$serviceName"
if(!(Test-Path $registryKey)) {
if (-Not (Test-Path $registryKey)) {
Write-Warning "`"$registryKey`" is not found in registry, cannot enable it."
Exit 1
}
# -- 3. Enable if not already enabled
$defaultStartupRegValue = `
if ($defaultStartupMode -eq 'Boot') { '0' } `
elseif($defaultStartupMode -eq 'System') { '1' } `
elseif($defaultStartupMode -eq 'Automatic') { '2' } `
elseif($defaultStartupMode -eq 'Manual') { '3' } `
else { throw "Unknown start mode: $defaultStartupMode"}
if( $(Get-ItemProperty -Path "$registryKey").Start -eq $defaultStartupRegValue) {
$defaultStartupRegValue = switch ($defaultStartupMode) {
'Boot' { 0 }
'System' { 1 }
'Automatic' { 2 }
'Manual' { 3 }
default {
Write-Error "Error: Unknown startup mode specified: `"$defaultStartupMode`". Revert cannot proceed."
return
}
}
if ($(Get-ItemProperty -Path "$registryKey").Start -eq $defaultStartupRegValue) {
Write-Host "`"$serviceName`" is already enabled with `"$defaultStartupMode`" start."
} else {
try {
Set-ItemProperty $registryKey -Name Start -Value $defaultStartupRegValue -Force
Write-Host "Enabled `"$serviceName`" successfully with `"$defaultStartupMode`" start, this may require restarting your computer."
Write-Host "Successfully restored `"$serviceName`" with `"$defaultStartupMode`" start, this may require restarting your computer."
} catch {
Write-Error "Could not enable `"$serviceName`": $_"
Exit 1
}
}
# -- 4. Start if not running (must be enabled first)
if($defaultStartupMode -eq 'Automatic') {
if ($defaultStartupMode -ne 'Manual') {
if ($service.Status -ne [System.ServiceProcess.ServiceControllerStatus]::Running) {
Write-Host "`"$serviceName`" is not running, trying to start it."
try {
Start-Service $serviceName -ErrorAction Stop
Write-Host "Started `"$serviceName`" successfully."
Start-Service -Name $serviceName -ErrorAction Stop
Write-Host 'Service started successfully.'
} catch {
Write-Warning "Could not start `"$serviceName`", requires restart, it will be started after reboot.`r`n$_"
Write-Warning "Failed to restart service. It will be started after reboot. Error: $($_.Exception.Message)"
}
} else {
Write-Host "`"$serviceName`" is already running, no need to start."
}
}
-
name: DisableServiceInRegistryAsTrustedInstaller
# 💡 Purpose:
# Disables a specified service via the registry with TrustedInstaller privileges for higher access rights.
# Use this method only if `DisableServiceInRegistry` fails due to permission issues.
# Marked: refactor-with-variables
# The logic is almost same as `DisableServiceInRegistry`, but this is executed as TrustedInstaller.
# The logic should be reused.
parameters: # Ensure that this function has the same parameters as `DisableService` and `DisableServiceInRegistry` to simplify testing and interchangeability.
- name: serviceName
- name: defaultStartupMode # Allowed values: Boot | System | Automatic | Manual
- name: waitForDependentServicesOnStop # Set to `true` to stop the service and wait for all dependent services to stop as well.
optional: true # Set to `false` to stop the service immediately without waiting for dependents.
call:
-
function: Comment
parameters:
codeComment: "Disable the service `{{ $serviceName }}` using TrustedInstaller privileges"
revertCodeComment: "Restore the service `{{ $serviceName }}` using TrustedInstaller privileges"
-
function: RunInlineCodeAsTrustedInstaller
parameters:
# Some services are not stoppable (i.e. WdFilter) and attempting to stop it with `sc stop` returns:
# `[SC] ControlService FAILED 1052: The requested control is not valid for this service.`. This code
# handles it, and provides an user-friendly error message. If the error is something else, it prints the error
# to the console.
# Marked refactor-with-if-syntax:
# {{ with }} is used awkwardly with commented out code.
code: |-
setlocal EnableDelayedExpansion
set "serviceName={{ $serviceName }}"
{{ with $waitForDependentServicesOnStop }}set "stopWithDependencies=true"{{ end }}
{{ with $waitForDependentServicesOnStop }}:: {{ end }}set "stopWithDependencies=false"
if "!stopWithDependencies!"=="true" (
echo Stopping the service "!serviceName!" and waiting for its dependencies to stop.
net stop "!serviceName!" /yes
) else (
echo Stopping the service "!serviceName!".
sc stop "!serviceName!" >nul 2>&1
)
if !ERRORLEVEL! EQU 0 (
echo Successfully stopped the service "!serviceName!".
) else (
if !ERRORLEVEL! EQU 1052 (
echo Warning: The service "!serviceName!" does not accept a stop command and may need to be stopped manually or on reboot.
) else (
echo Error: Failed to stop service "!serviceName!" with exit code: !ERRORLEVEL!. Retrieving more information...
>&2 net helpmsg !ERRORLEVEL!
)
)
echo Updating registry settings to disable service "!serviceName!"...
reg add "HKLM\SYSTEM\CurrentControlSet\Services\!serviceName!" /v "Start" /t REG_DWORD /d "4" /f
if !ERRORLEVEL! EQU 0 (
echo Service "!serviceName!" has been successfully disabled in the registry and will not start automatically on next boot.
) else (
echo Error: Unable to disable service "!serviceName!" in the registry. Please check your permissions or contact your administrator.
)
endlocal
revertCode: |-
setlocal EnableDelayedExpansion
set "serviceName={{ $serviceName }}"
set "defaultStartupMode={{ $defaultStartupMode }}"
set "defaultStartupRegValue=-1"
echo Restoring changes for "!serviceName!"...
if /i "!defaultStartupMode!"=="Boot" (
set "defaultStartupRegValue=0"
) else if /i "!defaultStartupMode!"=="System" (
set "defaultStartupRegValue=1"
) else if /i "!defaultStartupMode!"=="Automatic" (
set "defaultStartupRegValue=2"
) else if /i "!defaultStartupMode!"=="Manual" (
set "defaultStartupRegValue=3"
) else (
echo Error: Unknown startup mode specified: "!defaultStartupMode!". Revert cannot proceed.
exit /b 1
)
echo Restoring registry settings for service "!serviceName!" to default startup mode "!defaultStartupMode!"...
reg add "HKLM\SYSTEM\CurrentControlSet\Services\!serviceName!" /v "Start" /t REG_DWORD /d "!defaultStartupRegValue!" /f
if !ERRORLEVEL! EQU 0 (
echo Successfully restored the registry settings for "!serviceName!".
) else (
echo Error: Failed to update registry settings for "!serviceName!". Check permissions or contact your administrator.
)
if /i not "!defaultStartupMode!"=="Manual" (
echo Attempting to restart service "!serviceName!"...
sc start "!serviceName!" >nul 2>&1
if !ERRORLEVEL! EQU 0 (
echo Service "!serviceName!" restarted successfully.
) else (
echo Warning: Unable to restart service "!serviceName!". It may require a manual start or system reboot.
)
)
endlocal
-
name: SetMpPreference
# Configures preferences for Microsoft Defender scans and updates.
@@ -30799,7 +30748,7 @@ functions:
}
-
name: DisableService
parameters: # Ensure that this function has the same parameters as `DisableServiceInRegistry` and `DisableServiceInRegistryAsTrustedInstaller` to simplify testing and interchangeability.
parameters: # Ensure that this function has the same parameters as `DisableServiceInRegistry` to simplify testing and interchangeability.
- name: serviceName
- name: defaultStartupMode # Allowed values: Automatic | Manual
- name: ignoreMissingOnRevert # When set to true, the revert operation will skip any actions for services that cannot be found, instead of failing.
@@ -31047,9 +30996,12 @@ functions:
optional: true
- name: recurse # If set, includes all files and directories recursively.
optional: true
- name: elevateToTrustedInstaller # See `RunPowerShellWithOptionalElevation`
optional: true
call:
function: RunPowerShell
function: RunPowerShellWithOptionalElevation
parameters:
elevateToTrustedInstaller: '{{ with $elevateToTrustedInstaller }}true{{ end }}'
code: |-
$pathGlobPattern = "{{ $pathGlob }}"
$expandedPath = [System.Environment]::ExpandEnvironmentVariables($pathGlobPattern)
@@ -32183,6 +32135,8 @@ functions:
optional: true
- name: setupCode # See `RunPowerShellWithWindowsVersionConstraints`
optional: true
- name: elevateToTrustedInstaller # See `RunPowerShellWithOptionalElevation`
optional: true
- name: minimumWindowsVersion # See `RunPowerShellWithWindowsVersionConstraints`
optional: true
docs: |-
@@ -32190,10 +32144,23 @@ functions:
> 💡 Use this function for a consistent approach instead of directly using `reg add` or `reg delete` commands.
call:
function: RunPowerShellWithWindowsVersionConstraints
-
function: Comment
parameters:
# Avoid outputting the registry data, as it may be ugly code (see `evaluateDataAsPowerShell`)
codeComment: 'Set the registry value: "{{ $keyPath }}!{{ $valueName }}"'
revertCodeComment: >-
{{ with $deleteOnRevert }}
Delete the registry value "{{ $keyPath }}!{{ $valueName }}"
{{ end }}{{ with $dataOnRevert }}
Set the registry value "{{ $keyPath }}!{{ $valueName }}"
{{ end }}
-
function: RunPowerShellWithOptionalElevation
parameters:
setupCode: '{{ with $setupCode }}{{ . }}{{ end }}'
minimumWindowsVersion: '{{ with $minimumWindowsVersion }}{{ . }}{{ end }}'
elevateToTrustedInstaller: '{{ with $elevateToTrustedInstaller }}true{{ end }}'
code: |-
$data = '{{ $data }}'
{{ with $evaluateDataAsPowerShell }}
@@ -33008,37 +32975,6 @@ functions:
{{ end }}
code: '{{ $code }}'
revertCode: '{{ with $revertCode }}{{ . }}{{ end }}'
-
name: SetRegistryValueAsTrustedInstaller
parameters: # The parameters should be always in sync/compatible with `SetRegistryValue`.
- name: keyPath # Full path of the subkey or entry to be added.
- name: valueName # Name of the add registry entry.
- name: dataType # Type for the registry entry.
- name: data # Data for the new registry entry.
- name: deleteOnRevert # Set to 'true' to revert to the initial state by deleting the registry key.
optional: true
- name: dataOnRevert # Specifies the value to restore when reverting the registry change, instead of deleting the entry.
optional: true
- name: minimumWindowsVersion # See `RunPowerShellWithWindowsVersionConstraints`
optional: true
docs: >-
Sets registry value using TrustedInstaller privileges.
> - 💡 Use this function for a consistent approach instead of directly using `reg add` or `reg delete` commands.
> - ❗️ Use this function only when `SetRegistryValue` fails with permission errors.
call:
# Marked: refactor-with-variables
# Should be re-using same code as SetRegistryValue but only as TrustedInstaller.
function: RunInlineCodeAsTrustedInstaller
parameters:
code: reg add "{{ $keyPath }}" /v "{{ $valueName }}" /t "{{ $dataType }}" /d "{{ $data }}" /f
revertCode: |-
{{ with $deleteOnRevert }}
reg delete "{{ $keyPath }}" /v "{{ $valueName }}" /f 2>nul
{{ end }}{{ with $dataOnRevert }}
reg add "{{ $keyPath }}" /v "{{ $valueName }}" /t "{{ $dataType }}" /d "{{ . }}" /f
{{ end }}
minimumWindowsVersion: '{{ with $minimumWindowsVersion }}{{ . }}{{ end }}'
-
name: DeleteVisualStudioLicense
parameters: