Click here to Skip to main content
13,251,605 members (86,646 online)
Click here to Skip to main content
Add your own
alternative version

Stats

12.6K views
905 downloads
39 bookmarked
Posted 9 Jan 2017

The Secrets of Wi-Fi Credentials

, 9 Jan 2017
Rate this:
Please Sign up or sign in to vote.
The article focuses on Wi-Fi stored credentials and how they can easily be fetched and decrypted.

Introduction

When you connect to a Wifi network and choose to save the credentials, they can be later fetched not only by Windows but by anyone who knows where and how to look for them. We developed a small utility named GetWifiData for the purpose of displaying any stored Wifi data. We will maintain this tool and publish updates in a dedicated web site.  See also How Skype account details can be obtained.

Purpose of the article

In the past (Windows XP), credentials were stored in the Registry, however since Windows 7, the credentials are stored in separate XML files. The Native Wifi also provides a centralized way to access the credentials, while Windows Cryptography provides the necessities to decrypt the encryption keys back. Several articles were published about Wifi credentials but some of them are outdated which is why I wrote this article and created the utility to display all stored Wifi credentials.  

How Wifi Credentials are stored

When you connect to a Wifi network and choose to save the credentials, they can be later fetched not only by Windows but by anyone who knows where and how to look for them.

The location is different among different versions of Windows.

On Windows XP that place would be under the following Registry location:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WZCSVC\Parameters\Interfaces\

On Windows Vista, 7, 8, 8.1 and 10 that place would be in a file (not in the Registry)

C:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\{Random-GUID}.xml

Under each interface you can find separate files per each stored network.

Windows Native Wifi

The more recent Windows “Native Wifi” provides a better way to access the Wifi credentials as it is the front end of any API call to automatically configure component configures, to connect or disconnect from / to a Wifi network. Further, Windows Native Wifi can store profiles on the networks it interacts with in the form of XML documents.

The source code of this article uses a simple method to fetch each element from these XML files and to generate a report of all stored Wifi credentials.

We initilize our program as follow:

WLAN_INTERFACE_INFO_LIST* pWirelessAdapterList = NULL;
dwResult = WlanEnumInterfaces(hWlan, NULL, &pWirelessAdapterList);
if (dwResult != ERROR_SUCCESS)
{
    WlanCloseHandle(hWlan, NULL);
    return result;
}

int nResCount = 1;
WLAN_INTERFACE_INFO* pWirelessAdapterInfo = NULL;

Interpretation of the XML credential files

Let's take a sample credential file as an example. The file name is:

C:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces\{9D0E4D68-B83A-4745-8021-DE4381E509BF}\{5094B710-D0BF-473A-BC7D-A51D4885F681}.xml

 As you can see in the photo above, the file holds the credentials of a Wifi network named Villa_Carriagehouse from a great B&B hotel in Indinapolis. We stayed there several months ago (great hotel, by the way) so the credentials are stored in my PC and can be fetched, as you can see.

 

 

Going back to our topic...

Windows uses the WLAN_profile Schema to define each WLAN's profile using the following XML elements:

 

SSID - Both plain text and HEX versions can be found and contain the SSID of a wireless LAN.

name - The 'name' element is the SSID in the form of plan text.

authentication - The 'authentication' element specifies the authentication method to be used. 

encryption - The 'encryption' element specifies the type of data encryption to be used.

keyMaterial - The 'keyMaterial' element contains a network key or passphrase. If the protected element has a value of TRUE, then this key material is encrypted; otherwise, the key material is unencrypted. Encrypted key material is expressed in hexadecimal form.

How Wi-Fi credentials can be decrypted

When the Wi-Fi credentials are encrypted, they can be decrypted using Windows Cryptography. Microsoft cryptographic technologies include CryptoAPI, Cryptographic Service Providers (CSP), CryptoAPI Tools, CAPICOM, WinTrust, issuing and managing certificates, and developing customizable public key infrastructures. 

First, we need to locate an element named keyMaterial and isolate it into a string variable (strKey).

Given strKey is a CString variable holding an encrypted Wi-Fi credential key (pass code), the following code block uses CryptUnprotectedData to decrypt it back.

BYTE byteKey[1024] = { 0 };
DWORD dwLength = 1024;
DATA_BLOB dataOut, dataVerify;

BOOL bRes = CryptStringToBinary(strKey, strKey.GetLength(), CRYPT_STRING_HEX, byteKey, &dwLength, 0, 0);

if (bRes)
{
        dataOut.cbData = dwLength;
        dataOut.pbData = (BYTE*)byteKey;

        if (CryptUnprotectData(&dataOut, NULL, NULL, NULL, NULL, 0, &dataVerify))
        {
                TCHAR str[MAX_PATH] = { 0 };
                wsprintf(str, L"%hs", dataVerify.pbData);
                strKey = str;
        }
}

As a result, strKey will hold now the decrypted password for the given Wi-Fi network.

Wrapping up

Now, all we need to do is to go over each Wi-Fi / Network interface and per each interface go over each XML profile and fetch the Wi-Fi credentials of that profile, all into one report on screen and in a file.

To do so, here are some helper functions we use at Secured Globe, Inc

Logging using WriteStatus()

We use logging for several purposes and in most cases we want to see anything important that happens, on a Console window (even with UI based applications) as well as in a text file (the 'log') which can be used later.

