涂鸦 T5+ hashcat 自动化破解 WPA2:从单缺 M2 到全自动值守的踩坑实录 破解wifi 密码

涂鸦 T5(ESP32-S3)抓 WPA2 握手 + 显卡 hashcat 自动化破解------全链路实战复盘

合规声明:本文所有操作仅在我自有/已获授权的家庭网络上进行。对未经授权的网络实施监听、去认证攻击、密码破解在大多数国家和地区属于违法行为。请读者仅将本文用于学习无线安全原理与防御目的。

一、效果一览(TL;DR)

环节 结果
目标 家庭热点(SSID:602W / 602陈,WPA2-PSK)
抓包硬件 涂鸦 T5 开发板(ESP32-S3),约 ¥20
破解硬件 笔记本 RTX 5060 Laptop GPU
最终结果 抓到完整 M1+M2 握手后,显卡 14 秒 跑出密码 12345678
显卡实测速度 486.0 kH/s (独显)/ 504.5 kH/s(含核显合计)

一句话原理:单片机负责"偷听 + 踢人",显卡负责"猜密码"。全程不碰路由器本身,只听空气里的无线电波,然后离线暴力验证。

二、原理:单片机干什么,显卡干什么

2.1 单片机:监听器 + "踢人"的门卫

普通电脑网卡只收"发给自己的"数据,而 ESP32-S3 的 WiFi 芯片可以切到监听模式(promiscuous mode) ,像一台全频收音机,把锁定信道上空气中所有原始 802.11 帧都收下来。它干三件事:

  1. 扫描定位 :找到目标热点在哪个信道(实测 602W 在信道 4,RSSI -57;602陈 同信道 4,RSSI -50),锁定蹲守;
  2. 踢人(发 deauth 去认证帧) :伪造一个"路由器叫你滚下线"的无线包发给在线设备。设备被踢后手机会自动重连------重连那一刻必须重新走一遍登录流程(四次握手),而这个流程是明文飞在空气里的;
  3. 抓拍:四次握手的帧飞过空气时被它抄下来,通过 USB 串口(115200 波特率)实时传回电脑,存成 pcap 文件。

它解不了任何密,就是个偷听器 + 门卫。电脑网卡在 Windows 上干不了这事(不能监听、不能发原始帧),二十块钱的 ESP32 反而是最顺手的工具。

2.2 显卡:离线验证机

关键点:密码从来不通过空气传输 。握手里飞的是密码算出来的"指纹"(MIC)。所以抓到的东西不能反推出密码,但可以验证任何一个猜测:

text 复制代码
候选密码
   │  PBKDF2-HMAC-SHA1(密码, SSID, 4096 轮迭代)   ← 故意设计得慢
   ▼
  PMK(成对主密钥)
   │  + AP 的 MAC + 手机的 MAC + 两个随机数(ANonce/SNonce)
   ▼
  PTK(临时密钥)→ 取前 16 字节 KCK
   │  用 KCK 对抄下来的 M2 帧算签名
   ▼
  算出的 MIC  vs  空气里抄下来的 MIC
     一样   → 这个候选就是真密码
     不一样 → 换下一个候选

每猜一次要算 4096 轮 SHA-1,CPU 一秒只能试几千个;显卡有几千个核心,同一道题上万份并发一起算(hashcat),速度快两个数量级。

2.3 为什么 M2 是唯一的钥匙

四次握手四个帧,能用来离线验证的只有 M1+M2 这一对:

帧 内容 能否用于破解
M1(AP→设备) ANonce,明文 提供一个随机数
M2(设备→AP) SNonce + MIC 唯一同时带 SNonce 和可验证 MIC 的帧
M3(AP→设备) ANonce + MIC 缺 SNonce
M4(设备→AP) MIC,但 SNonce 字段全零 算不出 PTK

M4 自己把 SNonce 清零了,所以 M3/M4 拿到手也没用。另外本目标的 M1 不带 PMKID(keydata 全空),PMKID 攻击路线也走不通------M2 是唯一的钥匙。这也是整个项目反复卡壳的地方:三次抓包(两次 M1+M3、一次 M1×3+M3+M4)全都单缺 M2。

三、硬件与软件环境

类别 型号/版本
抓包硬件 涂鸦 T5 开发板(ESP32-S3 内核),USB CDC 串口 COM25 @115200
显卡 NVIDIA GeForce RTX 5060 Laptop(8GB)+ Intel UHD 770 核显
固件工具链 PlatformIO Core 6.2.0,esptool(pio 内置 v4.11.0)
破解工具 hashcat 7.1.2(-m 22000 WPA-PBKDF2-PMKID+EAPOL)
脚本语言 Python 3.12 + pyserial

