|
1 | 1 | from binascii import unhexlify |
2 | 2 | import logging |
3 | 3 | import ntpath |
4 | | -from typing import List |
| 4 | +from typing import Any, List |
5 | 5 | from xml.dom import minidom |
| 6 | +from lxml import objectify |
6 | 7 |
|
7 | 8 | from dploot.lib.dpapi import decrypt_blob, find_masterkey_for_blob |
8 | 9 |
|
9 | 10 | from dploot.lib.smb import DPLootSMBConnection |
10 | 11 | from dploot.lib.target import Target |
11 | 12 | from dploot.triage.masterkeys import Masterkey |
12 | 13 |
|
| 14 | +EAP_TYPES = { |
| 15 | + 13:"EAP TLS", |
| 16 | + 18:"EAP SIM", |
| 17 | + 21:"EAP TTLS", |
| 18 | + 23:"EAP AKA", |
| 19 | + 25:"PEAP", |
| 20 | + 50:"EAP AKA PRIME", |
| 21 | + } |
| 22 | + |
13 | 23 | class WifiCred: |
14 | | - def __init__(self, ssid: str, auth: str, username: str = 'N/A', password: str = 'N/A') -> None: |
| 24 | + |
| 25 | + def __init__(self, ssid: str, auth: str, encryption: str, password: str = None, xml_data: Any = None) -> None: |
15 | 26 | self.ssid = ssid |
16 | 27 | self.auth = auth |
17 | | - self.username = username |
| 28 | + self.encryption = encryption |
18 | 29 | self.password = password |
| 30 | + self.xml_data = xml_data |
| 31 | + |
| 32 | + # EAP params |
| 33 | + self.onex = None |
| 34 | + self.eap_host_config = None |
| 35 | + self.eap_type = None |
| 36 | + |
| 37 | + if self.auth == 'WPA2' or self.auth == 'WPA': |
| 38 | + self.onex = getattr(self.xml_data.MSM.security, "{http://www.microsoft.com/networking/OneX/v1}OneX") |
| 39 | + self.eap_host_config = getattr(self.onex.EAPConfig, "{http://www.microsoft.com/provisioning/EapHostConfig}EapHostConfig") |
| 40 | + eap_type = int(getattr(self.eap_host_config.EapMethod, "{http://www.microsoft.com/provisioning/EapCommon}Type")) |
| 41 | + self.eap_type = EAP_TYPES[eap_type] |
19 | 42 |
|
20 | 43 | def dump(self) -> None: |
21 | 44 | print('[WIFI]') |
22 | 45 | print('SSID:\t\t%s' % self.ssid) |
23 | | - print('AuthType:\t%s' % self.auth.upper()) |
24 | | - print('Username:\t%s' % self.username) |
25 | | - print('Password:\t%s' % self.password) |
| 46 | + if self.auth.upper() in ['WPAPSK', 'WPA2PSK']: |
| 47 | + print('AuthType:\t%s' % self.auth.upper()) |
| 48 | + print('Encryption:\t%s' % self.encryption.upper()) |
| 49 | + print('Preshared key:\t%s' % self.password.decode('latin-1')) |
| 50 | + elif self.auth.upper() in ['WPA', 'WPA2']: |
| 51 | + print('AuthType:\t%s EAP' % self.auth.upper()) |
| 52 | + print('Encryption:\t%s' % self.encryption.upper()) |
| 53 | + print('EAP Type:\t%s' % self.eap_type) |
| 54 | + print() |
| 55 | + self.dump_all_xml(self.eap_host_config) |
| 56 | + elif self.auth.upper() == 'OPEN': |
| 57 | + print('AuthType:\t%s' % self.auth.upper()) |
| 58 | + print('Encryption:\t%s' % self.encryption.upper()) |
26 | 59 | print() |
27 | 60 |
|
| 61 | + def dump_all_xml(self,node, n: int = 0) -> None: |
| 62 | + key = node.tag |
| 63 | + if type(node) is objectify.ObjectifiedElement: |
| 64 | + key = key.split("}")[1] if '}' in key else key |
| 65 | + print(' '*n+key+":") |
| 66 | + for element in node.iterchildren() : |
| 67 | + self.dump_all_xml(element, n+1) |
| 68 | + else: |
| 69 | + key = key.split("}")[1] if '}' in key else key |
| 70 | + print("%s%s: %s" % (' '*n, key, node.text)) |
| 71 | + |
| 72 | + |
| 73 | + |
28 | 74 | def dump_quiet(self) -> None: |
29 | 75 | if self.auth.upper() == 'OPEN': |
30 | 76 | print("[WIFI] %s - OPEN" % (self.ssid)) |
31 | | - elif self.auth.upper() in ['WPAPSK', 'WPA2PSK']: |
| 77 | + if self.auth.upper() in ['WPAPSK', 'WPA2PSK']: |
32 | 78 | print("[WIFI] %s - %s - Passphrase: %s" % (self.ssid, self.auth.upper(), self.password)) |
| 79 | + else: |
| 80 | + print("[WIFI] %s - WPA EAP - %s" % (self.ssid, self.eap_type)) |
33 | 81 |
|
34 | 82 | class WifiTriage: |
35 | 83 |
|
@@ -61,22 +109,69 @@ def triage_wifi(self) -> List[WifiCred]: |
61 | 109 | logging.info("Found Wifi connection file: \\\\%s\\%s\\%s" % (self.target.address,self.share,wifi_interface_filepath)) |
62 | 110 | wifi_interface_data = self.conn.readFile(self.share, wifi_interface_filepath) |
63 | 111 | self.looted_files[filename] = wifi_interface_data |
64 | | - xml_data = minidom.parseString(wifi_interface_data) |
65 | | - ssid = xml_data.getElementsByTagName('SSID')[0].getElementsByTagName('name')[0].childNodes[0].data |
66 | | - auth_type = xml_data.getElementsByTagName('authentication')[0].childNodes[0].data |
67 | 112 |
|
68 | | - dpapi_blob = None |
| 113 | + main = objectify.fromstring(wifi_interface_data) |
| 114 | + |
| 115 | + ssid = main.SSIDConfig.SSID.name.text |
| 116 | + auth_type = main.MSM.security.authEncryption.authentication.text |
| 117 | + encryption = main.MSM.security.authEncryption.encryption.text |
| 118 | + |
69 | 119 | if auth_type == 'WPA2PSK' or auth_type == 'WPAPSK': |
70 | | - dpapi_blob = xml_data.getElementsByTagName('keyMaterial')[0].childNodes[0].data |
71 | | - elif auth_type == 'open': |
72 | | - continue |
| 120 | + |
| 121 | + dpapi_blob = main.MSM.security.sharedKey.keyMaterial |
| 122 | + masterkey = find_masterkey_for_blob(unhexlify(dpapi_blob.text), masterkeys=self.masterkeys) |
| 123 | + password = '' |
| 124 | + if masterkey is not None: |
| 125 | + password = decrypt_blob(unhexlify(dpapi_blob.text), masterkey=masterkey) |
| 126 | + wifi_creds.append(WifiCred( |
| 127 | + ssid=ssid, |
| 128 | + auth=auth_type, |
| 129 | + encryption=encryption, |
| 130 | + password=password, |
| 131 | + xml_data=main)) |
73 | 132 | else: |
74 | | - logging.debug('Unsupported authentication type: %s. Please open issue to improve the project!' % auth_type) |
75 | | - masterkey = find_masterkey_for_blob(unhexlify(dpapi_blob), masterkeys=self.masterkeys) |
76 | | - password = '' |
77 | | - if masterkey is not None: |
78 | | - password = decrypt_blob(unhexlify(dpapi_blob), masterkey=masterkey) |
79 | | - wifi_creds.append(WifiCred(ssid, auth_type, password=password)) |
| 133 | + wifi_creds.append(WifiCred( |
| 134 | + ssid=ssid, |
| 135 | + auth=auth_type, |
| 136 | + encryption=encryption, |
| 137 | + xml_data=main)) |
| 138 | + # onex = getattr(main.MSM.security, "{http://www.microsoft.com/networking/OneX/v1}OneX") |
| 139 | + # print(objectify.dump(onex.EAPConfig)) |
| 140 | + # eap_host_config = getattr(onex.EAPConfig, "{http://www.microsoft.com/provisioning/EapHostConfig}EapHostConfig") |
| 141 | + # eap_type = getattr(eap_host_config.EapMethod, "{http://www.microsoft.com/provisioning/EapCommon}Type") |
| 142 | + # print(eap_type) |
| 143 | + # # onex = getattr(onex.EAPConfig, "{http://www.microsoft.com/networking/OneX/v1}EAPConfig") |
| 144 | + # # print(objectify.dump(onex)) |
| 145 | + |
| 146 | + # import sys |
| 147 | + # sys.exit(1) |
| 148 | + |
| 149 | + # xml_data = minidom.parseString(wifi_interface_data) |
| 150 | + # ssid = xml_data.getElementsByTagName('SSID')[0].getElementsByTagName('name')[0].childNodes[0].data |
| 151 | + # auth_type = xml_data.getElementsByTagName('authentication')[0].childNodes[0].data |
| 152 | + # encryption = xml_data.getElementsByTagName('encryption')[0].childNodes[0].data |
| 153 | + # if auth_type == 'WPA2PSK' or auth_type == 'WPAPSK': # WPA Personnal |
| 154 | + # dpapi_blob = xml_data.getElementsByTagName('keyMaterial')[0].childNodes[0].data |
| 155 | + # masterkey = find_masterkey_for_blob(unhexlify(dpapi_blob), masterkeys=self.masterkeys) |
| 156 | + # password = '' |
| 157 | + # if masterkey is not None: |
| 158 | + # password = decrypt_blob(unhexlify(dpapi_blob), masterkey=masterkey) |
| 159 | + # wifi_creds.append(WifiCred(ssid, auth_type, encryption=encryption,password=password)) |
| 160 | + # elif auth_type == 'WPA2' or auth_type == 'WPA': # WPA Entreprise |
| 161 | + # print('waza') |
| 162 | + # print(wifi_interface_data.decode('utf-8')) |
| 163 | + |
| 164 | + # eap_type = xml_data.getElementsByTagName('Type')[0].childNodes[0].data |
| 165 | + # eap_config = xml_data.getElementsByTagName('EAPConfig') |
| 166 | + # print(eap_config) |
| 167 | + # # eap_type = xml_data.getElementsByTagName('authMode')[0].childNodes[0].data |
| 168 | + |
| 169 | + # # https://learn.microsoft.com/en-us/windows/win32/nativewifi/wpa2-enterprise-with-peap-mschapv2-profile-sample |
| 170 | + # wifi_creds.append(WifiCred(ssid, auth_type, encryption=encryption,eap_type=eap_type)) |
| 171 | + # elif auth_type == 'open': # OPEN |
| 172 | + # wifi_creds.append(WifiCred(ssid, auth_type, encryption=encryption)) |
| 173 | + # else: |
| 174 | + # logging.debug('Unsupported authentication type: %s. Please open issue to improve the project!' % auth_type) |
80 | 175 | except Exception as e: |
81 | 176 | if logging.getLogger().level == logging.DEBUG: |
82 | 177 | import traceback |
|
0 commit comments