【無線安全實驗4】基于偽隨機數的WPS PIN碼逆向(精靈塵埃/仙塵攻擊)

文章目錄

    • 1 原理分析
      • 1.1 WPS連接過程
        • 1.1.1 初始階段
        • 1.1.2 注冊階段
      • 1.2 WPS攻擊原理
        • 1.2.1 在線攻擊
        • 1.2.2 離線攻擊
          • 1.2.2.1 Ralink模式
          • 1.2.2.2 eCos模式
    • 2 實驗過程
    • 3 參考資料

在2011年 Stefan Viehb?ck 演示過WPS的在線暴力攻擊,由于PIN碼猜測最多只需11000種組合,平均6小時就能攻破一臺路由器。而在2014年 Dominique Bongard 又演示了一種離線暴力坡解的攻擊,這種可怕的攻擊可在不到一秒時間內破譯WPA密鑰,Bongard先生還在其幻燈片結尾發出警告:“立即禁用WPS!”

【教程合集】

【無線抓包實驗1】抓包獲取隱藏WiFi名稱

【無線抓包實驗2】5G WiFi抓包跑包全流程

【無線抓包實驗3】批量抓包與無客戶端抓包

【無線安全實驗4】WPS離線破譯原理與實驗

1 原理分析

WPS(Wi-Fi Protected Setup)是一項旨在簡化無線網絡安全配置的標準,它通過PIN碼(Personal Identification Number)或PBC(Push Button Configuration)等方式,使家庭用戶能夠輕松地將新設備安全地接入Wi-Fi網絡。在PIN碼模式下,WPS使用EAP-WSC(Extensible Authentication Protocol for Wi-Fi Simple Configuration)協議完成認證與密鑰交換過程,該過程包含八個階段(M1-M8)的消息交換。本文將深入探討這八個階段的詳細流程,并重點分析其中涉及的關鍵參數(如E-Hash1、E-Hash2、PKE、PKR、AuthKey、E-Nonce等)的作用與相互計算關系。通過對這些參數和流程的理解,我們能夠更深入地認識WPS的安全機制及其潛在脆弱性。

1.1 WPS連接過程

在WPS中有兩個角色概念Enrollee和Registrar,Enrollee是入網設備(即手機物聯網家居等各種終端),Registrar為認證服務器,一般也由AP(即路由器等設備)充當。

1.1.1 初始階段

img

【發現過程】

  1. AP端的WSC開始工作后,它會廣播帶有WSC IE字段的beacon包,以聲明AP支持WSC

  2. 如果Enrollee收到來自AP的端的beacon包,那么它會解析beacon包中的 WSC IE,并向AP發送單播Probe Request包;如果Enrollee沒有收到帶有WSC IE的beacon包,那么它就會去搜索周圍支持WSC的AP,所以會向周圍發送Probe Request廣播包。

    如果Enrollee發現周圍有兩個或者兩個以上的AP在跑WPS,則Enrollee會在發現階段停止繼續執行;同理,如果AP發現有兩個或兩個以上的Enrollee在嘗試建立WPS連接,AP也會停止運行WPS。如果哪一天按下你router的WPS按鈕,發現wps燈快閃了幾下就不閃了,可能就是當時同時有兩個Enrollee在嘗試WPS連接。

  3. AP收到帶有 WSC IE的Probe Request請求包以后,就會回復Probe Response包,這個包里面帶有WSC IE,會告訴Enrollee一些信息,這些信息很多,Enrollee會根據這些信息來決定下一步的動作

【關聯過程】

  1. 對于PIN WPS需要在這個步驟輸入PIN,對于PUSH BUTTON則不需要輸入,當然PIN有分AP PIN和client PIN,這個決定了需要在AP端還是在Enrollee端輸入PIN, 這種輸入都是in-band的方式,當然也可以使用out-band的方式輸入信息,如NFC
  2. 當Enrollee獲取到AP端的信息,并且通過判斷符合接入條件的時候,Enrollee會嘗試去和AP進行認證,向AP發送Auth包
  3. AP端回復Auth 成功包,認證成功
  4. 然后Enrollee發送Association Request 關聯請求包,并附帶WSC IE 信息,這個信息很重要,目的是告訴AP我這邊使用的協議(如802.1x WPS 1.0 協議),我們接下來的M1-M8過程也將會遵守這個協議進行交互,如果不能接受這種協議的話,請及時告訴我。
  5. 這時,AP端表示這種協議是支持的,發送一個Association Response包給Enrollee,完成關聯。

【準備過程】

  1. 發送EAPOL-Start
  2. 在STA和AP雙方開展EAP-WSC流程前,AP需要確定STA的Identity以及使用的身份驗證算法。該過程涉及三次EAP包交換。這三次包交換的內容,首先,AP發送EAP-Request/Identity以確定STA的ID
  3. 對于打算使用WSC認證方法的STA來說,它需要在回復的EAP-Response/Identity包中設置Identity為"WFA-SimpleConfig-Enrollee-1-0"。
  4. AP確定STA的Identity為"WFA-SimpleConfig-Enrollee-1-0"后,將發送EAP-Request/WSC_Start包以啟動EAP-WSC認證流程。而后進入WPS認證與配置的M1~M8階段。
1.1.2 注冊階段

