PowerShell-Script Showcase: Get-WifiPassword

Created May 3, 2023

PowerShell is a powerful scripting language that can be used to automate a variety of tasks.

In this blog post, we will explore my Get-WifiPassword script that retrieves stored Wifi passwords on Windows machines. The script overcomes the issue of localization that arises when parsing the output of the 'netsh.exe' command.

To retrieve the stored Wifi passwords, most users rely on the 'netsh.exe' command. This command can be parsed with PowerShell by looking for the 'key content' line and splitting it by ':' to obtain the password of the Wifi profile. However, this approach fails on non-English Windows machines, where the 'key content' line may be labeled differently.

I initially tried to call the 'netsh.exe' command in a consistent language to solve this problem, but this proved unsuccessful. I then sought the help of ChatGPT, which recommended using CIM-Classes. However, this approach also failed, and I decided to analyze the 'netsh.exe' command more closely.

I discovered that the 'netsh.exe' command has an export argument that exports all profiles at once. The output is in the form of several XML files, all in English. This led me to read all the XML files, extract the Wifi-SID and password, and store them as 'pscustomobjects' to output them.

Overall, my Get-WifiPassword script is an excellent example of how to overcome localization issues in PowerShell scripting. By exporting all profiles at once, my script is able to obtain the stored Wifi passwords in a consistent language, regardless of the language of the underlying operating system.

The final script looks like this now:

<#
    .SYNOPSIS
    This function displays all stored WIFI passwords on the client
    .DESCRIPTION
    This function gets the output of netsh command and will trim it to display all SSID`s and also the passwords.
    If a profile has no password it will inform the user.
    .EXAMPLE
    Get-WIFIPassword
#>
function Get-WifiPassword {
    [CmdletBinding()]
    param (
        
    )
    
    begin {
        try {
            # Export all Wifi profiles and collect their XML file paths
            $netshOutput = $(netsh wlan export profile key=clear)
            $XmlFilePaths = foreach($line in $netshOutput){
                if($line -match '\"(.*?\\.*?\.xml)(?=\")'){
                    $matches[1]
                }
            }
        }
        catch {
            Write-Error "Failed to export Wifi profiles: $($_.Exception.Message)"
            return
        }
        
    }
    
    process {
        foreach ($XmlFilePath in $XmlFilePaths) {
            try {
                # Read the XML file and extract the Wifi profile name and password
                $Xml = [xml](Get-Content -Path $XmlFilePath)

                # Output the profile name, password, and whether the operation succeeded
                [PSCustomObject]@{
                    Name = $Xml.WLANProfile.Name
                    Password = $Password = $Xml.WLANProfile.MSM.Security.SharedKey.KeyMaterial
                    Succeed = [bool]$Password
                }
                # Remove the XML file
                Remove-Item $XmlFilePath -ErrorAction Stop
            }
            catch {
                Write-Error "Failed to read Wifi profile from '$XmlFilePath': $($_.Exception.Message)"
            }
        }
    }
    
    end {
        
    }
}

I want to mention that I am aware of the 'wlanapi.dll', which is a C-Library on Windows that could also be used for this task. However, my goal was to keep the script as simple as possible without adding tons of confusing code.

If you have any ideas to improve this script, please feel free to raise an issue on Github, or share them with me on Twitter at Christian Ritter. I am always looking to improve my scripts and welcome any feedback or suggestions.

Best regards,

Christian