How to Extract Saved WiFi Passwords in Python

Learn how you can extract Wi-Fi passwords that are saved in your machine (either Windows or Linux) using Python without installing any third-party library.
  · 5 min read · Updated nov 2021 · Ethical Hacking


Wi-Fi is used to connect to multiple networks at different places, your machine has a way to store the Wi-Fi password so the next time you connect, you don't have to re-type it again.

In this tutorial, you will learn how you can make a quick Python script to extract saved Wi-Fi passwords in either Windows or Linux machines.

We won't need any third-party library to be installed, as we'll be using interacting with netsh in Windows, and the NetworkManager folder in Linux. Importing the libraries:

import subprocess
import os
import re
from collections import namedtuple
import configparser

Getting Wi-Fi Passwords on Windows

On Windows, to get all the Wi-Fi names (ssids), we use the netsh wlan show profiles command, below function uses subprocess to call that command and parses it into Python:

def get_windows_saved_ssids():
    """Returns a list of saved SSIDs in a Windows machine using netsh command"""
    # get all saved profiles in the PC
    output = subprocess.check_output("netsh wlan show profiles").decode()
    ssids = []
    profiles = re.findall(r"All User Profile\s(.*)", output)
    for profile in profiles:
        # for each SSID, remove spaces and colon
        ssid = profile.strip().strip(":").strip()
        # add to the list
        ssids.append(ssid)
    return ssids

We're using regular expressions to find the network profiles. Next, we can use show profile [ssid] key=clear in order to get the password of that network:

def get_windows_saved_wifi_passwords(verbose=1):
    """Extracts saved Wi-Fi passwords saved in a Windows machine, this function extracts data using netsh
    command in Windows
    Args:
        verbose (int, optional): whether to print saved profiles real-time. Defaults to 1.
    Returns:
        [list]: list of extracted profiles, a profile has the fields ["ssid", "ciphers", "key"]
    """
    ssids = get_windows_saved_ssids()
    Profile = namedtuple("Profile", ["ssid", "ciphers", "key"])
    profiles = []
    for ssid in ssids:
        ssid_details = subprocess.check_output(f"""netsh wlan show profile "{ssid}" key=clear""").decode()
        # get the ciphers
        ciphers = re.findall(r"Cipher\s(.*)", ssid_details)
        # clear spaces and colon
        ciphers = "/".join([c.strip().strip(":").strip() for c in ciphers])
        # get the Wi-Fi password
        key = re.findall(r"Key Content\s(.*)", ssid_details)
        # clear spaces and colon
        try:
            key = key[0].strip().strip(":").strip()
        except IndexError:
            key = "None"
        profile = Profile(ssid=ssid, ciphers=ciphers, key=key)
        if verbose >= 1:
            print_windows_profile(profile)
        profiles.append(profile)
    return profiles

def print_windows_profile(profile):
    """Prints a single profile on Windows"""
    print(f"{profile.ssid:25}{profile.ciphers:15}{profile.key:50}")

First, we call our get_windows_saved_ssids() to get all the SSIDs we connected to before, we then initialize our namedtuple to include ssid, ciphers and the key. We call the show profile [ssid] key=clear for each SSID extracted, we parse the ciphers and the key (password), and print it with the simple print_windows_profile() function.

Let's call this function now:

def print_windows_profiles(verbose):
    """Prints all extracted SSIDs along with Key on Windows"""
    print("SSID                     CIPHER(S)      KEY")
    print("-"*50)
    get_windows_saved_wifi_passwords(verbose)

So print_windows_profiles() prints all SSIDs along with the cipher and key (password).

Getting Wi-Fi Passwords on Linux

On Linux, it's different, in the /etc/NetworkManager/system-connections/ directory, all previously connected networks are located here as INI files, we just have to read these files and print them in a nice format:

def get_linux_saved_wifi_passwords(verbose=1):   
    """Extracts saved Wi-Fi passwords saved in a Linux machine, this function extracts data in the
    `/etc/NetworkManager/system-connections/` directory
    Args:
        verbose (int, optional): whether to print saved profiles real-time. Defaults to 1.
    Returns:
        [list]: list of extracted profiles, a profile has the fields ["ssid", "auth-alg", "key-mgmt", "psk"]
    """
    network_connections_path = "/etc/NetworkManager/system-connections/"
    fields = ["ssid", "auth-alg", "key-mgmt", "psk"]
    Profile = namedtuple("Profile", [f.replace("-", "_") for f in fields])
    profiles = []
    for file in os.listdir(network_connections_path):
        data = { k.replace("-", "_"): None for k in fields }
        config = configparser.ConfigParser()
        config.read(os.path.join(network_connections_path, file))
        for _, section in config.items():
            for k, v in section.items():
                if k in fields:
                    data[k.replace("-", "_")] = v
        profile = Profile(**data)
        if verbose >= 1:
            print_linux_profile(profile)
        profiles.append(profile)
    return profiles


def print_linux_profile(profile):
    """Prints a single profile on Linux"""
    print(f"{str(profile.ssid):25}{str(profile.auth_alg):5}{str(profile.key_mgmt):10}{str(profile.psk):50}") 

As mentioned, we're using os.listdir() on that directory to list all files, we then use configparser to read the INI file, and iterate over the items, if we find the fields we're interested in, we simply include them in our data.

There is other information, but we're sticking to the SSID, auth-alg, key-mgmt and psk (password). Next, let's call the function now:

def print_linux_profiles(verbose):
    """Prints all extracted SSIDs along with Key (PSK) on Linux"""
    print("SSID                     AUTH KEY-MGMT  PSK")
    print("-"*50)
    get_linux_saved_wifi_passwords(verbose)

Finally, let's make a function that calls either print_linux_profiles() or print_windows_profiles() based on our OS:

def print_profiles(verbose=1):
    if os.name == "nt":
        print_windows_profiles(verbose)
    elif os.name == "posix":
        print_linux_profiles(verbose)
    else:
        raise NotImplemented("Code only works for either Linux or Windows")
    
    
if __name__ == "__main__":
    print_profiles()

Running the script:

$ python get_wifi_passwords.py

Output on my Windows machine:

SSID                     CIPHER(S)      KEY
--------------------------------------------------
OPPO F9                  CCMP/GCMP      [email protected]
TP-Link_83BE_5G          CCMP/GCMP      0xxxxxxx
Access Point             CCMP/GCMP      super123
HUAWEI P30               CCMP/GCMP      00055511
ACER                     CCMP/GCMP      20192019
HOTEL VINCCI MARILLIA    CCMP           01012019
Bkvz-U01Hkkkkkzg         CCMP/GCMP      00000011
nadj                     CCMP/GCMP      burger010
Griffe T1                CCMP/GCMP      110011110111111
BIBLIO02                 None           None
AndroidAP                CCMP/GCMP      185338019mbs
ilfes                    TKIP           25252516
Point                    CCMP/GCMP      super123

And this is the Linux output:

SSID                     AUTH KEY-MGMT  PSK
--------------------------------------------------
KNDOMA                   open wpa-psk   5060012009690
TP-LINK_C4973F           None None      None
None                     None None      None
Point                    open wpa-psk   super123
Point                    None None      None

Conclusion

Alright, that's it for this tutorial. I'm sure this is a piece of useful code for you to quickly get the saved Wi-Fi passwords on your machine.

Check the full code here.

Learn also: How to Extract Chrome Passwords in Python

Happy coding ♥

View Full Code
Sharing is caring!



Read Also




Comment panel