Как извлечь сохраненные пароли WiFi в Python

Как вы, возможно, уже знаете, Wi-Fi используется в разных местах для подключения к нескольким сетям, и на вашем компьютере определенно есть способ где-то хранить пароль Wi‑Fi, поэтому при следующем подключении вам не приходится повторно вводить его снова.

Здесь вы узнаете, как быстро создать скрипт Python для извлечения сохраненного пароля Wi‑Fi на компьютерах с Windows или Linux.

Нам не потребуется установка какой-либо сторонней библиотеки, так как мы будем использовать netsh в Windows и анализ папки NetworkManager в Linux. Импорт библиотек:

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

Получение паролей Wi‑Fi в Windows

В Windows, чтобы получить все имена Wi‑Fi (ssids), используем команду ОС netsh wlan show profiles, функция ниже использует subprocess() для вызова этой команды и анализирует результат её выполнения в Python:

def get_windows_saved_ssids():
    """Возвращает список сохраненных SSID на машине Windows с помощью команды netsh"""
    # получить все сохраненные профили на ПК
    output = subprocess.check_output("netsh wlan show profiles").decode()
    ssids = []
    profiles = re.findall(r"Весь профиль пользователя\s(.*)", output)
    for profile in profiles:
        # для каждого SSID удалите пробелы и двоеточие
        ssid = profile.strip().strip(":").strip()
        # добавить в список
        ssids.append(ssid)
    return ssids

Используем регулярные выражения для поиска сетевых профилей. Затем можно использовать show profile [ssid] key = clear для получения пароли сети:

def get_windows_saved_wifi_passwords(verbose=1):
    """Извлекает сохраненные пароли Wi‑Fi на машине Windows, эта функция извлекает данные с помощью netsh
    команды в Windows
    Аргументы:
        verbose (int, optional): whether to print saved profiles real-time. Defaults to 1.
    Результат:
        [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()
        # получить шифры
        ciphers = re.findall(r"Cipher\s(.*)", ssid_details)
        # очистить пробелы и двоеточие
        ciphers = "/".join([c.strip().strip(":").strip() for c in ciphers])
        # получить пароль Wi‑Fi
        key = re.findall(r"Key Content\s(.*)", ssid_details)
        # очистить пробелы и двоеточие
        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):
    """Печать одного профиля в Windows"""
    print(f"{profile.ssid:25}{profile.ciphers:15}{profile.key:50}")

Сначала вызываем наш get_windows_saved_ssids(), чтобы получить все SSID, к которым мы подключались ранее, затем инициализируем наш namedtuple, чтобы включить ssid, ciphers и key. Вызываем show profile [ssid] key=clear для каждого извлеченного SSID и анализируем шифры и ключ (пароль), распечатываем его с помощью простой функции print_windows_profile().

Сейчас запишем эту функцию:

def print_windows_profiles(verbose):
    """Печатает все извлеченные SSID вместе с ключом в Windows"""
    print("SSID                     CIPHER(S)      KEY")
    print("-"*50)
    get_windows_saved_wifi_passwords(verbose)

Итак, print_windows_profiles() печатает все SSID вместе с шифром и ключом (паролем).

Получение паролей Wi‑Fi в Linux

В Linux все по-другому, информация о всех ранее подключенных сетях находится в каталоге /etc/NetworkManager/system-connections/ в виде файлов INI, нам просто нужно прочитать эти файлы и распечатать их в удобном формате:

def get_linux_saved_wifi_passwords(verbose=1):   
    """Извлекает сохраненные пароли Wi‑Fi на машине Linux, эта функция извлекает данные в каталоге `/etc/NetworkManager/system-connections/`
    Аргументы:
        verbose (int, optional): whether to print saved profiles real-time. Defaults to 1.
    Результат:
        [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):
    """Печатает один профиль в Linux"""
    print(f"{str(profile.ssid):25}{str(profile.auth_alg):5}{str(profile.key_mgmt):10}{str(profile.psk):50}") 

Как уже упоминалось, мы вызываем os.listdir() в этом каталоге для вывода списка всех файлов, затем используем configparser для чтения файла INI и перебираем элементы, если мы находим поля, которые нам интересны, просто добавляем их в наши данные.

В файлах INI есть и другая информация, но нас интересует только SSID, auth-alg, key-mgmt и psk(password). Далее запишем функцию печати:

