与python的wpa握手 - 哈希困难

时间:2012-08-18 13:22:47

标签: python hash handshake wpa

我尝试编写一个计算WPA握手的Python程序,但是我遇到了哈希问题。为了比较,我安装了cowpatty (看看我开始出错的地方)

我的PMK生成工作正常,但PTK计算似乎也是错误的。我不确定是否必须格式化输入(macadresses和noces)或者只是将它们作为字符串放入函数中。

我会给你我的路由器信息,这是没有问题的,因为我只是设置它进行测试。

我的程序如下:

import hmac,hashlib,binascii

passPhrase  = "10zZz10ZZzZ"
ssid        = "Netgear 2/158" 
A           = "Pairwise key expansion" 
APmac       = "001e2ae0bdd0"
Clientmac   = "cc08e0620bc8"
ANonce      = "61c9a3f5cdcdf5fae5fd760836b8008c863aa2317022c7a202434554fb38452b"
SNonce      = "60eff10088077f8b03a0e2fc2fc37e1fe1f30f9f7cfbcfb2826f26f3379c4318"
B           = min(APmac,Clientmac)+max(APmac,Clientmac)+min(ANonce,SNonce)+max(ANonce,SNonce)
data="0103005ffe010900200000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

def customPRF512(key,A,B):
    blen = 64
    i    = 0
    R    = ''
    while i<=((blen*8+159)/160):
        hmacsha1 = hmac.new(key,A+chr(0x00)+B+chr(i),sha)
        i+=1
        R = R+hmacsha1.digest()
    return R[:blen]


pmk = pbkdf2(passPhrase, ssid, 4096, 32) #no sourcecode, since b2a_p(pmk) output fits to those of cowpatty

ptk = customPRF512(pmk,A,B) #the prf-function fits the pseudocode in the ieee, but does not give me the correct output (like cowpatty does)
# and i have no idea why :(

print b2a_p(pmk),"\n\n\n"
print b2a_p(ptk),"\n\n\n"

mic1 = hmac.new(ptk[0:16],data)
print mic1.hexdigest() #should be the mic-calculation, not sure if this is correct...

所需的输出(cowpatty确认)是:

PMK is
 01b8 09f9 ab2f b5dc 4798 4f52 fb2d 112e
 13d8 4ccb 6b86 d4a7 193e c529 9f85 1c48

Calculated PTK for "10zZz10ZZzZ" is
 bf49 a95f 0494 f444 2716 2f38 696e f8b6 
 428b cf8b a3c6 f0d7 245a d314 a14c 0d18
 efd6 38aa e653 c908 a7ab c648 0a7f 4068
 2479 c970 8aaa abc3 eb7e da28 9d06 d535

Calculated MIC with "10zZz10ZZzZ" is
 4528 2522 bc67 07d6 a70a 0317 a3ed 48f0

也许有人能告诉我,为什么我的程序根本不起作用。 hmac功能是否正常工作?我的输入格式错了吗?在任何地方我都要考虑到endianess吗?感谢您提前的时间,我将不胜感激任何帮助!

2 个答案:

答案 0 :(得分:5)

好吧,我自己想通了......更多的是通过绝望的测试和一些运气,而不是成功的研究,这导致了不够长的时间。我不得不使用MAC-adresses和nonces作为它们的字符串,而是不得不将它们解开。我用了

a2b_hex() #alternatively unhexlify()

我的最终代码看起来有点像这样,defs排除在外:

import hmac,hashlib,binascii
passPhrase="10zZz10ZZzZ"
ssid        = "Netgear 2/158"
A           = "Pairwise key expansion"
APmac       = a2b_hex("001e2ae0bdd0")
Clientmac   = a2b_hex("cc08e0620bc8")
ANonce      = a2b_hex("61c9a3f5cdcdf5fae5fd760836b8008c863aa2317022c7a202434554fb38452b")
SNonce      = a2b_hex("60eff10088077f8b03a0e2fc2fc37e1fe1f30f9f7cfbcfb2826f26f3379c4318")
B           = min(APmac,Clientmac)+max(APmac,Clientmac)+min(ANonce,SNonce)+max(ANonce,SNonce)
data        = a2b_hex("0103005ffe01090020000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")

pmk     = pbkdf2(passPhrase, ssid, 4096, 32) 
ptk     = customPRF512(pmk,A,B)
mic     = hmac.new(ptk[0:16],data)

print "desiredpmk:\t","01b809f9ab2fb5dc47984f52fb2d112e13d84ccb6b86d4a7193ec5299f851c48"
print "pmk:\t\t",b2a_hex(pmk),"\n"
print "desired ptk:\t","bf49a95f0494f44427162f38696ef8b6"
print "ptk:\t\t",b2a_hex(ptk[0:16]),"\n"
print "desired mic:\t","45282522bc6707d6a70a0317a3ed48f0"
print "mic:\t\t",mic.hexdigest(),"\n"

所以我的问题的答案是:是的,哈希函数正常工作,是的,输入格式错误,不,没有结束 - 问题。

答案 1 :(得分:0)

感谢您的发布。这帮助了我,所以发布了我的修订版本:

