Posted by
Share this article
Windows stores WLAN profile information in the following location.
%SYSTEMDRIVE%\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces\{INTERFACE_GUID}\{PROFILE_GUID}.xml
These files contain information such as the SSID, encryption type, and the encrypted passphrase stored as a HEX encoded string.
<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
<name>Chun-Li</name>
<SSIDConfig>
<SSID>
<hex>4368756E2D4C69</hex>
<name>Chun-Li</name>
</SSID>
</SSIDConfig>
<connectionType>ESS</connectionType>
<connectionMode>manual</connectionMode>
<MSM>
<security>
<authEncryption>
<authentication>WPA2PSK</authentication>
<encryption>AES</encryption>
<useOneX>false</useOneX>
</authEncryption>
<sharedKey>
<keyType>passPhrase</keyType>
<protected>true</protected>
<keyMaterial>01000000D0...snip...DD0F6377F4</keyMaterial>
</sharedKey>
</security>
</MSM>
<MacRandomization xmlns="http://www.microsoft.com/networking/WLAN/profile/v3">
<enableRandomization>false</enableRandomization>
</MacRandomization>
</WLANProfile>
There are two interesting things I noticed.
- The WLAN profiles will persist through a system reboot even when “connect automatically” is unticked when authenticating (this is the connectionMode element)
- The XML files are accessible by all users.
The passphrase is encrypted with the machine credentials using Windows Data Protection API (DPAPI) before being converted to a HEX encoded string. The code block below shows how the plaintext passphrase could be retrieved.
using System;
using System.Text;
using System.Security.Cryptography;
public class WlanDecrypt
{
public static void Main()
{
try
{
string hexEncodedPassword = "01000000D0...snip...DD0F6377F4";
// convert to a byte array
byte[] passwordByteArray = new byte[hexEncodedPassword.Length / 2];
for (int i = 0; i < hexEncodedPassword.Length; i += 2)
passwordByteArray[i / 2] =
Convert.ToByte(hexEncodedPassword.Substring(i, 2), 16);
// decrypt byte array
byte[] unprotectedBytes =
ProtectedData.Unprotect(passwordByteArray, null,
DataProtectionScope.LocalMachine);
string cleartextPassword =
Encoding.ASCII.GetString(unprotectedBytes);
Console.WriteLine(cleartextPassword);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
This is all just to demonstrate the decryption, since the cleartext passphrase can be easily retrieved with netsh, e.g.
![Code 4](/assets/main/Insights-Images/_800xAUTO_crop_center-center_none/Code-4.png)
You can’t retrieve the plaintext passphrase using netsh from the context of a different user, but with access to the profile XML files you could take the HEX string and decrypt it with the ProtectedData class. You could also just use Metasploit or NirSoft WirelessKeyView.
This WLAN_profile XML schema is supported from Windows XP SP3 onwards, where prior to this the passphrases were stored in the registry at the following location.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WZCSVC\Parameters\Interfaces\{INTERFACE_GUID}
In addition, the passphrase here is stored in REG_BINARY format and will require some extra decoding.
References:
- https://docs.microsoft.com/en-us/windows/win32/nativewifi/wlan-profileschema-schema
- https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata
- https://docs.microsoft.com/en-us/windows-server/networking/technologies/netsh/netsh
- https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/wlan/wlan_profile.rb
- http://www.nirsoft.net/utils/wireless_key.html
- https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptbinarytostringa
Contact us
Speak with a Tesserent
Security Specialist
Tesserent is a full-service cybersecurity and secure cloud services provider, partnering with clients from all industries and all levels of government. Let’s talk.
![Tess head 4 min](/assets/template/_650xAUTO_crop_center-center_none/tess-head-4-min.png)