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

@ -61,7 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Defense-in-depth (WPAD already disabled by framework)
- Recommended for air-gapped/standalone systems
**Privacy Module Expansion (55+ → 77 settings)**
**Privacy Module Expansion (55+ → 78 settings)**
- Cloud Clipboard toggle (user-configurable)
- Enhanced compliance verification
- Improved bloatware detection
@ -71,7 +71,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Automatic detection of Kaspersky, Norton, Bitdefender, etc.
- ASR module gracefully skipped when 3rd-party AV active
- Clear user notification explaining why
- All other modules continue normally (613 settings)
- All other modules continue normally (614 settings)
**Smart Registry Backup System**
- JSON fallback for protected system keys
@ -81,7 +81,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
**Documentation**
- AV Compatibility section: "Designed for Microsoft Defender Works with Any Antivirus"
- Clear 632 vs 613 explanation for Defender vs. 3rd-party AV setups
- Clear 633 vs 614 explanation for Defender vs. 3rd-party AV setups
- Improved troubleshooting guides
### 🔨 Fixed
@ -113,9 +113,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
| Component | v2.1.0 | v2.2.0 |
|-----------|--------|--------|
| Total Settings | 580+ | **632** |
| Total Settings | 580+ | **633** |
| AntiAI Policies | 24 | **32** |
| Privacy Settings | 55+ | **77** |
| Privacy Settings | 55+ | **78** |
| NonInteractive Mode | ❌ | ✅ |
| 3rd-Party AV Detection | ❌ | ✅ |
| Pre-Framework ASR Snapshot | ❌ | ✅ |

View file