WPS使用EAP-WSC(EAP for Wi-Fi Simple Configuration)協議來完成配置過程,這部分是WPS的核心部分。該協議基于EAP(Extensible Authentication Protocol)框架,但專門用于WPS的設備注冊流程。整個認證過程包含8個消息交換階段(M1至M8),這些消息通過EAPoL-Data幀在Enrollee(設備)和Registrar(AP)之間傳輸,安全地交換配置信息(如 SSID、網絡密鑰等)。

消息方向說明主要作用與內容
M1設備 → AP發起注冊Enrollee 發送能力信息和公鑰PKE和隨機數N1,啟動注冊流程。
M2AP → 設備派生密鑰Registrar 發送能力信息和公鑰PKR和隨機數N1,并開始密鑰派生。
M3設備 → AP生成證明Enrollee 發送設備PIN碼的哈希證明E-Hash1E-Hash2
M4AP → 設備生成證明Registrar 回應設備PIN碼的哈希證明R-Hash1R-Hash2,并提交第一個秘密隨機數R-S1
M5設備 → AP驗證證明Enrollee 提交第一個秘密隨機數 E-S1
M6AP → 設備驗證證明Registrar 提交第二個秘密隨機數 R-S2
M7設備 → AP驗證證明Enrollee 提交第二個秘密隨機數 E-S2
M8AP → 設備配置網絡Registrar 發送最終的加密配置信息(如 SSID、網絡密鑰等)。

deepseek_mermaid_20250908_59dba1

【建立加密】

  • 【M1】:初始化注冊請求,提供Enrollee設備信息和安全能力。Enrollee選擇隨機數 A 為私鑰,計算公鑰 PKE = g^A mod p (使用指定的 1536-bit MODP 群)。

    發送UUID-E, MAC-E, PKE, N1(Enrollee隨機數), Device Password ID, 能力屬性等。

  • 【M2】:響應注冊請求,提供Registrar信息并啟動密鑰交換。Registrar選擇隨機數 B 為私鑰,計算公鑰 PKR = g^B mod p

    發送UUID-R, PKR, N2(Registrar隨機數), N1(回顯), Auth_M2, 能力屬性等。

根據交互的公鑰與隨機數,雙方相互獨立計算出共享密鑰DHShared和密鑰派生密鑰KDK:
DHShared=PKEBmodp=PKRAmodp=g(A?B)modpDHKey=SHA-256(zeropad(DHShared,192))KDK=HMAC?SHA256(DHKey,N1∣∣MAC?E∣∣N2)DHShared = PKE^B \mod p = PKR^A \mod p = g^{(A \cdot B)} \mod p\\ DHKey = \text{SHA-256}(\text{zeropad}(DHShared, 192))\\ KDK = HMAC-SHA256(DHKey, N1 || MAC-E || N2) DHShared=PKEBmodp=PKRAmodp=g(A?B)modpDHKey=SHA-256(zeropad(DHShared,192))KDK=HMAC?SHA256(DHKey,N1∣∣MAC?E∣∣N2)
最終派生出兩個關鍵的會話密鑰AuthKey和KeyWrapKey:
AuthKey∣∣KeyWrapKey∣∣EMSK=kdf(KDK,"Wi?FiEasyandSecureKeyDerivation",640)AuthKey || KeyWrapKey || EMSK = kdf(KDK, "Wi-Fi Easy and Secure Key Derivation", 640) AuthKey∣∣KeyWrapKey∣∣EMSK=kdf(KDK,"Wi?FiEasyandSecureKeyDerivation",640)

PS:kdf 是使用 HMAC-SHA256 的迭代函數,輸出 640 位,分割為:

  • AuthKey (256 bits): 用于消息認證 (HMAC)。
  • KeyWrapKey (128 bits): 用于加密敏感數據 (AES)。
  • EMSK (256 bits): 擴展主會話密鑰,可用于派生其他應用密鑰。

M2中的Auth_M2 = HMAC-SHA256(AuthKey, M2_Data)M2_Data 是 M2 消息中在 Authenticator 屬性之前的所有屬性。后續M3-M8的Auth_MX計算同理。

至此,雙方通過Diffie-Hellman密鑰交換算法已共享 KDK, AuthKey, KeyWrapKey,為后續加密和認證打下基礎。