目录结构(工作目录 D:\Desktop\wifi):

text 复制代码
firmware/src/main.cpp   ESP32-S3 嗅探固件(v8)
sniff_capture.py        串口 → pcap 采集
hs_extract.py           pcap → hashcat 22000 哈希(含自测)
watch_m2.py             自动值守:监控 M2 → 提哈希 → 调 GPU → 记录结果
crack_run.py            手动分阶段破解入口
hashcat/hashcat-7.1.2/  hashcat 本体(必须在它自己的目录里运行)
wifi_dict_*.txt 等      密码本若干

四、系统架构

text 复制代码
                    ┌────────────────────────── ESP32-S3(涂鸦 T5)──────────────────────────┐
                    │  扫描定位目标 SSID/BSSID → 锁信道(ch4)                                │
 空气中的 802.11 帧 │  promiscuous 监听 → 只入队 EAPOL 候选帧 + 目标相关管理帧(队列 20 帧)   │
 ─────────────────▶│  学习在线 STA 的 MAC → 周期发 广播+单播 deauth 踢人                      │
                    │  见到 EAPOL 后 4 秒静默不发(防自残撞掉 M2)                            │
                    └───────────────┬──────────────────────────────────────────────────────┘
                                    │ USB 串口 hex 行(带长度+XOR 校验)
                                    ▼
                    ┌────────────────────────── Windows PC ─────────────────────────────────┐
                    │  sniff_capture.py:校验 → 组 pcap(LINKTYPE 105)                      │
                    │  watch_m2.py 每 45 秒轮询 pcap:                                       │
                    │     出现可配对的 M1+M2 → 调 hs_extract 生成 22000 哈希                  │
                    │     → hashcat 11 阶段自动跑(字典→纯数字→手机号)                       │
                    │     → potfile 出现明文 → 写入 找到密码.txt                             │
                    │  (值守还负责:抓包进程死了自动拉起;按 BSSID 从日志取当前 SSID)        │
                    └───────────────────────────────────────────────────────────────────────┘

五、固件设计(v7 → v8)

5.1 v7 诊断版:全链路计数器定位丢帧环节

v7 固件的核心是每 10 秒打一行全链路计数,把 M2 丢失环节定位到具体一段:

text 复制代码
MSG cb=258596 badrx=0 mgmt=0 data=13242 eapol=0 m2=0 qdrop=0 printed=0 deauth=4599 uni=2292 stas=0
    │      │         │        │         │       │      │         │         │       └ 在线 STA 数
    │      │         │        │         │       │      │         └────── 单播 deauth 数
    │      │         │        │         │       │      └ 打印帧数
    │      │         │        │         │       └ 队列丢弃
    │      │         │        │         └── 分类为 M2 的帧数 ★核心指标
    │      │         │        └── 通过 BSSID 过滤的数据帧
    │      │         └ 目标相关管理帧
    │      └ FCS 等坏帧
    └ 回调总进入

靠它发现了两个关键事实:data 一直涨但 eapol=0 说明设备根本没掉线重连;另一个热点接口翻转时 data 冻结、stas 归零。

5.2 v8 的三处关键改动

改动一:单播去认证。 v7 只发广播 deauth(收件人 FF:FF:FF:FF:FF:FF),现代手机普遍无视。v8 从通过 BSSID 过滤的数据帧里学习在线 STA 的 MAC (上行看 SA、下行看 DA),对每台设备定点单播踢:

cpp 复制代码
static void learn_sta(const uint8_t* m) {
    if (m[0] & 1) return;          // 广播/组播不算
    if (is_tgt_mac(m)) return;     // AP 自己不算
    // ...LRU 式 8 槽位表,2 分钟内有过数据的才算"在线"
}

// 踢人时:广播 + 对每台在线 STA 单播
send_deauth(tgt_bssid[t], NULL);            // 广播
send_deauth(tgt_bssid[t], sta_mac[i]);      // 单播定点

改动二:握手让路(防自残)。 去认证的发射窗口期间芯片听不到东西;四次握手全程才几十毫秒,v7 的 3 连发 deauth 正好可能蹭掉 M2------前两次抓包就是单缺 M2。v8 检测到目标 EAPOL 后 4 秒静默:

cpp 复制代码
if (now - last_eapol_ms < EAPOL_QUIET_MS) {
    delay(50);   // 握手窗口内让路,不发射
}

改动三:扫描避让。 周期性重扫描要切信道,期间听不到帧。v8 在 EAPOL 活跃后 30 秒内顺延扫描(SCAN_AVOID_MS)。

其余保持 v7:队列 20 帧×400 字节、EAPOL 候选帧带 XOR 校验 hex 输出、逐帧元数据行(速率/MCS/重试/RSSI),输出格式与 PC 端管线完全兼容。

