Here’s the source code first:
#!/usr/bin/python import base64 import os import re import subprocess import sys import time def writepem(certdata): f = "" e = base64.b64encode(certdata) x = 0; l = len(e) f += ("-----BEGIN CERTIFICATE-----\n") while (x < l): f += ("%s\n" % (e[x+0:x+64])) x += 64 f += ("-----END CERTIFICATE-----\n") return f def brutecert(pcapdata): l = 900 while (l <= 1024): p = writepem(pcapdata[:l]) #sys.stderr.write(p+"\n") try: certchk = subprocess.check_output("echo '%s' | openssl verify 2>&1 | grep '^OK$'" % (p), shell=True) except: certchk = "" if (certchk != ""): break l += 1 if (certchk != ""): sys.stdout.write(p) return 1 return 0 os.system("killall -9 tcpdump > /dev/null 2>&1 ; killall -9 tcpdump > /dev/null 2>&1") os.system("rm -fv wifi.pcap > /dev/null 2>&1 ; tcpdump -i %s -w wifi.pcap -U > /dev/null 2>&1 &" % (sys.argv[1])) sys.stderr.write("Note: If you want to interrupt this script, press Control+Z and killall -9 python\n") r = 0 while (1): try: tcpout = subprocess.check_output("tcpdump -xr wifi.pcap 2> /dev/null | tr '\\t' ' ' | sed -e 's/^ [ ]*0x[0-9A-Fa-f][0-9A-Fa-f]*:[ ]*//'", shell=True) tcplist = tcpout.split("\n") eapdata = ""; eapindx = 0; eapsize = -16 for x in range(0, len(tcplist)): if (eapindx < (eapsize + 4)): h = "" for c in tcplist[x].strip(): if (not c in "0123456789ABCDEFabcdef"): continue h += c if (len(h) == 2): if (eapindx >= (eapsize + 4)): sys.stderr.write("EAP read error [%d] >= [%d]...\n" % (eapindx + 1, eapsize)) else: if (eapindx >= 4): eapdata += chr(int(h, 16)) eapindx += 1; h = "" else: z = re.match("^[0-9][0-9]:[0-9][0-9]:[0-9][0-9].* EAP packet.* v2.* len ([0-9]+)$", tcplist[x].strip(), re.I) if (z): eapindx = 0; eapsize = int(str(z.group(1))) sys.stderr.write("Possible EAP data: line [%d] len [%d]...\n" % (x, eapsize)) p = 0; l = len(eapdata) tlsdata = ""; tlsindx = 0; tlssize = -16 while (p < l): i = p; m = [["\x01","\x02"],[],[],[],["\x15"],[None],[],[],[],[]] for j in m: if (i >= l): pass elif (len(j) < 1): i += 1 elif (None in j): if ((ord(eapdata[i]) & 0x80) > 0): i += 1 else: for k in j: if (eapdata[i] == k): i += 1 if (i == (p + len(m))): tlslen = ((ord(eapdata[p+2])<<8) + (ord(eapdata[p+3])<<0)) tlsmlen = ((ord(eapdata[p+6])<<24) + (ord(eapdata[p+7])<<16) + (ord(eapdata[p+8])<<8) + (ord(eapdata[p+9])<<0)) sys.stderr.write("Possible TLS data: index [%d] len [%d] mlen [%d]...\n" % (p, tlslen, tlsmlen)) p += 10 if (tlssize < 1): tlsindx = 0; tlssize = tlsmlen for x in range(0, tlslen - 10): if ((tlsindx >= tlssize) or (p >= l)): pass else: tlsdata += eapdata[p] p += 1 tlsindx += 1 if (tlsindx >= tlssize): if (tlsindx > tlssize): sys.stderr.write("TLS read error [%d] >= [%d]...\n" % (tlsindx, tlssize)) tlsindx = 0; tlssize = -16 p -= 1 p += 1 p = 0; l = len(tlsdata) while (p < l): if (r == 0): i = p; m = "\x30\x82\x03" for j in m: if (tlsdata[i] == j): i += 1 if (i == (p + len(m))): sys.stderr.write("Possible CA data: index [%d]...\n" % (p)) r = brutecert(tlsdata[p:]) p += 1 except: pass if (r != 0): break time.sleep(1) os.system("killall -9 tcpdump > /dev/null 2>&1 ; killall -9 tcpdump > /dev/null 2>&1")
Then you run the command:
# python cagrab.py wlan0 | tee ca.crt Note: If you want to interrupt this script, press Control+Z and killall -9 python Possible EAP data: line [0] len [5]... Possible EAP data: line [4] len [6]... Possible EAP data: line [22] len [1024]... Possible EAP data: line [90] len [1024]... Possible EAP data: line [158] len [480]... Possible EAP data: line [204] len [69]... Possible EAP data: line [219] len [4]... Possible TLS data: index [11] len [1024] mlen [2498]... Possible TLS data: index [1035] len [1024] mlen [2498]... Possible TLS data: index [2059] len [480] mlen [2498]... Possible TLS data: index [2539] len [69] mlen [59]... Possible CA data: index [74]... Possible CA data: index [1006]... -----BEGIN CERTIFICATE----- MIIDtTCCAp2gAwIBAgIJAKhl2tXce/J4MA0GCSqGSIb3DQEBBQUAMHExCzAJBgNV BAYTAkNBMRAwDgYDVQQIDAdPbnRhcmlvMRAwDgYDVQQHDAdUb3JvbnRvMQ8wDQYD VQQKDAZzdG9vcHMxEjAQBgNVBAMMCXJhZHNydi1jYTEZMBcGCSqGSIb3DQEJARYK cm9vdEBsb2NhbDAeFw0xNDAzMjYwMTQ1MjJaFw0yNDAzMjMwMTQ1MjJaMHExCzAJ BgNVBAYTAkNBMRAwDgYDVQQIDAdPbnRhcmlvMRAwDgYDVQQHDAdUb3JvbnRvMQ8w DQYDVQQKDAZzdG9vcHMxEjAQBgNVBAMMCXJhZHNydi1jYTEZMBcGCSqGSIb3DQEJ ARYKcm9vdEBsb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMh2 sAnJApatDY+2IjWUmdvMuBmNBXP29FAKUfO6D6EY90MBVPShzaOsr/p4Il7oUDqy rs3wdeCBRLvGV+cHsgyMBlHh2jS6PKHMvVEh3n2kaTb+BAXe6Q2dDdkpGz5BSr31 mYfGuDvBtDop7fE/HQH6NwMM7qHKv8yO433JPPN3E6l7ln1WXRberFkGS39CTA0j dpAzjz2+J8Wfm2zGd/z22ggf1PGw2VukbC+o0TOQpKb05sprLQmqDykMmzv3V5N2 Sa9KUFtQNihGOjHgjRwmys5gniV52cJnAU0hSickMBiWDXp65MEXBaPCqaaqj3DM eHkRArBOcCMnfL7KwWMCAwEAAaNQME4wHQYDVR0OBBYEFO3bA+BXWeWip7bIjvXq vzi3AvshMB8GA1UdIwQYMBaAFO3bA+BXWeWip7bIjvXqvzi3AvshMAwGA1UdEwQF MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJlRk1MPGGONHKmU8WnryvnrhFr+KPfO 5eBzn+7HOSjK27FEmCRoYM3gk6SJJbIX0BtLgtz6o/E+WX7A611Jf5jXbNNOOz1L d8F9NxmcbA3nYXaeTm2/BBOIF4diizQjHIkNS8R+MMOchKMV6WpAb7Ia7W849IbM pQ1I5RxoTMjMy6hdpr1YUYqbTeq6X8z2P9AxiH0cKHxshQVkXFan8JTp290l2IIX tCzIzOCqPWBcScrrhCYTbJl+9YZ1CSRwdos5/XWpCvCHI9cRA9qPLjkoiaZ8ZCHY pxnYlLauxJnCmyk2HW00V5bUJ1vIb1mDV78Y/1kekSwZAvhOW9M1Pag= -----END CERTIFICATE-----
Then you attempt a real connection to the WPA Enterprise access point (with fake credentials!) and wait for the script above to write out the CA Certificate file (verify it against a hash first!). You can then move this file to a user’s directory and point to it with a Wi-Fi connection client. This helps because the built-in Wi-Fi clients on Linux don’t seem to present any server certificate when connecting initially which forces one to manually transfer it around everywhere which is annoying when you have no network connection to begin with!