【驗證PIN碼】

  • 【M3】:Enrollee其證明持有PIN碼。Enrollee將PIN碼分割為兩部分(如8位PIN碼12345670左右均分為1234和5670),再派生出PSK1PSK2
    PSK1=First?128?bits?of(HMAC?SHA256(AuthKey,First?Half?Password))PSK2=First?128?bits?of(HMAC?SHA256(AuthKey,Second?Half?Password))PSK1 = First-128-bits-of( HMAC-SHA256(AuthKey, First-Half-Password) )\\ PSK2 = First-128-bits-of( HMAC-SHA256(AuthKey, Second-Half-Password) ) PSK1=First?128?bits?of(HMAC?SHA256(AuthKey,First?Half?Password))PSK2=First?128?bits?of(HMAC?SHA256(AuthKey,Second?Half?Password))
    然后生成秘密隨機數E-S1, E-S2 (各 128 bits),計算證明哈希E-Hash1E-Hash2
    E?Hash1=HMAC?SHA256(AuthKey,E?S1∣∣PSK1∣∣PKE∣∣PKR)E?Hash2=HMAC?SHA256(AuthKey,E?S1∣∣PSK2∣∣PKE∣∣PKR)E-Hash1 = HMAC-SHA256(AuthKey, E-S1 || PSK1 || PKE || PKR)\\ E-Hash2 = HMAC-SHA256(AuthKey, E-S1 || PSK2 || PKE || PKR) E?Hash1=HMAC?SHA256(AuthKey,E?S1∣∣PSK1∣∣PKE∣∣PKR)E?Hash2=HMAC?SHA256(AuthKey,E?S1∣∣PSK2∣∣PKE∣∣PKR)
    發送 N2(回顯), E-Hash1, E-Hash2, Auth_M3。

  • 【M4】:Registrar其證明持有PIN碼,提供秘密隨機數讓Enrollee驗證PIN碼第一部分。Registrar按同樣方法分割PIN碼并派生PSK1和PSK2,再生成秘密隨機數R-S1, R-S2 ,計算證明哈希R-Hash1R-Hash2
    R?Hash1=HMAC?SHA256(AuthKey,R?S1∣∣PSK1∣∣PKE∣∣PKR)R?Hash2=HMAC?SHA256(AuthKey,R?S1∣∣PSK2∣∣PKE∣∣PKR)R-Hash1 = HMAC-SHA256(AuthKey, R-S1 || PSK1 || PKE || PKR)\\ R-Hash2 = HMAC-SHA256(AuthKey, R-S1 || PSK2 || PKE || PKR) R?Hash1=HMAC?SHA256(AuthKey,R?S1∣∣PSK1∣∣PKE∣∣PKR)R?Hash2=HMAC?SHA256(AuthKey,R?S1∣∣PSK2∣∣PKE∣∣PKR)
    而后生成隨機數IV(128bit),結合KeyWrapKey將第一個秘密隨機數R-S1加密到EncryptedSettings,并使用AuthKey生成KWA以保護R-S1的完整性:
    KWA=First?64?bits?of(HMAC?SHA256(AuthKey,R?S1))DataToEncrypt=R?S1∣∣KWAEncryptedSettings=AES?Encrypt?CBC(KeyWrapKey,IV,DataToEncrypt)KWA = First-64-bits-of( HMAC-SHA256(AuthKey, R-S1) )\\ DataToEncrypt = R-S1 || KWA\\ EncryptedSettings = AES-Encrypt-CBC(KeyWrapKey, IV, DataToEncrypt) KWA=First?64?bits?of(HMAC?SHA256(AuthKey,R?S1))DataToEncrypt=R?S1∣∣KWAEncryptedSettings=AES?Encrypt?CBC(KeyWrapKey,IV,DataToEncrypt)
    發送 N1(回顯), R-Hash1, R-Hash2, EncryptedSettings (R-S1), IV, Auth_M4。

  • 【M5】:Enrollee提供秘密隨機數讓Registrar驗證PIN碼第一部分。Enrollee解密R-S1并驗證其完整性:
    Data∣∣KWA′=AES?Decrypt?CBC(KeyWrapKey,IV,EncryptedSettings)KWA′==First?64?bits?of(HMAC?SHA256(AuthKey,R?S1))Data || KWA' = AES-Decrypt-CBC(KeyWrapKey, IV, EncryptedSettings)\\ KWA' == First-64-bits-of( HMAC-SHA256(AuthKey, R-S1) ) Data∣∣KWA=AES?Decrypt?CBC(KeyWrapKey,IV,EncryptedSettings)KWA==First?64?bits?of(HMAC?SHA256(AuthKey,R?S1))
    使用解密得到的 R-S1 和自己已知的 PSK1, PKE, PKR 重新計算 R-Hash1,與 M4 中的值比較。若計算不一致,觸發WSC_NACK終止會話(后續同)。然后使用同樣方法將自己的第一個秘密隨機數E-S1加密到EncryptedSettings

    發送 N2(回顯), EncryptedSettings (E-S1), IV, Auth_M5。

  • 【M6】:**Registrar提供秘密隨機數讓Enrollee驗證PIN碼第二部分。**Registrar解密E-S1并計算E-Hash1,將自己的第二個秘密隨機數R-S2加密到EncryptedSettings

    發送 N1(回顯), EncryptedSettings (R-S2), IV, Auth_M6。

  • 【M7】:**Enrollee提供秘密隨機數讓Registrar驗證PIN碼第二部分。**Enrollee解密R-S2并計算R-Hash2,將自己的第二個秘密隨機數E-S2加密到EncryptedSettings

    發送 N2(回顯), EncryptedSettings (E-S2 + Config-if-AP), IV, Auth_M7。

【配置網絡】

  • 【M8】:**完成驗證并配置網絡。**Registrar解密E-S2并計算E-Hash2,雙向認證全部完成。組裝ConfigData網絡配置信息:
    ConfigData=Credential(SSID,NetworkKey,AuthType,EncType,...)ConfigData = Credential (SSID, Network Key, AuthType, EncType, ...) ConfigData=Credential(SSID,NetworkKey,AuthType,EncType,...)
    同樣使用 KeyWrapKey 加密 ConfigData (過程同前,附加 KWA)。

    發送 N1(回顯), EncryptedSettings (ConfigData), IV, Auth_M8。最終Enrollee 解密并應用 ConfigData,協議完成。