void WriteStatus(LPCTSTR lpText, ...)
{
    FILE *fp;
    CTime Today = CTime::GetCurrentTime();
    CString sMsg;
    CString sLine;
    va_list ptr;
    va_start(ptr, lpText);
    sMsg.FormatV(lpText, ptr);

    sLine.Format(L"%s",(LPCTSTR)sMsg);
    _wfopen_s(&fp, utilsLogFilename, L"a");
    if (fp)
    {
        fwprintf(fp, L"%s", sLine);
        fclose(fp);
    }
    wprintf(L"%s", sMsg);
}

 

Basically, instead of using printf (or wprintf) you just call WriteStatus with the same arguments. 

The output of the GetWifiData program is generated using this function.

Ensuring Administration privileges

Such program requires Administrator privileges. That can be achieved first by forcing the user to elevate. 

Go to the project's properties. Then go to Linker -> Manifest File -> UAC Execution Level, and set the value to requireAdministrator (/level='requireAdministrator').

In addition, there is a way to detect the execution level during runtime. We use the following function:

BOOL IsElevated()
{
    DWORD dwSize = 0;
    HANDLE hToken = NULL;
    BOOL bReturn = FALSE;

    TOKEN_ELEVATION tokenInformation;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
        return FALSE;

    if (GetTokenInformation(hToken, TokenElevation, &tokenInformation, sizeof(TOKEN_ELEVATION), &dwSize))
    {
        bReturn = (BOOL)tokenInformation.TokenIsElevated;
    }

    CloseHandle(hToken);
    return bReturn;
}

Then you can warn the user in case the program isn't running "As Administrator" which isn't really needed given the project's settings described herein, but for the purpose of describing the IsElevated() function, I placed the following line in our source code:

if (!IsElevated()) WriteStatus(L"[!] Running without administrative rights\n");

Displaying output using a fancy Console window

For the purpose of showing the program's output during runtime, without having to wait for the log file, we use the following functions and functionalities:

To get the Desktop measures for the purpose of resizing the console to fit the maximum size possible (larger size = more data to be displayed), we use the following function:

void GetDesktopResolution(int& horizontal, int& vertical)
{
    RECT desktop;
    // Get a handle to the desktop window
    const HWND hDesktop = GetDesktopWindow();
    // Get the size of screen to the variable desktop
    GetWindowRect(hDesktop, &desktop);
    // The top left corner will have coordinates (0,0)
    // and the bottom right corner will have coordinates
    // (horizontal, vertical)
    horizontal = desktop.right;
    vertical = desktop.bottom;
}

Then we control the color of the text using the following function:

#define LOG_COLOR_WHITE 7
#define LOG_COLOR_GREEN 10
#define LOG_COLOR_YELLOW 14 
#define LOG_COLOR_MAGENTA 13
#define LOG_COLOR_CIAN 11

void SetColor(int ForgC)
{
    WORD wColor;
    static int LastColor = -1;
    if (LastColor == ForgC) return;
    LastColor = ForgC;
    //This handle is needed to get the current background attribute

    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    //csbi is used for wAttributes word

    if (GetConsoleScreenBufferInfo(hStdOut, &csbi))
    {
        //To mask out all but the background attribute, and to add the color
        wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
        SetConsoleTextAttribute(hStdOut, wColor);
    }
    return;
}

Of course this is only an example and you can define other colors and set more combinations of foreground and background colors to fit your needs.

Then to combine all together here is an example:

SetColor(LOG_COLOR_CIAN);
if (!IsElevated()) WriteStatus(L"[!] Running without administrative rights\n");
WriteStatus(L"WiFi Stored Credentials Report\nproduced by GetWifiData, by Secured Globe, Inc.\n\n");
SetColor(LOG_COLOR_MAGENTA);
WriteStatus(L"http://www.securedglobe.com\n\n\n");
SetColor(LOG_COLOR_CIAN);

The source code

This article is accompanied with a Visual Studio 2013 Ultimate, c++ project. The source code is independent and generates a single executable that can run on its own with no external DLLs needed and no pre-installation required.

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Michael Haephrati
CEO Secured Globe, Inc.
United States United States
Michael Haephrati, is an entrepreneur, inventor and a musician. Haephrati worked on many ventures starting from HarmonySoft, designing Rashumon, the first Graphical Multi-lingual word processor for Amiga computer. During 1995-1996 he worked as a Contractor with Apple at Cupertino. Worked at a research institute made the fist steps developing the credit scoring field in Israel. He founded Target Scoring and developed a credit scoring system named ThiS, based on geographical statistical data, participating VISA CAL, Isracard, Bank Leumi and Bank Discount (Target Scoring, being the VP Business Development of a large Israeli institute).

During 2000, he founded Target Eye, and developed the first remote PC surveillance and monitoring system, named Target Eye.


Other ventures included: Data Cleansing (as part of the DataTune system which was implemented in many organizations.



You may also be interested in...

Comments and Discussions

 
GeneralDidn't realize it was that simple! Pin
DaveAuld14-Jan-17 18:55
protectorDaveAuld14-Jan-17 18:55 
GeneralRe: Didn't realize it was that simple! Pin
Michael Haephrati30-Jan-17 12:53
professionalMichael Haephrati30-Jan-17 12:53 
QuestionGood article ! Pin
Flaviu211-Jan-17 1:31
memberFlaviu211-Jan-17 1:31 
GeneralMy vote of 5 Pin
Member 1236439010-Jan-17 23:38
memberMember 1236439010-Jan-17 23:38 
QuestionGreat Pin
Member 129414589-Jan-17 4:41
memberMember 129414589-Jan-17 4:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.171114.1 | Last Updated 9 Jan 2017
Article Copyright 2017 by Michael Haephrati
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid