Introduction
We shall only focus on versions of Windows from Vista up to 10 since the location of wireless credentials prior to this are stored in the registry.
Enumerate Interfaces
C:\>reg query HKLM\SOFTWARE\Microsoft\Wlansvc\Interfaces HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{012C8D7D-D104-47F8-83FE-B9751F699A2F} HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{12487653-A815-4A9D-84E1-736D96554215} HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{13ECC539-1C25-4036-9615-D85A5D1B47CE} HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{295A80EE-8DC0-465F-ACF2-70DA1F036948} HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{3306C2A4-E4A5-42B3-A087-67EB542F0EC0} HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{40F69FB8-F23A-433E-94D9-D3983F220874} HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{66BA1985-E08C-4F57-9E36-2C229EB1BFCE} HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{6E318579-A15B-43AA-BC85-5A38133888A6} HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{AFEED710-CC5E-41BD-8975-E6EE0487B5C9} HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{F6B2D705-CCA4-439D-B7AF-4950A98CE00C}
To perform this programatically in C.
DWORD EnumInterfaces(VOID) { HKEY hSubKey; DWORD dwError, dwIndex, cbSize; WCHAR adapterGuid[256], profileList[4096*4]; PWCHAR pProfileGuid; std::wstring description; dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Wlansvc\\Interfaces", 0, KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &hSubKey); if (dwError != ERROR_SUCCESS) { xstrerror(L"RegOpenKeyEx(\"SOFTWARE\\Microsoft\\Wlansvc\\Interfaces\""); return 0; } dwIndex = 0; for (;;) { cbSize = sizeof(adapterGuid) / sizeof(wchar_t); dwError = RegEnumKeyEx(hSubKey, dwIndex, adapterGuid, &cbSize, NULL, NULL, NULL, NULL); if (dwError != ERROR_SUCCESS) break; if (dwError == ERROR_SUCCESS) { description = GetAdapterDescription(adapterGuid); cbSize = sizeof(profileList) / sizeof(wchar_t); dwError = RegGetValue(hSubKey, adapterGuid, L"ProfileList", RRF_RT_REG_MULTI_SZ, 0, profileList, &cbSize); if (dwError == ERROR_SUCCESS) { pProfileGuid = profileList; wprintf(L"\n\n %s %s", description.c_str(), adapterGuid); wprintf(L"\n %-20s %-10s %-20s %-64s %-20s", std::wstring(20, L'-').c_str(), std::wstring(10, L'-').c_str(), std::wstring(20, L'-').c_str(), std::wstring(20, L'-').c_str(), std::wstring(20, L'-').c_str()); wprintf(L"\n %-20s %-10s %-20s %-64s %-20s", L"SSID", L"Auth", L"Encryption", L"Key(Ascii)", L"Key(Hex)"); wprintf(L"\n %-20s %-10s %-20s %-64s %-20s", std::wstring(20, L'-').c_str(), std::wstring(10, L'-').c_str(), std::wstring(20, L'-').c_str(), std::wstring(20, L'-').c_str(), std::wstring(20, L'-').c_str()); for (;;) { DumpWLANProfile(adapterGuid, pProfileGuid); pProfileGuid += wcslen(pProfileGuid) + 1; if (pProfileGuid[0] == 0) break; } } } dwIndex++; } RegCloseKey(hSubKey); return 0; }
Each GUID represents a unique wireless adapter. To obtain a textual representation of this, we need to look at
reg query HKLM\SYSTEM\Select HKEY_LOCAL_MACHINE\SYSTEM\Select Current REG_DWORD 0x2 Default REG_DWORD 0x2 Failed REG_DWORD 0x1 LastKnownGood REG_DWORD 0x3
If we take the first GUID from the WLAN interfaces and query it.
C:\>reg query "HKLM\SYSTEM\ControlSet002\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{012C8D7D-D104-47F8-83FE-B9751F699A2F}\Connection HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{012C8D7D-D104-47F8-83FE-B9751F699A2F}\Connection DefaultNameResourceId REG_DWORD 0x70e DefaultNameIndex REG_DWORD 0x6 Name REG_SZ Wireless Network Connection 6 PnpInstanceID REG_SZ {5D624F94-8850-40C3-A3FA-A4FD2080BAF3}\VWIFIMP\7&79A56D7&0&03 MediaSubType REG_DWORD 0x2
The PnpInstanceID
C:\>reg query "HKLM\SYSTEM\ControlSet002\Enum\{5D624F94-8850-40C3-A3FA-A4FD2080BAF3}\VWIFIMP\7&79A56D7&0&03" HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Enum\{5D624F94-8850-40C3-A3FA-A4FD2080BAF3}\VWIFIMP\7&79A56D7&0&03 DeviceDesc REG_SZ @netvwifimp.inf,%vwifimp.devicedesc%;Microsoft Virtual WiFi Miniport Adapter LocationInformation REG_SZ VWiFi Bus 0 Capabilities REG_DWORD 0xa0 UINumber REG_DWORD 0x3 HardwareID REG_MULTI_SZ {5d624f94-8850-40c3-a3fa-a4fd2080baf3}\vwifimp CompatibleIDs REG_MULTI_SZ {5d624f94-8850-40c3-a3fa-a4fd2080baf3}\vwifimp ContainerID REG_SZ {df3771ea-c60e-5fae-9656-83aa71808f29} ConfigFlags REG_DWORD 0x0 ClassGUID REG_SZ {4d36e972-e325-11ce-bfc1-08002be10318} Driver REG_SZ {4d36e972-e325-11ce-bfc1-08002be10318}\0023 FriendlyName REG_SZ Microsoft Virtual WiFi Miniport Adapter #3 Class REG_SZ Net Mfg REG_SZ @netvwifimp.inf,%msft%;Microsoft Service REG_SZ vwifimp HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Enum\{5D624F94-8850-40C3-A3FA-A4FD2080BAF3}\VWIFIMP\7&79A56D7&0&03\Device Parameters HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Enum\{5D624F94-8850-40C3-A3FA-A4FD2080BAF3}\VWIFIMP\7&79A56D7&0&03\LogConf HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Enum\{5D624F94-8850-40C3-A3FA-A4FD2080BAF3}\VWIFIMP\7&79A56D7&0&03\Properties
Programatically in C
std::wstring GetAdapterDescription(std::wstring guid) { static DWORD dwCtrlIdx = 0; LSTATUS lStatus; DWORD cbSize; std::wstring description = L"<unavailable>"; wchar_t path[1024], pnpInstance[1024], deviceDesc[1024]; PWCHAR pDesc; if (dwCtrlIdx == 0) { cbSize = sizeof(DWORD); lStatus = SHGetValue(HKEY_LOCAL_MACHINE, L"SYSTEM\\Select", L"Default", 0, &dwCtrlIdx, &cbSize); if (lStatus != ERROR_SUCCESS) { dwCtrlIdx = 1; } } _snwprintf(path, sizeof(path) / sizeof(wchar_t), L"SYSTEM\\ControlSet%03i\\Control\\Network\\" L"{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", dwCtrlIdx, guid.c_str()); cbSize = sizeof(pnpInstance) / sizeof(wchar_t); lStatus = SHGetValue(HKEY_LOCAL_MACHINE, path, L"PnpInstanceID", 0, pnpInstance, &cbSize); if (lStatus == ERROR_SUCCESS) { _snwprintf(path, 1024, L"SYSTEM\\ControlSet%03i\\Enum\\%s", dwCtrlIdx, pnpInstance); cbSize = sizeof(deviceDesc) / sizeof(wchar_t); lStatus = SHGetValue(HKEY_LOCAL_MACHINE, path, L"DeviceDesc", 0, &deviceDesc, &cbSize); pDesc = wcsrchr(deviceDesc, L';'); if (pDesc != 0) { description = ++pDesc; } } return description; }
So there we have the description of adapter, and how to get profiles?
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{012C8D7D-D104-47F8-83FE-B9751F699A2F}" HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{012C8D7D-D104-47F8-83FE-B9751F699A2F} PortType REG_DWORD 0x2 ProfileList REG_MULTI_SZ {AC1D44A3-9444-43E8-8496-E998433A5188} Parameters REG_BINARY 0000000001000000010000000000000003000000 Scan Interval REG_BINARY 60EA0000 Fail To Reset Time REG_BINARY 60EA0000 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wlansvc\Interfaces\{012C8D7D-D104-47F8-83FE-B9751F699A2F}\Profiles
This profile list contains a string which corresponds to a file stored on disk with the profile.
dir C:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces Volume in drive C has no label. Volume Serial Number is CFED-1E13 Directory of C:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces 07/01/2017 02:25 PM . 07/01/2017 02:25 PM .. 09/30/2015 11:54 PM {012C8D7D-D104-47F8-83FE-B9751F699A2F} 02/08/2015 10:31 AM {12487653-A815-4A9D-84E1-736D96554215} 01/26/2016 12:13 AM {13ECC539-1C25-4036-9615-D85A5D1B47CE} 04/15/2016 07:34 PM {295A80EE-8DC0-465F-ACF2-70DA1F036948} 09/10/2015 07:50 PM {3306C2A4-E4A5-42B3-A087-67EB542F0EC0} 04/15/2016 07:21 PM {40F69FB8-F23A-433E-94D9-D3983F220874} 07/23/2013 06:54 PM {6E318579-A15B-43AA-BC85-5A38133888A6} 07/01/2017 02:25 PM {AFEED710-CC5E-41BD-8975-E6EE0487B5C9}
Programming in C
void DumpWLANProfile( wchar_t adapterGuid[], wchar_t profileGuid[]) { wchar_t path[MAX_PATH]; wchar_t programData[MAX_PATH]; HRESULT hr; CComPtr<IXMLDOMDocument2> pDoc; VARIANT_BOOL bIsSuccessful; SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, programData); _snwprintf(path, MAX_PATH, L"%s\\Microsoft\\Wlansvc\\Profiles\\Interfaces\\%s\\%s.xml", programData, adapterGuid, profileGuid); hr = CoInitialize(NULL); if (FAILED(hr)) { wprintf(L"\nCoInitialize() failed : %08x", hr); return; } hr = CoCreateInstance(CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&pDoc); if (SUCCEEDED(hr)) { hr = pDoc->load(CComVariant(path), &bIsSuccessful); if (SUCCEEDED(hr) && bIsSuccessful) { profile_properties(pDoc, 0); profile_properties(pDoc, 1); } else { wprintf(L"\n IXMLDOMDocument2->load() failed : %08x", hr); } pDoc = NULL; } else { wprintf(L"\n CoCreateInstance() failed : %08x", hr); } CoUninitialize(); }
There are 2 different name space
// required to parse WLAN profiles #define WLAN_NS L"xmlns:s=\"http://www.microsoft.com/networking/WLAN/profile/v1\"" #define WLANAP_NS L"xmlns:s=\"http://www.microsoft.com/networking/WLANAP/profile/v1\"" void profile_properties(CComPtr<IXMLDOMDocument2> pDoc, DWORD idx) { PWCHAR xml[2]={WLAN_NS, WLANAP_NS}; PWCHAR profiles[2]={L"WLANProfile", L"WLANAPProfile"}; HRESULT hr; CComVariant ns; PWCHAR pt; std::wstring ssid, auth, enc, key; ns = xml[idx]; pt = profiles[idx]; hr = pDoc->setProperty(BSTR(L"SelectionNamespaces"), ns); if (SUCCEEDED(hr)) { ssid = get_text(pDoc, pt, L"/s:SSIDConfig/s:SSID/s:name"); auth = get_text(pDoc, pt, L"/s:MSM/s:security/s:authEncryption/s:authentication"); enc = get_text(pDoc, pt, L"/s:MSM/s:security/s:authEncryption/s:encryption"); key = get_text(pDoc, pt, L"/s:MSM/s:security/s:sharedKey/s:keyMaterial"); if (!ssid.empty()) { wprintf(L"\n %-20s %-10s %-20s", ssid.c_str(), auth.c_str(), enc.c_str()); if (!key.empty()) { DecryptKey(key); } } } else { wprintf(L"\n IXMLDOMDocument2->setProperty() failed : %08x", hr); } ns = NULL; }
Demonstration
Source code
Requires MSVC with support for ATL to compile. See here.
Can you please reupload the source code or at least the DecryptKey() function or tell me how to decrypt the password?
LikeLike
It’s on github now.
LikeLike