【通俗解釋】

  1. Enrollee (手機):“你好路由器,我想加入網絡,這是我的信息(M1)。”
  2. Registrar (路由器):“好的手機,請證明你知道PIN碼。驗證通過后,我就把Wi-Fi密碼給你(M2)。“
  3. 雙方都生成兩個上鎖的箱子(E-Hash1/E-Hash2, R-Hash1/R-Hash2),里面是能證明自己身份的秘密。箱子的鑰匙(E-S1/E-S2, R-S1/R-S2)在自己手里。Enrollee 先把自己的兩個鎖上的箱子(M3)交給 Registrar,說:“給,這是我的證明。”
  4. Registrar 說:“好吧,但我看不到里面。為了表示誠意,這是我能打開你第一個箱子的鑰匙(加密的R-S1),同時我也把我的兩個鎖上的箱子(R-Hash1/R-Hash2)給你。”(M4)
  5. Enrollee 用只有自己才有的密鑰(KDK)解密拿到鑰匙(R-S1), 打開Registrar的第一個箱子(驗證R-Hash1)。一旦驗證成功,Enrollee 就確信 Registrar 知道真正的 PIN。于是,Enrollee 放心地把打開自己第一個箱子所需的鑰匙(E-S1)交給 Registrar(M5)。
  6. Registrar 用 E-S1 驗證 Enrollee 的第一個箱子(E-Hash1),也確認了 Enrollee 的身份。后續的 M6、M7 重復這個過程,用第二對箱子和鑰匙(E-Hash2/E-S2, R-Hash2/R-S2)進行二次確認。

1.2 WPS攻擊原理

1.2.1 在線攻擊

PIN碼為8位純數字,而第8位為前面1-7位的校驗和,所以總共只有10的7次方種組合。而由于PIN碼的驗證過程是分段式的,即先驗證前4位,再驗證后4位,則攻擊者只需先猜測前4位組合(104),再猜測后四位組合(103),即最多11000種組合即可猜出正確PIN碼。而WPS協議最初默認沒有對PIN的驗證次數進行限制,這就使在線PIN坡解成為了可能。傳統的在線攻擊方案可以借助 reaver 或 bully 簡便地實現,信號良好情況下大約 3s/pin(WPS1.0,無鎖 PIN 現象),平均幾小時即可攻破一臺路由器。

image-20250910002321896

注意在WPS在線攻擊中,攻擊者電腦扮演的是Registrar,而受攻擊路由器則充當Enrollee(與前面分析的邏輯相反)。攻擊工具(如reaverbully)運行在攻擊者的電腦上(Supplicant/Client)。它宣稱自己是一個“外部注冊器(External Registrar)”,使受攻擊目標接受管理并傳輸網絡配置信息。

image-20250910212210563

攻擊者通過遍歷所有PIN碼組合,發送M4幀后根據是否收到AP回復的WSC_NACK來確定前半段PIN碼是否正確,若不正確則遞增下一個組合。直到猜中前半段PIN碼,再發送M6幀并根據是否收到AP回復的WSC_NACK來確定后半段PIN碼是否正確,最終完全確認整個PIN碼。

image-20250910195829673

1.2.2 離線攻擊

現在多數路由器都是 WPS2.0(WSC),會出現鎖 PIN 現象,一定程度提高了安全性。可就算是幾次 PIN 嘗試的機會,也留給了攻擊者可乘之機。2014年Dominique Bongard演示了一種離線WPS的方法,對某些存在安全漏洞的路由器可在不到一秒內破譯。該攻擊利用了某些路由廠商芯片只能生成低熵的偽隨機數,進而坡解加密過程。攻擊稱為“pixie-dust attack”,翻譯為“小精靈塵埃攻擊”或“仙塵”攻擊(外國人起名靈感感覺大都跟游戲影視作品有關)。

image-20250909172542790

入網設備和AP之間沒有傳輸PIN碼,是通過計算PIN碼的Hash值來驗證的。如果PIN碼驗證失敗,流程會止于M4階段。根據之前在線PIN坡解過程分析,攻擊者可以獲取到PIN碼最終計算產物E-Hash1和E-Hash2(AP發送的M3幀),以及中間計算值AuthKey、PKE、PKE,而初始參數PIN碼與兩個中間計算使用的隨機數E-S1和E-S2是不知道的。但是如果攻擊者能猜測到AP生成的隨機數E-S1和E-S2,就可以通過代入所有PIN碼組合去猜測驗證,最終獲取到PIN碼。

其實這里筆者有點疑惑,為什么攻擊者不按常規流程充當Enrollee角色,去獲取AP發送的M4幀,這樣還可以多獲取到一個隨機數信息。可能是因為代碼是基于reaver改編的分支,而reaver就是使用Registrar角色去進行攻擊吧。

那么怎么能猜到AP生成的隨機數呢?Dominique Bongard發現某些路由器的芯片生成的是不安全的偽隨機數(Pseudo-Random Number Generator,PRNG),導致其可以通過上一個隨機數進行逆向預測。例如,Broadcom基本上使用C中的Rand()函數,在Ralink中隨機數始終不會生成(因此為0),而RTL819x生成的隨機數存在復用(N1、E-S1、E-S2均相同)。