5.3 编译与烧录

bash 复制代码
cd firmware
pio run                                   # RAM 15.3% / Flash 18.6%
pio run -t upload --upload-port COM25     # 623680 字节,约 12.6 秒烧完

六、PC 侧管线

6.1 sniff_capture.py:串口 → pcap

  • 解析固件的 EAPOL/BEACON/MGMT hex 行,长度 + XOR 双校验,坏行丢弃并打印;
  • 写标准 pcap(LINKTYPE_IEEE802_11 = 105),追加模式,进程重启不丢已抓帧;
  • 串口自动探测(不再写死 COM 号):优先原配置口,失败则枚举所有 USB 串口。

6.2 hs_extract.py:pcap → hashcat 22000 哈希

  • 解析四次握手帧,按 keyinfo 位(ACK/MIC/Secure)分类 M1--M4;
  • 配对同 BSSID + 同 STA 的 M1+M2,生成 hashcat 22000 行:
text 复制代码
WPA*02*<MIC 32 hex>*<mac_ap>*<mac_sta>*<essid hex>*<anonce>*<eapol(MIC清零)>*00
  • 踩过并修掉的 bug:固件对部分非 QoS 数据帧在 LLC 头前多带 2 字节填充,固定按 24 字节帧头解析会漏帧(一次 M3 就是这样丢的)。修复为 24/26 两种偏移都探测 LLC SNAP 头;
  • 自带 --selftest:用已知密码合成握手 → 生成哈希 → hashcat 12 秒解出,验证整条链路。

6.3 watch_m2.py:自动值守

每 45 秒轮询一次 pcap,全自动闭环:

  1. 出现可配对的 M1+M2(且排除自家那台输错过密码的手机 MAC)→ 生成哈希文件;
  2. 依次跑 11 个 hashcat 阶段(见第七节),独立 potfile,每阶段日志落盘;
  3. potfile 出现明文 → 写入 找到密码.txt,全程事件 + 10 分钟心跳写入 watchdog.log;
  4. 自愈:抓包进程不在了自动重新拉起(PID 文件 + OpenProcess 探活,2 分钟退避);
  5. SSID 盐映射 :SSID 是 WPA 哈希的盐,热点会改名(602陈 ↔ 602W,两个 BSSID),脚本从固件日志的 target 行按 BSSID 取当前 SSID,否则密码对了也解不出来。

值守进程本身用 WMI Win32_Process.Create 启动(见踩坑 3)。

七、破解阶段与字典规模

11 个阶段按"性价比"排序,命中即停:

# 阶段 内容 量级
01 字典 wifi_dict_all.txt 1,042,860
02 字典 rockyou.txt 14,344,391
03 字典 dict_master.txt 1,919,559
04 字典 dict_cn_1m.txt 1,000,000
05 字典 dict_letter.txt 47,603
06 掩码 6 位纯数字 ?d?d?d?d?d?d 100 万
07 掩码 7 位纯数字 1,000 万
08 掩码 8 位纯数字 1 亿
09 掩码 9 位纯数字 10 亿
10 掩码 11 位手机号 -1 3456789,1?1?d?d?d?d?d?d?d?d?d 70 亿
11 掩码 10 位纯数字 100 亿

全部密码本合计 19,588,441 行(去重前)。

八、性能实测(RTX 5060 Laptop,-m 22000)

实测方法:改一个字节 SSID 盐构造"永不可能命中"的哈希,跑完整 rockyou 读速度行。

设备 速度
RTX 5060 Laptop(独显) 486.0 kH/s ≈ 48.6 万次/秒
Intel UHD 770(核显) 18,535 H/s
合计 504.5 kH/s ≈ 50 万次/秒

注意"一次"= 完整走一遍 PBKDF2-HMAC-SHA1 4096 轮 + PRF + MIC 计算,相当于每秒约 20 亿次 SHA-1 运算 。14,344,391 条的 rockyou 实测 20 秒跑完。

换算成攻击耗时(按 48.6 万次/秒):

密码空间 数量级 耗时
6 位纯数字 10⁶ ~2 秒
7 位纯数字 10⁷ ~21 秒
8 位纯数字 10⁸ ~3.4 分钟
9 位纯数字 10⁹ ~34 分钟
11 位手机号 7×10⁹ ~4 小时
10 位纯数字 10¹⁰ ~5.7 小时

结论很直白:纯数字密码在现代消费级显卡面前等于裸奔;字母+数字混合到 10 位以上、或用长随机密码,才是安全的。

九、踩坑清单

