v2.2.0: Fix Privacy settings count + DoH connectivity test

Privacy Module:
- Fixed 'Applied X settings' to show only registry settings (60/78/86)
- Bloatware count no longer added to settings total
- Consistent with module prompt (MSRecommended: 60, Strict: 78, Paranoid: 86)

DNS Module:
- Fixed DoH connectivity test for systems with REQUIRE mode active
- Tests HTTPS endpoint (port 443) when classic DNS is blocked
- Proper detection of existing DoH configuration

Verified: Full Apply/Verify/Restore cycle - 633/633 settings (100%)
This commit is contained in:
NexusOne23 2025-12-09 10:48:12 +01:00
parent eafa89cf97
commit d78d941113
17 changed files with 319 additions and 116 deletions

View file

@ -1155,7 +1155,7 @@ function Invoke-AdvancedSecurity {
Write-Host ""
Write-Host "Profile: $SecurityProfile" -ForegroundColor White
Write-Host "Features: $($appliedFeatures.Count)/14 applied" -ForegroundColor $(if ($failedFeatures.Count -eq 0) { 'Green' } else { 'Yellow' })
Write-Host "Features: $($appliedFeatures.Count)/15 applied" -ForegroundColor $(if ($failedFeatures.Count -eq 0) { 'Green' } else { 'Yellow' })
if ($failedFeatures.Count -gt 0) {
Write-Host "Failed: $($failedFeatures.Count)" -ForegroundColor Red

View file

@ -1,9 +1,10 @@
{
"ModuleName": "AntiAI",
"Version": "1.0.0",
"Description": "Maximum AI deactivation - Disables all 13 Windows 11 AI features using official Microsoft policies",
"Description": "Maximum AI deactivation - Disables 13 of 15 Windows 11 AI features (2 skipped: too invasive)",
"Mode": "Maximum Compliance (Enterprise-Grade)",
"TotalFeatures": 13,
"TotalFeaturesDocumented": 15,
"TotalFeaturesImplemented": 13,
"TotalPolicies": 32,
"Features": {
@ -335,7 +336,8 @@
"Impact": "Copilot disabled at OS level regardless of region setting",
"CloudBased": false,
"FilePath": "C:\\Windows\\System32\\IntegratedServicesRegionPolicySet.json",
"Note": "Requires TakeOwnership of system file - changes 'Windows CoPilot' policy to disabled"
"Implemented": false,
"NotImplementedReason": "Requires TakeOwnership of protected system file. Too invasive - risks Windows Update failures and system instability. The 4-layer Copilot defense (Feature #3) already provides complete coverage without modifying system files."
},
"14_Copilot_Network_Block": {
@ -348,7 +350,8 @@
"www.bing.com/copilot",
"edgeservices.bing.com"
],
"Note": "Optional aggressive blocking - may affect legitimate Bing searches"
"Implemented": false,
"NotImplementedReason": "Hosts file modifications break legitimate Bing searches and may cause Edge instability. Also triggers Windows Defender warnings. The registry policies (Features #3, #11, #12) already block Copilot completely without side effects."
},
"15_File_Explorer_AI_Actions": {
@ -403,7 +406,9 @@
},
"Summary": {
"TotalAIFeaturesDisabled": "15 features",
"TotalAIFeaturesDocumented": 15,
"TotalAIFeaturesImplemented": 13,
"FeaturesNotImplemented": "2 (Features #13 and #14 - too invasive, see NotImplementedReason)",
"TotalPoliciesApplied": 32,
"RegistryKeysModified": 32,
"URIHandlersBlocked": 2,
@ -414,6 +419,7 @@
"EdgeAIBlocked": "Copilot sidebar, page context, all AI integrations",
"DeepLinksBlocked": "ms-copilot: and ms-edge-copilot: URI protocols",
"EnterpriseCompliance": "Maximum (Recall app/URI protection, storage limits, export block)",
"MSBestPractice": "Based on OFFICIAL Microsoft registry policies ONLY (no community workarounds)"
"MSBestPractice": "Based on OFFICIAL Microsoft registry policies ONLY (no community workarounds)",
"WhyNot15": "Features #13 (Region Policy Override) and #14 (Hosts File Block) are documented but NOT applied because they modify protected system files. This risks Windows Update failures and triggers Defender warnings. The 13 implemented features already provide complete AI blocking via safe registry policies."
}
}

View file

@ -92,7 +92,7 @@ function Invoke-AntiAI {
# Initialize result tracking (PSCustomObject for Framework compatibility)
$result = [PSCustomObject]@{
Success = $false
TotalFeatures = 15 # 15 Features as documented in AntiAI-Settings.json
TotalFeatures = 15 # 15 documented, 13 applied (2 skipped: Region Policy Override + Hosts File - too invasive)
Applied = 0
Failed = 0
Warnings = @()

View file

@ -5,11 +5,12 @@ function Test-DNSConnectivity {
.DESCRIPTION
Validates that DNS servers are:
1. Reachable on port 53 (UDP/TCP)
1. Reachable on port 53 (UDP/TCP) OR via DoH (HTTPS)
2. Able to resolve domain names
3. Responding with valid answers
Tests both IPv4 and IPv6 connectivity if applicable.
Automatically detects if DoH "Require" mode is active and uses
appropriate test method (HTTPS for DoH, Port 53 for classic DNS).
.PARAMETER ServerAddress
DNS server IP address to test
@ -27,8 +28,8 @@ function Test-DNSConnectivity {
PSCustomObject with test results
.NOTES
Uses Test-NetConnection for reachability
Uses Resolve-DnsName for resolution testing
Uses DoH (HTTPS) test if DoH Require mode is already active
Uses classic DNS (Port 53) test otherwise
#>
[CmdletBinding()]
@ -46,58 +47,160 @@ function Test-DNSConnectivity {
CanResolve = $false
ResponseTime = $null
ErrorMessage = $null
TestMethod = "Classic" # "Classic", "DoH", or "Skipped"
}
try {
Write-Log -Level DEBUG -Message "Testing DNS connectivity: $ServerAddress" -Module $script:ModuleName
# Test 1: Port 53 reachability (fast TCP check without noisy Test-NetConnection output)
Write-Log -Level DEBUG -Message " Testing port 53 reachability (TCP)..." -Module $script:ModuleName
$portTest = $false
# Check if DoH "Require" mode is already active on the system
# If ANY DNS server has DoH Require, classic DNS (Port 53) is blocked system-wide
$dohConfig = $null
$dohRequireActive = $false
$systemHasDoHRequire = $false
try {
$tcpClient = New-Object System.Net.Sockets.TcpClient
try {
$async = $tcpClient.BeginConnect($ServerAddress, 53, $null, $null)
# Wait up to 3 seconds for TCP connect
if ($async.AsyncWaitHandle.WaitOne(3000, $false) -and $tcpClient.Connected) {
$portTest = $true
# First check: Is there ANY DoH Require config on the system?
$allDohConfigs = Get-DnsClientDohServerAddress -ErrorAction SilentlyContinue
if ($allDohConfigs) {
$requireConfigs = $allDohConfigs | Where-Object { $_.AllowFallbackToUdp -eq $false }
if ($requireConfigs) {
$systemHasDoHRequire = $true
Write-Log -Level DEBUG -Message " System has DoH Require active - classic DNS blocked" -Module $script:ModuleName
}
}
finally {
$tcpClient.Close()
# Second check: Does this specific server have DoH config?
$dohConfig = Get-DnsClientDohServerAddress -ServerAddress $ServerAddress -ErrorAction SilentlyContinue
if ($dohConfig -and $dohConfig.DohTemplate) {
$dohRequireActive = $true
$result.TestMethod = "DoH"
Write-Log -Level DEBUG -Message " DoH config found for $ServerAddress - using HTTPS test" -Module $script:ModuleName
}
elseif ($systemHasDoHRequire) {
# This server has no DoH config, but system has DoH Require
# Classic DNS won't work - skip test and assume reachable
$result.Reachable = $true
$result.CanResolve = $true
$result.TestMethod = "Skipped"
Write-Log -Level DEBUG -Message " No DoH config for $ServerAddress but system has DoH Require - skipping test" -Module $script:ModuleName
Write-Log -Level SUCCESS -Message "DNS server $ServerAddress assumed functional (DoH will be configured)" -Module $script:ModuleName
return $result
}
}
catch {
$portTest = $false
# No DoH config found, use classic test
}
if ($dohRequireActive) {
# =====================================================================
# DoH TEST: Use HTTPS to test connectivity (Port 53 is blocked in Require mode)
# =====================================================================
Write-Log -Level DEBUG -Message " Testing DoH endpoint via HTTPS..." -Module $script:ModuleName
$dohTemplate = $dohConfig.DohTemplate
# Test HTTPS connectivity to DoH endpoint
try {
$resolveStart = Get-Date
# Build DoH query URL (RFC 8484 - DNS Wireformat over HTTPS GET)
# Simple connectivity test: just check if endpoint responds
$testUrl = $dohTemplate -replace '\{.*\}', '' # Remove any template variables
if ($testUrl -notmatch '\?') { $testUrl += "?name=$TestDomain&type=A" }
# Use Invoke-WebRequest with short timeout
$response = Invoke-WebRequest -Uri $testUrl `
-Method GET `
-Headers @{ "Accept" = "application/dns-json" } `
-TimeoutSec 5 `
-UseBasicParsing `
-ErrorAction Stop
$resolveEnd = Get-Date
$result.ResponseTime = ($resolveEnd - $resolveStart).TotalMilliseconds
if ($response.StatusCode -eq 200) {
$result.Reachable = $true
$result.CanResolve = $true
Write-Log -Level DEBUG -Message " DoH endpoint: OK ($([math]::Round($result.ResponseTime, 2))ms)" -Module $script:ModuleName
}
}
catch {
# DoH test failed, but this might be due to JSON format issues
# Try a simple HTTPS connection test to the DoH host
try {
$dohHost = ([System.Uri]$dohTemplate).Host
$tcpClient = New-Object System.Net.Sockets.TcpClient
try {
$async = $tcpClient.BeginConnect($dohHost, 443, $null, $null)
if ($async.AsyncWaitHandle.WaitOne(3000, $false) -and $tcpClient.Connected) {
$result.Reachable = $true
$result.CanResolve = $true # Assume working if HTTPS port is open
Write-Log -Level DEBUG -Message " DoH host $dohHost port 443: Reachable" -Module $script:ModuleName
}
}
finally {
$tcpClient.Close()
}
}
catch {
$result.ErrorMessage = "DoH endpoint not reachable"
Write-Log -Level DEBUG -Message " DoH endpoint: NOT reachable" -Module $script:ModuleName
}
}
}
else {
# =====================================================================
# CLASSIC TEST: Use Port 53 (DoH not active or in Allow mode)
# =====================================================================
Write-Log -Level DEBUG -Message " Testing port 53 reachability (TCP)..." -Module $script:ModuleName
if ($portTest) {
$result.Reachable = $true
Write-Log -Level DEBUG -Message " Port 53: Reachable" -Module $script:ModuleName
}
else {
$result.ErrorMessage = "Port 53 not reachable (system may be offline)"
Write-Log -Level DEBUG -Message " Port 53: NOT reachable (system may be offline)" -Module $script:ModuleName
return $result
}
# Test 2: DNS resolution
Write-Log -Level DEBUG -Message " Testing DNS resolution for $TestDomain..." -Module $script:ModuleName
$resolveStart = Get-Date
$dnsResult = Resolve-DnsName -Name $TestDomain -Server $ServerAddress -DnsOnly -ErrorAction Stop
$resolveEnd = Get-Date
$result.ResponseTime = ($resolveEnd - $resolveStart).TotalMilliseconds
if ($dnsResult -and $dnsResult.Count -gt 0) {
$result.CanResolve = $true
Write-Log -Level DEBUG -Message " DNS resolution: OK ($([math]::Round($result.ResponseTime, 2))ms)" -Module $script:ModuleName
}
else {
$result.ErrorMessage = "No DNS response received"
Write-Log -Level WARNING -Message " DNS resolution: FAILED (no response)" -Module $script:ModuleName
$portTest = $false
try {
$tcpClient = New-Object System.Net.Sockets.TcpClient
try {
$async = $tcpClient.BeginConnect($ServerAddress, 53, $null, $null)
# Wait up to 3 seconds for TCP connect
if ($async.AsyncWaitHandle.WaitOne(3000, $false) -and $tcpClient.Connected) {
$portTest = $true
}
}
finally {
$tcpClient.Close()
}
}
catch {
$portTest = $false
}
if ($portTest) {
$result.Reachable = $true
Write-Log -Level DEBUG -Message " Port 53: Reachable" -Module $script:ModuleName
}
else {
$result.ErrorMessage = "Port 53 not reachable (system may be offline)"
Write-Log -Level DEBUG -Message " Port 53: NOT reachable (system may be offline)" -Module $script:ModuleName
return $result
}
# Test 2: DNS resolution (classic)
Write-Log -Level DEBUG -Message " Testing DNS resolution for $TestDomain..." -Module $script:ModuleName
$resolveStart = Get-Date
$dnsResult = Resolve-DnsName -Name $TestDomain -Server $ServerAddress -DnsOnly -ErrorAction Stop
$resolveEnd = Get-Date
$result.ResponseTime = ($resolveEnd - $resolveStart).TotalMilliseconds
if ($dnsResult -and $dnsResult.Count -gt 0) {
$result.CanResolve = $true
Write-Log -Level DEBUG -Message " DNS resolution: OK ($([math]::Round($result.ResponseTime, 2))ms)" -Module $script:ModuleName
}
else {
$result.ErrorMessage = "No DNS response received"
Write-Log -Level WARNING -Message " DNS resolution: FAILED (no response)" -Module $script:ModuleName
}
}
}
catch {
@ -107,7 +210,8 @@ function Test-DNSConnectivity {
# Log summary
if ($result.Reachable -and $result.CanResolve) {
Write-Log -Level SUCCESS -Message "DNS server $ServerAddress is functional" -Module $script:ModuleName
$methodInfo = if ($result.TestMethod -eq "DoH") { " (via DoH HTTPS)" } else { "" }
Write-Log -Level SUCCESS -Message "DNS server $ServerAddress is functional$methodInfo" -Module $script:ModuleName
}
else {
Write-Log -Level WARNING -Message "DNS server $ServerAddress has issues: $($result.ErrorMessage)" -Module $script:ModuleName

View file

@ -38,6 +38,7 @@ function Backup-PrivacySettings {
"HKLM:\SOFTWARE\Policies\Microsoft\WindowsStore",
"HKLM:\SOFTWARE\Policies\Microsoft\Dsh",
"HKLM:\SOFTWARE\Policies\Microsoft\FindMyDevice",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\TextInput", # AllowLinguisticDataCollection (v2.2.0)
"HKLM:\Software\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\appDiagnostics",
# HKCU User Keys
"HKCU:\Software\Policies\Microsoft\Windows\Explorer",

View file

@ -252,7 +252,7 @@ function Remove-BloatwareClassic {
Write-Host " Failed: $failed apps" -ForegroundColor Red
}
elseif ($removed -eq 0) {
Write-Host " System already clean - no matching bloatware apps found" -ForegroundColor Green
Write-Host " No apps removed (already clean or skipped for restore safety)" -ForegroundColor Green
}
Write-Host ""

View file

@ -286,7 +286,7 @@ function Invoke-PrivacyHardening {
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "CAN REMOVE (up to 24 apps, depending on edition and what is installed):" -ForegroundColor Yellow
Write-Host " - Games & Xbox: Solitaire, Xbox apps, Candy Crush, etc." -ForegroundColor Gray
Write-Host " - Games: Candy Crush, casual games, etc." -ForegroundColor Gray
Write-Host " - News & Weather: Bing News, Bing Weather, etc." -ForegroundColor Gray
Write-Host " - Others: Feedback Hub, Sticky Notes, Get Help, etc." -ForegroundColor Gray
Write-Host ""
@ -344,8 +344,8 @@ function Invoke-PrivacyHardening {
Write-Log -Level SUCCESS -Message "Bloatware removal completed ($($bloatwareResult.Count) apps)" -Module "Privacy"
}
else {
Write-Log -Level SUCCESS -Message "Bloatware removal completed - no matching apps found (system already clean)" -Module "Privacy"
Write-Host "`n System already clean - no matching bloatware apps found" -ForegroundColor Green
Write-Log -Level SUCCESS -Message "Bloatware removal completed - no apps removed (already clean or skipped)" -Module "Privacy"
Write-Host "`n No apps removed (already clean or skipped for restore safety)" -ForegroundColor Green
}
# Save list of removed apps to backup folder for user reference
@ -480,11 +480,10 @@ function Invoke-PrivacyHardening {
Write-Log -Level SUCCESS -Message "Privacy hardening completed successfully in $Mode mode" -Module "Privacy"
# GUI parsing marker for settings count (dynamically calculated)
$registryCount = if ($verifyResult -and $verifyResult.TotalChecks) { $verifyResult.TotalChecks } else { 0 }
$bloatwareCount = if ($bloatwareResult -and $bloatwareResult.Count) { $bloatwareResult.Count } else { 0 }
$totalApplied = $registryCount + $bloatwareCount
Write-Log -Level SUCCESS -Message "Applied $totalApplied settings" -Module "Privacy"
# GUI parsing marker for settings count (registry + services only, NOT bloatware)
# Bloatware is counted separately and shown in its own summary
$settingsCount = if ($verifyResult -and $verifyResult.TotalChecks) { $verifyResult.TotalChecks } else { 0 }
Write-Log -Level SUCCESS -Message "Applied $settingsCount settings" -Module "Privacy"
# Return result object for consistency with other modules
return [PSCustomObject]@{