| 1 | <# |
| 2 | .SYNOPSIS |
| 3 | Analyzes Windows Wi-Fi profiles to extract SSID, Security, and Certificate Trust details. |
| 4 | |
| 5 | .DESCRIPTION |
| 6 | This tool provides a detailed analysis of Wi-Fi connection profiles, specifically focusing on |
| 7 | Enterprise (802.1X) security settings. It extracts the Trusted Root CA Thumbprint, Server |
| 8 | Name constraints, and validates if the required certificates are present in the local machine store. |
| 9 | |
| 10 | It operates in three modes: |
| 11 | 1. Interactive Mode: select from a menu of saved profiles. |
| 12 | 2. Direct Mode: Analyze a specific profile by name. |
| 13 | 3. File Mode: Analyze an existing XML profile file. |
| 14 | |
| 15 | .EXAMPLE |
| 16 | .\Get-Wifi-Profile-Analyzer.ps1 -Interactive |
| 17 | Launches a menu to select a Wi-Fi profile. |
| 18 | |
| 19 | .EXAMPLE |
| 20 | .\Get-Wifi-Profile-Analyzer.ps1 -ProfileName "ContosoWLAN" |
| 21 | Analyzes the "ContosoWLAN" profile directly. |
| 22 | #> |
| 23 | |
| 24 | [CmdletBinding(DefaultParameterSetName="ShowHelp")] |
| 25 | param( |
| 26 | # Mode 1: Interactive Menu |
| 27 | [Parameter(ParameterSetName="Interactive", Mandatory=$true)] |
| 28 | [switch]$Interactive, |
| 29 | |
| 30 | # Mode 2: Direct System Profile |
| 31 | [Parameter(ParameterSetName="ByName", Mandatory=$true, Position=0)] |
| 32 | [string]$ProfileName, |
| 33 | |
| 34 | # Mode 3: Analyze an existing XML file |
| 35 | [Parameter(ParameterSetName="ByFile", Mandatory=$true, Position=0)] |
| 36 | [Alias("ProfilePath")] |
| 37 | [string]$Path |
| 38 | ) |
| 39 | |
| 40 | # --- HELPER 1: CORE XML ANALYSIS --- |
| 41 | function Analyze-WifiProfileXml { |
| 42 | param ([xml]$XmlProfile, [string]$SourceName) |
| 43 | |
| 44 | Write-Host "==================================================" -ForegroundColor Cyan |
| 45 | Write-Host " WI-FI PROFILE ANALYZER: $($XmlProfile.WLANProfile.name)" -ForegroundColor Cyan |
| 46 | Write-Host "==================================================" -ForegroundColor Cyan |
| 47 | Write-Host "Source: $SourceName`n" |
| 48 | |
| 49 | # --- PART 1: GENERAL SETTINGS --- |
| 50 | Write-Host "--- General Wi-Fi Settings ---" -ForegroundColor Yellow |
| 51 | |
| 52 | # Extract standard fields (safe navigation) |
| 53 | $SSIDName = $XmlProfile.WLANProfile.SSIDConfig.SSID.name |
| 54 | $ConnType = $XmlProfile.WLANProfile.connectionType |
| 55 | $ConnMode = $XmlProfile.WLANProfile.connectionMode |
| 56 | $AutoSwitch = $XmlProfile.WLANProfile.autoSwitch |
| 57 | |
| 58 | Write-Host "SSID Name: $SSIDName" |
| 59 | Write-Host "Network Type: $ConnType" |
| 60 | Write-Host "Connection Mode: $ConnMode" |
| 61 | Write-Host "Auto-Connect: $AutoSwitch" |
| 62 | |
| 63 | # --- PART 2: SECURITY BASICS --- |
| 64 | Write-Host "`n--- Security Basics ---" -ForegroundColor Yellow |
| 65 | |
| 66 | $AuthAlgo = $XmlProfile.WLANProfile.MSM.security.authEncryption.authentication |
| 67 | $Cipher = $XmlProfile.WLANProfile.MSM.security.authEncryption.encryption |
| 68 | $UseOneX = $XmlProfile.WLANProfile.MSM.security.authEncryption.useOneX |
| 69 | $AuthMode = $XmlProfile.WLANProfile.MSM.security.OneX.authMode |
| 70 | |
| 71 | Write-Host "Authentication: $AuthAlgo" |
| 72 | Write-Host "Encryption: $Cipher" |
| 73 | Write-Host "802.1X Enabled: $UseOneX" |
| 74 | if ($AuthMode) { Write-Host "Auth Mode: $AuthMode" } |
| 75 | |
| 76 | # --- PART 3: ADVANCED TRUST SETTINGS --- |
| 77 | if ($UseOneX -eq "true") { |
| 78 | Write-Host "`n--- Certificate Trust & EAP Settings ---" -ForegroundColor Yellow |
| 79 | |
| 80 | # 1. Trusted Root CA Hash |
| 81 | $RootCANodes = $XmlProfile.GetElementsByTagName("TrustedRootCA") |
| 82 | if ($RootCANodes.Count -gt 0) { |
| 83 | $RawHash = $RootCANodes[0].InnerText |
| 84 | $CleanHash = $RawHash -replace '\s','' |
| 85 | |
| 86 | Write-Host "Trusted Root CA (Thumbprint):" |
| 87 | Write-Host " $CleanHash" -ForegroundColor Green |
| 88 | |
| 89 | # --- LOOKUP CERTIFICATE --- |
| 90 | Write-Host " ...Checking local store..." -NoNewline |
| 91 | |
| 92 | $CertPaths = @("Cert:\LocalMachine\Root", "Cert:\LocalMachine\CA", "Cert:\LocalMachine\My", "Cert:\CurrentUser\Root") |
| 93 | $CertFound = $null |
| 94 | |
| 95 | foreach ($CertPath in $CertPaths) { |
| 96 | if (Test-Path $CertPath) { |
| 97 | $CertFound = Get-ChildItem -Path $CertPath -ErrorAction SilentlyContinue | Where-Object { $_.Thumbprint -eq $CleanHash } | Select-Object -First 1 |
| 98 | if ($CertFound) { break } |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | if ($CertFound) { |
| 103 | Write-Host " FOUND in $($CertFound.PSParentPath.Split('\')[-1])" -ForegroundColor Green |
| 104 | Write-Host " Subject: $($CertFound.Subject)" |
| 105 | Write-Host " Issuer: $($CertFound.Issuer)" |
| 106 | Write-Host " Expires: $($CertFound.NotAfter)" |
| 107 | if ($CertFound.NotAfter -lt (Get-Date)) { |
| 108 | Write-Host " STATUS: ❌ EXPIRED" -ForegroundColor Red |
| 109 | } else { |
| 110 | Write-Host " STATUS: ✅ Valid" -ForegroundColor Green |
| 111 | } |
| 112 | } else { |
| 113 | Write-Host " NOT FOUND on this machine." -ForegroundColor Red |
| 114 | Write-Host " (Profile trusts this hash, but cert is missing)" |
| 115 | } |
| 116 | } else { |
| 117 | Write-Host "Trusted Root CA: Not explicitly defined (May use system defaults)" -ForegroundColor DarkGray |
| 118 | } |
| 119 | |
| 120 | # 2. Server Name Constraints |
| 121 | $ServerNameNodes = $XmlProfile.GetElementsByTagName("ServerNames") |
| 122 | if ($ServerNameNodes.Count -gt 0) { |
| 123 | Write-Host "`nServer Name Constraint:" |
| 124 | Write-Host " $($ServerNameNodes[0].InnerText)" -ForegroundColor Green |
| 125 | } else { |
| 126 | Write-Host "`nServer Name Constraint: None" -ForegroundColor DarkGray |
| 127 | } |
| 128 | |
| 129 | # 3. Validation Flags |
| 130 | $ValidationNodes = $XmlProfile.GetElementsByTagName("PerformServerValidation") |
| 131 | if ($ValidationNodes.Count -gt 0) { |
| 132 | Write-Host "`nPerform Server Validation:" |
| 133 | Write-Host " $($ValidationNodes[0].InnerText)" |
| 134 | } |
| 135 | } else { |
| 136 | Write-Host "`n(No EAP/Certificate settings to analyze for non-Enterprise networks)" |
| 137 | } |
| 138 | Write-Host "`n==================================================" -ForegroundColor Cyan |
| 139 | } |
| 140 | |
| 141 | # --- HELPER 2: EXPORT AND PROCESS SYSTEM PROFILE --- |
| 142 | function Process-SystemProfile { |
| 143 | param ([string]$Name) |
| 144 | |
| 145 | # Create temp folder |
| 146 | $TempDir = Join-Path $env:TEMP "WifiProfileExport_$(Get-Random)" |
| 147 | New-Item -ItemType Directory -Path $TempDir -Force | Out-Null |
| 148 | |
| 149 | try { |
| 150 | # Export profile |
| 151 | $ExportResult = netsh wlan export profile name="$Name" folder="$TempDir" | Out-String |
| 152 | $ExportedFile = Get-ChildItem -Path $TempDir -Filter "*.xml" | Select-Object -First 1 |
| 153 | |
| 154 | if ($ExportedFile) { |
| 155 | [xml]$XmlData = Get-Content -Path $ExportedFile.FullName -Raw |
| 156 | Analyze-WifiProfileXml -XmlProfile $XmlData -SourceName "System Profile (Live Export)" |
| 157 | } else { |
| 158 | Write-Error "Failed to export profile '$Name'. Verify the name and ensure you have Administrator rights (required for GPO profiles)." |
| 159 | } |
| 160 | } |
| 161 | finally { |
| 162 | # Cleanup |
| 163 | Remove-Item -Path $TempDir -Recurse -Force -ErrorAction SilentlyContinue |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | # --- MAIN LOGIC --- |
| 168 | |
| 169 | if ($PSCmdlet.ParameterSetName -eq "ByFile") { |
| 170 | # MODE A: Parsing an existing file |
| 171 | if (-not (Test-Path $Path)) { |
| 172 | Write-Error "File not found: $Path" |
| 173 | return |
| 174 | } |
| 175 | [xml]$XmlData = Get-Content -Path $Path -Raw |
| 176 | Analyze-WifiProfileXml -XmlProfile $XmlData -SourceName "XML File ($Path)" |
| 177 | |
| 178 | } elseif ($PSCmdlet.ParameterSetName -eq "ByName") { |
| 179 | # MODE B: Exporting Specific System Profile |
| 180 | Process-SystemProfile -Name $ProfileName |
| 181 | |
| 182 | } elseif ($PSCmdlet.ParameterSetName -eq "Interactive") { |
| 183 | # MODE C: Interactive Menu |
| 184 | Write-Host "`nScanning system for Wi-Fi profiles..." -ForegroundColor Cyan |
| 185 | |
| 186 | $NetshOutput = netsh wlan show profiles |
| 187 | $ProfileList = @() |
| 188 | |
| 189 | # 1. Capture Standard Profiles (Format: " All User Profile : Name") |
| 190 | $StandardProfiles = $NetshOutput | Select-String -Pattern "All User Profile\s*:\s*(.+)$" |
| 191 | if ($StandardProfiles) { |
| 192 | foreach ($item in $StandardProfiles) { |
| 193 | $ProfileList += $item.Matches.Groups[1].Value.Trim() |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | # 2. Capture GPO/Other Profiles (Format: " Name" - just indented, no key:value) |
| 198 | $GpoCandidates = $NetshOutput | Where-Object { |
| 199 | $_ -match "^\s{2,}" -and # Must be indented |
| 200 | $_ -notmatch ":" -and # No colon (avoids 'Key : Value' lines) |
| 201 | $_ -notmatch "-{3,}" -and # No separator lines (-----) |
| 202 | $_ -notmatch "<None>" -and # No empty indicators |
| 203 | $_ -notmatch "Profiles on" -and |
| 204 | $_ -notmatch "Group policy" -and |
| 205 | $_ -notmatch "User profiles" |
| 206 | } |
| 207 | |
| 208 | if ($GpoCandidates) { |
| 209 | foreach ($line in $GpoCandidates) { |
| 210 | $cleanName = $line.Trim() |
| 211 | if (-not [string]::IsNullOrWhiteSpace($cleanName)) { |
| 212 | $ProfileList += $cleanName |
| 213 | } |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | # Remove duplicates and sort |
| 218 | # WRAPPER: @(...) ensures this remains an array even if 1 result exists |
| 219 | $ProfileList = @($ProfileList | Select-Object -Unique | Sort-Object) |
| 220 | |
| 221 | if ($ProfileList.Count -eq 0) { |
| 222 | Write-Warning "No Wi-Fi profiles found on this system." |
| 223 | return |
| 224 | } |
| 225 | |
| 226 | # Display Menu |
| 227 | Write-Host "`nSelect a profile to analyze:" -ForegroundColor Yellow |
| 228 | $i = 1 |
| 229 | foreach ($P in $ProfileList) { |
| 230 | Write-Host " [$i] $P" |
| 231 | $i++ |
| 232 | } |
| 233 | |
| 234 | # Get User Input |
| 235 | $Selection = Read-Host "`nEnter number (1-$($ProfileList.Count))" |
| 236 | |
| 237 | # Validate and Run |
| 238 | if ($Selection -match "^\d+$" -and $Selection -ge 1 -and $Selection -le $ProfileList.Count) { |
| 239 | $SelectedProfile = $ProfileList[$Selection - 1] |
| 240 | Write-Host "`nAnalyzing '$SelectedProfile'..." -ForegroundColor Cyan |
| 241 | Process-SystemProfile -Name $SelectedProfile |
| 242 | } else { |
| 243 | Write-Error "Invalid selection." |
| 244 | } |
| 245 | |
| 246 | } else { |
| 247 | # MODE D: Show Help (Default) |
| 248 | Write-Host "==================================================" -ForegroundColor Cyan |
| 249 | Write-Host " WI-FI PROFILE ANALYZER HELP" -ForegroundColor Cyan |
| 250 | Write-Host "==================================================" -ForegroundColor Cyan |
| 251 | Write-Host "`nThis tool analyzes Wi-Fi profiles to show Security and Certificate Trust details." |
| 252 | |
| 253 | Write-Host "`n[OPTION 1] Interactive Menu (Recommended)" -ForegroundColor Yellow |
| 254 | Write-Host " Usage: .\Get-Wifi-Profile-Analyzer.ps1 -Interactive" |
| 255 | |
| 256 | Write-Host "`n[OPTION 2] Analyze by Name" -ForegroundColor Yellow |
| 257 | Write-Host " Usage: .\Get-Wifi-Profile-Analyzer.ps1 -ProfileName `"ContosoWLAN`"" |
| 258 | |
| 259 | Write-Host "`n[OPTION 3] Analyze Exported File" -ForegroundColor Yellow |
| 260 | Write-Host " Usage: .\Get-Wifi-Profile-Analyzer.ps1 -Path `"C:\Temp\Profile.xml`"" |
| 261 | |
| 262 | Write-Host "`n--------------------------------------------------" -ForegroundColor DarkGray |
| 263 | Write-Host "HANDY MANUAL COMMANDS (NETSH)" -ForegroundColor DarkGray |
| 264 | Write-Host "--------------------------------------------------" -ForegroundColor DarkGray |
| 265 | Write-Host " > To list all profiles on your PC:" |
| 266 | Write-Host " netsh wlan show profiles" -ForegroundColor White |
| 267 | |
| 268 | Write-Host "`n > To manually export a profile to XML:" |
| 269 | Write-Host " netsh wlan export profile name=`"ContosoWLAN`" folder=`".`"" -ForegroundColor White |
| 270 | |
| 271 | Write-Host "`n==================================================" -ForegroundColor Cyan |
| 272 | } |
ergosteur / Windows PowerShell Wifi Profile Analyzer
Last active 1 month ago
PowerShell script that analyzes Windows Wi-Fi profiles to extract SSID, Security, and Certificate Trust details.