#==========================================================================================
#
# Verify the MIC code in EAPoL Message #2 is valid, or not (WPA2)
#
#==========================================================================================
#
# The home for this code is (so check for updates):
#
#     https://www.duckware.com/tech/verify-mic-in-four-way-handshake.py.txt
#
#   and this code is fully public, as it was based on/derived from this public code:
#
#     https://stackoverflow.com/questions/12018920/wpa-handshake-with-python-hashing-difficulties
#
# 1. PMK: 'Pairwise Master Key' (256-bit) is generated from SSID/PASS in WPA2:
#
#     o https://www.wireshark.org/tools/wpa-psk.html (SSID/PASS to PMK)
#     o http://anandam.name/pbkdf2/ (Password-Based Key Derivation Function 2)
#
# 2. PRF512: The PRF-512 function is used to compute four 128-bit keys (KCK,KEK,TK1,TK2).
#    For details on this function, see:
#
#     o http://etutorials.org/Networking/802.11+security.+wi-fi+protected+access+and+802.11i/Part+II+The+Design+of+Wi-Fi+Security/Chapter+10.+WPA+and+RSN+Key+Hierarchy/Computing+the+Temporal+Keys/
#
# 3. KCK: The KCK (first 128 bits of the PTK; see above) are used to generate the MIC:
#
#     o https://tldp.org/HOWTO/8021X-HOWTO/intro.html
#
# RUN: Run the code below in an ONLINE Python 2.7 compiler.  For example:
#
#     o https://repl.it/languages/python
#     o https://www.tutorialspoint.com/execute_python_online.php
#
# CUSTOMIZE: How to customize the code below:
#
#    1) PCAP the problematic handshake (TIP: use tcpdump with ether host xx:xx:xx:xx:xx:xx)
#    2) Update SSID/PASS vars below with the known Wi-Fi name/password
#    3) Copy entire Ethernet frames for EAPoL Message #1/#2 into EAPOL1/2 vars below.
#       TIP: In Wireshark, right click on Ethernet frame, 'Copy' / '...as a Hex Stream' / paste below
#    4) Use first with a working 4-way handshake (to confirm proper usage; MIC match), then apply
#       to non-working 4-way handshake to confirm that the MIC in Message #2 is good/bad.
#    5) The code below, unmodified, results in a MIC found/calculated 'match'
#
# See also:
#
#     o https://www.wifi-professionals.com/2019/01/4-way-handshake
#     o https://stackoverflow.com/questions/15133797/creating-wpa-message-integrity-code-mic-with-python
#     o https://www.shellvoide.com/wifi/understanding-wpa-wpa2-hash-mic-cracking-process-python/
#     o https://ww.ins1gn1a.com/understanding-wpa-psk-cracking/
#     o https://docs.python.org/3/library/binascii.html
#     o https://stackoverflow.com/questions/9020843/how-to-convert-a-mac-number-to-mac-string
#
#==========================================================================================

import hmac,hashlib,binascii

def to_mac(addr): return ':'.join(addr[i:i+2] for i in range(0,len(addr),2))
def PRF_512(key,A,B): return ''.join(hmac.new(key,A+chr(0)+B+chr(i),hashlib.sha1).digest() for i in range(4))[:64]
def a2b(s): return binascii.a2b_hex(s);
def b2a(by): return binascii.b2a_hex(by);

EAPOL1 = a2b("60f189052d94a00460216606888e0203005f02008a00100000000000000001141f7a3ebdc0b51712934bef6e43ea13f80cb460f121f35408aa607046e239980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
EAPOL2 = a2b("a0046021660660f189052d94888e0103007502010a000000000000000000015b46c7165f504c664aed90b78f3b705e02b4b029a67e3189d1632479d7e7a4e6000000000000000000000000000000000000000000000000000000000000000056de18f5efa272a4663560b73c537a65001630140100000fac040100000fac040100000fac028000")
SSID   = "your-wifi-ssid"
PASS   = "your-wifi-password"
PMK    = hashlib.pbkdf2_hmac('sha1', PASS, SSID, 4096, 32)  

VER_WPA = 2   # WPA2 means use 'SHA1'
XAUTH   = a2b("888E")
if EAPOL1[0:6]==EAPOL2[6:12] and EAPOL2[0:6]==EAPOL1[6:12] and EAPOL1[12:14]==XAUTH and EAPOL1[12:14]==XAUTH:
  if ord(EAPOL1[20])%8==VER_WPA and ord(EAPOL2[20])%8==VER_WPA:
    R1 = EAPOL1[31:63]      # random 1 (AP nonce)
    R2 = EAPOL2[31:63]      # random 2 (STA nonce)
    M1 = EAPOL2[0:6]        # MAC 1 (AP MAC)
    M2 = EAPOL1[0:6]        # MAC 2 (STA MAC)

    # Generate KCK, KEK, TK1, TK2 from the PMK (and AP/STA info)
    PTK = PRF_512(PMK,"Pairwise key expansion",min(M1,M2)+max(M1,M2)+min(R1,R2)+max(R1,R2))
    KCK = PTK[0:16];

    # try to validate the MIC in EAPoL message #2 is correct
    MICRAW   = hmac.new(KCK,EAPOL2[14:95]+a2b("00000000000000000000000000000000")+EAPOL2[111:],hashlib.sha1)
    MICFOUND = b2a(EAPOL2[95:111])
    MICCALC  = MICRAW.hexdigest()[0:32]

    print "SSID/PASS: ",SSID,"/",PASS
    print "PMK:       ",b2a(PMK)
    print "AP-MAC:    ",to_mac(b2a(M1))
    print "STA-MAC:   ",to_mac(b2a(M2))
    print "AP-NONCE:  ",b2a(R1)
    print "STA-NONCE: ",b2a(R2)
    print "KCK:       ",b2a(KCK)
    print "MIC-found: ",MICFOUND
    print "MIC-calc:  ",MICCALC
    print "Result:    ",("OK: EAPoL message #2 validated" if MICFOUND==MICCALC else "ERROR: MIC does not match")
  else:
    print "***ERROR: Did not find expected 'WPA2' version in EAPoL messages"
else:
  print "***ERROR: Problem validated Ethernet frames.  Do EAPOL1 and EAPOL2 both include the Ethernet headers?"