def print_linux_profiles(verbose):
    """Печатает все извлеченные SSID вместе с ключом (PSK) в Linux"""
    print("SSID                     AUTH KEY-MGMT  PSK")
    print("-"*50)
    get_linux_saved_wifi_passwords(verbose)

Наконец, запишем функцию, которая вызывает print_linux_profiles() или print_windows_profiles() в зависимости от нашей ОС:

def print_profiles(verbose=1):
    if os.name == "nt":
        print_windows_profiles(verbose)
    elif os.name == "posix":
        print_linux_profiles(verbose)
    else:
        raise NotImplemented("Код работает только для ОС Linux или Windows")
    
    
if __name__ == "__main__":
    print_profiles()

Запускаем скрипт:

$ python get_wifi_passwords.py

Вывод на моей машине с Windows:

SSID                     CIPHER(S)      KEY
--------------------------------------------------
OPPO F9                  CCMP/GCMP      0120123489@
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

И это результат на Linux:

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

Заключение

Хорошо, и всё на сегоня. Я уверен, что для вас это полезный код и вы сможете быстро получить сохраненные пароли Wi‑Fi на своём компьютере.

Посмотрие полный код.

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


def get_windows_saved_ssids():
    """Возвращает список сохраненных SSID на машине Windows с помощью команды netsh"""
    # получить все сохраненные профили на ПК
    output = subprocess.check_output("netsh wlan show profiles").decode()
    ssids = []
    profiles = re.findall(r"Весь профиль пользователя\s(.*)", output)
    for profile in profiles:
        # для каждого SSID удалите пробелы и двоеточие
        ssid = profile.strip().strip(":").strip()
        # добавить в список
        ssids.append(ssid)
    return ssids


def get_windows_saved_wifi_passwords(verbose=1):
    """Извлекает сохраненные пароли Wi‑Fi на машине Windows, эта функция извлекает данные с помощью netsh
    команды в Windows
    Аргумены:
        verbose (int, optional): whether to print saved profiles real-time. Defaults to 1.
    Результат:
        [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()
        # получить шифры
        ciphers = re.findall(r"Cipher\s(.*)", ssid_details)
        # убрать пробелы и двоеточие
        ciphers = "/".join([c.strip().strip(":").strip() for c in ciphers])
        # получить пароль Wi‑Fi
        key = re.findall(r"Key Content\s(.*)", ssid_details)
        # убрать пробелы и двоеточие
        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):
    """Печать одного профиля в Windows"""
    print(f"{profile.ssid:25}{profile.ciphers:15}{profile.key:50}")


def print_windows_profiles(verbose):
    """Печатает все извлеченные SSID вместе с ключом в Windows"""
    print("SSID                     CIPHER(S)      KEY")
    get_windows_saved_wifi_passwords(verbose)


def get_linux_saved_wifi_passwords(verbose=1):   
    """Извлекает сохраненные пароли Wi‑Fi на машине Linux, эта функция извлекает данные в каталоге `/etc/NetworkManager/system-connections/`
    Аргументы:
        verbose (int, optional): whether to print saved profiles real-time. Defaults to 1.
    Результат:
        [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):
    """Печатает один профиль в Linux"""
    print(f"{str(profile.ssid):25}{str(profile.auth_alg):5}{str(profile.key_mgmt):10}{str(profile.psk):50}") 


def print_linux_profiles(verbose):
    """Печатает все извлеченные SSID вместе с ключом (PSK) в Linux"""
    print("SSID                     AUTH KEY-MGMT  PSK")
    get_linux_saved_wifi_passwords(verbose)
    
    
def print_profiles(verbose=1):
    if os.name == "nt":
        print_windows_profiles(verbose)
    elif os.name == "posix":
        print_linux_profiles(verbose)
    else:
        raise NotImplemented("Код работает только для ОС Linux or Windows")
    
    
if __name__ == "__main__":
    print_profiles()

По мотивам How to Extract Saved WiFi Passwords in Python

Print Friendly, PDF & Email

CC BY-NC 4.0 Как извлечь сохраненные пароли WiFi в Python, опубликовано К ВВ, лицензия — Creative Commons Attribution-NonCommercial 4.0 International.


Респект и уважуха

Добавить комментарий