@ -534,8 +534,8 @@ function Invoke-Hardening {
Write-Host ""
Write-Host " > Applies privacy settings based on selected mode:" -ForegroundColor Gray
Write-Host " - Telemetry control (3 modes: MSRecommended/Strict/Paranoid)" -ForegroundColor Gray
Write-Host " - MSRecommended: 59 settings (default, max compatibility)" -ForegroundColor DarkGray
Write-Host " - Strict: 77 settings, Paranoid: 85 settings" -ForegroundColor DarkGray
Write-Host " - MSRecommended: 60 settings (default, max compatibility)" -ForegroundColor DarkGray
Write-Host " - Strict: 78 settings, Paranoid: 86 settings" -ForegroundColor DarkGray
Write-Host " - Disable ads, tips, personalization" -ForegroundColor Gray
Write-Host " - Remove bloatware (up to 24 apps, if present)" -ForegroundColor Gray
Write-Host " - OneDrive hardening (keeps sync functional)" -ForegroundColor Gray

View file

@ -119,7 +119,7 @@ function Update-SessionDisplayName {
"SecurityBaseline" = 425 # 335 Registry + 67 Security Template + 23 Audit
"ASR" = 19 # 19 ASR Rules
"DNS" = 5 # 5 DNS Settings
"Privacy" = 77 # 53 Registry (MSRecommended) + 24 Bloatware
"Privacy" = 78 # 54 Registry (MSRecommended) + 24 Bloatware
"AntiAI" = 32 # 32 Registry Policies (15 features)
"EdgeHardening" = 24 # 24 Edge Policies (22-23 applied depending on extensions)
"AdvancedSecurity" = 50 # 50 Advanced Settings (15 features incl. Discovery Protocols + IPv6)

View file

@ -121,7 +121,7 @@ function Get-WindowsVersion {
# Windows 11 build numbers
# 22000 = 21H2, 22621 = 22H2, 22631 = 23H2, 26100 = 24H2, 26200 = 25H2
$isWindows11 = $buildNumber -ge 22000
$isSupported = $buildNumber -ge 26100 # 24H2 or newer
$isSupported = $buildNumber -ge 26100 # 24H2 or newer required
$versionName = switch ($buildNumber) {
{ $_ -ge 26200 } { "Windows 11 25H2"; break }

View file

@ -1,7 +1,7 @@
# NoID Privacy - Complete Feature List
**Framework Version:** v2.2.0
**Total Security Settings:** 632 (Paranoid mode)
**Total Security Settings:** 633 (Paranoid mode)
**Modules:** 7 (All Production-Ready)
**Last Updated:** December 8, 2025
@ -14,11 +14,11 @@
| **SecurityBaseline** | 425 | ✅ v2.2.0 | Microsoft Security Baseline for Windows 11 v25H2 |
| **ASR** | 19 | ✅ v2.2.0 | Attack Surface Reduction rules |
| **DNS** | 5 | ✅ v2.2.0 | Secure DNS with DoH encryption |
| **Privacy** | 77 | ✅ v2.2.0 | Telemetry control, OneDrive hardening (Strict: 69 Registry + 2 Services + 6 OneDrive) |
| **Privacy** | 78 | ✅ v2.2.0 | Telemetry control, OneDrive hardening (Strict: 70 Registry + 2 Services + 6 OneDrive) |
| **AntiAI** | 32 | ✅ v2.2.0 | AI lockdown (15 features, 32 compliance checks) |
| **EdgeHardening** | 24 | ✅ v2.2.0 | Microsoft Edge browser security (24 policies) |
| **AdvancedSecurity** | 50 | ✅ v2.2.0 | Advanced hardening beyond MS Baseline (incl. Wireless Display, Discovery Protocols, IPv6) |
| **TOTAL** | **632** | ✅ **100%** | **Complete Framework (Paranoid mode)** |
| **TOTAL** | **633** | ✅ **100%** | **Complete Framework (Paranoid mode)** |
---
@ -150,7 +150,7 @@
---
## 🔇 Module 4: Privacy (77 Settings)
## 🔇 Module 4: Privacy (78 Settings)
**Description:** Windows telemetry control, OneDrive/MS Store telemetry, and bloatware removal
@ -205,13 +205,12 @@ After enrollment, you can optionally re-apply Privacy hardening. Insider builds
- MicrosoftStickyNotes, GamingApp, WindowsFeedbackHub
- Xbox components (GamingOverlay, IdentityProvider)
**ClassicMethod (24 apps - All other editions):**
**ClassicMethod (up to 24 apps - All other editions):**
```
Microsoft.BingNews, Microsoft.BingWeather
Microsoft.MicrosoftSolitaireCollection, Microsoft.MicrosoftStickyNotes
Microsoft.GamingApp, Microsoft.XboxApp
Microsoft.XboxGamingOverlay, Microsoft.XboxIdentityProvider
Microsoft.XboxSpeechToTextOverlay, Microsoft.Xbox.TCUI
Microsoft.MicrosoftStickyNotes, Microsoft.GamingApp
Microsoft.XboxApp, Microsoft.XboxGamingOverlay
Microsoft.XboxIdentityProvider
Microsoft.ZuneMusic, Microsoft.ZuneVideo
Microsoft.WindowsFeedbackHub, Microsoft.GetHelp
Microsoft.Getstarted, Microsoft.MixedReality.Portal
@ -220,6 +219,10 @@ Clipchamp.Clipchamp, SpotifyAB.SpotifyMusic
*CandyCrush*, Disney.*, Facebook.*, TikTok.TikTok
```
**Skipped for restore safety (not in winget msstore):**
- Microsoft.MicrosoftSolitaireCollection
- Microsoft.XboxSpeechToTextOverlay, Microsoft.Xbox.TCUI
### Protected Apps (19 kept):
- **Core Apps:** WindowsStore, WindowsCalculator, Photos, Paint
- **Productivity:** WindowsNotepad, WindowsTerminal, WindowsCamera, ScreenSketch, WindowsSoundRecorder
@ -724,7 +727,7 @@ Some UI elements in Paint and Photos apps may **still be visible** but non-funct
NoID Privacy v2.2.0
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total Settings: 632
Total Settings: 633
Modules: 7/7 (100%) ✅
Production Status: Ready ✅
Verification: 100% ✅

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]@{

View file

@ -472,16 +472,50 @@ function Show-ModuleMenu {
Write-Banner
Write-Header "SELECT MODULES TO APPLY"
# Module definitions with descriptions
$moduleDefinitions = @{
"SecurityBaseline" = "Microsoft Security Baseline (425 settings)"
"ASR" = "Attack Surface Reduction (19 rules)"
"DNS" = "Secure DNS with DoH (Quad9/Cloudflare/AdGuard)"
"Privacy" = "Telemetry & Privacy hardening (3 modes)"
"AntiAI" = "Disable Windows AI features (15 features, 32 policies)"
"EdgeHardening" = "Secure Microsoft Edge browser (24 policies)"
"AdvancedSecurity" = "Beyond MS Baseline (50 settings, 15 features)"
}
# Try to load config.json to check module status
$configPath = Join-Path $PSScriptRoot "config.json"
$config = $null
if (Test-Path $configPath) {
try {
$config = Get-Content $configPath -Raw | ConvertFrom-Json
}
catch {
# If config fails to load, all modules default to enabled
}
}
# Build module list with status from config
$modules = @(
[PSCustomObject]@{ Key = "1"; Name = "SecurityBaseline"; Description = "Microsoft Security Baseline (425 settings)"; Enabled = $true }
[PSCustomObject]@{ Key = "2"; Name = "ASR"; Description = "Attack Surface Reduction (19 rules)"; Enabled = $true }
[PSCustomObject]@{ Key = "3"; Name = "DNS"; Description = "Secure DNS with DoH (Quad9/Cloudflare/AdGuard)"; Enabled = $true }
[PSCustomObject]@{ Key = "4"; Name = "Privacy"; Description = "Telemetry & Privacy hardening (3 modes)"; Enabled = $true }
[PSCustomObject]@{ Key = "5"; Name = "AntiAI"; Description = "Disable Windows AI features (15 features, 32 policies)"; Enabled = $true }
[PSCustomObject]@{ Key = "6"; Name = "EdgeHardening"; Description = "Secure Microsoft Edge browser (24 policies)"; Enabled = $true }
[PSCustomObject]@{ Key = "7"; Name = "AdvancedSecurity"; Description = "15 security features (50 settings): RDP/Credentials/Ports/TLS/WPAD/PSv2/SRP/WinUpdate/WirelessDisplay/Discovery/IPv6"; Enabled = $true }
[PSCustomObject]@{ Key = "1"; Name = "SecurityBaseline"; Description = $moduleDefinitions["SecurityBaseline"]; Enabled = $true }
[PSCustomObject]@{ Key = "2"; Name = "ASR"; Description = $moduleDefinitions["ASR"]; Enabled = $true }
[PSCustomObject]@{ Key = "3"; Name = "DNS"; Description = $moduleDefinitions["DNS"]; Enabled = $true }
[PSCustomObject]@{ Key = "4"; Name = "Privacy"; Description = $moduleDefinitions["Privacy"]; Enabled = $true }
[PSCustomObject]@{ Key = "5"; Name = "AntiAI"; Description = $moduleDefinitions["AntiAI"]; Enabled = $true }
[PSCustomObject]@{ Key = "6"; Name = "EdgeHardening"; Description = $moduleDefinitions["EdgeHardening"]; Enabled = $true }
[PSCustomObject]@{ Key = "7"; Name = "AdvancedSecurity"; Description = $moduleDefinitions["AdvancedSecurity"]; Enabled = $true }
)
# Override enabled status from config.json if available
if ($config -and $config.modules) {
foreach ($module in $modules) {
$configModule = $config.modules.PSObject.Properties[$module.Name]
if ($configModule -and $configModule.Value.PSObject.Properties['enabled']) {
$module.Enabled = [bool]$configModule.Value.enabled
}
}
}
foreach ($module in $modules) {
if ($module.Enabled) {
Write-ColorText " [$($module.Key)]" -Color Green -NoNewline
@ -609,8 +643,9 @@ function Invoke-HardeningWorkflow {
Write-ColorText "FAILED [-]" -Color Red
}
Write-ColorText " Modules Applied: " -Color Gray -NoNewline
Write-ColorText " Modules Selected: " -Color Gray -NoNewline
Write-ColorText "$($modulesToRun.Count)" -Color White
Write-ColorText " (Check output above for actual results per module)" -Color DarkGray
Write-Host ""
@ -619,7 +654,7 @@ function Invoke-HardeningWorkflow {
}
else {
Write-ColorText " Some modules had warnings or were skipped. Check details above." -Color Yellow
Write-ColorText " Most security settings were still applied successfully." -Color White
Write-ColorText " Review the log file for complete details." -Color White
}
Write-Host ""
@ -885,11 +920,15 @@ try {
exit 1
}
# Load framework
# Load Framework (required for core functions like Test-IsAdmin used by modules)
$frameworkPath = Join-Path $PSScriptRoot "Core\Framework.ps1"
if (Test-Path $frameworkPath) {
. $frameworkPath
}
else {
Write-Host "[ERROR] Framework.ps1 not found!" -ForegroundColor Red
exit 1
}
while ($true) {
# Clear before each main menu redraw

View file

@ -244,7 +244,7 @@ if (-not $Module) {
$verifyScript = Join-Path $script:RootPath "Tools\Verify-Complete-Hardening.ps1"
if (Test-Path $verifyScript) {
# Discard return value so that 'True' / 'False' is not printed to console
$null = & $verifyScript -Detailed
$null = & $verifyScript
}
else {
Write-Host "ERROR: Verification script not found" -ForegroundColor Red
@ -256,17 +256,72 @@ if (-not $Module) {
exit 0
}
"R" {
# Restore from backup
# Restore from backup - Interactive session selection from disk
Write-Host ""
Write-Host "Loading backup system..." -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " RESTORE FROM BACKUP" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# Call Restore-AllBackups function from Rollback.ps1
if (Get-Command Restore-AllBackups -ErrorAction SilentlyContinue) {
Restore-AllBackups
# Get all backup sessions from disk
$sessions = Get-BackupSessions
if ($sessions.Count -eq 0) {
Write-Host "No backup sessions found." -ForegroundColor Yellow
Write-Host "Backups are created when you apply hardening modules." -ForegroundColor Gray
Write-Host ""
Write-Host "Press any key to continue..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 0
}
Write-Host "Available backup sessions:" -ForegroundColor White
Write-Host ""
$i = 1
foreach ($session in $sessions) {
$moduleNames = ($session.Modules | ForEach-Object { $_.name }) -join ", "
$dateStr = $session.Timestamp.ToString("yyyy-MM-dd HH:mm:ss")
Write-Host " [$i] $dateStr" -ForegroundColor Green
Write-Host " Modules: $moduleNames" -ForegroundColor Gray
Write-Host " Items: $($session.TotalItems)" -ForegroundColor Gray
Write-Host ""
$i++
}
Write-Host " [0] Cancel and return" -ForegroundColor Red
Write-Host ""
$selection = Read-Host "Select session to restore [1-$($sessions.Count), 0=Cancel]"
if ($selection -eq "0" -or [string]::IsNullOrWhiteSpace($selection)) {
Write-Host "Restore cancelled." -ForegroundColor Yellow
exit 0
}
$selIndex = [int]$selection - 1
if ($selIndex -lt 0 -or $selIndex -ge $sessions.Count) {
Write-Host "Invalid selection." -ForegroundColor Red
exit 1
}
$selectedSession = $sessions[$selIndex]
Write-Host ""
Write-Host "Restoring session: $($selectedSession.SessionId)" -ForegroundColor Cyan
Write-Host ""
# Call Restore-Session with the session path
$success = Restore-Session -SessionPath $selectedSession.FolderPath
if ($success) {
Write-Host ""
Write-Host "Restore completed successfully!" -ForegroundColor Green
}
else {
Write-Host "ERROR: Restore function not available" -ForegroundColor Red
Write-Host ""
Write-Host "Restore completed with some errors. Check logs for details." -ForegroundColor Yellow
}
Write-Host ""

View file

@ -193,7 +193,7 @@
- ALLOW mode (optional): fallback allowed for VPN/mobile/enterprise networks
- IPv4 + IPv6 dual-stack support
### 🔒 Privacy Hardening (77 Settings)
### 🔒 Privacy Hardening (78 Settings)
**3 Operating Modes**
- **MSRecommended** (Default) MS-supported, max compatibility
@ -358,18 +358,18 @@ cd noid-privacy
### Verification
```powershell
# Full verification (632 checks with Paranoid mode)
# Full verification (633 checks with Paranoid mode)
.\Tools\Verify-Complete-Hardening.ps1
# Expected output (all modules enabled, Paranoid mode):
# SecurityBaseline: 425/425 verified
# ASR: 19/19 verified
# DNS: 5/5 verified
# Privacy: 77/77 verified
# Privacy: 78/78 verified
# AntiAI: 32/32 verified
# EdgeHardening: 24/24 verified
# AdvancedSecurity: 50/50 verified
# Total: 632/632 (100%)
# Total: 633/633 (100%)
```
### Restore
@ -392,11 +392,11 @@ cd noid-privacy
| **SecurityBaseline** | 425 | Microsoft Security Baseline 25H2 | v2.2.0 |
| **ASR** | 19 | Attack Surface Reduction Rules | v2.2.0 |
| **DNS** | 5 | Secure DNS with DoH encryption | v2.2.0 |
| **Privacy** | 77 | Telemetry, Bloatware, OneDrive hardening (Strict) | v2.2.0 |
| **Privacy** | 78 | Telemetry, Bloatware, OneDrive hardening (Strict) | v2.2.0 |
| **AntiAI** | 32 | AI lockdown (15 features, 32 compliance checks) | v2.2.0 |
| **EdgeHardening** | 24 | Microsoft Edge security (24 policies) | v2.2.0 |
| **AdvancedSecurity** | 50 | Beyond MS Baseline (SRP, Legacy protocols, Wireless Display, Discovery Protocols, IPv6) | v2.2.0 |
| **TOTAL** | **632** | **Complete Framework (Paranoid mode)** | **Production** |
| **TOTAL** | **633** | **Complete Framework (Paranoid mode)** | **Production** |
**Release Highlights:**
@ -447,7 +447,7 @@ cd noid-privacy
- Use [Microsoft Security Baselines](https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/windows-security-configuration-framework/security-compliance-toolkit-10) with Group Policy instead
**Windows 10 or Older**
- This tool is designed for Windows 11 (24H2/25H2 recommended, 23H2 compatible)
- This tool is designed for Windows 11 24H2 or newer
**Legacy Software Dependencies**
- If you rely on unsafe SMB1/RPC/DCOM
@ -465,7 +465,7 @@ NoID Privacy is designed for modern, officially supported Windows 11 systems.
If your PC can run Windows 11 according to Microsoft's **official requirements**, it is compatible with NoID Privacy:
- **OS:** Windows 11 24H2/25H2 recommended (23H2 compatible)
- **OS:** Windows 11 24H2 or newer (25H2 fully tested)
- **CPU:** Any CPU on Microsoft's Windows 11 support list (Intel 8th Gen / AMD Ryzen 2000+)
- **Firmware:** UEFI with **Secure Boot** enabled
- **TPM:** 2.0 (required for BitLocker, Credential Guard, VBS)
@ -480,7 +480,7 @@ If your PC can run Windows 11 according to Microsoft's **official requirements**
|------------|--------|
| Windows 11 25H2 (Build 26200+) | **Fully Tested** |
| Windows 11 24H2 (Build 26100+) | Compatible |
| Windows 11 23H2 (Build 22631+) | Some features N/A |
| Windows 11 23H2 or older | ❌ Not Supported |
### Legacy Devices & Protocols
@ -525,8 +525,8 @@ This is the **recommended setup** just install Windows 11, keep Defender act
| Your Setup | What Happens | Coverage |
|------------|--------------|----------|
| **Defender Active** | All modules applied | **632 settings** (100%) |
| **3rd-Party AV** (Kaspersky, Norton, Bitdefender, etc.) | ASR skipped, all other modules applied | **613 settings** (~97%) |
| **Defender Active** | All modules applied | **633 settings** (100%) |
| **3rd-Party AV** (Kaspersky, Norton, Bitdefender, etc.) | ASR skipped, all other modules applied | **614 settings** (~97%) |
**Why?** ASR (Attack Surface Reduction) rules are a **Microsoft Defender exclusive feature**. Third-party antivirus products provide their own equivalent protection. NoID Privacy detects this and gracefully skips ASR while applying everything else.

View file

@ -17,8 +17,8 @@ title NoID Privacy v2.2.0
REM Get the directory where this batch file is located
set "SCRIPT_DIR=%~dp0"
REM Check if already running as administrator
net session >nul 2>&1
REM Check if already running as administrator (robust method that works even if Server service is disabled)
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if %errorLevel% == 0 (
REM Already admin, run PowerShell script directly
echo Running NoID Privacy Interactive Menu with Administrator privileges...

View file

@ -16,7 +16,7 @@
NOTE: This shows the TRUTH about what is configured in your system.
Total: 632 settings (Paranoid mode)
Total: 633 settings (Paranoid mode)
SecurityBaseline: 425 (335 Registry + 67 SecTemplate + 23 Audit)
ASR: 19
DNS: 5
@ -48,7 +48,7 @@ $EXPECTED_ASR_COUNT = 19
$EXPECTED_EDGE_COUNT = 24 # 24 total Edge policies from EdgePolicies.json
$EXPECTED_ADVANCED_COUNT = 50 # 50 total AdvancedSecurity policy checks (incl. Discovery Protocols WSD/mDNS + IPv6)
$EXPECTED_DNS_COUNT = 5
$EXPECTED_PRIVACY_COUNT = 77 # 53 registry from Privacy-MSRecommended.json + 24 bloatware apps
$EXPECTED_PRIVACY_COUNT = 78 # 54 registry from Privacy-MSRecommended.json + 24 bloatware apps
$EXPECTED_ANTIAI_COUNT = 32 # 32 AntiAI registry policy checks (15 features)
Write-Host ""
@ -380,7 +380,6 @@ try {
else {
# Check if this is a DELETE operation (**del..., **delvals)
# For DELETE operations, "Value not found" means SUCCESS (value was deleted or never existed)
$registryCounter++
if ($setting.ValueName -like "**del*") {
$results.Verified++
$registryPassed += [PSCustomObject]@{
@ -405,7 +404,6 @@ try {
else {
# Check if this is a DELETE operation (**del..., **delvals)
# For DELETE operations, "Key not found" means SUCCESS (key was deleted or never existed)
$registryCounter++
if ($setting.ValueName -like "**del*") {
$results.Verified++
$registryPassed += [PSCustomObject]@{
@ -475,7 +473,6 @@ try {
else {
# Check if this is a DELETE operation (**del..., **delvals)
# For DELETE operations, "Value not found" means SUCCESS (value was deleted or never existed)
$registryCounter++
if ($setting.ValueName -like "**del*") {
$results.Verified++
$registryPassed += [PSCustomObject]@{
@ -500,7 +497,6 @@ try {
else {
# Check if this is a DELETE operation (**del..., **delvals)
# For DELETE operations, "Key not found" means SUCCESS (key was deleted or never existed)
$registryCounter++
if ($setting.ValueName -like "**del*") {
$results.Verified++
$registryPassed += [PSCustomObject]@{