实战中踩过的坑,按时间线:

  1. 假阳性握手 :输错密码的手机也会算一个"签名"发出去,被显卡解出来的是你输错的那个数(本例中是 99999999)。判断标准:只发了 M2、没有 M3/M4 的握手大概率是失败尝试;真正联网成功的设备才会有 M3/M4。
  2. 结论只对单条握手有效:"已排除 8 位纯数字"只对当时那条握手成立,换了新握手(新设备/新密码)必须全部重跑。
  3. 后台进程静默死亡 :从终端 Start-Process 启动的后台 Python 进程,会随命令结束被作业对象(Job Object)连带回收,日志戛然而止、无任何报错。解法:用 WMI Win32_Process.Create 启动脱离作业对象,并在值守脚本里加进程自愈。
  4. hashcat 找不到 OpenCL 内核 :它按相对路径找 ./OpenCL/,必须在 hashcat 自己的目录里运行(或设 cwd),否则秒退。
  5. 广播 deauth 被 PMF 无视 :对一台在线设备发了 2200+ 个单播 deauth 它都不掉线(data 照涨),基本可断定开了 PMF(802.11w)。此时主动踢人失效,只能等设备自然重连(锁屏唤醒、断流重试、热点开关都会触发)。
  6. 去认证发射窗口撞掉 M2:见 5.2 改动二。
  7. SSID 是哈希的盐 :热点改名(602陈↔602W)会导致用旧 SSID 提的哈希永远解不出来。必须按 BSSID 动态取当前 SSID。
  8. 帧头长度想当然:非 QoS 数据帧的 LLC 头前可能多 2 字节填充,解析要按 LLC SNAP 魔数探测偏移而不是固定 24。
  9. 串口号会变:重新插拔/烧录后 COM 号可能漂移,采集脚本要自动探测。

十、实战结果

时间线(全部真实数据):

text 复制代码
09-28 01:47  抓到自己手机输错密码的握手 → 解出 99999999(假阳性,排除)
09-28 09:13  抓到设备 fc:ab:d0:c5:73:99 的 M1+M3×4(缺 M2)
09-28 11:53  抓到设备 48:45:e6:6c:71:43 的 M1×3+M3+M4(缺 M2)
09-30 12:24  烧录 v8 固件:单播 deauth 生效(stas=1, uni 递增)
09-30 13:18  热点接口翻转(602W → 602陈),在线设备被甩下线(stas 1→0)
09-30 15:56:24  设备回连,v8 抓到完整 M1+M2 → 自动生成哈希
09-30 15:56:38  RTX 5060 从 104 万字典中解出密码(14 秒)

potfile 记录:

text 复制代码
9ee0e9128048e907b6ca12d58b29c51b:7ac62b24e63e:fcabd0c57399:602W:12345678

可靠性判据:发 M2 的那台设备在此前(09-28 09:13)就成功完成过认证(抓到过它的 M3),说明它手机里存的是真密码,MIC 数学验证通过------排除了踩坑 1 的假阳性情形。

十一、延伸:为什么 WPA3 不怕这套

  • 防离线猜测:WPA3-SAE 的握手设计使抓到的帧无法用来离线验证候选密码,显卡这套"猜+验"直接失效;
  • PMF/802.11w:加密管理帧,伪造 deauth 被丢弃------本项目踩坑 5 已实际观察到;
  • 防御建议:路由器开 WPA3(或 WPA2/WPA3 过渡)、开 PMF、密码 12 位以上随机组合、关闭 WPS。

本文基于真实家庭网络授权测试整理,文中 MAC/SSID 等信息已获家人同意发布。

相关推荐
天远API7 小时前
零信任架构实战:基于天远运营商三要素简版V即时版查询构建自动化司乘安全绑定网关
人工智能·安全·架构·自动化
꯭自꯭闭꯭8 小时前
达梦SQL优化相关
linux·运维·数据库·sql
ZhangJun958 小时前
在 32GB 内存电脑上本地搭建 Qwen3.6-35B-A3B 大模型踩坑实录
运维·人工智能·阿里云·ai·软件构建
一条破秋裤9 小时前
Linux 共享内存通信:POSIX 共享内存与 mmap
linux·运维·服务器
贵州山魈羡民9 小时前
【玩转手机】通过 Podroid 上的 Alpine 部署 1Panel,把微型服务器装进口袋
运维·服务器
小白的码BUG之路9 小时前
Docker -- 构建nacos镜像
运维·docker·容器
谷哥的小弟10 小时前
CentOS Stream浴火重生
linux·运维·centos
FPGA小徐11 小时前
STM32五路气敏传感器阵列电路详解:从HHC1000分压到AD8606跟随器和ADC采样
stm32·单片机·嵌入式硬件
程序员-Benothing11 小时前
Shell输入输出详解:read、echo、printf、颜色输出
linux·运维·服务器