Created
August 25, 2025 07:02
-
-
Save c7x43t/cf52cd594a7ad6c25c6d3570af27da42 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| Windows 11 Enterprise Post-Stripdown Security Audit | |
| Author: you + ChatGPT | |
| Run as: Administrator (recommended) | |
| Outputs: concise table + per-item details | |
| #> | |
| $results = New-Object System.Collections.Generic.List[object] | |
| function Add-Result($Feature, $Status, $Details) { | |
| $results.Add([pscustomobject]@{ | |
| Feature = $Feature | |
| Status = $Status | |
| Details = $Details | |
| }) | |
| } | |
| # Helper: Service status | |
| function Get-Svc($name){ | |
| try { (Get-Service -Name $name -ErrorAction Stop).Status } catch { "NotFound" } | |
| } | |
| # Helper: Optional feature state | |
| function Get-FeatureState($featureName){ | |
| try { | |
| $f = Get-WindowsOptionalFeature -Online -FeatureName $featureName -ErrorAction Stop | |
| return $f.State | |
| } catch { "NotFound" } | |
| } | |
| # ----- OS / Edition ----- | |
| try { | |
| $prod = (Get-ComputerInfo -Property WindowsProductName,OsName,OsVersion).WindowsProductName | |
| Add-Result "Windows Edition" "Info" $prod | |
| } catch { | |
| Add-Result "Windows Edition" "Unknown" "Could not read edition info." | |
| } | |
| # ----- Secure Boot ----- | |
| try { | |
| $sb = Confirm-SecureBootUEFI -ErrorAction Stop | |
| Add-Result "Secure Boot" ($(if($sb){"On"} else {"Off"})) "UEFI Secure Boot state." | |
| } catch { | |
| Add-Result "Secure Boot" "Unknown" "Not UEFI / unsupported cmdlet / access denied." | |
| } | |
| # ----- TPM 2.0 ----- | |
| try { | |
| $tpm = Get-Tpm | |
| $ver = ($tpm.SpecVersion -split ',')[0].Trim() | |
| $tpmState = if($tpm.TpmPresent){ if($tpm.TpmReady){"Ready"} else {"Present-NotReady"} } else {"NotPresent"} | |
| Add-Result "TPM" $tpmState "SpecVersion: $ver" | |
| } catch { | |
| Add-Result "TPM" "Unknown" "Get-Tpm failed." | |
| } | |
| # ----- BitLocker ----- | |
| try { | |
| $bl = Get-BitLockerVolume | |
| foreach($v in $bl){ | |
| $drive = $v.MountPoint | |
| $prot = if($v.ProtectionStatus -eq 'On'){'Protected'} else {'NotProtected'} | |
| $pct = if($v.EncryptionPercentage -ne $null){ "$($v.EncryptionPercentage)%" } else { "n/a" } | |
| Add-Result "BitLocker ($drive)" $prot "VolumeStatus: $($v.VolumeStatus); Encryption: $pct" | |
| } | |
| } catch { | |
| Add-Result "BitLocker" "Unknown" "Get-BitLockerVolume failed." | |
| } | |
| # ----- Defender AV core ----- | |
| try { | |
| $mp = Get-MpComputerStatus | |
| $flags = @() | |
| if($mp.AMServiceEnabled){ $flags += "AMService" } | |
| if($mp.AntivirusEnabled){ $flags += "Antivirus" } | |
| if($mp.RealTimeProtectionEnabled){ $flags += "RealTime" } | |
| if($mp.BehaviorMonitorEnabled){ $flags += "BehaviorMon" } | |
| $status = if($flags.Count -gt 0){"On"} else {"Off"} | |
| Add-Result "Microsoft Defender AV" $status ("Enabled: " + ($flags -join ", ")) | |
| } catch { | |
| Add-Result "Microsoft Defender AV" "Unknown" "Get-MpComputerStatus failed (service removed/disabled?)." | |
| } | |
| # ----- Firewall ----- | |
| try { | |
| $fp = Get-NetFirewallProfile | |
| foreach($p in $fp){ | |
| Add-Result "Firewall ($($p.Name))" ($(if($p.Enabled){"On"}else{"Off"})) ("DefaultInbound: " + $p.DefaultInboundAction + "; DefaultOutbound: " + $p.DefaultOutboundAction) | |
| } | |
| } catch { | |
| Add-Result "Windows Firewall" "Unknown" "Get-NetFirewallProfile failed." | |
| } | |
| # ----- SmartScreen (Explorer-level) ----- | |
| try { | |
| $ss = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer" -ErrorAction Stop).SmartScreenEnabled | |
| # Values: "RequireAdmin", "Warn", "Off" | |
| $map = @{ "RequireAdmin"="On(RequireAdmin)"; "Warn"="On(Warn)"; "Off"="Off" } | |
| $val = if($map.ContainsKey($ss)){$map[$ss]} else {"Unknown:$ss"} | |
| Add-Result "SmartScreen (Apps/Downloads)" $val "HKLM:\...\Explorer\SmartScreenEnabled" | |
| } catch { | |
| Add-Result "SmartScreen (Apps/Downloads)" "Unknown" "Registry value missing (possibly stripped)." | |
| } | |
| # ----- ASR (Attack Surface Reduction) ----- | |
| try { | |
| $pref = Get-MpPreference | |
| $actions = $pref.AttackSurfaceReductionRules_Actions | |
| $ids = $pref.AttackSurfaceReductionRules_Ids | |
| if($actions -and $ids){ | |
| # Map counts | |
| # Actions: 0=Disabled, 1=Block, 2=Audit, 6=Warn | |
| $counts = @{ Disabled=0; Block=0; Audit=0; Warn=0 } | |
| for($i=0;$i -lt $actions.Count;$i++){ | |
| switch([int]$actions[$i]){ | |
| 0 { $counts.Disabled++ } | |
| 1 { $counts.Block++ } | |
| 2 { $counts.Audit++ } | |
| 6 { $counts.Warn++ } | |
| default { } | |
| } | |
| } | |
| $summary = "Block:$($counts.Block) Audit:$($counts.Audit) Warn:$($counts.Warn) Disabled:$($counts.Disabled)" | |
| $status = if($counts.Block -gt 0 -or $counts.Warn -gt 0 -or $counts.Audit -gt 0){"Configured"} else {"NotConfigured"} | |
| Add-Result "Attack Surface Reduction (ASR)" $status $summary | |
| } else { | |
| Add-Result "Attack Surface Reduction (ASR)" "NotConfigured" "No ASR rules present." | |
| } | |
| } catch { | |
| Add-Result "Attack Surface Reduction (ASR)" "Unknown" "Get-MpPreference failed." | |
| } | |
| # ----- Controlled Folder Access ----- | |
| try { | |
| $pref2 = Get-MpPreference | |
| # EnableControlledFolderAccess: 0=Off, 1=On, 2=Audit | |
| $cfa = $pref2.EnableControlledFolderAccess | |
| $cfaStatus = switch ($cfa) { 1 {"On"} 2 {"Audit"} default {"Off"} } | |
| Add-Result "Controlled Folder Access" $cfaStatus ("ProtectedFolders: " + ($pref2.ControlledFolderAccessProtectedFolders -join "; ")) | |
| } catch { | |
| Add-Result "Controlled Folder Access" "Unknown" "Get-MpPreference failed or property missing." | |
| } | |
| # ----- VBS/Credential Guard/HVCI ----- | |
| try { | |
| $dg = Get-CimInstance -ClassName Win32_DeviceGuard | |
| $svcsCfg = $dg.SecurityServicesConfigured | |
| $svcsRun = $dg.SecurityServicesRunning | |
| # 1=CredentialGuard, 2=HVCI, 3=SecureKernel | |
| $mapSvc = @{ 1="CredentialGuard"; 2="HVCI"; 3="SecureKernel" } | |
| $cfgList = @(); foreach($n in $svcsCfg){ if($mapSvc.ContainsKey($n)){$cfgList+= $mapSvc[$n]} } | |
| $runList = @(); foreach($n in $svcsRun){ if($mapSvc.ContainsKey($n)){$runList+= $mapSvc[$n]} } | |
| $vbsState = switch ($dg.VirtualizationBasedSecurityStatus) { 0{"Off"} 1{"Enabled"} 2{"Running"} default {"Unknown"} } | |
| Add-Result "VBS (Virtualization-Based Security)" $vbsState ("Configured: " + ($cfgList -join ", ") + " | Running: " + ($runList -join ", ")) | |
| $cgStatus = if($runList -contains "CredentialGuard"){"On"} else {"Off"} | |
| Add-Result "Credential Guard" $cgStatus ("Configured: " + (($cfgList -contains "CredentialGuard") ? "Yes" : "No")) | |
| $hvciStatus = if($runList -contains "HVCI"){"On"} else {"Off"} | |
| Add-Result "HVCI (Memory Integrity)" $hvciStatus ("Configured: " + (($cfgList -contains "HVCI") ? "Yes" : "No")) | |
| } catch { | |
| Add-Result "VBS / Credential Guard / HVCI" "Unknown" "Win32_DeviceGuard query failed." | |
| } | |
| # ----- AppLocker (Enterprise) ----- | |
| try { | |
| $applXml = Get-AppLockerPolicy -Effective -Xml -ErrorAction Stop | |
| if($applXml -match "<RuleCollection"){ | |
| # AppIDSvc must run for enforcement | |
| $appIdSvc = Get-Svc "AppIDSvc" | |
| Add-Result "AppLocker" "Configured" ("Application Identity service: $appIdSvc") | |
| } else { | |
| Add-Result "AppLocker" "NotConfigured" "No effective rule collections." | |
| } | |
| } catch { | |
| Add-Result "AppLocker" "Unknown" "Cmdlet failed (edition? removed components?)." | |
| } | |
| # ----- WDAC (Application Control / Code Integrity) ----- | |
| try { | |
| # Use registry presence rather than Get-CIPolicy (not always installed) | |
| $ciKey = "HKLM:\SYSTEM\CurrentControlSet\Control\CI\Policy" | |
| if(Test-Path $ciKey){ | |
| $sub = Get-ChildItem $ciKey -ErrorAction SilentlyContinue | |
| $active = if($sub){ "Configured" } else { "NotConfigured" } | |
| Add-Result "WDAC (Code Integrity Policy)" $active "Registry: HKLM:\SYSTEM\CCS\Control\CI\Policy" | |
| } else { | |
| Add-Result "WDAC (Code Integrity Policy)" "NotConfigured" "CI policy key not found." | |
| } | |
| } catch { | |
| Add-Result "WDAC (Code Integrity Policy)" "Unknown" "Registry check failed." | |
| } | |
| # ----- Windows Sandbox / Application Guard ----- | |
| try { | |
| $sandbox = Get-FeatureState "Containers-DisposableClientVM" | |
| Add-Result "Windows Sandbox" $sandbox "Windows Optional Feature state." | |
| } catch { | |
| Add-Result "Windows Sandbox" "Unknown" "Feature query failed." | |
| } | |
| try { | |
| $mdag = Get-FeatureState "Windows-Defender-ApplicationGuard" | |
| Add-Result "Defender Application Guard (Edge)" $mdag "Windows Optional Feature state." | |
| } catch { | |
| Add-Result "Defender Application Guard (Edge)" "Unknown" "Feature query failed." | |
| } | |
| # ----- Key services (post-debloat sanity) ----- | |
| $svcList = @( | |
| @{ Name="WinDefend"; Label="Microsoft Defender AV Service" }, | |
| @{ Name="SecurityHealthService"; Label="Windows Security Center (Health)" }, | |
| @{ Name="wscsvc"; Label="Security Center" }, | |
| @{ Name="Sense"; Label="Microsoft Defender for Endpoint (EDR)" }, | |
| @{ Name="AppIDSvc"; Label="Application Identity (AppLocker)" } | |
| ) | |
| foreach($s in $svcList){ | |
| $state = Get-Svc $s.Name | |
| Add-Result ("Service: " + $s.Label) $state ("ServiceName: " + $s.Name) | |
| } | |
| # ----- Output ----- | |
| # Sort: Bad first (Off/NotProtected/NotConfigured), then On/Configured, then Info | |
| $ordered = $results | Sort-Object { | |
| switch -Regex ($_.Status) { | |
| "^(Off|NotProtected|NotConfigured|NotFound)$" { 0 } | |
| "^(Unknown)$" { 1 } | |
| "^(On|Protected|Configured|Running)$" { 2 } | |
| default { 3 } | |
| } | |
| }, $_.Feature | |
| # Pretty table | |
| $ordered | Format-Table -AutoSize | |
| # Also emit machine-readable JSON to screen (easy to save if needed) | |
| "`n---- JSON ----" | |
| $ordered | ConvertTo-Json -Depth 4 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment