简介《两小时破译无线路由器PIN码算法获得路由密码》是一份面向网络安全初学者、无线安全爱好者及教学人员的docx文档围绕WPS PIN码算法漏洞的案例复盘与防护展开。内容涵盖无线信号嗅探所获取的路由器信息、MAC地址与PIN码之间的换算关系、特定MAC地址段产品的受影响范围以及关闭WPS、启用WEP/WAP加密等基础加固思路兼顾原理理解与风险识别。压缩包内仅1个docx文件约191KB篇幅精炼适合作为无线安全入门读物、课堂案例或自查参考。已有1185人学习读者可借此建立对PIN码破解机理、WPS后门风险与无线网络防护要点的整体认识。1. 两小时这个数字是假的真正费时间的是搞懂它为什么成立2012 年那波无线路由器 PIN 码算法破译事件里流传最广的说法是「两小时拿到路由密码」。我把同样的流程在自己的实验路由器上完整跑了一遍掐表算下来从抓到 MAC 地址到算出完整 PIN实际动手时间不到四分钟——剩下那一小时五十六分钟全花在搞清楚它为什么成立、以及为什么换一台设备就立刻不成立。这个反差恰恰是理解无线路由器 PIN 码算法破译的入口它不是一个「技术多强」的问题而是「某几段 OUI 前缀的固件把本该随机的数字写成了可推导的公式」。下面我把 PIN 的位序结构、从 MAC 尾六位到十进制的搬运、脚本化验证的时序以及五条我亲自踩过的坑一条条摆出来。手里有闲置路由器想搞明白这事的新手能照着复现做无线侧评估的熟手能看到每一步的判定依据。2. WPS PIN 的位序结构先把算法拆成一道能验算的算术题2.1 七位还是八位把 PIN 的位序先钉死WPS 规范里的 PIN 是 8 位十进制数字但真正参与比对的是前 7 位第 8 位由前 7 位算出来。这 7 位有效数字的内部划分各家固件实现并不完全一致但公开资料里最常见的分法是前 4 位与 AP 的 OUI、MAC 存在派生关系中间 3 位是出厂写入的随机值末位是校验。当年被破译的那批固件把这个「派生关系」做成了最粗暴的版本——直接取 MAC 地址的最后 6 个十六进制字符转成十进制不足 6 位左边补 0得到一串 6 位数字整段当成 PIN 的高位使用。这就解释了为什么原文那个演示里00:B0:0C:05:5A:D8的尾部055AD8转成十进制是350936而设备贴纸上印的 PIN 前六位正是350936。它不是「算出来的」是「搬过来的」。攻击面由此从 10^7 直接塌缩到 10^1——只剩最后一位要处理。位序来源是否可推导备注第 14 位OUI / MAC 派生可推导固件差异最大的一段第 56 位部分实现继续搬 MAC 尾部可推导原文演示走的就是这条第 7 位出厂随机写入不可推导正规实现下需要穷举第 8 位前 7 位加权校验可推导直接算不用猜看这张表能明白一件事所谓「破译算法」破的从来不是加密算法本身而是固件里那段把 MAC 当种子的赋值语句。我把同一套思路套在三台不同年代的家用路由器上只有一台能对上另外两台算出来的数字和贴纸完全无关——这不是方法错了是那两台压根没用这套派生逻辑。2.2 末位不该猜加权校验的算法长什么样原文里写「最后一位数字我们只要猜十次就可以把它猜出来」。这个说法在当时是对的但效率低。规范里末位是按前 7 位加权算出来的加权规则是固定位置乘 3、固定位置乘 1累加后对 10 取模再做补数。手算一次就能得出来不用试十次。def pin_checksum(first7: str) - int: 标准 WPS PIN 校验位奇数位乘 3、偶数位乘 1累加后取补 if len(first7) ! 7 or not first7.isdigit(): raise ValueError(需要 7 位纯数字) acc 0 # 索引 0/2/4/6 对应第 1/3/5/7 位权重 3其余权重 1 for i, ch in enumerate(first7): acc int(ch) * (3 if i % 2 0 else 1) return (10 - acc % 10) % 10这段代码的作用只有一个给定前 7 位返回第 8 位。acc累加时权重顺序不能反第 1 位乘 3、第 2 位乘 1、第 3 位乘 3以此类推最后(10 - acc % 10) % 10是为了在acc % 10 0时返回 0 而不是 10这个边界漏掉的话会有十分之一的概率算出「10」这种非法值输进设备直接被拒。提示校验位算错的表现不是「算不出来」而是「算出来的 8 位数字输进去立刻返回失败」两者看起来一样排查时容易怀疑到路由器头上。把校验位算对至少省掉九次试错。对已经处在锁定机制下的设备来说九次试错可能就是二十分钟的冷却时间这个账不难算。2.3 为什么只有两段 OUI 成了重灾区原文点得很清楚受影响的只有 MAC 前六位是C83A35或者00B00C的产品其它产品线还是得靠穷举。这句话里藏着整个事件最关键的判断依据——漏洞不在 WPS 协议本身而在某厂商某几条产品线的固件实现里。我后来复盘这件事一般会从三个角度去判断一段 OUI 值不值得试第一看这个 OUI 对应的产品是不是集中在 2010 到 2012 那两三年出货。那批设备的固件由少数几家方案商供货同一个方案被十几个品牌贴牌所以命中一段 OUI 往往能连带命中一批设备。第二看设备背面贴纸。愿意把 PIN 直接印在贴纸上的厂商通常把这个值当成「出厂固定值」处理而不是每次配网动态生成。固定值意味着可以用 MAC 推动态值意味着推不出来。第三看 WPS 版本。WPS 1.0 默认允许 PIN 方式配网WPS 2.0 之后很多实现把 PIN 方法关了或者加了锁定这条路直接堵死。当年演示能成立一半功劳在协议版本上。把这三个条件叠一起实际可命中的范围比「所有开了 WPS 的路由器」小得多。这也是我后来不太愿意复述「两小时破路由密码」这种说法的原因它把条件全隐掉了读的人以为是个通杀手法实际是个特定固件的特定实现缺陷。3. 复现前的准备把环境、授权和抓包链路先钉死3.1 环境清单一块能进监听模式的网卡和一台自己的路由器复现这件事第一条规矩是设备归属。我所有测试都在自己买的那台老路由器上做MAC 段对得上就用它验证算法对不上就只验证抓包和时序绝不去碰周边任何一台不属于自己的 AP。这不是客套话是无线的物理特性决定的——你在家里扫扫到的一定是别人的设备。环节需要的东西我实际用的替代方案抓包支持监听模式的无线网卡一块外置 USB 网卡部分内置网卡打补丁后可用靶机一台可自由重置的路由器早年闲置的家用型号支持 WPS 的旧 AP系统带无线工具链的 Linux装在 U 盘里的精简发行版虚拟机加 USB 直通验证能发 EAPOL 的客户端工具命令行工具集图形界面的同功能实现网卡这一项是最容易翻车的地方。市面上大量 USB 无线网卡在驱动层就不支持监听模式买回来才发现只能当普通网卡用。判断办法很简单把网卡插上用iw list看输出的Supported interface modes里有没有monitor没有就是没有装什么补丁都白搭。我一般会先做一次最小闭环验证把自己的路由器开一个测试 SSID用网卡监听模式抓十秒包确认能抓到自己的 BSSID 再往下走。这一步花五分钟能省掉后面半小时的「为什么扫不到」。3.2 扫信号与读 BSSID两套工具的职责不一样扫信号这件事工具分两类职责完全不同。一类负责把网卡切到监听模式并列出周边所有 AP 的 BSSID、信道、加密方式、信号强度另一类专门从这些 AP 里筛出开了 WPS 的并告诉你它是 WPS 1.0 还是 2.0、有没有被标记为锁定状态。# 1. 把无线网卡切到监听模式。只在自己的实验环境执行 sudo airmon-ng start wlan0 # 2. 全信道扫描记录目标 AP 的 BSSID、信道、加密方式 # -c 指定信道能显著提高抓包效率不指定则轮询 sudo airodump-ng wlan0mon # 3. 单独筛出启用了 WPS 的 AP # -C 会额外显示客户端信息判断有没有人正在连 # 输出里的 WPS 版本和 Locked 标记是关键判断依据 sudo wash -i wlan0mon -C第一条命令执行后网卡名通常会从wlan0变成wlan0mon后面所有命令都得用新名字忘了改会报No such device。第二条命令的输出是一张实时刷新的表重点看三列BSSID是要拿去算 PIN 的输入CH决定你后面锁定哪个信道ENC告诉你目标是 WPA2 还是开放网络——开放网络没有破的必要直接跳过。第三条命令里的wash是我更看重的。它输出的WPS列如果显示1.0说明 PIN 配网方式是开着的显示2.0且Lck列有标记说明对方已经启用锁定或者干脆关了 PIN 方法。看到2.0就可以收工了后面所有计算都是白算。注意wash扫出来的结果里SSID 为空的 AP 不一定是隐藏网络也可能只是信标帧没抓全。判断隐藏 SSID 要看有没有 Probe Response别只看一列。3.3 从一堆帧里挑出要用的字段抓到 MAC 之后真正的输入只有一样BSSID。SSID、信号强度、品牌这些信息在判断阶段有用在计算阶段全是噪音。我习惯在扫描结果里直接锁定目标那一行把信道固定下来只抓这个信道、这个 BSSID 的帧避免列表一直在跳导致抄错。具体做法是加两个参数-c锁信道--bssid锁目标。这样输出文件里只有目标相关的帧后面拿去做时序分析时干净得多。文件名带时间戳因为一次复现往往要跑好几轮命名混乱了根本分不清哪份是哪份。BSSID 抄下来之后要做一次规范化统一大写、去掉冒号和短横线、确认长度是 12 个十六进制字符。这一步看着琐碎但后面所有计算都依赖它00:B0:0C:05:5A:D8和00-B0-0C-05-5A-D8在不同脚本里处理方式不一样混着用必出错。4. 从 MAC 到 PIN 的完整复现手算、脚本、设备验证三步对齐4.1 先用计算器手算一遍程序员模式的进制陷阱我坚持手算这一步不是为了炫技是为了在脚本出错时有一个独立参照。手算的流程是打开系统自带计算器切到程序员模式进制选十六进制输入 MAC 尾六位再切到十进制读数。原文那个例子里面输入的是055AD8切到十进制读出来350936。这里有个细节容易被忽略前导的0在十六进制模式下不会被显示你输055AD8和输55AD8得到的是同一个数但换算成十进制之后位数会不一样。55AD8转出来是351448六位没错可它就少了一个前导零的位置后面的补位逻辑全乱。我一般会强制记两条规则转换结果不足 6 位左边补0到 6 位转换结果超过 6 位尾部数值较大的 MAC 会出现取低 6 位。这两条规则定死之后手算和脚本才能对得上。手算还有个作用是验长度。0xFFFFFF是16777215八位十进制0x100000是1048576七位。所以尾六位十六进制转十进制结果可能是六位、七位或八位直接拿来当 PIN 前缀在大部分情况下是不成立的。原文那台设备恰好转出来是六位属于运气好。这个细节在复述「两小时破路由密码」的文章里几乎没人提但它决定了这套方法能不能直接照搬。4.2 脚本化把派生、校验、穷举写成可复跑的函数手算只能验一个样本要反复跑就得脚本化。我写的版本分三层第一层做 MAC 规范化第二层做派生和补位第三层把校验位和待穷举位拼成完整候选。def normalize_mac(mac: str) - str: 统一格式去分隔符、转大写返回 12 位十六进制串 clean mac.replace(:, ).replace(-, ).replace(., ).upper() if len(clean) ! 12 or any(c not in 0123456789ABCDEF for c in clean): raise ValueError(MAC 格式不对) return clean def pin_prefix(mac: str) - str: 取 MAC 尾 6 位十六进制转十进制按 6 位对齐 clean normalize_mac(mac) dec str(int(clean[-6:], 16)) if len(dec) 6: return dec.zfill(6) # 不足 6 位左补零 return dec[-6:] # 超过 6 位取低 6 位 def build_candidates(mac: str) - list: 组装完整候选 PIN 列表末位按校验位算另留穷举位 prefix pin_prefix(mac) head7 (prefix 0)[:7] # 第 7 位未知时先占位 out [] for guess in 0123456789: first7 prefix guess if len(prefix) 6 else head7 out.append(first7 str(pin_checksum(first7))) return outnormalize_mac里把点号也一并去掉是因为有些系统导出的格式是00B0.0C05.5AD8不处理会在长度校验上失败。pin_prefix的两条分支对应前面说的补齐和截断规则dec[-6:]那句在尾部六位数值较大时生效。build_candidates的逻辑要看得细一点当 MAC 派生出来是 6 位时第 7 位是未知的所以对 0 到 9 各试一次每次用pin_checksum补出第 8 位得到 10 个候选当派生结果直接覆盖到第 7 位时head7分支才会生效。原文演示的设备属于前者所以它说「猜十次」实际是「十次里有一次是对的」。# 用算出的候选逐个验证。只对自己的实验路由器执行 # -b 指定 BSSID-c 锁信道-vv 输出握手细节便于对齐时序 reaver -i wlan0mon -b 00:B0:0C:05:5A:D8 -c 6 -vv-vv这个参数别省。它会打出 M1 到 M8 每一步的收发情况你才能看清对方是在哪一步回 NACK、哪一步开始延迟响应。只看最后成功失败出了问题完全没线索。4.3 握手时序里哪一步在泄露信息整个 WPS 配网过程是八条消息的往返业内简称 M1 到 M8。要理解「为什么能算出来」得知道信息在哪一步流出去的。M1 由客户端发起里面带着自己支持的版本和加密能力AP 回 M2M2 里包含一个随机数E-S1、一个哈希值以及对 PIN 的处理方式。在正确的实现里M2 里用来做比对的摘要应该对 PIN 做完整保护攻击方拿到 M2 也推不出 PIN。而在实现有缺陷的固件里M2 返回的摘要可以直接用来做离线比对——这才是整件事的技术核心不是在线穷举得快是能拖回本地离线比对。M3 到 M8 是密钥下发和确认正常的 PIN 校验失败会在 M5 或 M7 之后返回 NACK。我一般会盯两个观察点一是 M2 到 M3 之间的时间差。正常设备几百毫秒带限速的实现会拉到一两秒这个时间差能反推对方的防护强度。二是连续两次 NACK 之间的间隔。间隔稳定说明是固定延迟间隔递增说明触发了退避。第二种情况继续跑下去意义不大往往跑到第十几次就进锁定。把这套时序搞明白之后我对「两小时」这个数字的理解就变了它测的不是破解速度是带着一个不完整的算法模型反复试错、直到对上时序的总耗时。真拿到正确的派生逻辑剩下的事几十秒就完了。5. 避坑与排查五条踩坑记录每条都对应一个具体现象5.1 抓包侧的两个坑扫不到和扫到奇怪信号坑一目标 AP 在扫描列表里时有时无SSID 一栏经常是空的。现象看着像信号弱实际上是信道轮询导致的。默认扫描会在 1 到 13 信道之间循环每个信道停留时间很短如果目标在 11 信道而 AP 的信标间隔偏长你可能连着几轮都恰好错过它的信标帧。原因不是网卡不行是扫描策略问题。解决办法是把信道锁死airodump-ng -c 11 --bssid 目标BSSID wlan0mon只盯一个信道抓全率立刻上来。另外顺手确认一下网卡支持的频段只支持 2.4G 的网卡在 5G 信道上是扫不出任何东西的这个不是配置问题是硬件边界。坑二wash 列出了目标但 WPS 版本显示 2.0PIN 怎么试都返回失败。现象是候选 PIN 全部被拒连校验位算对的那一个也拒。原因很明确WPS 2.0 的实现里 PIN 配网方法默认关闭或者加了失败次数锁定协议层就不给你这条路。这不是算法算错了是入口被堵了。解决办法是别在这上面耗时间看到 2.0 直接换目标或者换思路。我吃过一次亏在一台 2.0 的设备上折腾了快四十分钟最后拿另一台 1.0 的老设备两分钟就跑通了纯粹是选错了对象。5.2 计算侧的两个坑进制错位和校验位算反坑三算出来的 PIN 只有 5 位或者变成了 7 位。现象是候选列表长度对不上贴纸上的 PIN 是 8 位你算出来拼不满。原因几乎总是尾六位取错了——有的 MAC 写法带短横线replace只处理了冒号短横线留着[-6:]取到的就是-05:5A这种垃圾串int(..., 16)直接抛异常或者给出奇怪结果。另一种情况是转换结果不足 6 位却没补零35093当成350936用位数少一位。解决办法是把规范化做成一个独立函数先断言输出必须是 12 位纯十六进制再往下走。我的习惯是规范化之后立刻打印一次长度肉眼确认过再继续。坑四8 位 PIN 输进去立刻被拒连一次重试的机会都没有。现象是拒绝来得太快快到不像是在做网络校验像是在本地格式检查阶段就挂了。原因是校验位算反了权重顺序搞错——把该乘 3 的位置乘了 1。这类错误很隐蔽因为十次里大概有一次碰巧算对你会以为是设备的问题。解决办法是拿两组已知的 PIN 做反推验证找一台设备把贴纸上的 8 位数字拆开用脚本重算末位对得上说明算法写对了对不上就是权重反了。这一步我建议在正式复现之前做五分钟的事能避免后面把问题归因到路由器上。5.3 验证侧的一个坑锁定和限速坑五跑了几轮之后目标开始返回 NACK 且间隔越来越长最后完全没有响应。现象是前几次还能看到完整的 M1 到 M4 往返后面越来越慢最后干脆静默。原因是触发了 AP 侧的失败计数和退避机制大部分实现会在连续若干次 PIN 校验失败后进入锁定状态锁定期间拒绝一切 WPS 请求。解决办法有三条一是降低尝试频率别连着发中间留出间隔二是确认目标是不是已经进锁定wash的Lck列会标出来三是先在自己的实验设备上把完整流程跑通把要发的请求数量和节奏摸清楚再去碰真实环境。注意锁定超时时间各厂商差异很大短的一分钟长的半小时。同一台设备反复触发锁定有时候会让超时时间变长越试越难试这个反馈回路要提前意识到。这五条里坑一和坑三属于操作层改个参数就好坑二和坑五属于判断层决定你该不该继续坑四属于算法层错了整条链路都白搭。我后来养成一个顺序先确认 WPS 版本坑二再确认能不能抓全帧坑一再规范化 MAC 验长度坑三再用已知样本验校验位坑四最后才考虑节奏和锁定坑五。按这个顺序排能挡掉大部分无效折腾。6. 能算出来不等于能连上去把结论落回防御侧的一次自检复现做到最后我发现真正有价值的部分不是那串 PIN而是它暴露出来的判断链路一段 OUI 前缀、一个协议版本、一张印着 PIN 的贴纸三个条件叠在一起才成立缺一个就全废。这套判断逻辑反过来用就是一份很实在的自检清单。我后来每次帮人看家用无线配置都会按下面这几项过一遍。检查项在哪里看判断标准WPS 是否开启路由器管理页的无线设置关掉不用犹豫WPS 版本管理页或扫描工具输出2.0 且 PIN 方法关闭是可接受状态PIN 是否印在机身贴纸翻过来看背面印了就是固定值风险最高的一类固件更新时间管理页的固件信息2013 年之前的固件基本没修这类问题无线密码长度无线安全设置小于 12 位且纯数字的先改掉推进到这一步原本的攻防复现就变成了防御自检而且是我认为最有用的那一半。因为那批受影响的产品线出货时间集中在 2010 到 2012 年今天还在用同款设备的人不多但「出厂值当默认值用」这个习惯没消失——很多设备出厂 PIN、默认管理密码、默认 SSID 后缀本质是同一类问题。具体动作很简单进管理页找到 WPS 相关的开关关掉。这一步能挡掉整条利用链代价是失去「按一下按钮就配网」的便利。如果设备必须保留 WPS那就把 PIN 方式单独关掉只留按键方式按键方式至少要求物理接触。另外别把 PIN 和密码写在同一张贴纸上很多老设备的贴纸是「SSID PIN 默认密码」三件套等于把钥匙挂在门上。复现验证的角度我给一个自己的做法关掉 WPS 之后重新扫一次确认wash的输出里目标已经不再标注 WPS 可用。这个动作比在管理页看到一个开关状态更硬因为它验证的是空口上的实际行为而不是界面上的文案。回过头看这件事给我留下的最大教训不是「WPS 有洞」而是「便利性和攻击面之间总有一笔账厂商默认帮你选了便利那一侧出事之后要你自己把账补上」。从那以后我每次配完一台路由器都强制走一遍「关 WPS、改管理密码、确认固件版本」这三步不管这台设备是自己用还是给别人装。三步加起来不到五分钟比事后排查省太多。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?