易受攻擊的路由器收錄:https://docs.google.com/spreadsheets/d/1tSlbqVQ59kGn8hgmwcPTHUECQ3o9YhXR91A_p7Nnj5Y/edit#gid=2048815923

在攻擊過程中,M1階段受攻擊路由器會生成隨機數N1(E-Nonce),到M3階段又會生成的隨機數E-S1和E-S2,這兩個隨機數是緊接著N1生成的。而N1可以直接捕獲到,如果路由器生成的是偽隨機數,就可以進行逆向分析。下面分析pixiewps源碼中的兩種逆推偽隨機數的模式:Ralink模式(直接計算)和eCos模式(暴力枚舉)。

1.2.2.1 Ralink模式
  • Ralink基于線性反饋移位寄存器(LFSR)算法生成偽隨機數,使用的是 32 位 Galois LFSR(掩碼 0x80000057),生成代碼如下。
//Ranlink隨機數生成
static unsigned char ralink_randbyte(struct ralink_randstate *state)
{unsigned char r = 0;for (int i = 0; i < 8; i++) {unsigned char result;if (state->sreg & 0x00000001) {      // 檢查LSBstate->sreg = ((state->sreg ^ 0x80000057) >> 1) | 0x80000000;result = 1;}else {state->sreg = state->sreg >> 1;  // 簡單右移result = 0;}r = (r << 1) | result;              // MSB優先累積}return r;
}

偽隨機數生成流程:

  1. 選定一個初始的數S0,在LFSR中通常稱為狀態(可以理解為種子,如:1010…1011 ,共32位),先取最低位(Least Significant Bit,LBS)作為輸出隨機數的第一位(最左邊的一位)。
  2. 如果最低位為1則S0與多項式(0x80000057)進行異或操作,如果最低位為0則不變,得到S0‘。
  3. 對S0‘右移一位,如果進行了異或操作則高位補1,如果沒有操作則高位補0,得到S1。
  4. 接著重復這個過程,再次對S1取值、操作、右移,一步步得到隨機數的第二、三、…、八位,循環做8次就可以得到1字節(8bit)的隨機數。而N1為16字節,則需做8x16次運算。
static void ralink_randstate_restore(struct ralink_randstate *state, uint8_t r)
{for (int i = 0; i < 8; i++) {const unsigned char result = r & 1;  // 取LSB(從后向前處理)r = r >> 1;if (result) {                        // 如果輸出位是1state->sreg = (((state->sreg) << 1) ^ 0x80000057) | 0x00000001;}else {                               // 如果輸出位是0state->sreg = state->sreg << 1;  // 簡單左移}}
}

通過隨機數逆向種子:

由隨機數的最后一位,可以知道上一次的操作數Sn的最后一位(如果隨機數最后一位是0,則Sn’的最后一位為0;如果隨機數最后一位是1,則Sn’的最后一位為1)。同理,由隨機數倒數第二位,可以知道上上次的操作數Sn-1的最后一位,以此類推。由于知道每次操作數的最后一位,從最后一次操作數Sn開始進行補值、操作、左移(逆運算)。

  1. 如假如隨機數最后一位為1,則設最后一次操作數Sn為0000…0001(最后一位為0則設0000…0000,最后一位前面的值隨便設,因為后續會不斷左移去掉)。
  2. 然后觀察隨機數倒數第二位,倒數第二位為1,則說明Sn-1’到Sn做了異或操作,那么需要再與多項式(0x80000057)做一次異或操作使其變為Sn-1’;如果隨機數倒數第二位為0,則無需操作Sn即Sn-1’。
  3. 將Sn-1‘左移,然后末尾補隨機數的倒數第二位,變為Sn-1。
  4. 重復這個過程,直至將最開始Sn的最后一位左移到第一位。一共32位,所以做31次即可逆向出某個時刻的操作數(種子)。
static unsigned char ralink_randbyte_backwards(struct ralink_randstate *state)
{unsigned char r = 0;for (int i = 0; i < 8; i++) {unsigned char result;if (state->sreg & 0x80000000) {      // 檢查MSBstate->sreg = ((state->sreg << 1) ^ 0x80000057) | 0x00000001;result = 1;}else {state->sreg = state->sreg << 1;  // 簡單左移result = 0;}r |= result << i;                    // LSB優先累積}return r;
}

通過種子逆向生成隨機數:

前面是通過種子往后生成隨機數,這個代碼是通過種子往前生成隨機數,過程類似。

  1. 選定一個初始的數Sn,先取最高位(Most Significant Bit,MSB)作為輸出隨機數的最后一位(最右邊的一位,這里是第八位)。
  2. 如果最高位為1則S0與多項式(0x80000057)進行異或操作,如果最高位為0則不變,得到Sn‘。
  3. 對Sn‘右移一位,如果進行了異或操作則低位補1,如果沒有操作則低位補0,得到Sn-1。
  4. 接著重復這個過程,再次對Sn-1取值、操作、左移,一步步得到隨機數的第七、六、…、一位,循環做8次就可以得到1字節(8bit)的隨機數。

deepseek_mermaid_20250913_c68ff0

LFSR算法生成的隨機數是完全可逆的,在源碼中是先通過隨機數N1(E-Nonce)反推種子,然后回退 16 字節得到 E?S2,再接著回退 16 字節得到 E?S1。這里筆者是挺疑惑的,按照WSC規范,生成順序應該是N1 -> E-S1 -> E-S2。不清楚代碼為什么不是從N1繼續正向生成隨機數E-S1和E-S2,而是逆向生成E-S2和E-S1,也許這個隨機數的生成邏輯就是逆向生成吧。

1.2.2.2 eCos模式
  • eCos simple 模式基于線性同余生成器(LCG,Linear Congruential Generator)算法生成偽隨機數,源自 C 語言標準庫的rand()函數,生成代碼如下。
static uint32_t ecos_rand_simple(uint32_t *seed)
{uint32_t s = *seed;uint32_t uret;// 第一步:線性同余生成s = (s * 1103515245) + 12345;          // 生成s1uret = s & 0xffe00000;                 // 取高11位 (bits 31-21)// 第二步:繼續生成  s = (s * 1103515245) + 12345;          // 生成s2uret += (s & 0xfffc0000) >> 11;        // 取高14位右移11位 (bits 31-18 → bits 20-7)// 第三步:再次生成s = (s * 1103515245) + 12345;          // 生成s3uret += (s & 0xfe000000) >> (11 + 14); // 取高7位右移25位 (bits 31-25 → bits 6-0)*seed = s;return uret;  // 返回32位值,但實際只使用低8位
}//使用時只取低8位
output_byte = ecos_rand_simple(&seed) & 0xFF;

偽隨機數生成流程:

  1. 選定一個初始的數S0(32位)作為種子。對這個數乘以一個乘數(1103515245),再進行增量(12345),得到S1,取高11位作為隨機數的高11位。
  2. 對S1再乘以乘數并進行增量,得到S2,取高14位作為隨機數中間14位。
  3. 對S2再乘以乘數并進行增量,得到S3,取高7位作為隨機數低7位。總共得到11+14+7=32位隨機數,但使用時只取低8位。

整體操作為對操作數做3次LCG固定計算s = (s * a + c) % m,每次取部分高位拼接成隨機數。末尾取模在代碼中沒有顯式編寫,實際上因為使用了無符號整數(232),計算后溢出的高位會被丟棄,相當于取2^32的模。

uint32_t known = wps->e_nonce[0] << 25; /* 將熵從32位減少到25位 */
uint32_t seed, counter = 0;
while (counter < 0x02000000) {  // 2^25 = 33,554,432次嘗試int i;seed = known | counter;  // 構建候選種子// 驗證后續15個字節for (i = 1; i < WPS_NONCE_LEN; i++) {if (wps->e_nonce[i] != (uint8_t)(ecos_rand_simple(&seed) & 0xff))break;}// 如果所有字節都匹配if (i == WPS_NONCE_LEN) {// 找到正確種子,繼續生成E-S1和E-S2wps->s1_seed = seed;for (i = 0; i < WPS_SECRET_NONCE_LEN; i++)wps->e_s1[i] = (uint8_t)(ecos_rand_simple(&seed) & 0xff);wps->s2_seed = seed;for (i = 0; i < WPS_SECRET_NONCE_LEN; i++)wps->e_s2[i] = (uint8_t)(ecos_rand_simple(&seed) & 0xff);break;}counter++;
}

通過隨機數逆向種子:

首先一字節的隨機數(8位)的后7位就是取自最后一次操作數的S3的前7位,那么對于S3還有剩下的25位未知。而LCG算法與前面LFSR算法不同,生成隨機數會溢出部分數據導致計算不可逆。但偽隨機數的特點就是計算過程是固定的,通過分析連續生成的隨機數,知道結果就可以直接套初始值去猜測,最終逆推出種子。

deepseek_mermaid_20250913_d391ea

對于WPS中生成的N1(E-Nonce)總共16字節,我們取第1個字節,其前7位做種子的前7位,對于未知的后25位進行枚舉猜測,同樣使用LCG算法去計算后面生成的隨機數,與N1的后15字節結果進行比對。如果計算結果比對實際隨機數完全一致,那就說明猜測成功。這種方式即暴力坡解,最多猜測2^25次(33,554,432),計算機可在幾秒內完成。

猜出種子后,再往后計算就可以得到E-S1和E-S2。


2 實驗過程

本次實驗以無線安全審計目的,意在對路由器安全強度進行測試,僅做學習研究之用。請注意遵循相關法律法規。

其實現在大多數路由器已經沒有WPS漏洞了,越新的路由器會采用更新的無線安全標準(如WPA3),同時禁用WPS功能。無線安全水平是在不斷提升的,但也不排除還有少部分老舊路由器沒有被淘汰更新。

本次實驗使用的軟件為WiFiGrab

百度云盤下載:https://pan.baidu.com/s/1Q9oWrHF_nKgwOtKyVcb7IQ?pwd=xxwd

123云盤下載:https://www.123684.com/s/q496Td-Ru95H

  1. 接入USB抓包網卡后啟動軟件。

    image-20250913231853167

  2. 在設置中可同時啟用2.4G和5G掃描,并將掃描時間改長一些,確認。

    image-20250913231924840

    image-20250913231951653

  3. 點擊掃描WiFi,對附近無線網絡進行掃描。

    掃描完成,可以觀察邊框顏色,黑色邊框說明AP啟用了WPS,灰色邊框說明AP未啟用WPS(軟件通過AP信標幀中的wifi_protected_setup_state字段確定)。

    僅對已啟用WPS的AP進行測試(需注意隱藏WiFi即使啟用了WPS,也無法直接進行WPS攻擊,因為不知道WiFi名稱無法接入。但其實WiFi名稱是可以通過抓包獲取的,不過本軟件不涉及該內容)。

    image-20250913233000916

  4. 以筆者自己的路由器(榮耀CD16)進行測試,選擇目標后,點擊PIN。

    image-20250913234505706

  5. 運行后WPS離線攻擊沒有成功,說明該路由器沒有偽隨機數漏洞。

    觀察日志可以看到,軟件如前面分析的,對AP發起WPS的流程。通過M1到M3交互獲取到E-Nonce、PKR、PKE、AuthKey等信息,然后嘗試猜測E-S1和E-S2,但未猜測成功,該AP可能基于物理過程生成的是真隨機數,或是使用其他算法生成的隨機數。

    image-20250913234908815

  6. 筆者對周圍的路由器也進行了安全測試,發現大多數路由器也不存在此漏洞,是較新的路由設備。但也有極個別路由器(可能是采用老式芯片的光貓或路由器)是有該漏洞存在的。

    前文有易受攻擊的路由器收錄的信息,而WPS的廣播信息中有兩個字段Model Name和Model Number標識了AP設備的型號與編號,由此能得知AP是否易受攻擊。易受攻擊的路由器在軟件中會顯示為藍色邊框,同時在MAC地址后側括號中會顯示該設備信息(如Ralink Wireless Access Point RT2860)。

    筆者找到了個別顯示藍色邊框的路由器進行測試,發現其PIN碼信息可以被計算出來,且只需要不到十幾秒時間。

    image-20250914015718940


3 參考資料

https://ifconfig.dk/pixiedust/

https://github.com/2EXP/2exp.github.io/issues/3

https://mlg556.github.io/posts/bruteforce-wps-with-reaver-and-pixiewps/bruteforce-wps-with-reaver-and-pixiewps.html

https://blog.csdn.net/moonlinux20704/article/details/109102318

http://archive.hack.lu/2014/Hacklu2014_offline_bruteforce_attack_on_wps.pdf

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/100444.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/100444.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/100444.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

IDEA開發過程中經常使用到的快捷鍵

IntelliJ IDEA 開發 Java 時常用的快捷鍵列表 代碼編輯與行操作快捷鍵功能描述Ctrl Y刪除當前行。Ctrl D復制當前行到下一行。Shift Alt ↑將當前行&#xff08;或選中塊&#xff09;向上移動。Shift Alt ↓將當前行&#xff08;或選中塊&#xff09;向下移動。Ctrl /注…

ubuntu使用webrtc庫開發一個webrtc推拉流程序

目錄 一. 前言 二. 整體交互流程 三. 類實現說明 1. WebRtcClient 2. SignalPeerClient 3. WebRTCStream 4. 視頻源類 5. 拉流渲染 四. 使用示例 1. 推流代碼示例 2. 拉流代碼示例 一. 前言 在 《ubuntu編譯webrtc庫》我們介紹了如何在 ubuntu 上使用 webrtc 源代碼…

【Block總結】ConverseNet:神經網絡中的反向卷積算子

1. 論文信息 標題:Reverse Convolution and Its Applications to Image Restoration 發布平臺:arXiv 論文鏈接:https://arxiv.org/pdf/2508.09824 代碼倉庫:https://github.com/cszn/converseNet 任務領域:圖像恢復(去噪、超分辨率、去模糊) 核心貢獻:提出了一種新的反…

優化瀏覽體驗:4個設置讓Google Chrome更好用!

想要更流暢、更快速的瀏覽體驗嗎&#xff1f;本文章將向大家展示Google Chrome中你應該立即更改的4個重要設置&#xff0c;設置調整將幫助您提升性能&#xff0c;讓你的瀏覽更高效。1、打開瀏覽器&#xff0c;在地址欄輸入“chrome://flags"確定&#xff0c;在搜索標志中輸…

【Git】一篇文章帶你入門Git

1. 初識 Git 1.1 Git 是什么&#xff1f; Git 是一個開源的分布式版本控制系統&#xff0c;用于高效地跟蹤和管理項目代碼的變更歷史&#xff08;不僅僅是代碼&#xff0c;還有其它格式也是可以的~&#xff09; 1.2 為什么要有 Git 在學習或者是工作的時候&#xff0c;比如…

8 基于機器學習進行遙感影像的地物分類-以隨機森林為例

目錄 1 讀取數據 2 數據預處理 3 模型訓練 4 精度分析 5 模型預測 1 讀取數據 1.右鍵數據所在文件夾,用pycharm打開為項目 2.在settings中設置python環境為先前配置的帶GDAL和sklearn的環境 3.新建一個文件夾命名為code來存放代碼,在code文件夾中新建一個rfc.py

極簡版 Nginx 反向代理實驗步驟

以下是最核心的反向代理實現步驟&#xff0c;專注于 “客戶端→Nginx 代理→后端服務” 的基礎轉發功能&#xff1a;一、準備 2 臺服務器角色IP 示例需安裝軟件代理服務器192.168.1.10Nginx后端服務器192.168.1.11Nginx/Apache二、后端服務器配置&#xff08;192.168.1.11&…

Windsurf 插件正式登陸 JetBrains IDE:讓 AI 直接在你的 IDE 里“打工”

那天你說,我們可以永遠在一起——成了我聽到的最高興的,而后知后覺的謊言。 而今天,AI 說:“我可以幫你寫完這段代碼。” —— 這才是真正的“永遠在一起”。 最近,AI 編程工具賽道迎來一場“潛行式革命”:Windsurf Wave 7 正式發布 JetBrains IDE 插件版本,徹底打破“A…

188. Java 異常 - Java 異常處理規范

文章目錄188. Java 異常 - Java 異常處理規范&#x1f4dc; 什么是“Catch or Specify Requirement”&#xff1f;? 兩種滿足方式方法一&#xff1a;使用 try-catch 捕獲異常方法二&#xff1a;使用 throws 聲明異常? 不遵守規則會怎樣&#xff1f;&#x1f4a1; 哪些異常必須…

泛型通配符 T、E、K、V、?

在Java后端開發中&#xff0c;你一定在寫集合類或工具類時&#xff0c;見過 T、E、K、V、? 這樣的泛型通配符。但你是否有過以下疑惑&#xff1a; T、E、K、V 到底有什么區別&#xff1f;為什么大家都用這些字母&#xff1f;List<?> 和 List 有什么不同&#xff1f;什么…

基于腳手架微服務的視頻點播系統-數據管理與網絡通信部分的預備工作

基于腳手架微服務的視頻點播系統-數據管理與網絡通信部分的預備工作一.數據管理二.網絡通信2.1客戶端通信模塊及測試用例的實現2.2MockServer搭建的相關接口介紹2.3MockServer的搭建示例一.數據管理 在前?的實現中&#xff0c;程序中的數據、以及界?操作等全部攪合在?起&am…

html表單登錄模式代碼

使用的是Content-Typeapplication/x-www-form-urlencoded形式如代碼如下的html&#xff0c;后端沒寫下去&#xff1a;<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>管理員登錄</title><…

NLP:Transformer之self-attention(特別分享3)

本文目錄&#xff1a;一、核心思想&#xff1a;一句話概括二、計算流程的直觀比喻三、分步計算詳解&#xff08;附數字例子&#xff09;第 1 步&#xff1a;創建 Query, Key, Value 向量第 2 步&#xff1a;計算注意力分數第 3 步&#xff1a;縮放并應用 Softmax第 4 步&#x…

25、優化算法與正則化技術:深度學習的調優藝術

學習目標:深入理解各種優化算法的原理和適用場景,掌握學習率調度的方法和策略,學會使用Dropout、批歸一化等正則化技術,理解早停和驗證策略,建立深度學習調優的系統性知識。 深度學習的成功不僅依賴于精巧的模型架構,更在于巧妙的訓練策略。如果說網絡架構是房屋的設計圖…

Netty-01-NIO前置知識

目錄 NIO三大組件 一. ByteBuffer 基本用法 DirectByteBuffer與HeapByteBuffer對比 字符串轉ByteBuffer ByteBuffer.wrap(byte[] ) 粘包與拆包 文件編程 零拷貝transferTo 二. 阻塞與非阻塞Channel 三. Selector SelectionKey&#xff08;重點&#xff09; Select…

知識點17:多Agent系統架構設計模式

知識點17&#xff1a;多Agent系統架構設計模式 核心概念 掌握系統架構思維&#xff0c;理解多Agent系統的設計原則和模式 架構設計核心概念 在構建多Agent系統時&#xff0c;良好的架構設計是系統成功的關鍵。本節將介紹多Agent系統架構設計中的核心概念&#xff0c;包括單點瓶…

數據庫造神計劃第五天---增刪改查(CRUD)(1)

&#x1f525;個人主頁&#xff1a;尋星探路 &#x1f3ac;作者簡介&#xff1a;Java研發方向學習者 &#x1f4d6;個人專欄&#xff1a;《從青銅到王者&#xff0c;就差這講數據結構&#xff01;&#xff01;&#xff01;》、 《JAVA&#xff08;SE&#xff09;----如此簡單&a…

基于Vue3的人工智能生成內容標識服務平臺前端頁面設計

效果圖&#xff1a;素材庫&#xff1a;App.vue<template><div id"app"><!-- 頭部導航 --><Header /><!-- 主要內容區域 --><main class"main-content"><div class"container"><!-- 強制性國家標準…

使用 MyCat 實現 MySQL 主從讀寫分離

文章目錄使用 MyCat 實現 MySQL 主從讀寫分離完整指南一、MySQL 讀寫分離基礎概述1.1 讀寫分離工作原理1.2 為什么需要讀寫分離1.3 讀寫分離的兩種實現方式主流讀寫分離中間件對比二、MyCat 中間件簡介2.1 MyCat 核心功能2.2 MyCat 適用場景三、環境準備與 MyCat 安裝3.1 前提&…

物聯網傳感器檢測實驗

/*------------------------------------------------------------------------------ * @文件名 : handle * @描述 : 用戶處理函數 * @作者 : 物聯網項目組 * @日期 : 2023/04/01 * @版本 : V0.0.2 *****************************…