noid-privacy/Modules/ASR/Private/Backup-ASRRegistry.ps1

105 lines
4.2 KiB
PowerShell

<#
.SYNOPSIS
Backup current ASR registry settings
.DESCRIPTION
Creates backup of ASR registry keys before modification
.PARAMETER BackupId
Identifier for this backup
.OUTPUTS
PSCustomObject with backup info
#>
function Backup-ASRRegistry {
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$BackupId = "ASR_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
)
$result = [PSCustomObject]@{
Success = $true
BackupPath = $null
Errors = @()
}
try {
$asrPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender\Windows Defender Exploit Guard\ASR"
# BACKUP 1: Registry (for reference/verify)
# CRITICAL FIX: Call Backup-RegistryKey unconditionally!
# If key exists: Creates .reg backup
# If key missing: Creates _EMPTY.json marker (Required for proper cleanup during restore)
try {
$regBackup = Backup-RegistryKey -KeyPath $asrPath -BackupName "ASR_Config"
if ($regBackup) {
if ($regBackup -match "_EMPTY\.json$") {
Write-Log -Level INFO -Message "ASR registry key does not exist - Created Empty Marker for cleanup" -Module "ASR"
}
else {
Write-Log -Level INFO -Message "ASR registry backed up with ID: $BackupId" -Module "ASR"
}
}
}
catch {
Write-Log -Level WARNING -Message "Registry backup failed: $_" -Module "ASR"
$result.Errors += "Registry backup failed: $_"
}
# BACKUP 2: Get-MpPreference (CRITICAL for restore)
# Registry-only restore doesn't work after Clear-ASRRules
# We MUST save the active Defender configuration
# IMPORTANT: We backup even if 0 rules are active (pre-hardening state)
try {
$mpPref = Get-MpPreference -ErrorAction Stop
$asrBackupData = @{
BackupDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
BackupId = $BackupId
Rules = @()
}
# If rules exist, save them
if ($mpPref.AttackSurfaceReductionRules_Ids -and $mpPref.AttackSurfaceReductionRules_Ids.Count -gt 0) {
# Pair IDs with Actions
for ($i = 0; $i -lt $mpPref.AttackSurfaceReductionRules_Ids.Count; $i++) {
$asrBackupData.Rules += @{
GUID = $mpPref.AttackSurfaceReductionRules_Ids[$i]
Action = $mpPref.AttackSurfaceReductionRules_Actions[$i]
}
}
Write-Log -Level INFO -Message "Backing up $($asrBackupData.Rules.Count) active ASR rules from Get-MpPreference" -Module "ASR"
}
else {
Write-Log -Level INFO -Message "No active ASR rules in Get-MpPreference - backing up empty state (pre-hardening)" -Module "ASR"
}
# ALWAYS create the JSON file, even if Rules array is empty
# This is critical for restore to know "system had 0 rules before hardening"
$asrJson = $asrBackupData | ConvertTo-Json -Depth 5
$backupFile = Register-Backup -Type "ASR" -Data $asrJson -Name "ASR_ActiveConfiguration"
if ($backupFile) {
Write-Log -Level SUCCESS -Message "ASR MpPreference configuration backed up ($($asrBackupData.Rules.Count) rules)" -Module "ASR"
}
else {
Write-Log -Level WARNING -Message "Failed to register ASR MpPreference backup" -Module "ASR"
$result.Errors += "MpPreference backup registration failed"
}
}
catch {
Write-Log -Level WARNING -Message "Get-MpPreference backup failed: $_" -Module "ASR"
$result.Errors += "MpPreference backup failed: $_"
}
}
catch {
$result.Success = $false
$result.Errors += "Backup failed: $($_.Exception.Message)"
Write-Log -Level ERROR -Message "ASR backup failed: $($_.Exception.Message)" -Module "ASR"
}
return $result
}