diff --git a/documentation/search.js b/documentation/search.js
index 0037d97..8c80f7e 100644
--- a/documentation/search.js
+++ b/documentation/search.js
@@ -1,6 +1,6 @@
window.pdocSearch = (function(){
/** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u
A class to handle command completion for the smbclient-ng shell.
\n\nThis class provides a command completion feature that suggests possible command names based on the current input.\nIt uses a dictionary to store commands and their descriptions, which helps in providing hints during the command line\ninteraction in the smbclient-ng shell.
\n\nAttributes:\n smbSession (SMBSession): An instance of SMBSession which maintains the current SMB session.\n commands (dict): A dictionary containing command names as keys and their descriptions and subcommands as values.
\n\nMethods:\n __init__(self, smbSession): Initializes the CommandCompleter with an SMBSession.
\n"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.__init__", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.__init__", "kind": "function", "doc": "\n", "signature": "(smbSession, config)"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.commands", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.commands", "kind": "variable", "doc": "\n", "default_value": "{'bat': {'description': ['Pretty prints the contents of a remote file.', "Syntax: 'bat <file>'"], 'subcommands': []}, 'cat': {'description': ['Get the contents of a remote file.', "Syntax: 'cat <file>'"], 'subcommands': []}, 'cd': {'description': ['Change the current working directory.', "Syntax: 'cd <directory>'"], 'subcommands': []}, 'close': {'description': ['Closes the SMB connection to the remote machine.', "Syntax: 'close'"], 'subcommands': []}, 'connect': {'description': ['Connect to the remote machine (useful if connection timed out).', "Syntax: 'connect'"], 'subcommands': []}, 'debug': {'description': ['Command for dev debugging.', "Syntax: 'debug'"], 'subcommands': []}, 'dir': {'description': ['List the contents of the current working directory.', "Syntax: 'dir'"], 'subcommands': []}, 'exit': {'description': ['Exits the smbclient-ng script.', "Syntax: 'exit'"], 'subcommands': []}, 'get': {'description': ['Get a remote file.', "Syntax: 'get [-r] <directory or file>'"], 'subcommands': []}, 'help': {'description': ['Displays this help message.', "Syntax: 'help'"], 'subcommands': ['format']}, 'info': {'description': ['Get information about the server and or the share.', "Syntax: 'info [server|share]'"], 'subcommands': ['server', 'share']}, 'lbat': {'description': ['Pretty prints the contents of a local file.', "Syntax: 'lbat <file>'"], 'subcommands': []}, 'lcat': {'description': ['Print the contents of a local file.', "Syntax: 'lcat <file>'"], 'subcommands': []}, 'lcd': {'description': ['Changes the current local directory.', "Syntax: 'lcd <directory>'"], 'subcommands': []}, 'lcp': {'description': ['Create a copy of a local file.', "Syntax: 'lcp <srcfile> <dstfile>'"], 'subcommands': []}, 'lls': {'description': ['Lists the contents of the current local directory.', "Syntax: 'lls'"], 'subcommands': []}, 'lmkdir': {'description': ['Creates a new local directory.', "Syntax: 'lmkdir <directory>'"], 'subcommands': []}, 'lpwd': {'description': ['Shows the current local directory.', "Syntax: 'lpwd'"], 'subcommands': []}, 'lrename': {'description': ['Renames a local file.', "Syntax: 'lrename <oldfilename> <newfilename>'"], 'subcommands': []}, 'lrm': {'description': ['Removes a local file.', "Syntax: 'lrm <file>'"], 'subcommands': []}, 'lrmdir': {'description': ['Removes a local directory.', "Syntax: 'lrmdir <directory>'"], 'subcommands': []}, 'ls': {'description': ['List the contents of the current remote working directory.', "Syntax: 'ls'"], 'subcommands': []}, 'ltree': {'description': ['Displays a tree view of the local directories.', "Syntax: 'ltree [directory]'"], 'subcommands': []}, 'mkdir': {'description': ['Creates a new remote directory.', "Syntax: 'mkdir <directory>'"], 'subcommands': []}, 'module': {'description': ['Loads a specific module for additional functionalities.', "Syntax: 'module <name>'"], 'subcommands': []}, 'mount': {'description': ['Creates a mount point of the remote share on the local machine.', "Syntax: 'mount <remote_path> <local_mountpoint>'"], 'subcommands': []}, 'put': {'description': ['Put a local file or directory in a remote directory.', "Syntax: 'put [-r] <directory or file>'"], 'subcommands': []}, 'reconnect': {'description': ['Reconnect to the remote machine (useful if connection timed out).', "Syntax: 'reconnect'"], 'subcommands': []}, 'reset': {'description': ['Reset the TTY output, useful if it was broken after printing a binary file on stdout.', "Syntax: 'reset'"], 'subcommands': []}, 'rmdir': {'description': ['Removes a remote directory.', "Syntax: 'rmdir <directory>'"], 'subcommands': []}, 'rm': {'description': ['Removes a remote file.', "Syntax: 'rm <file>'"], 'subcommands': []}, 'sizeof': {'description': ['Recursively compute the size of a folder.', "Syntax: 'sizeof [directory|file]'"], 'subcommands': []}, 'shares': {'description': ['Lists the SMB shares served by the remote machine.', "Syntax: 'shares'"], 'subcommands': []}, 'tree': {'description': ['Displays a tree view of the remote directories.', "Syntax: 'tree [directory]'"], 'subcommands': []}, 'umount': {'description': ['Removes a mount point of the remote share on the local machine.', "Syntax: 'umount <local_mount_point>'"], 'subcommands': []}, 'use': {'description': ['Use a SMB share.', "Syntax: 'use <sharename>'"], 'subcommands': []}}"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.smbSession", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.smbSession", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.config", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.config", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.complete", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.complete", "kind": "function", "doc": "Function to handle command completion in the LDAP console.
\n\nThis function completes the user\"s input based on the available options for commands in the LDAP console.
\n\nArgs:\n text (str): The current text input by the user.\n state (int): The current state of completion.
\n\nReturns:\n str: The next completion suggestion based on the user\"s input state.
\n", "signature": "(self, text, state):", "funcdef": "def"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.print_help", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.print_help", "kind": "function", "doc": "Prints help information for a specific command or all commands if no command is specified.
\n\nThis method displays the help information for the command passed as an argument. If no command is specified,\nit prints the help information for all available commands. The help information includes the command syntax,\ndescription, and any subcommands associated with it. This method is designed to provide users with the necessary\nguidance on how to use the commands in the smbclient-ng shell.
\n\nArgs:\n command (str, optional): The command to display help information for. If None, help for all commands is displayed.
\n\nReturns:\n None
\n", "signature": "(self, command=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.print_help_format", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.print_help_format", "kind": "function", "doc": "Prints the help information for the 'format' used in remote 'ls' and 'dir' commands.
\n\nThis function displays the format of file attributes used in the smbclient-ng shell. It explains the meaning\nof each character in the file attribute string, such as whether a file is read-only, hidden, or a directory.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.Config", "modulename": "smbclientng.core.Config", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.Config.Config", "modulename": "smbclientng.core.Config", "qualname": "Config", "kind": "class", "doc": "Configuration handler for smbclientng.
\n\nThis class manages the configuration settings for the smbclientng tool, including debug and color output settings.\nIt provides a structured way to access and modify these settings throughout the application.
\n\nAttributes:\n _debug (bool): Flag to enable or disable debug mode.\n _no_colors (bool): Flag to enable or disable colored output, depending on the platform.
\n\nMethods:\n debug: Property to get or set the debug mode.\n no_colors: Property to get or set the colored output preference.
\n"}, {"fullname": "smbclientng.core.Config.Config.__init__", "modulename": "smbclientng.core.Config", "qualname": "Config.__init__", "kind": "function", "doc": "\n", "signature": "(debug=False, no_colors=None)"}, {"fullname": "smbclientng.core.Config.Config.debug", "modulename": "smbclientng.core.Config", "qualname": "Config.debug", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.Config.Config.no_colors", "modulename": "smbclientng.core.Config", "qualname": "Config.no_colors", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell", "modulename": "smbclientng.core.InteractiveShell", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell.command_arguments_required", "modulename": "smbclientng.core.InteractiveShell", "qualname": "command_arguments_required", "kind": "function", "doc": "\n", "signature": "(func):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.active_smb_connection_needed", "modulename": "smbclientng.core.InteractiveShell", "qualname": "active_smb_connection_needed", "kind": "function", "doc": "\n", "signature": "(func):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.smb_share_is_set", "modulename": "smbclientng.core.InteractiveShell", "qualname": "smb_share_is_set", "kind": "function", "doc": "\n", "signature": "(func):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell", "kind": "class", "doc": "Class InteractiveShell is designed to manage the interactive command line interface for smbclient-ng.
\n\nThis class handles user input, executes commands, and manages the state of the SMB session. It provides\na command line interface for users to interact with SMB shares, execute commands like directory listing,\nfile transfer, and more.
\n\nAttributes:\n smbSession (SMBConnection): The active SMB connection session.\n debug (bool): Flag to enable or disable debug mode.\n smb_share (str): The current SMB share in use.\n smb_path (str): The current path within the SMB share.\n commandCompleterObject (CommandCompleter): Object to handle command completion and help generation.
\n\nMethods:\n __init__(self, smbSession, debug=False): Initializes the InteractiveShell with the given SMB session and debug mode.\n run(self): Starts the command line interface loop, processing user input until exit.
\n"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.__init__", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.__init__", "kind": "function", "doc": "\n", "signature": "(smbSession, config)"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.smbSession", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.smbSession", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.config", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.config", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.commandCompleterObject", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.commandCompleterObject", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.modules", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.modules", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.run", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.run", "kind": "function", "doc": "\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.process_command", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.process_command", "kind": "function", "doc": "\n", "signature": "(self, command, arguments=[]):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_debug", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_debug", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_bat", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_bat", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_cd", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_cd", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_cat", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_cat", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_close", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_close", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_get", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_get", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_help", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_help", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_info", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_info", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lcat", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lcat", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lcd", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lcd", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lcp", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lcp", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lbat", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lbat", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lls", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lls", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lmkdir", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lmkdir", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lpwd", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lpwd", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lrename", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lrename", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lrm", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lrm", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lrmdir", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lrmdir", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_ltree", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_ltree", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_ls", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_ls", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_mkdir", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_mkdir", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_module", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_module", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_mount", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_mount", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_put", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_put", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_reconnect", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_reconnect", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_reset", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_reset", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_rm", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_rm", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_rmdir", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_rmdir", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_sizeof", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_sizeof", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_shares", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_shares", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_tree", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_tree", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_umount", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_umount", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_use", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_use", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.LocalFileIO", "modulename": "smbclientng.core.LocalFileIO", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO", "kind": "class", "doc": "Class LocalFileIO is designed to handle local file input/output operations within the smbclient-ng tool.\nIt provides functionalities to open, read, write, and manage progress of file operations based on the expected size of the file.
\n\nAttributes:\n mode (str): The mode in which the file should be opened (e.g., 'rb', 'wb').\n path (str): The path to the file that needs to be handled.\n expected_size (int, optional): The expected size of the file in bytes. This is used to display progress.\n debug (bool): Flag to enable debug mode which provides additional output during operations.
\n\nMethods:\n __init__(self, mode, path=None, expected_size=None, debug=False): Initializes the LocalFileIO instance.\n write(self, data): Writes data to the file and updates the progress bar if expected size is provided.\n read(self, size): Reads data from the file up to the specified size and updates the progress bar if expected size is provided.
\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.__init__", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.__init__", "kind": "function", "doc": "\n", "signature": "(\tmode,\tpath=None,\texpected_size=None,\tkeepRemotePath=False,\tdebug=False)"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.mode", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.mode", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.path", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.path", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.dir", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.dir", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.debug", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.debug", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.expected_size", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.expected_size", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.keepRemotePath", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.keepRemotePath", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.write", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.write", "kind": "function", "doc": "Writes data to the file.
\n\nThis method writes the specified data to the file and updates the progress bar with the amount of data written if the expected size is set.
\n\nArgs:\n data (bytes): The data to be written to the file.
\n\nReturns:\n int: The number of bytes written.
\n", "signature": "(self, data):", "funcdef": "def"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.read", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.read", "kind": "function", "doc": "Reads a specified amount of data from the file.
\n\nThis method reads data from the file based on the size specified. It also updates the progress bar with the amount of data read if the expected size is set.
\n\nArgs:\n size (int): The number of bytes to read from the file.
\n\nReturns:\n bytes: The data read from the file.
\n", "signature": "(self, size):", "funcdef": "def"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.close", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.close", "kind": "function", "doc": "Closes the file descriptor and optionally removes the file.
\n\nThis method ensures that the file descriptor is properly closed and the file is removed if specified.\nIt also stops the progress bar if it was initiated and cleans up the object by deleting it.
\n\nArgs:\n remove (bool): If True, the file at the path will be removed after closing the file descriptor.
\n", "signature": "(self, remove=False):", "funcdef": "def"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.set_error", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.set_error", "kind": "function", "doc": "Sets an error message in the progress bar's description and modifies the progress bar to show only essential columns.
\n\nThis method is used to communicate error states or important messages directly in the progress bar interface.\nIt updates the task description with the provided message and simplifies the progress bar to show only the text\nand download columns, removing other elements like speed and time remaining which may not be relevant in an error state.
\n\nArgs:\n message (str): The error or status message to display in the progress bar.
\n", "signature": "(self, message):", "funcdef": "def"}, {"fullname": "smbclientng.core.Module", "modulename": "smbclientng.core.Module", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.Module.Module", "modulename": "smbclientng.core.Module", "qualname": "Module", "kind": "class", "doc": "A parent class for all modules in the smbclient-ng tool.
\n\nThis class provides common attributes and methods that are shared among different modules.
\n"}, {"fullname": "smbclientng.core.Module.Module.__init__", "modulename": "smbclientng.core.Module", "qualname": "Module.__init__", "kind": "function", "doc": "\n", "signature": "(smbSession, config)"}, {"fullname": "smbclientng.core.Module.Module.name", "modulename": "smbclientng.core.Module", "qualname": "Module.name", "kind": "variable", "doc": "\n", "default_value": "''"}, {"fullname": "smbclientng.core.Module.Module.description", "modulename": "smbclientng.core.Module", "qualname": "Module.description", "kind": "variable", "doc": "\n", "default_value": "''"}, {"fullname": "smbclientng.core.Module.Module.smbSession", "modulename": "smbclientng.core.Module", "qualname": "Module.smbSession", "kind": "variable", "doc": "\n", "default_value": "None"}, {"fullname": "smbclientng.core.Module.Module.options", "modulename": "smbclientng.core.Module", "qualname": "Module.options", "kind": "variable", "doc": "\n", "default_value": "None"}, {"fullname": "smbclientng.core.Module.Module.config", "modulename": "smbclientng.core.Module", "qualname": "Module.config", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.Module.Module.parseArgs", "modulename": "smbclientng.core.Module", "qualname": "Module.parseArgs", "kind": "function", "doc": "\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.Module.Module.run", "modulename": "smbclientng.core.Module", "qualname": "Module.run", "kind": "function", "doc": "Placeholder method for running the module.
\n\nThis method should be implemented by subclasses to define the specific behavior of the module.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.Module.Module.processArguments", "modulename": "smbclientng.core.Module", "qualname": "Module.processArguments", "kind": "function", "doc": "\n", "signature": "(self, parser, arguments):", "funcdef": "def"}, {"fullname": "smbclientng.core.ModuleArgumentParser", "modulename": "smbclientng.core.ModuleArgumentParser", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.ModuleArgumentParser.ModuleArgumentParser", "modulename": "smbclientng.core.ModuleArgumentParser", "qualname": "ModuleArgumentParser", "kind": "class", "doc": "A custom argument parser for handling module-specific command-line arguments in the smbclientng application.
\n\nThis class extends the argparse.ArgumentParser and provides custom error handling specific to the needs of smbclientng modules.\nIt is designed to provide clear and user-friendly command-line interfaces for various modules within the smbclientng suite.
\n\nAttributes:\n None
\n\nMethods:\n error(message: str):\n Overrides the default error handling to provide a more informative error message and display the help text.
\n", "bases": "argparse.ArgumentParser"}, {"fullname": "smbclientng.core.ModuleArgumentParser.ModuleArgumentParser.error", "modulename": "smbclientng.core.ModuleArgumentParser", "qualname": "ModuleArgumentParser.error", "kind": "function", "doc": "Overrides the default error handling of argparse.ArgumentParser to provide a custom error message and help display.
\n\nThis method is called when ArgumentParser encounters an error. It writes the error message to stderr,\ndisplays the help message, and then exits the program with a status code of 2.
\n\nArgs:\n message (str): The error message to be displayed.
\n", "signature": "(self, message):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession", "modulename": "smbclientng.core.SMBSession", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession", "kind": "class", "doc": "Class SMBSession is designed to handle the session management for SMB (Server Message Block) protocol connections.\nIt provides functionalities to connect to an SMB server, authenticate using either NTLM or Kerberos, and manage SMB shares.
\n\nAttributes:\n address (str): The IP address or hostname of the SMB server.\n domain (str): The domain name for SMB server authentication.\n username (str): The username for SMB server authentication.\n password (str): The password for SMB server authentication.\n lmhash (str): The LM hash of the user's password, if available.\n nthash (str): The NT hash of the user's password, if available.\n use_kerberos (bool): A flag to determine whether to use Kerberos for authentication.\n kdcHost (str): The Key Distribution Center (KDC) host for Kerberos authentication.\n debug (bool): A flag to enable debug output.\n smbClient (object): The SMB client object used for the connection.\n connected (bool): A flag to check the status of the connection.\n smb_share (str): The current SMB share in use.\n smb_path (str): The current path within the SMB share.
\n\nMethods:\n __init__(address, domain, username, password, lmhash, nthash, use_kerberos=False, kdcHost=None, debug=False):\n Initializes the SMBSession with the specified parameters.\n init_smb_session():\n Initializes the SMB session by connecting to the server and authenticating using the specified method.
\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.__init__", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.__init__", "kind": "function", "doc": "\n", "signature": "(\taddress,\tdomain,\tusername,\tpassword,\tlmhash,\tnthash,\tuse_kerberos=False,\tkdcHost=None,\tconfig=None)"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.config", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.config", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.address", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.address", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.domain", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.domain", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.username", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.username", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.password", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.password", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.lmhash", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.lmhash", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.nthash", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.nthash", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.use_kerberos", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.use_kerberos", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.kdcHost", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.kdcHost", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.smbClient", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.smbClient", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.connected", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.connected", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.available_shares", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.available_shares", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.smb_share", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.smb_share", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.smb_cwd", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.smb_cwd", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.smb_tree_id", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.smb_tree_id", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.init_smb_session", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.init_smb_session", "kind": "function", "doc": "Initializes and establishes a session with the SMB server.
\n\nThis method sets up the SMB connection using either Kerberos or NTLM authentication based on the configuration.\nIt attempts to connect to the SMB server specified by the address
attribute and authenticate using the credentials provided during the object's initialization.
The method will print debug information if the debug
attribute is set to True. Upon successful connection and authentication, it sets the connected
attribute to True.
Returns:\n bool: True if the connection and authentication are successful, False otherwise.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.close_smb_session", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.close_smb_session", "kind": "function", "doc": "Closes the current SMB session by disconnecting the SMB client.
\n\nThis method ensures that the SMB client connection is properly closed. It checks if the client is connected\nand if so, it closes the connection and resets the connection status.
\n\nRaises:\n Exception: If the SMB client is not initialized or if there's an error during the disconnection process.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.read_file", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.read_file", "kind": "function", "doc": "\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.find", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.find", "kind": "function", "doc": "\n", "signature": "(self, paths=[], callback=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.get_file", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.get_file", "kind": "function", "doc": "Retrieves a file from the specified path on the SMB share.
\n\nThis method attempts to retrieve a file from the given path within the currently connected SMB share.\nIf the path points to a directory, it skips the retrieval. It handles file retrieval by creating a local\nfile object and writing the contents of the remote file to it using the SMB client's getFile method.
\n\nParameters:\n path (str): The path of the file to retrieve. If None, uses the current smb_path.
\n\nReturns:\n None
\n", "signature": "(self, path=None, keepRemotePath=False):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.get_file_recursively", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.get_file_recursively", "kind": "function", "doc": "Recursively retrieves files from a specified path on the SMB share.
\n\nThis method navigates through all directories starting from the given path,\nand downloads all files found. It handles directories recursively, ensuring\nthat all nested files are retrieved. The method skips over directory entries\nand handles errors gracefully, attempting to continue the operation where possible.
\n\nParameters:\n path (str): The initial directory path from which to start the recursive file retrieval.\n If None, it starts from the root of the configured SMB share.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.get_entry", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.get_entry", "kind": "function", "doc": "Retrieves information about a specific entry located at the provided path on the SMB share.
\n\nThis method checks if the specified path exists on the SMB share. If the path exists, it retrieves the details of the entry at that path, including the directory name and file name. If the entry is found, it returns the entry object; otherwise, it returns None.
\n\nArgs:\n path (str): The path of the entry to retrieve information about.
\n\nReturns:\n Entry: An object representing the entry at the specified path, or None if the entry is not found.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.info", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.info", "kind": "function", "doc": "Displays information about the server and optionally the shares.
\n\nThis method prints detailed information about the server's characteristics such as NetBIOS names, DNS details, OS information, and SMB capabilities. If the share
parameter is set to True and a share is currently set, it will also attempt to display information about the share.
Parameters:\n share (bool): If True, display information about the current share.\n server (bool): If True, display information about the server.
\n\nReturns:\n None
\n", "signature": "(self, share=True, server=True):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.list_contents", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.list_contents", "kind": "function", "doc": "Lists the contents of a specified directory on the SMB share.
\n\nThis method retrieves the contents of a directory specified by shareName
and path
. If shareName
or path
\nis not provided, it defaults to the instance's current SMB share or path. The method returns a dictionary with\nthe long names of the files and directories as keys and their respective SMB entry objects as values.
Args:\n shareName (str, optional): The name of the SMB share. Defaults to the current SMB share if None.\n path (str, optional): The directory path to list contents from. Defaults to the current path if None.
\n\nReturns:\n dict: A dictionary with file and directory names as keys and their SMB entry objects as values.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.list_shares", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.list_shares", "kind": "function", "doc": "Lists all the shares available on the connected SMB server.
\n\nThis method queries the SMB server to retrieve a list of all available shares. It populates the shares
dictionary\nwith key-value pairs where the key is the share name and the value is a dictionary containing details about the share\nsuch as its name, type, raw type, and any comments associated with the share.
Returns:\n dict: A dictionary containing information about each share available on the server.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.mkdir", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.mkdir", "kind": "function", "doc": "Creates a directory at the specified path on the SMB share.
\n\nThis method takes a path and attempts to create the directory structure on the SMB share. If the path includes\nnested directories, it will create each directory in the sequence. If a directory already exists, it will skip\nthe creation for that directory without raising an error.
\n\nArgs:\n path (str, optional): The full path of the directory to create on the SMB share. Defaults to None.
\n\nNote:\n The path should use forward slashes ('/') which will be converted to backslashes (ntpath.sep) for SMB compatibility.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.mount", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.mount", "kind": "function", "doc": "\n", "signature": "(self, local_mount_point, remote_path):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.path_exists", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.path_exists", "kind": "function", "doc": "Checks if the specified path exists on the SMB share.
\n\nThis method determines if a given path exists on the SMB share by attempting to list the contents of the path.\nIf the path listing is successful and returns one or more entries, the path is considered to exist.
\n\nArgs:\n path (str, optional): The path to check on the SMB share. Defaults to None.
\n\nReturns:\n bool: True if the path exists, False otherwise or if an error occurs.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.path_isdir", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.path_isdir", "kind": "function", "doc": "Checks if the specified path is a directory on the SMB share.
\n\nThis method determines if a given path corresponds to a directory on the SMB share. It does this by listing the\ncontents of the path and filtering for entries that match the basename of the path and are marked as directories.
\n\nArgs:\n path (str, optional): The path to check on the SMB share. Defaults to None.
\n\nReturns:\n bool: True if the path is a directory, False otherwise or if an error occurs.
\n", "signature": "(self, pathFromRoot=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.path_isfile", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.path_isfile", "kind": "function", "doc": "Checks if the specified path is a file on the SMB share.
\n\nThis method determines if a given path corresponds to a file on the SMB share. It does this by listing the\ncontents of the path and filtering for entries that match the basename of the path and are not marked as directories.
\n\nArgs:\n path (str, optional): The path to check on the SMB share. Defaults to None.
\n\nReturns:\n bool: True if the path is a file, False otherwise or if an error occurs.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.ping_smb_session", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.ping_smb_session", "kind": "function", "doc": "Tests the connectivity to the SMB server by sending an echo command.
\n\nThis method attempts to send an echo command to the SMB server to check if the session is still active.\nIt updates the connected
attribute of the class based on the success or failure of the echo command.
Returns:\n bool: True if the echo command succeeds (indicating the session is active), False otherwise.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.put_file", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.put_file", "kind": "function", "doc": "Uploads a single file to the SMB share.
\n\nThis method takes a local file path, opens the file, and uploads it to the SMB share at the specified path.\nIt handles exceptions such as broken pipe errors or keyboard interrupts by closing and reinitializing the SMB session.\nGeneral exceptions are caught and logged, with a traceback provided if debugging is enabled.
\n\nArgs:\n localpath (str, optional): The local file path of the file to be uploaded. Defaults to None.
\n", "signature": "(self, localpath=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.put_file_recursively", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.put_file_recursively", "kind": "function", "doc": "Recursively uploads files from a specified local directory to the SMB share.
\n\nThis method walks through the given local directory and all its subdirectories, uploading each file to the\ncorresponding directory structure on the SMB share. It first checks if the local path is a directory. If it is,\nit iterates over all files and directories within the local path, creating necessary directories on the SMB share\nand uploading files. If the local path is not a directory, it prints an error message.
\n\nArgs:\n localpath (str, optional): The local directory path from which files will be uploaded. Defaults to None.
\n", "signature": "(self, localpath=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.rmdir", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.rmdir", "kind": "function", "doc": "Removes a directory from the SMB share at the specified path.
\n\nThis method attempts to delete a directory located at the given path on the SMB share. If the operation fails,\nit prints an error message indicating the failure and the reason. If debugging is enabled, it also prints\nthe stack trace of the exception.
\n\nArgs:\n path (str, optional): The path of the directory to be removed on the SMB share. Defaults to None.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.rm", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.rm", "kind": "function", "doc": "Removes a file from the SMB share at the specified path.
\n\nThis method attempts to delete a file located at the given path on the SMB share. If the operation fails,\nit prints an error message indicating the failure and the reason. If debugging is enabled, it also prints\nthe stack trace of the exception.
\n\nArgs:\n path (str, optional): The path of the file to be removed on the SMB share. Defaults to None.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.tree", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.tree", "kind": "function", "doc": "Recursively lists the directory structure of the SMB share starting from the specified path.
\n\nThis function prints a visual representation of the directory tree of the remote SMB share. It uses\nrecursion to navigate through directories and lists all files and subdirectories in each directory.\nThe output is color-coded and formatted to enhance readability, with directories highlighted in cyan.
\n\nArgs:\n path (str, optional): The starting path on the SMB share from which to begin listing the tree.\n Defaults to the root of the current share.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.umount", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.umount", "kind": "function", "doc": "\n", "signature": "(self, local_mount_point):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.set_share", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.set_share", "kind": "function", "doc": "Sets the current SMB share to the specified share name.
\n\nThis method updates the SMB session to use the specified share name. It checks if the share name is valid\nand updates the smb_share attribute of the SMBSession instance.
\n\nParameters:\n shareName (str): The name of the share to set as the current SMB share.
\n\nRaises:\n ValueError: If the shareName is None or an empty string.
\n", "signature": "(self, shareName):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.set_cwd", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.set_cwd", "kind": "function", "doc": "Sets the current working directory on the SMB share to the specified path.
\n\nThis method updates the current working directory (cwd) of the SMB session to the given path if it is a valid directory.\nIf the specified path is not a directory, the cwd remains unchanged.
\n\nParameters:\n path (str): The path to set as the current working directory.
\n\nRaises:\n ValueError: If the specified path is not a directory.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils", "modulename": "smbclientng.core.utils", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.utils.parse_lm_nt_hashes", "modulename": "smbclientng.core.utils", "qualname": "parse_lm_nt_hashes", "kind": "function", "doc": "Parse the input string containing LM and NT hash values and return them separately.
\n\nThis function takes a string containing LM and NT hash values, typically separated by a colon (:).\nIt returns the LM and NT hash values as separate strings. If only one hash value is provided, it is\nassumed to be the NT hash and the LM hash is set to its default value. If no valid hash values are\nfound, both return values are empty strings.
\n\nArgs:\n lm_nt_hashes_string (str): A string containing LM and NT hash values separated by a colon.
\n\nReturns:\n tuple: A tuple containing two strings (lm_hash_value, nt_hash_value).\n - lm_hash_value: The LM hash value or its default if not provided.\n - nt_hash_value: The NT hash value or its default if not provided.
\n\nExtracted from p0dalirius/sectools library\nSrc: https://github.com/p0dalirius/sectools/blob/7bb3f5cb7815ad4d4845713c8739e2e2b0ea4e75/sectools/windows/crypto.py#L11-L24
\n", "signature": "(lm_nt_hashes_string):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils.b_filesize", "modulename": "smbclientng.core.utils", "qualname": "b_filesize", "kind": "function", "doc": "Convert a file size from bytes to a more readable format using the largest appropriate unit.
\n\nThis function takes an integer representing a file size in bytes and converts it to a human-readable\nstring using the largest appropriate unit from bytes (B) to petabytes (PB). The result is rounded to\ntwo decimal places.
\n\nArgs:\n l (int): The file size in bytes.
\n\nReturns:\n str: A string representing the file size in a more readable format, including the appropriate unit.
\n", "signature": "(l):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils.unix_permissions", "modulename": "smbclientng.core.utils", "qualname": "unix_permissions", "kind": "function", "doc": "Generate a string representing the Unix-style permissions for a given file or directory.
\n\nThis function uses the os.lstat() method to retrieve the status of the specified file or directory,\nthen constructs a string that represents the Unix-style permissions based on the mode of the file.
\n\nArgs:\n entryname (str): The path to the file or directory for which permissions are being determined.
\n\nReturns:\n str: A string of length 10 representing the Unix-style permissions (e.g., '-rwxr-xr--').\n The first character is either 'd' (directory), '-' (not a directory), followed by\n three groups of 'r', 'w', 'x' (read, write, execute permissions) for owner, group,\n and others respectively.
\n", "signature": "(entryname):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils.STYPE_MASK", "modulename": "smbclientng.core.utils", "qualname": "STYPE_MASK", "kind": "function", "doc": "Extracts the share type flags from a given share type value.
\n\nThis function uses bitwise operations to determine which share type flags are set in the provided stype_value
.\nIt checks against known share type flags and returns a list of the flags that are set.
Parameters:\n stype_value (int): The share type value to analyze, typically obtained from SMB share properties.
\n\nReturns:\n list: A list of strings, where each string represents a share type flag that is set in the input value.
\n", "signature": "(stype_value):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils.windows_ls_entry", "modulename": "smbclientng.core.utils", "qualname": "windows_ls_entry", "kind": "function", "doc": "This function generates a metadata string based on the attributes of the provided entry object.
\n\nParameters:\n entry (object): An object representing a file or directory entry.
\n\nReturns:\n str: A string representing the metadata of the entry, including attributes like directory, archive, compressed, hidden, normal, readonly, system, and temporary.
\n", "signature": "(entry, config, pathToPrint=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils.local_tree", "modulename": "smbclientng.core.utils", "qualname": "local_tree", "kind": "function", "doc": "This function recursively lists the contents of a directory in a tree-like format.
\n\nParameters:\n path (str): The path to the directory to list.\n config (object): Configuration settings which may affect the output, such as whether to use colors.
\n\nReturns:\n None: This function does not return anything but prints the directory tree to the console.
\n", "signature": "(path, config):", "funcdef": "def"}, {"fullname": "smbclientng.modules", "modulename": "smbclientng.modules", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.modules.Find", "modulename": "smbclientng.modules.Find", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.modules.Find.Find", "modulename": "smbclientng.modules.Find", "qualname": "Find", "kind": "class", "doc": "A class to search for files in a directory hierarchy.
\n\nThis class provides functionality to search for files based on various criteria in a directory hierarchy.
\n", "bases": "smbclientng.core.Module.Module"}, {"fullname": "smbclientng.modules.Find.Find.name", "modulename": "smbclientng.modules.Find", "qualname": "Find.name", "kind": "variable", "doc": "\n", "default_value": "'find'"}, {"fullname": "smbclientng.modules.Find.Find.description", "modulename": "smbclientng.modules.Find", "qualname": "Find.description", "kind": "variable", "doc": "\n", "default_value": "'Search for files in a directory hierarchy'"}, {"fullname": "smbclientng.modules.Find.Find.parseArgs", "modulename": "smbclientng.modules.Find", "qualname": "Find.parseArgs", "kind": "function", "doc": "Parses the command line arguments provided to the module.
\n\nThis method initializes the argument parser with the module's name and description, and defines all the necessary arguments that the module accepts. It then parses the provided command line arguments based on these definitions.
\n\nArgs:\n arguments (str): A string of command line arguments.
\n\nReturns:\n ModuleArgumentParser.Namespace | None: The parsed arguments as a Namespace object if successful, None if there are no arguments or help is requested.
\n", "signature": "(self, arguments):", "funcdef": "def"}, {"fullname": "smbclientng.modules.Find.Find.run", "modulename": "smbclientng.modules.Find", "qualname": "Find.run", "kind": "function", "doc": "This function recursively searches for files in a directory hierarchy and prints the results based on specified criteria.
\n\nArgs:\n base_dir (str): The base directory to start the search from.\n paths (list): List of paths to search within the base directory.\n depth (int): The current depth level in the directory hierarchy.
\n\nReturns:\n None
\n", "signature": "(self, arguments):", "funcdef": "def"}, {"fullname": "smbclientng.modules.GPPPasswords", "modulename": "smbclientng.modules.GPPPasswords", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords", "kind": "class", "doc": "GPPPasswords is a module designed to search and retrieve stored Group Policy Preferences (GPP) passwords from specified network shares. \nIt leverages the SMB protocol to access files across the network, parse them, and extract credentials that are often stored within Group Policy Preferences files.
\n\nThis module is particularly useful in penetration testing scenarios where discovering stored credentials can lead to further system access or reveal poor security practices.
\n\nAttributes:\n name (str): The name of the module, used in command line invocation.\n description (str): A brief description of what the module does.
\n\nMethods:\n parseArgs(arguments): Parses and handles command line arguments for the module.\n parse_xmlfile_content(pathtofile): Parses the content of an XML file to extract credentials.
\n", "bases": "smbclientng.core.Module.Module"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.name", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.name", "kind": "variable", "doc": "\n", "default_value": "'gpppasswords'"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.description", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.description", "kind": "variable", "doc": "\n", "default_value": "'Searches for Group Policy Preferences Passwords in a share.'"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.parseArgs", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.parseArgs", "kind": "function", "doc": "Parses the command line arguments provided to the module.
\n\nThis method initializes the argument parser with the module's name and description, and defines all the necessary arguments that the module accepts. It then parses the provided command line arguments based on these definitions.
\n\nArgs:\n arguments (str): A string of command line arguments.
\n\nReturns:\n ModuleArgumentParser.Namespace | None: The parsed arguments as a Namespace object if successful, None if there are no arguments or help is requested.
\n", "signature": "(self, arguments):", "funcdef": "def"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.parse_xmlfile_content", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.parse_xmlfile_content", "kind": "function", "doc": "Parses the content of an XML file to extract credentials related to Group Policy Preferences.
\n\nThis method attempts to retrieve and parse the content of the specified XML file from the SMB share. It looks for credentials stored within the XML structure, specifically targeting the 'cpassword' attribute which is commonly used for storing encrypted passwords in Group Policy Preferences files.
\n\nArgs:\n pathtofile (str): The path to the XML file on the SMB share.
\n\nReturns:\n list: A list of dictionaries, each containing details about found credentials such as username, encrypted and decrypted passwords, and other relevant attributes.
\n", "signature": "(self, pathtofile):", "funcdef": "def"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.decrypt_password", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.decrypt_password", "kind": "function", "doc": "Decrypts a password from its Base64 encoded form using a known AES key and IV.
\n\nThis method takes a Base64 encoded string which is encrypted using AES-CBC with a fixed key and IV as per Microsoft's published details. It decodes the Base64 string, decrypts it using the AES key and IV, and returns the plaintext password.
\n\nArgs:\n pw_enc_b64 (str): The Base64 encoded string of the encrypted password.
\n\nReturns:\n str: The decrypted password in plaintext, or an empty string if input is empty or decryption fails.
\n", "signature": "(self, pw_enc_b64):", "funcdef": "def"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.run", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.run", "kind": "function", "doc": "This function recursively searches for files in a directory hierarchy and prints the results based on specified criteria.
\n\nArgs:\n base_dir (str): The base directory to start the search from.\n paths (list): List of paths to search within the base directory.\n depth (int): The current depth level in the directory hierarchy.
\n\nReturns:\n None
\n", "signature": "(self, arguments):", "funcdef": "def"}]; + /** pdoc search index */const docs = [{"fullname": "smbclientng", "modulename": "smbclientng", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core", "modulename": "smbclientng.core", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.CommandCompleter", "modulename": "smbclientng.core.CommandCompleter", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter", "kind": "class", "doc": "A class to handle command completion for the smbclient-ng shell.
\n\nThis class provides a command completion feature that suggests possible command names based on the current input.\nIt uses a dictionary to store commands and their descriptions, which helps in providing hints during the command line\ninteraction in the smbclient-ng shell.
\n\nAttributes:\n smbSession (SMBSession): An instance of SMBSession which maintains the current SMB session.\n commands (dict): A dictionary containing command names as keys and their descriptions and subcommands as values.
\n\nMethods:\n __init__(self, smbSession): Initializes the CommandCompleter with an SMBSession.
\n"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.__init__", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.__init__", "kind": "function", "doc": "\n", "signature": "(smbSession, config)"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.commands", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.commands", "kind": "variable", "doc": "\n", "default_value": "{'bat': {'description': ['Pretty prints the contents of a remote file.', "Syntax: 'bat <file>'"], 'subcommands': []}, 'cat': {'description': ['Get the contents of a remote file.', "Syntax: 'cat <file>'"], 'subcommands': []}, 'cd': {'description': ['Change the current working directory.', "Syntax: 'cd <directory>'"], 'subcommands': []}, 'close': {'description': ['Closes the SMB connection to the remote machine.', "Syntax: 'close'"], 'subcommands': []}, 'connect': {'description': ['Connect to the remote machine (useful if connection timed out).', "Syntax: 'connect'"], 'subcommands': []}, 'debug': {'description': ['Command for dev debugging.', "Syntax: 'debug'"], 'subcommands': []}, 'dir': {'description': ['List the contents of the current working directory.', "Syntax: 'dir'"], 'subcommands': []}, 'exit': {'description': ['Exits the smbclient-ng script.', "Syntax: 'exit'"], 'subcommands': []}, 'get': {'description': ['Get a remote file.', "Syntax: 'get [-r] <directory or file>'"], 'subcommands': []}, 'help': {'description': ['Displays this help message.', "Syntax: 'help'"], 'subcommands': ['format']}, 'info': {'description': ['Get information about the server and or the share.', "Syntax: 'info [server|share]'"], 'subcommands': ['server', 'share']}, 'lbat': {'description': ['Pretty prints the contents of a local file.', "Syntax: 'lbat <file>'"], 'subcommands': []}, 'lcat': {'description': ['Print the contents of a local file.', "Syntax: 'lcat <file>'"], 'subcommands': []}, 'lcd': {'description': ['Changes the current local directory.', "Syntax: 'lcd <directory>'"], 'subcommands': []}, 'lcp': {'description': ['Create a copy of a local file.', "Syntax: 'lcp <srcfile> <dstfile>'"], 'subcommands': []}, 'lls': {'description': ['Lists the contents of the current local directory.', "Syntax: 'lls'"], 'subcommands': []}, 'lmkdir': {'description': ['Creates a new local directory.', "Syntax: 'lmkdir <directory>'"], 'subcommands': []}, 'lpwd': {'description': ['Shows the current local directory.', "Syntax: 'lpwd'"], 'subcommands': []}, 'lrename': {'description': ['Renames a local file.', "Syntax: 'lrename <oldfilename> <newfilename>'"], 'subcommands': []}, 'lrm': {'description': ['Removes a local file.', "Syntax: 'lrm <file>'"], 'subcommands': []}, 'lrmdir': {'description': ['Removes a local directory.', "Syntax: 'lrmdir <directory>'"], 'subcommands': []}, 'ls': {'description': ['List the contents of the current remote working directory.', "Syntax: 'ls'"], 'subcommands': []}, 'ltree': {'description': ['Displays a tree view of the local directories.', "Syntax: 'ltree [directory]'"], 'subcommands': []}, 'mkdir': {'description': ['Creates a new remote directory.', "Syntax: 'mkdir <directory>'"], 'subcommands': []}, 'module': {'description': ['Loads a specific module for additional functionalities.', "Syntax: 'module <name>'"], 'subcommands': []}, 'mount': {'description': ['Creates a mount point of the remote share on the local machine.', "Syntax: 'mount <remote_path> <local_mountpoint>'"], 'subcommands': []}, 'put': {'description': ['Put a local file or directory in a remote directory.', "Syntax: 'put [-r] <directory or file>'"], 'subcommands': []}, 'reconnect': {'description': ['Reconnect to the remote machine (useful if connection timed out).', "Syntax: 'reconnect'"], 'subcommands': []}, 'reset': {'description': ['Reset the TTY output, useful if it was broken after printing a binary file on stdout.', "Syntax: 'reset'"], 'subcommands': []}, 'rmdir': {'description': ['Removes a remote directory.', "Syntax: 'rmdir <directory>'"], 'subcommands': []}, 'rm': {'description': ['Removes a remote file.', "Syntax: 'rm <file>'"], 'subcommands': []}, 'sizeof': {'description': ['Recursively compute the size of a folder.', "Syntax: 'sizeof [directory|file]'"], 'subcommands': []}, 'shares': {'description': ['Lists the SMB shares served by the remote machine.', "Syntax: 'shares'"], 'subcommands': ['rights']}, 'tree': {'description': ['Displays a tree view of the remote directories.', "Syntax: 'tree [directory]'"], 'subcommands': []}, 'umount': {'description': ['Removes a mount point of the remote share on the local machine.', "Syntax: 'umount <local_mount_point>'"], 'subcommands': []}, 'use': {'description': ['Use a SMB share.', "Syntax: 'use <sharename>'"], 'subcommands': []}}"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.smbSession", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.smbSession", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.config", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.config", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.complete", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.complete", "kind": "function", "doc": "Function to handle command completion in the LDAP console.
\n\nThis function completes the user\"s input based on the available options for commands in the LDAP console.
\n\nArgs:\n text (str): The current text input by the user.\n state (int): The current state of completion.
\n\nReturns:\n str: The next completion suggestion based on the user\"s input state.
\n", "signature": "(self, text, state):", "funcdef": "def"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.print_help", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.print_help", "kind": "function", "doc": "Prints help information for a specific command or all commands if no command is specified.
\n\nThis method displays the help information for the command passed as an argument. If no command is specified,\nit prints the help information for all available commands. The help information includes the command syntax,\ndescription, and any subcommands associated with it. This method is designed to provide users with the necessary\nguidance on how to use the commands in the smbclient-ng shell.
\n\nArgs:\n command (str, optional): The command to display help information for. If None, help for all commands is displayed.
\n\nReturns:\n None
\n", "signature": "(self, command=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.CommandCompleter.CommandCompleter.print_help_format", "modulename": "smbclientng.core.CommandCompleter", "qualname": "CommandCompleter.print_help_format", "kind": "function", "doc": "Prints the help information for the 'format' used in remote 'ls' and 'dir' commands.
\n\nThis function displays the format of file attributes used in the smbclient-ng shell. It explains the meaning\nof each character in the file attribute string, such as whether a file is read-only, hidden, or a directory.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.Config", "modulename": "smbclientng.core.Config", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.Config.Config", "modulename": "smbclientng.core.Config", "qualname": "Config", "kind": "class", "doc": "Configuration handler for smbclientng.
\n\nThis class manages the configuration settings for the smbclientng tool, including debug and color output settings.\nIt provides a structured way to access and modify these settings throughout the application.
\n\nAttributes:\n _debug (bool): Flag to enable or disable debug mode.\n _no_colors (bool): Flag to enable or disable colored output, depending on the platform.
\n\nMethods:\n debug: Property to get or set the debug mode.\n no_colors: Property to get or set the colored output preference.
\n"}, {"fullname": "smbclientng.core.Config.Config.__init__", "modulename": "smbclientng.core.Config", "qualname": "Config.__init__", "kind": "function", "doc": "\n", "signature": "(debug=False, no_colors=None)"}, {"fullname": "smbclientng.core.Config.Config.debug", "modulename": "smbclientng.core.Config", "qualname": "Config.debug", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.Config.Config.no_colors", "modulename": "smbclientng.core.Config", "qualname": "Config.no_colors", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell", "modulename": "smbclientng.core.InteractiveShell", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell.command_arguments_required", "modulename": "smbclientng.core.InteractiveShell", "qualname": "command_arguments_required", "kind": "function", "doc": "\n", "signature": "(func):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.active_smb_connection_needed", "modulename": "smbclientng.core.InteractiveShell", "qualname": "active_smb_connection_needed", "kind": "function", "doc": "\n", "signature": "(func):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.smb_share_is_set", "modulename": "smbclientng.core.InteractiveShell", "qualname": "smb_share_is_set", "kind": "function", "doc": "\n", "signature": "(func):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell", "kind": "class", "doc": "Class InteractiveShell is designed to manage the interactive command line interface for smbclient-ng.
\n\nThis class handles user input, executes commands, and manages the state of the SMB session. It provides\na command line interface for users to interact with SMB shares, execute commands like directory listing,\nfile transfer, and more.
\n\nAttributes:\n smbSession (SMBConnection): The active SMB connection session.\n debug (bool): Flag to enable or disable debug mode.\n smb_share (str): The current SMB share in use.\n smb_path (str): The current path within the SMB share.\n commandCompleterObject (CommandCompleter): Object to handle command completion and help generation.
\n\nMethods:\n __init__(self, smbSession, debug=False): Initializes the InteractiveShell with the given SMB session and debug mode.\n run(self): Starts the command line interface loop, processing user input until exit.
\n"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.__init__", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.__init__", "kind": "function", "doc": "\n", "signature": "(smbSession, config)"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.smbSession", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.smbSession", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.config", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.config", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.commandCompleterObject", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.commandCompleterObject", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.modules", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.modules", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.run", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.run", "kind": "function", "doc": "\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.process_command", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.process_command", "kind": "function", "doc": "\n", "signature": "(self, command, arguments=[]):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_debug", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_debug", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_bat", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_bat", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_cd", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_cd", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_cat", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_cat", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_close", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_close", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_get", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_get", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_help", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_help", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_info", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_info", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lcat", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lcat", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lcd", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lcd", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lcp", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lcp", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lbat", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lbat", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lls", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lls", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lmkdir", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lmkdir", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lpwd", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lpwd", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lrename", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lrename", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lrm", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lrm", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_lrmdir", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_lrmdir", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_ltree", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_ltree", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_ls", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_ls", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_mkdir", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_mkdir", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_module", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_module", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_mount", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_mount", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_put", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_put", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_reconnect", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_reconnect", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_reset", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_reset", "kind": "function", "doc": "\n", "signature": "(self, arguments, command):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_rm", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_rm", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_rmdir", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_rmdir", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_sizeof", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_sizeof", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_shares", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_shares", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_tree", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_tree", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_umount", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_umount", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.InteractiveShell.InteractiveShell.command_use", "modulename": "smbclientng.core.InteractiveShell", "qualname": "InteractiveShell.command_use", "kind": "function", "doc": "\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, {"fullname": "smbclientng.core.LocalFileIO", "modulename": "smbclientng.core.LocalFileIO", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO", "kind": "class", "doc": "Class LocalFileIO is designed to handle local file input/output operations within the smbclient-ng tool.\nIt provides functionalities to open, read, write, and manage progress of file operations based on the expected size of the file.
\n\nAttributes:\n mode (str): The mode in which the file should be opened (e.g., 'rb', 'wb').\n path (str): The path to the file that needs to be handled.\n expected_size (int, optional): The expected size of the file in bytes. This is used to display progress.\n debug (bool): Flag to enable debug mode which provides additional output during operations.
\n\nMethods:\n __init__(self, mode, path=None, expected_size=None, debug=False): Initializes the LocalFileIO instance.\n write(self, data): Writes data to the file and updates the progress bar if expected size is provided.\n read(self, size): Reads data from the file up to the specified size and updates the progress bar if expected size is provided.
\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.__init__", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.__init__", "kind": "function", "doc": "\n", "signature": "(\tmode,\tpath=None,\texpected_size=None,\tkeepRemotePath=False,\tdebug=False)"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.mode", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.mode", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.path", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.path", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.dir", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.dir", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.debug", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.debug", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.expected_size", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.expected_size", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.keepRemotePath", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.keepRemotePath", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.write", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.write", "kind": "function", "doc": "Writes data to the file.
\n\nThis method writes the specified data to the file and updates the progress bar with the amount of data written if the expected size is set.
\n\nArgs:\n data (bytes): The data to be written to the file.
\n\nReturns:\n int: The number of bytes written.
\n", "signature": "(self, data):", "funcdef": "def"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.read", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.read", "kind": "function", "doc": "Reads a specified amount of data from the file.
\n\nThis method reads data from the file based on the size specified. It also updates the progress bar with the amount of data read if the expected size is set.
\n\nArgs:\n size (int): The number of bytes to read from the file.
\n\nReturns:\n bytes: The data read from the file.
\n", "signature": "(self, size):", "funcdef": "def"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.close", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.close", "kind": "function", "doc": "Closes the file descriptor and optionally removes the file.
\n\nThis method ensures that the file descriptor is properly closed and the file is removed if specified.\nIt also stops the progress bar if it was initiated and cleans up the object by deleting it.
\n\nArgs:\n remove (bool): If True, the file at the path will be removed after closing the file descriptor.
\n", "signature": "(self, remove=False):", "funcdef": "def"}, {"fullname": "smbclientng.core.LocalFileIO.LocalFileIO.set_error", "modulename": "smbclientng.core.LocalFileIO", "qualname": "LocalFileIO.set_error", "kind": "function", "doc": "Sets an error message in the progress bar's description and modifies the progress bar to show only essential columns.
\n\nThis method is used to communicate error states or important messages directly in the progress bar interface.\nIt updates the task description with the provided message and simplifies the progress bar to show only the text\nand download columns, removing other elements like speed and time remaining which may not be relevant in an error state.
\n\nArgs:\n message (str): The error or status message to display in the progress bar.
\n", "signature": "(self, message):", "funcdef": "def"}, {"fullname": "smbclientng.core.Module", "modulename": "smbclientng.core.Module", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.Module.Module", "modulename": "smbclientng.core.Module", "qualname": "Module", "kind": "class", "doc": "A parent class for all modules in the smbclient-ng tool.
\n\nThis class provides common attributes and methods that are shared among different modules.
\n"}, {"fullname": "smbclientng.core.Module.Module.__init__", "modulename": "smbclientng.core.Module", "qualname": "Module.__init__", "kind": "function", "doc": "\n", "signature": "(smbSession, config)"}, {"fullname": "smbclientng.core.Module.Module.name", "modulename": "smbclientng.core.Module", "qualname": "Module.name", "kind": "variable", "doc": "\n", "default_value": "''"}, {"fullname": "smbclientng.core.Module.Module.description", "modulename": "smbclientng.core.Module", "qualname": "Module.description", "kind": "variable", "doc": "\n", "default_value": "''"}, {"fullname": "smbclientng.core.Module.Module.smbSession", "modulename": "smbclientng.core.Module", "qualname": "Module.smbSession", "kind": "variable", "doc": "\n", "default_value": "None"}, {"fullname": "smbclientng.core.Module.Module.options", "modulename": "smbclientng.core.Module", "qualname": "Module.options", "kind": "variable", "doc": "\n", "default_value": "None"}, {"fullname": "smbclientng.core.Module.Module.config", "modulename": "smbclientng.core.Module", "qualname": "Module.config", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.Module.Module.parseArgs", "modulename": "smbclientng.core.Module", "qualname": "Module.parseArgs", "kind": "function", "doc": "\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.Module.Module.run", "modulename": "smbclientng.core.Module", "qualname": "Module.run", "kind": "function", "doc": "Placeholder method for running the module.
\n\nThis method should be implemented by subclasses to define the specific behavior of the module.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.Module.Module.processArguments", "modulename": "smbclientng.core.Module", "qualname": "Module.processArguments", "kind": "function", "doc": "\n", "signature": "(self, parser, arguments):", "funcdef": "def"}, {"fullname": "smbclientng.core.ModuleArgumentParser", "modulename": "smbclientng.core.ModuleArgumentParser", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.ModuleArgumentParser.ModuleArgumentParser", "modulename": "smbclientng.core.ModuleArgumentParser", "qualname": "ModuleArgumentParser", "kind": "class", "doc": "A custom argument parser for handling module-specific command-line arguments in the smbclientng application.
\n\nThis class extends the argparse.ArgumentParser and provides custom error handling specific to the needs of smbclientng modules.\nIt is designed to provide clear and user-friendly command-line interfaces for various modules within the smbclientng suite.
\n\nAttributes:\n None
\n\nMethods:\n error(message: str):\n Overrides the default error handling to provide a more informative error message and display the help text.
\n", "bases": "argparse.ArgumentParser"}, {"fullname": "smbclientng.core.ModuleArgumentParser.ModuleArgumentParser.error", "modulename": "smbclientng.core.ModuleArgumentParser", "qualname": "ModuleArgumentParser.error", "kind": "function", "doc": "Overrides the default error handling of argparse.ArgumentParser to provide a custom error message and help display.
\n\nThis method is called when ArgumentParser encounters an error. It writes the error message to stderr,\ndisplays the help message, and then exits the program with a status code of 2.
\n\nArgs:\n message (str): The error message to be displayed.
\n", "signature": "(self, message):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession", "modulename": "smbclientng.core.SMBSession", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession", "kind": "class", "doc": "Class SMBSession is designed to handle the session management for SMB (Server Message Block) protocol connections.\nIt provides functionalities to connect to an SMB server, authenticate using either NTLM or Kerberos, and manage SMB shares.
\n\nAttributes:\n address (str): The IP address or hostname of the SMB server.\n domain (str): The domain name for SMB server authentication.\n username (str): The username for SMB server authentication.\n password (str): The password for SMB server authentication.\n lmhash (str): The LM hash of the user's password, if available.\n nthash (str): The NT hash of the user's password, if available.\n use_kerberos (bool): A flag to determine whether to use Kerberos for authentication.\n kdcHost (str): The Key Distribution Center (KDC) host for Kerberos authentication.\n debug (bool): A flag to enable debug output.\n smbClient (object): The SMB client object used for the connection.\n connected (bool): A flag to check the status of the connection.\n smb_share (str): The current SMB share in use.\n smb_path (str): The current path within the SMB share.
\n\nMethods:\n __init__(address, domain, username, password, lmhash, nthash, use_kerberos=False, kdcHost=None, debug=False):\n Initializes the SMBSession with the specified parameters.\n init_smb_session():\n Initializes the SMB session by connecting to the server and authenticating using the specified method.
\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.__init__", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.__init__", "kind": "function", "doc": "\n", "signature": "(\taddress,\tdomain,\tusername,\tpassword,\tlmhash,\tnthash,\tuse_kerberos=False,\tkdcHost=None,\tconfig=None)"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.config", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.config", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.address", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.address", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.domain", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.domain", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.username", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.username", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.password", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.password", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.lmhash", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.lmhash", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.nthash", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.nthash", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.use_kerberos", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.use_kerberos", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.kdcHost", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.kdcHost", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.smbClient", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.smbClient", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.connected", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.connected", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.available_shares", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.available_shares", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.smb_share", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.smb_share", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.smb_cwd", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.smb_cwd", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.smb_tree_id", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.smb_tree_id", "kind": "variable", "doc": "\n"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.init_smb_session", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.init_smb_session", "kind": "function", "doc": "Initializes and establishes a session with the SMB server.
\n\nThis method sets up the SMB connection using either Kerberos or NTLM authentication based on the configuration.\nIt attempts to connect to the SMB server specified by the address
attribute and authenticate using the credentials provided during the object's initialization.
The method will print debug information if the debug
attribute is set to True. Upon successful connection and authentication, it sets the connected
attribute to True.
Returns:\n bool: True if the connection and authentication are successful, False otherwise.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.close_smb_session", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.close_smb_session", "kind": "function", "doc": "Closes the current SMB session by disconnecting the SMB client.
\n\nThis method ensures that the SMB client connection is properly closed. It checks if the client is connected\nand if so, it closes the connection and resets the connection status.
\n\nRaises:\n Exception: If the SMB client is not initialized or if there's an error during the disconnection process.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.read_file", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.read_file", "kind": "function", "doc": "\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.find", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.find", "kind": "function", "doc": "\n", "signature": "(self, paths=[], callback=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.get_file", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.get_file", "kind": "function", "doc": "Retrieves a file from the specified path on the SMB share.
\n\nThis method attempts to retrieve a file from the given path within the currently connected SMB share.\nIf the path points to a directory, it skips the retrieval. It handles file retrieval by creating a local\nfile object and writing the contents of the remote file to it using the SMB client's getFile method.
\n\nParameters:\n path (str): The path of the file to retrieve. If None, uses the current smb_path.
\n\nReturns:\n None
\n", "signature": "(self, path=None, keepRemotePath=False):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.get_file_recursively", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.get_file_recursively", "kind": "function", "doc": "Recursively retrieves files from a specified path on the SMB share.
\n\nThis method navigates through all directories starting from the given path,\nand downloads all files found. It handles directories recursively, ensuring\nthat all nested files are retrieved. The method skips over directory entries\nand handles errors gracefully, attempting to continue the operation where possible.
\n\nParameters:\n path (str): The initial directory path from which to start the recursive file retrieval.\n If None, it starts from the root of the configured SMB share.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.get_entry", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.get_entry", "kind": "function", "doc": "Retrieves information about a specific entry located at the provided path on the SMB share.
\n\nThis method checks if the specified path exists on the SMB share. If the path exists, it retrieves the details of the entry at that path, including the directory name and file name. If the entry is found, it returns the entry object; otherwise, it returns None.
\n\nArgs:\n path (str): The path of the entry to retrieve information about.
\n\nReturns:\n Entry: An object representing the entry at the specified path, or None if the entry is not found.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.info", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.info", "kind": "function", "doc": "Displays information about the server and optionally the shares.
\n\nThis method prints detailed information about the server's characteristics such as NetBIOS names, DNS details, OS information, and SMB capabilities. If the share
parameter is set to True and a share is currently set, it will also attempt to display information about the share.
Parameters:\n share (bool): If True, display information about the current share.\n server (bool): If True, display information about the server.
\n\nReturns:\n None
\n", "signature": "(self, share=True, server=True):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.list_contents", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.list_contents", "kind": "function", "doc": "Lists the contents of a specified directory on the SMB share.
\n\nThis method retrieves the contents of a directory specified by shareName
and path
. If shareName
or path
\nis not provided, it defaults to the instance's current SMB share or path. The method returns a dictionary with\nthe long names of the files and directories as keys and their respective SMB entry objects as values.
Args:\n shareName (str, optional): The name of the SMB share. Defaults to the current SMB share if None.\n path (str, optional): The directory path to list contents from. Defaults to the current path if None.
\n\nReturns:\n dict: A dictionary with file and directory names as keys and their SMB entry objects as values.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.list_shares", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.list_shares", "kind": "function", "doc": "Lists all the shares available on the connected SMB server.
\n\nThis method queries the SMB server to retrieve a list of all available shares. It populates the shares
dictionary\nwith key-value pairs where the key is the share name and the value is a dictionary containing details about the share\nsuch as its name, type, raw type, and any comments associated with the share.
Returns:\n dict: A dictionary containing information about each share available on the server.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.mkdir", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.mkdir", "kind": "function", "doc": "Creates a directory at the specified path on the SMB share.
\n\nThis method takes a path and attempts to create the directory structure on the SMB share. If the path includes\nnested directories, it will create each directory in the sequence. If a directory already exists, it will skip\nthe creation for that directory without raising an error.
\n\nArgs:\n path (str, optional): The full path of the directory to create on the SMB share. Defaults to None.
\n\nNote:\n The path should use forward slashes ('/') which will be converted to backslashes (ntpath.sep) for SMB compatibility.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.mount", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.mount", "kind": "function", "doc": "Generates the command to mount an SMB share on different platforms.
\n\nThis method takes the local mount point and the remote path of the SMB share and generates the appropriate mount command based on the platform.\nIt constructs the mount command using the provided parameters and executes it using the os.system() function.
\n\nArgs:\n local_mount_point (str): The local directory where the SMB share will be mounted.\n remote_path (str): The remote path on the SMB share to be mounted.
\n\nNote:\n - For Windows platform, the command uses 'net use' to mount the share.\n - For Linux platform, the command uses 'mount' to mount the share.\n - For macOS platform, the command uses 'mount_smbfs' to mount the share.\n - If the platform is not supported, an error message is displayed.
\n\nReturns:\n None
\n", "signature": "(self, local_mount_point, remote_path):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.path_exists", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.path_exists", "kind": "function", "doc": "Checks if the specified path exists on the SMB share.
\n\nThis method determines if a given path exists on the SMB share by attempting to list the contents of the path.\nIf the path listing is successful and returns one or more entries, the path is considered to exist.
\n\nArgs:\n path (str, optional): The path to check on the SMB share. Defaults to None.
\n\nReturns:\n bool: True if the path exists, False otherwise or if an error occurs.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.path_isdir", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.path_isdir", "kind": "function", "doc": "Checks if the specified path is a directory on the SMB share.
\n\nThis method determines if a given path corresponds to a directory on the SMB share. It does this by listing the\ncontents of the path and filtering for entries that match the basename of the path and are marked as directories.
\n\nArgs:\n path (str, optional): The path to check on the SMB share. Defaults to None.
\n\nReturns:\n bool: True if the path is a directory, False otherwise or if an error occurs.
\n", "signature": "(self, pathFromRoot=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.path_isfile", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.path_isfile", "kind": "function", "doc": "Checks if the specified path is a file on the SMB share.
\n\nThis method determines if a given path corresponds to a file on the SMB share. It does this by listing the\ncontents of the path and filtering for entries that match the basename of the path and are not marked as directories.
\n\nArgs:\n path (str, optional): The path to check on the SMB share. Defaults to None.
\n\nReturns:\n bool: True if the path is a file, False otherwise or if an error occurs.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.ping_smb_session", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.ping_smb_session", "kind": "function", "doc": "Tests the connectivity to the SMB server by sending an echo command.
\n\nThis method attempts to send an echo command to the SMB server to check if the session is still active.\nIt updates the connected
attribute of the class based on the success or failure of the echo command.
Returns:\n bool: True if the echo command succeeds (indicating the session is active), False otherwise.
\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.put_file", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.put_file", "kind": "function", "doc": "Uploads a single file to the SMB share.
\n\nThis method takes a local file path, opens the file, and uploads it to the SMB share at the specified path.\nIt handles exceptions such as broken pipe errors or keyboard interrupts by closing and reinitializing the SMB session.\nGeneral exceptions are caught and logged, with a traceback provided if debugging is enabled.
\n\nArgs:\n localpath (str, optional): The local file path of the file to be uploaded. Defaults to None.
\n", "signature": "(self, localpath=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.put_file_recursively", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.put_file_recursively", "kind": "function", "doc": "Recursively uploads files from a specified local directory to the SMB share.
\n\nThis method walks through the given local directory and all its subdirectories, uploading each file to the\ncorresponding directory structure on the SMB share. It first checks if the local path is a directory. If it is,\nit iterates over all files and directories within the local path, creating necessary directories on the SMB share\nand uploading files. If the local path is not a directory, it prints an error message.
\n\nArgs:\n localpath (str, optional): The local directory path from which files will be uploaded. Defaults to None.
\n", "signature": "(self, localpath=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.rmdir", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.rmdir", "kind": "function", "doc": "Removes a directory from the SMB share at the specified path.
\n\nThis method attempts to delete a directory located at the given path on the SMB share. If the operation fails,\nit prints an error message indicating the failure and the reason. If debugging is enabled, it also prints\nthe stack trace of the exception.
\n\nArgs:\n path (str, optional): The path of the directory to be removed on the SMB share. Defaults to None.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.rm", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.rm", "kind": "function", "doc": "Removes a file from the SMB share at the specified path.
\n\nThis method attempts to delete a file located at the given path on the SMB share. If the operation fails,\nit prints an error message indicating the failure and the reason. If debugging is enabled, it also prints\nthe stack trace of the exception.
\n\nArgs:\n path (str, optional): The path of the file to be removed on the SMB share. Defaults to None.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.tree", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.tree", "kind": "function", "doc": "Recursively lists the directory structure of the SMB share starting from the specified path.
\n\nThis function prints a visual representation of the directory tree of the remote SMB share. It uses\nrecursion to navigate through directories and lists all files and subdirectories in each directory.\nThe output is color-coded and formatted to enhance readability, with directories highlighted in cyan.
\n\nArgs:\n path (str, optional): The starting path on the SMB share from which to begin listing the tree.\n Defaults to the root of the current share.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.umount", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.umount", "kind": "function", "doc": "Unmounts the specified local mount point of the remote share.
\n\nThis method unmounts the specified local mount point of the remote share based on the platform.\nIt supports Windows, Linux, and macOS platforms for unmounting.
\n\nParameters:\n local_mount_point (str): The local mount point to unmount.
\n\nRaises:\n None
\n", "signature": "(self, local_mount_point):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.test_rights", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.test_rights", "kind": "function", "doc": "Tests the read and write access rights of the current SMB session.
\n\nThis method checks the read and write access rights of the current SMB session by attempting to list paths and create/delete temporary directories.
\n\nReturns:\n dict: A dictionary containing the read and write access rights status.\n - \"readable\" (bool): Indicates if the session has read access rights.\n - \"writable\" (bool): Indicates if the session has write access rights.
\n", "signature": "(self, sharename):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.set_share", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.set_share", "kind": "function", "doc": "Sets the current SMB share to the specified share name.
\n\nThis method updates the SMB session to use the specified share name. It checks if the share name is valid\nand updates the smb_share attribute of the SMBSession instance.
\n\nParameters:\n shareName (str): The name of the share to set as the current SMB share.
\n\nRaises:\n ValueError: If the shareName is None or an empty string.
\n", "signature": "(self, shareName):", "funcdef": "def"}, {"fullname": "smbclientng.core.SMBSession.SMBSession.set_cwd", "modulename": "smbclientng.core.SMBSession", "qualname": "SMBSession.set_cwd", "kind": "function", "doc": "Sets the current working directory on the SMB share to the specified path.
\n\nThis method updates the current working directory (cwd) of the SMB session to the given path if it is a valid directory.\nIf the specified path is not a directory, the cwd remains unchanged.
\n\nParameters:\n path (str): The path to set as the current working directory.
\n\nRaises:\n ValueError: If the specified path is not a directory.
\n", "signature": "(self, path=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils", "modulename": "smbclientng.core.utils", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.core.utils.parse_lm_nt_hashes", "modulename": "smbclientng.core.utils", "qualname": "parse_lm_nt_hashes", "kind": "function", "doc": "Parse the input string containing LM and NT hash values and return them separately.
\n\nThis function takes a string containing LM and NT hash values, typically separated by a colon (:).\nIt returns the LM and NT hash values as separate strings. If only one hash value is provided, it is\nassumed to be the NT hash and the LM hash is set to its default value. If no valid hash values are\nfound, both return values are empty strings.
\n\nArgs:\n lm_nt_hashes_string (str): A string containing LM and NT hash values separated by a colon.
\n\nReturns:\n tuple: A tuple containing two strings (lm_hash_value, nt_hash_value).\n - lm_hash_value: The LM hash value or its default if not provided.\n - nt_hash_value: The NT hash value or its default if not provided.
\n\nExtracted from p0dalirius/sectools library\nSrc: https://github.com/p0dalirius/sectools/blob/7bb3f5cb7815ad4d4845713c8739e2e2b0ea4e75/sectools/windows/crypto.py#L11-L24
\n", "signature": "(lm_nt_hashes_string):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils.b_filesize", "modulename": "smbclientng.core.utils", "qualname": "b_filesize", "kind": "function", "doc": "Convert a file size from bytes to a more readable format using the largest appropriate unit.
\n\nThis function takes an integer representing a file size in bytes and converts it to a human-readable\nstring using the largest appropriate unit from bytes (B) to petabytes (PB). The result is rounded to\ntwo decimal places.
\n\nArgs:\n l (int): The file size in bytes.
\n\nReturns:\n str: A string representing the file size in a more readable format, including the appropriate unit.
\n", "signature": "(l):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils.unix_permissions", "modulename": "smbclientng.core.utils", "qualname": "unix_permissions", "kind": "function", "doc": "Generate a string representing the Unix-style permissions for a given file or directory.
\n\nThis function uses the os.lstat() method to retrieve the status of the specified file or directory,\nthen constructs a string that represents the Unix-style permissions based on the mode of the file.
\n\nArgs:\n entryname (str): The path to the file or directory for which permissions are being determined.
\n\nReturns:\n str: A string of length 10 representing the Unix-style permissions (e.g., '-rwxr-xr--').\n The first character is either 'd' (directory), '-' (not a directory), followed by\n three groups of 'r', 'w', 'x' (read, write, execute permissions) for owner, group,\n and others respectively.
\n", "signature": "(entryname):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils.STYPE_MASK", "modulename": "smbclientng.core.utils", "qualname": "STYPE_MASK", "kind": "function", "doc": "Extracts the share type flags from a given share type value.
\n\nThis function uses bitwise operations to determine which share type flags are set in the provided stype_value
.\nIt checks against known share type flags and returns a list of the flags that are set.
Parameters:\n stype_value (int): The share type value to analyze, typically obtained from SMB share properties.
\n\nReturns:\n list: A list of strings, where each string represents a share type flag that is set in the input value.
\n", "signature": "(stype_value):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils.windows_ls_entry", "modulename": "smbclientng.core.utils", "qualname": "windows_ls_entry", "kind": "function", "doc": "This function generates a metadata string based on the attributes of the provided entry object.
\n\nParameters:\n entry (object): An object representing a file or directory entry.
\n\nReturns:\n str: A string representing the metadata of the entry, including attributes like directory, archive, compressed, hidden, normal, readonly, system, and temporary.
\n", "signature": "(entry, config, pathToPrint=None):", "funcdef": "def"}, {"fullname": "smbclientng.core.utils.local_tree", "modulename": "smbclientng.core.utils", "qualname": "local_tree", "kind": "function", "doc": "This function recursively lists the contents of a directory in a tree-like format.
\n\nParameters:\n path (str): The path to the directory to list.\n config (object): Configuration settings which may affect the output, such as whether to use colors.
\n\nReturns:\n None: This function does not return anything but prints the directory tree to the console.
\n", "signature": "(path, config):", "funcdef": "def"}, {"fullname": "smbclientng.modules", "modulename": "smbclientng.modules", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.modules.Find", "modulename": "smbclientng.modules.Find", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.modules.Find.Find", "modulename": "smbclientng.modules.Find", "qualname": "Find", "kind": "class", "doc": "A class to search for files in a directory hierarchy.
\n\nThis class provides functionality to search for files based on various criteria in a directory hierarchy.
\n", "bases": "smbclientng.core.Module.Module"}, {"fullname": "smbclientng.modules.Find.Find.name", "modulename": "smbclientng.modules.Find", "qualname": "Find.name", "kind": "variable", "doc": "\n", "default_value": "'find'"}, {"fullname": "smbclientng.modules.Find.Find.description", "modulename": "smbclientng.modules.Find", "qualname": "Find.description", "kind": "variable", "doc": "\n", "default_value": "'Search for files in a directory hierarchy'"}, {"fullname": "smbclientng.modules.Find.Find.parseArgs", "modulename": "smbclientng.modules.Find", "qualname": "Find.parseArgs", "kind": "function", "doc": "Parses the command line arguments provided to the module.
\n\nThis method initializes the argument parser with the module's name and description, and defines all the necessary arguments that the module accepts. It then parses the provided command line arguments based on these definitions.
\n\nArgs:\n arguments (str): A string of command line arguments.
\n\nReturns:\n ModuleArgumentParser.Namespace | None: The parsed arguments as a Namespace object if successful, None if there are no arguments or help is requested.
\n", "signature": "(self, arguments):", "funcdef": "def"}, {"fullname": "smbclientng.modules.Find.Find.run", "modulename": "smbclientng.modules.Find", "qualname": "Find.run", "kind": "function", "doc": "This function recursively searches for files in a directory hierarchy and prints the results based on specified criteria.
\n\nArgs:\n base_dir (str): The base directory to start the search from.\n paths (list): List of paths to search within the base directory.\n depth (int): The current depth level in the directory hierarchy.
\n\nReturns:\n None
\n", "signature": "(self, arguments):", "funcdef": "def"}, {"fullname": "smbclientng.modules.GPPPasswords", "modulename": "smbclientng.modules.GPPPasswords", "kind": "module", "doc": "\n"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords", "kind": "class", "doc": "GPPPasswords is a module designed to search and retrieve stored Group Policy Preferences (GPP) passwords from specified network shares. \nIt leverages the SMB protocol to access files across the network, parse them, and extract credentials that are often stored within Group Policy Preferences files.
\n\nThis module is particularly useful in penetration testing scenarios where discovering stored credentials can lead to further system access or reveal poor security practices.
\n\nAttributes:\n name (str): The name of the module, used in command line invocation.\n description (str): A brief description of what the module does.
\n\nMethods:\n parseArgs(arguments): Parses and handles command line arguments for the module.\n parse_xmlfile_content(pathtofile): Parses the content of an XML file to extract credentials.
\n", "bases": "smbclientng.core.Module.Module"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.name", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.name", "kind": "variable", "doc": "\n", "default_value": "'gpppasswords'"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.description", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.description", "kind": "variable", "doc": "\n", "default_value": "'Searches for Group Policy Preferences Passwords in a share.'"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.parseArgs", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.parseArgs", "kind": "function", "doc": "Parses the command line arguments provided to the module.
\n\nThis method initializes the argument parser with the module's name and description, and defines all the necessary arguments that the module accepts. It then parses the provided command line arguments based on these definitions.
\n\nArgs:\n arguments (str): A string of command line arguments.
\n\nReturns:\n ModuleArgumentParser.Namespace | None: The parsed arguments as a Namespace object if successful, None if there are no arguments or help is requested.
\n", "signature": "(self, arguments):", "funcdef": "def"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.parse_xmlfile_content", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.parse_xmlfile_content", "kind": "function", "doc": "Parses the content of an XML file to extract credentials related to Group Policy Preferences.
\n\nThis method attempts to retrieve and parse the content of the specified XML file from the SMB share. It looks for credentials stored within the XML structure, specifically targeting the 'cpassword' attribute which is commonly used for storing encrypted passwords in Group Policy Preferences files.
\n\nArgs:\n pathtofile (str): The path to the XML file on the SMB share.
\n\nReturns:\n list: A list of dictionaries, each containing details about found credentials such as username, encrypted and decrypted passwords, and other relevant attributes.
\n", "signature": "(self, pathtofile):", "funcdef": "def"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.decrypt_password", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.decrypt_password", "kind": "function", "doc": "Decrypts a password from its Base64 encoded form using a known AES key and IV.
\n\nThis method takes a Base64 encoded string which is encrypted using AES-CBC with a fixed key and IV as per Microsoft's published details. It decodes the Base64 string, decrypts it using the AES key and IV, and returns the plaintext password.
\n\nArgs:\n pw_enc_b64 (str): The Base64 encoded string of the encrypted password.
\n\nReturns:\n str: The decrypted password in plaintext, or an empty string if input is empty or decryption fails.
\n", "signature": "(self, pw_enc_b64):", "funcdef": "def"}, {"fullname": "smbclientng.modules.GPPPasswords.GPPPasswords.run", "modulename": "smbclientng.modules.GPPPasswords", "qualname": "GPPPasswords.run", "kind": "function", "doc": "This function recursively searches for files in a directory hierarchy and prints the results based on specified criteria.
\n\nArgs:\n base_dir (str): The base directory to start the search from.\n paths (list): List of paths to search within the base directory.\n depth (int): The current depth level in the directory hierarchy.
\n\nReturns:\n None
\n", "signature": "(self, arguments):", "funcdef": "def"}]; // mirrored in build-search-index.js (part 1) // Also split on html tags. this is a cheap heuristic, but good enough. diff --git a/documentation/smbclientng/core/CommandCompleter.html b/documentation/smbclientng/core/CommandCompleter.html index da8c6f7..9a8ffe3 100644 --- a/documentation/smbclientng/core/CommandCompleter.html +++ b/documentation/smbclientng/core/CommandCompleter.html @@ -335,7 +335,7 @@20class SMBSession(object): - 21 """ - 22 Class SMBSession is designed to handle the session management for SMB (Server Message Block) protocol connections. - 23 It provides functionalities to connect to an SMB server, authenticate using either NTLM or Kerberos, and manage SMB shares. - 24 - 25 Attributes: - 26 address (str): The IP address or hostname of the SMB server. - 27 domain (str): The domain name for SMB server authentication. - 28 username (str): The username for SMB server authentication. - 29 password (str): The password for SMB server authentication. - 30 lmhash (str): The LM hash of the user's password, if available. - 31 nthash (str): The NT hash of the user's password, if available. - 32 use_kerberos (bool): A flag to determine whether to use Kerberos for authentication. - 33 kdcHost (str): The Key Distribution Center (KDC) host for Kerberos authentication. - 34 debug (bool): A flag to enable debug output. - 35 smbClient (object): The SMB client object used for the connection. - 36 connected (bool): A flag to check the status of the connection. - 37 smb_share (str): The current SMB share in use. - 38 smb_path (str): The current path within the SMB share. - 39 - 40 Methods: - 41 __init__(address, domain, username, password, lmhash, nthash, use_kerberos=False, kdcHost=None, debug=False): - 42 Initializes the SMBSession with the specified parameters. - 43 init_smb_session(): - 44 Initializes the SMB session by connecting to the server and authenticating using the specified method. - 45 """ - 46 - 47 def __init__(self, address, domain, username, password, lmhash, nthash, use_kerberos=False, kdcHost=None, config=None): - 48 super(SMBSession, self).__init__() - 49 # Objects - 50 self.config = config - 51 - 52 # Target server - 53 self.address = address - 54 - 55 # Credentials - 56 self.domain = domain - 57 self.username = username - 58 self.password = password - 59 self.lmhash = lmhash - 60 self.nthash = nthash - 61 self.use_kerberos = use_kerberos - 62 self.kdcHost = kdcHost - 63 - 64 self.smbClient = None - 65 self.connected = False - 66 - 67 self.available_shares = {} - 68 self.smb_share = None - 69 self.smb_cwd = "" - 70 self.smb_tree_id = None - 71 - 72 self.list_shares() - 73 - 74 # Connect and disconnect SMB session - 75 - 76 def init_smb_session(self): - 77 """ - 78 Initializes and establishes a session with the SMB server. - 79 - 80 This method sets up the SMB connection using either Kerberos or NTLM authentication based on the configuration. - 81 It attempts to connect to the SMB server specified by the `address` attribute and authenticate using the credentials provided during the object's initialization. - 82 - 83 The method will print debug information if the `debug` attribute is set to True. Upon successful connection and authentication, it sets the `connected` attribute to True. - 84 - 85 Returns: - 86 bool: True if the connection and authentication are successful, False otherwise. - 87 """ - 88 - 89 self.connected = False - 90 - 91 if self.config.debug: - 92 print("[debug] [>] Connecting to remote SMB server '%s' ... " % self.address) - 93 try: - 94 self.smbClient = impacket.smbconnection.SMBConnection( - 95 remoteName=self.address, - 96 remoteHost=self.address, - 97 sess_port=int(445) - 98 ) - 99 except OSError as err: - 100 print("[!] %s" % err) - 101 self.smbClient = None - 102 - 103 if self.smbClient is not None: - 104 if self.use_kerberos: - 105 if self.config.debug: - 106 print("[debug] [>] Authenticating as '%s\\%s' with kerberos ... " % (self.domain, self.username)) - 107 try: - 108 self.connected = self.smbClient.kerberosLogin( - 109 user=self.username, - 110 password=self.password, - 111 domain=self.domain, - 112 lmhash=self.lmhash, - 113 nthash=self.nthash, - 114 aesKey=self.aesKey, - 115 kdcHost=self.kdcHost - 116 ) - 117 except impacket.smbconnection.SessionError as err: - 118 if self.config.debug: - 119 traceback.print_exc() - 120 print("[!] Could not login: %s" % err) - 121 self.connected = False - 122 - 123 else: - 124 if self.config.debug: - 125 print("[debug] [>] Authenticating as '%s\\%s' with NTLM ... " % (self.domain, self.username)) - 126 try: - 127 self.connected = self.smbClient.login( - 128 user=self.username, - 129 password=self.password, - 130 domain=self.domain, - 131 lmhash=self.lmhash, - 132 nthash=self.nthash - 133 ) - 134 except impacket.smbconnection.SessionError as err: - 135 if self.config.debug: - 136 traceback.print_exc() - 137 print("[!] Could not login: %s" % err) - 138 self.connected = False - 139 - 140 if self.connected: - 141 print("[+] Successfully authenticated to '%s' as '%s\\%s'!" % (self.address, self.domain, self.username)) - 142 else: - 143 print("[!] Failed to authenticate to '%s' as '%s\\%s'!" % (self.address, self.domain, self.username)) - 144 - 145 return self.connected - 146 - 147 def close_smb_session(self): - 148 """ - 149 Closes the current SMB session by disconnecting the SMB client. - 150 - 151 This method ensures that the SMB client connection is properly closed. It checks if the client is connected - 152 and if so, it closes the connection and resets the connection status. - 153 - 154 Raises: - 155 Exception: If the SMB client is not initialized or if there's an error during the disconnection process. - 156 """ - 157 - 158 if self.smbClient is not None: - 159 if self.connected: - 160 self.smbClient.close() - 161 self.connected = False - 162 if self.config.debug: - 163 print("[+] SMB connection closed successfully.") - 164 else: - 165 if self.config.debug: - 166 print("[!] No active SMB connection to close.") - 167 else: - 168 raise Exception("SMB client is not initialized.") - 169 - 170 # Operations - 171 - 172 def read_file(self, path=None): - 173 if self.path_isfile(path=path): - 174 tmp_file_path = self.smb_cwd + ntpath.sep + path - 175 matches = self.smbClient.listPath( - 176 shareName=self.smb_share, - 177 path=tmp_file_path - 178 ) - 179 - 180 fh = io.BytesIO() - 181 try: - 182 # opening the files in streams instead of mounting shares allows - 183 # for running the script from unprivileged containers - 184 self.smbClient.getFile(self.smb_share, tmp_file_path, fh.write) - 185 except impacket.smbconnection.SessionError as e: - 186 return None - 187 rawdata = fh.getvalue() - 188 fh.close() - 189 return rawdata - 190 else: - 191 print("[!] Remote path '%s' is not a file." % path) - 192 - 193 def find(self, paths=[], callback=None): - 194 def recurse_action(paths=[], depth=0, callback=None): - 195 if callback is None: - 196 return [] - 197 - 198 next_directories_to_explore = [] - 199 - 200 for path in paths: - 201 remote_smb_path = ntpath.normpath(self.smb_cwd + ntpath.sep + path) - 202 entries = [] - 203 - 204 try: - 205 entries = self.smbClient.listPath( - 206 shareName=self.smb_share, - 207 path=(remote_smb_path + ntpath.sep + '*') - 208 ) - 209 except impacket.smbconnection.SessionError as err: - 210 continue - 211 # Remove dot names - 212 entries = [e for e in entries if e.get_longname() not in [".", ".."]] - 213 # Sort the entries ignoring case - 214 entries = sorted(entries, key=lambda x:x.get_longname().lower()) - 215 - 216 for entry in entries: - 217 if entry.is_directory(): - 218 callback(entry, path + ntpath.sep + entry.get_longname() + ntpath.sep, depth) - 219 else: - 220 callback(entry, path + ntpath.sep + entry.get_longname(), depth) - 221 - 222 # Next directories to explore - 223 for entry in entries: - 224 if entry.is_directory(): - 225 next_directories_to_explore.append(path + ntpath.sep + entry.get_longname() + ntpath.sep) - 226 - 227 return next_directories_to_explore - 228 # - 229 if callback is not None: - 230 depth = 0 - 231 while len(paths) != 0: - 232 paths = recurse_action( - 233 paths=paths, - 234 depth=depth, - 235 callback=callback - 236 ) - 237 depth = depth + 1 - 238 else: - 239 print("[!] SMBSession.find(), callback function cannot be None.") - 240 - 241 def get_file(self, path=None, keepRemotePath=False): - 242 """ - 243 Retrieves a file from the specified path on the SMB share. - 244 - 245 This method attempts to retrieve a file from the given path within the currently connected SMB share. - 246 If the path points to a directory, it skips the retrieval. It handles file retrieval by creating a local - 247 file object and writing the contents of the remote file to it using the SMB client's getFile method. - 248 - 249 Parameters: - 250 path (str): The path of the file to retrieve. If None, uses the current smb_path. - 251 - 252 Returns: - 253 None - 254 """ - 255 - 256 tmp_file_path = self.smb_cwd + ntpath.sep + path - 257 matches = self.smbClient.listPath( - 258 shareName=self.smb_share, - 259 path=tmp_file_path - 260 ) - 261 - 262 for entry in matches: - 263 if entry.is_directory(): - 264 print("[>] Skipping '%s' because it is a directory." % tmp_file_path) - 265 else: - 266 try: - 267 if ntpath.sep in path: - 268 outputfile = ntpath.dirname(path) + ntpath.sep + entry.get_longname() - 269 else: - 270 outputfile = entry.get_longname() - 271 f = LocalFileIO( - 272 mode="wb", - 273 path=outputfile, - 274 expected_size=entry.get_filesize(), - 275 debug=self.config.debug, - 276 keepRemotePath=keepRemotePath - 277 ) - 278 self.smbClient.getFile( - 279 shareName=self.smb_share, - 280 pathName=tmp_file_path, - 281 callback=f.write - 282 ) - 283 f.close() - 284 except (BrokenPipeError, KeyboardInterrupt) as e: - 285 f.close() - 286 print("\x1b[v\x1b[o\r[!] Interrupted.") - 287 self.close_smb_session() - 288 self.init_smb_session() - 289 - 290 return None - 291 - 292 def get_file_recursively(self, path=None): - 293 """ - 294 Recursively retrieves files from a specified path on the SMB share. - 295 - 296 This method navigates through all directories starting from the given path, - 297 and downloads all files found. It handles directories recursively, ensuring - 298 that all nested files are retrieved. The method skips over directory entries - 299 and handles errors gracefully, attempting to continue the operation where possible. - 300 - 301 Parameters: - 302 path (str): The initial directory path from which to start the recursive file retrieval. - 303 If None, it starts from the root of the configured SMB share. - 304 """ - 305 - 306 def recurse_action(base_dir="", path=[]): - 307 if len(base_dir) == 0: - 308 remote_smb_path = ntpath.sep.join(path) - 309 else: - 310 remote_smb_path = base_dir + ntpath.sep + ntpath.sep.join(path) - 311 remote_smb_path = ntpath.normpath(remote_smb_path) - 312 - 313 entries = self.smbClient.listPath( - 314 shareName=self.smb_share, - 315 path=remote_smb_path + '\\*' - 316 ) - 317 if len(entries) != 0: - 318 files = [entry for entry in entries if not entry.is_directory()] - 319 directories = [entry for entry in entries if entry.is_directory() and entry.get_longname() not in [".", ".."]] - 320 - 321 # Files - 322 if len(files) != 0: - 323 print("[>] Retrieving files of '%s'" % remote_smb_path) - 324 for entry_file in files: - 325 if not entry_file.is_directory(): - 326 f = LocalFileIO( - 327 mode="wb", - 328 path=remote_smb_path + ntpath.sep + entry_file.get_longname(), - 329 expected_size=entry_file.get_filesize(), - 330 keepRemotePath=True, - 331 debug=self.config.debug - 332 ) - 333 try: - 334 self.smbClient.getFile( - 335 shareName=self.smb_share, - 336 pathName=remote_smb_path + ntpath.sep + entry_file.get_longname(), - 337 callback=f.write - 338 ) - 339 f.close() - 340 except BrokenPipeError as err: - 341 f.set_error(message="[bold red]Failed downloading '%s': %s" % (f.path, err)) - 342 f.close(remove=True) - 343 break - 344 except Exception as err: - 345 f.set_error(message="[bold red]Failed downloading '%s': %s" % (f.path, err)) - 346 f.close(remove=True) - 347 - 348 # Directories - 349 for entry_directory in directories: - 350 if entry_directory.is_directory(): - 351 recurse_action( - 352 base_dir=self.smb_cwd, - 353 path=path+[entry_directory.get_longname()] - 354 ) - 355 # Entrypoint - 356 try: - 357 recurse_action( - 358 base_dir=self.smb_cwd, - 359 path=[path] - 360 ) - 361 except (BrokenPipeError, KeyboardInterrupt) as e: - 362 print("\x1b[v\x1b[o\r[!] Interrupted.") - 363 self.close_smb_session() - 364 self.init_smb_session() - 365 - 366 def get_entry(self, path=None): - 367 """ - 368 Retrieves information about a specific entry located at the provided path on the SMB share. - 369 - 370 This method checks if the specified path exists on the SMB share. If the path exists, it retrieves the details of the entry at that path, including the directory name and file name. If the entry is found, it returns the entry object; otherwise, it returns None. - 371 - 372 Args: - 373 path (str): The path of the entry to retrieve information about. - 374 - 375 Returns: - 376 Entry: An object representing the entry at the specified path, or None if the entry is not found. - 377 """ - 378 - 379 if self.path_exists(path=path): - 380 matches = self.smbClient.listPath(shareName=self.smb_share, path=path) - 381 - 382 if len(matches) == 1: - 383 return matches[0] - 384 else: - 385 return None - 386 - 387 else: - 388 return None - 389 - 390 def info(self, share=True, server=True): - 391 """ - 392 Displays information about the server and optionally the shares. - 393 - 394 This method prints detailed information about the server's characteristics such as NetBIOS names, DNS details, OS information, and SMB capabilities. If the `share` parameter is set to True and a share is currently set, it will also attempt to display information about the share. +@@ -2371,32 +2689,32 @@21class SMBSession(object): + 22 """ + 23 Class SMBSession is designed to handle the session management for SMB (Server Message Block) protocol connections. + 24 It provides functionalities to connect to an SMB server, authenticate using either NTLM or Kerberos, and manage SMB shares. + 25 + 26 Attributes: + 27 address (str): The IP address or hostname of the SMB server. + 28 domain (str): The domain name for SMB server authentication. + 29 username (str): The username for SMB server authentication. + 30 password (str): The password for SMB server authentication. + 31 lmhash (str): The LM hash of the user's password, if available. + 32 nthash (str): The NT hash of the user's password, if available. + 33 use_kerberos (bool): A flag to determine whether to use Kerberos for authentication. + 34 kdcHost (str): The Key Distribution Center (KDC) host for Kerberos authentication. + 35 debug (bool): A flag to enable debug output. + 36 smbClient (object): The SMB client object used for the connection. + 37 connected (bool): A flag to check the status of the connection. + 38 smb_share (str): The current SMB share in use. + 39 smb_path (str): The current path within the SMB share. + 40 + 41 Methods: + 42 __init__(address, domain, username, password, lmhash, nthash, use_kerberos=False, kdcHost=None, debug=False): + 43 Initializes the SMBSession with the specified parameters. + 44 init_smb_session(): + 45 Initializes the SMB session by connecting to the server and authenticating using the specified method. + 46 """ + 47 + 48 def __init__(self, address, domain, username, password, lmhash, nthash, use_kerberos=False, kdcHost=None, config=None): + 49 super(SMBSession, self).__init__() + 50 # Objects + 51 self.config = config + 52 + 53 # Target server + 54 self.address = address + 55 + 56 # Credentials + 57 self.domain = domain + 58 self.username = username + 59 self.password = password + 60 self.lmhash = lmhash + 61 self.nthash = nthash + 62 self.use_kerberos = use_kerberos + 63 self.kdcHost = kdcHost + 64 + 65 self.smbClient = None + 66 self.connected = False + 67 + 68 self.available_shares = {} + 69 self.smb_share = None + 70 self.smb_cwd = "" + 71 self.smb_tree_id = None + 72 + 73 self.list_shares() + 74 + 75 # Connect and disconnect SMB session + 76 + 77 def init_smb_session(self): + 78 """ + 79 Initializes and establishes a session with the SMB server. + 80 + 81 This method sets up the SMB connection using either Kerberos or NTLM authentication based on the configuration. + 82 It attempts to connect to the SMB server specified by the `address` attribute and authenticate using the credentials provided during the object's initialization. + 83 + 84 The method will print debug information if the `debug` attribute is set to True. Upon successful connection and authentication, it sets the `connected` attribute to True. + 85 + 86 Returns: + 87 bool: True if the connection and authentication are successful, False otherwise. + 88 """ + 89 + 90 self.connected = False + 91 + 92 if self.config.debug: + 93 print("[debug] [>] Connecting to remote SMB server '%s' ... " % self.address) + 94 try: + 95 self.smbClient = impacket.smbconnection.SMBConnection( + 96 remoteName=self.address, + 97 remoteHost=self.address, + 98 sess_port=int(445) + 99 ) + 100 except OSError as err: + 101 print("[!] %s" % err) + 102 self.smbClient = None + 103 + 104 if self.smbClient is not None: + 105 if self.use_kerberos: + 106 if self.config.debug: + 107 print("[debug] [>] Authenticating as '%s\\%s' with kerberos ... " % (self.domain, self.username)) + 108 try: + 109 self.connected = self.smbClient.kerberosLogin( + 110 user=self.username, + 111 password=self.password, + 112 domain=self.domain, + 113 lmhash=self.lmhash, + 114 nthash=self.nthash, + 115 aesKey=self.aesKey, + 116 kdcHost=self.kdcHost + 117 ) + 118 except impacket.smbconnection.SessionError as err: + 119 if self.config.debug: + 120 traceback.print_exc() + 121 print("[!] Could not login: %s" % err) + 122 self.connected = False + 123 + 124 else: + 125 if self.config.debug: + 126 print("[debug] [>] Authenticating as '%s\\%s' with NTLM ... " % (self.domain, self.username)) + 127 try: + 128 self.connected = self.smbClient.login( + 129 user=self.username, + 130 password=self.password, + 131 domain=self.domain, + 132 lmhash=self.lmhash, + 133 nthash=self.nthash + 134 ) + 135 except impacket.smbconnection.SessionError as err: + 136 if self.config.debug: + 137 traceback.print_exc() + 138 print("[!] Could not login: %s" % err) + 139 self.connected = False + 140 + 141 if self.connected: + 142 print("[+] Successfully authenticated to '%s' as '%s\\%s'!" % (self.address, self.domain, self.username)) + 143 else: + 144 print("[!] Failed to authenticate to '%s' as '%s\\%s'!" % (self.address, self.domain, self.username)) + 145 + 146 return self.connected + 147 + 148 def close_smb_session(self): + 149 """ + 150 Closes the current SMB session by disconnecting the SMB client. + 151 + 152 This method ensures that the SMB client connection is properly closed. It checks if the client is connected + 153 and if so, it closes the connection and resets the connection status. + 154 + 155 Raises: + 156 Exception: If the SMB client is not initialized or if there's an error during the disconnection process. + 157 """ + 158 + 159 if self.smbClient is not None: + 160 if self.connected: + 161 self.smbClient.close() + 162 self.connected = False + 163 if self.config.debug: + 164 print("[+] SMB connection closed successfully.") + 165 else: + 166 if self.config.debug: + 167 print("[!] No active SMB connection to close.") + 168 else: + 169 raise Exception("SMB client is not initialized.") + 170 + 171 # Operations + 172 + 173 def read_file(self, path=None): + 174 if self.path_isfile(path=path): + 175 tmp_file_path = self.smb_cwd + ntpath.sep + path + 176 matches = self.smbClient.listPath( + 177 shareName=self.smb_share, + 178 path=tmp_file_path + 179 ) + 180 + 181 fh = io.BytesIO() + 182 try: + 183 # opening the files in streams instead of mounting shares allows + 184 # for running the script from unprivileged containers + 185 self.smbClient.getFile(self.smb_share, tmp_file_path, fh.write) + 186 except impacket.smbconnection.SessionError as e: + 187 return None + 188 rawdata = fh.getvalue() + 189 fh.close() + 190 return rawdata + 191 else: + 192 print("[!] Remote path '%s' is not a file." % path) + 193 + 194 def find(self, paths=[], callback=None): + 195 def recurse_action(paths=[], depth=0, callback=None): + 196 if callback is None: + 197 return [] + 198 + 199 next_directories_to_explore = [] + 200 + 201 for path in paths: + 202 remote_smb_path = ntpath.normpath(self.smb_cwd + ntpath.sep + path) + 203 entries = [] + 204 + 205 try: + 206 entries = self.smbClient.listPath( + 207 shareName=self.smb_share, + 208 path=(remote_smb_path + ntpath.sep + '*') + 209 ) + 210 except impacket.smbconnection.SessionError as err: + 211 continue + 212 # Remove dot names + 213 entries = [e for e in entries if e.get_longname() not in [".", ".."]] + 214 # Sort the entries ignoring case + 215 entries = sorted(entries, key=lambda x:x.get_longname().lower()) + 216 + 217 for entry in entries: + 218 if entry.is_directory(): + 219 callback(entry, path + ntpath.sep + entry.get_longname() + ntpath.sep, depth) + 220 else: + 221 callback(entry, path + ntpath.sep + entry.get_longname(), depth) + 222 + 223 # Next directories to explore + 224 for entry in entries: + 225 if entry.is_directory(): + 226 next_directories_to_explore.append(path + ntpath.sep + entry.get_longname() + ntpath.sep) + 227 + 228 return next_directories_to_explore + 229 # + 230 if callback is not None: + 231 depth = 0 + 232 while len(paths) != 0: + 233 paths = recurse_action( + 234 paths=paths, + 235 depth=depth, + 236 callback=callback + 237 ) + 238 depth = depth + 1 + 239 else: + 240 print("[!] SMBSession.find(), callback function cannot be None.") + 241 + 242 def get_file(self, path=None, keepRemotePath=False): + 243 """ + 244 Retrieves a file from the specified path on the SMB share. + 245 + 246 This method attempts to retrieve a file from the given path within the currently connected SMB share. + 247 If the path points to a directory, it skips the retrieval. It handles file retrieval by creating a local + 248 file object and writing the contents of the remote file to it using the SMB client's getFile method. + 249 + 250 Parameters: + 251 path (str): The path of the file to retrieve. If None, uses the current smb_path. + 252 + 253 Returns: + 254 None + 255 """ + 256 + 257 # Parse path + 258 path = path.replace('/', ntpath.sep) + 259 if ntpath.sep in path: + 260 tmp_search_path = ntpath.normpath(self.smb_cwd + ntpath.sep + ntpath.dirname(path)) + 261 else: + 262 tmp_search_path = ntpath.normpath(self.smb_cwd + ntpath.sep) + 263 # Parse filename + 264 filename = ntpath.basename(path) + 265 + 266 # Search for the file + 267 matches = self.smbClient.listPath( + 268 shareName=self.smb_share, + 269 path=tmp_search_path + ntpath.sep + '*' + 270 ) + 271 + 272 # Filter the entries + 273 matching_entries = [] + 274 for entry in matches: + 275 if entry.is_directory(): + 276 # Skip directories + 277 continue + 278 if entry.get_longname() == filename: + 279 matching_entries.append(entry) + 280 elif '*' in filename: + 281 regexp = filename.replace('.', '\\.').replace('*', '.*') + 282 if re.match(regexp, entry.get_longname()): + 283 matching_entries.append(entry) + 284 + 285 matching_entries = sorted(list(set(matching_entries)), key=lambda x: x.get_longname()) + 286 + 287 for entry in matching_entries: + 288 if entry.is_directory(): + 289 if self.config.debug: + 290 print("[debug] [>] Skipping '%s' because it is a directory." % (tmp_search_path + ntpath.sep + entry.get_longname())) + 291 else: + 292 try: + 293 if ntpath.sep in path: + 294 outputfile = ntpath.dirname(path) + ntpath.sep + entry.get_longname() + 295 else: + 296 outputfile = entry.get_longname() + 297 f = LocalFileIO( + 298 mode="wb", + 299 path=outputfile, + 300 expected_size=entry.get_filesize(), + 301 debug=self.config.debug, + 302 keepRemotePath=keepRemotePath + 303 ) + 304 self.smbClient.getFile( + 305 shareName=self.smb_share, + 306 pathName=tmp_search_path + ntpath.sep + entry.get_longname(), + 307 callback=f.write + 308 ) + 309 f.close() + 310 except (BrokenPipeError, KeyboardInterrupt) as e: + 311 f.close() + 312 print("\x1b[v\x1b[o\r[!] Interrupted.") + 313 self.close_smb_session() + 314 self.init_smb_session() + 315 + 316 return None + 317 + 318 def get_file_recursively(self, path=None): + 319 """ + 320 Recursively retrieves files from a specified path on the SMB share. + 321 + 322 This method navigates through all directories starting from the given path, + 323 and downloads all files found. It handles directories recursively, ensuring + 324 that all nested files are retrieved. The method skips over directory entries + 325 and handles errors gracefully, attempting to continue the operation where possible. + 326 + 327 Parameters: + 328 path (str): The initial directory path from which to start the recursive file retrieval. + 329 If None, it starts from the root of the configured SMB share. + 330 """ + 331 + 332 def recurse_action(base_dir="", path=[]): + 333 if len(base_dir) == 0: + 334 remote_smb_path = ntpath.sep.join(path) + 335 else: + 336 remote_smb_path = base_dir + ntpath.sep + ntpath.sep.join(path) + 337 remote_smb_path = ntpath.normpath(remote_smb_path) + 338 + 339 entries = self.smbClient.listPath( + 340 shareName=self.smb_share, + 341 path=remote_smb_path + '\\*' + 342 ) + 343 if len(entries) != 0: + 344 files = [entry for entry in entries if not entry.is_directory()] + 345 directories = [entry for entry in entries if entry.is_directory() and entry.get_longname() not in [".", ".."]] + 346 + 347 # Files + 348 if len(files) != 0: + 349 print("[>] Retrieving files of '%s'" % remote_smb_path) + 350 for entry_file in files: + 351 if not entry_file.is_directory(): + 352 f = LocalFileIO( + 353 mode="wb", + 354 path=remote_smb_path + ntpath.sep + entry_file.get_longname(), + 355 expected_size=entry_file.get_filesize(), + 356 keepRemotePath=True, + 357 debug=self.config.debug + 358 ) + 359 try: + 360 self.smbClient.getFile( + 361 shareName=self.smb_share, + 362 pathName=remote_smb_path + ntpath.sep + entry_file.get_longname(), + 363 callback=f.write + 364 ) + 365 f.close() + 366 except BrokenPipeError as err: + 367 f.set_error(message="[bold red]Failed downloading '%s': %s" % (f.path, err)) + 368 f.close(remove=True) + 369 break + 370 except Exception as err: + 371 f.set_error(message="[bold red]Failed downloading '%s': %s" % (f.path, err)) + 372 f.close(remove=True) + 373 + 374 # Directories + 375 for entry_directory in directories: + 376 if entry_directory.is_directory(): + 377 recurse_action( + 378 base_dir=self.smb_cwd, + 379 path=path+[entry_directory.get_longname()] + 380 ) + 381 # Entrypoint + 382 try: + 383 recurse_action( + 384 base_dir=self.smb_cwd, + 385 path=[path] + 386 ) + 387 except (BrokenPipeError, KeyboardInterrupt) as e: + 388 print("\x1b[v\x1b[o\r[!] Interrupted.") + 389 self.close_smb_session() + 390 self.init_smb_session() + 391 + 392 def get_entry(self, path=None): + 393 """ + 394 Retrieves information about a specific entry located at the provided path on the SMB share. 395 - 396 Parameters: - 397 share (bool): If True, display information about the current share. - 398 server (bool): If True, display information about the server. - 399 - 400 Returns: - 401 None - 402 """ - 403 - 404 if server: - 405 if self.config.no_colors: - 406 print("[+] Server:") - 407 print(" ├─NetBIOS:") - 408 print(" │ ├─ NetBIOS Hostname ──────── : %s" % (self.smbClient.getServerName())) - 409 print(" │ └─ NetBIOS Domain ────────── : %s" % (self.smbClient.getServerDomain())) - 410 print(" ├─DNS:") - 411 print(" │ ├─ DNS Hostname ──────────── : %s" % (self.smbClient.getServerDNSHostName())) - 412 print(" │ └─ DNS Domain ────────────── : %s" % (self.smbClient.getServerDNSDomainName())) - 413 print(" ├─OS:") - 414 print(" │ ├─ OS Name ───────────────── : %s" % (self.smbClient.getServerOS())) - 415 print(" │ └─ OS Version ────────────── : %s.%s.%s" % (self.smbClient.getServerOSMajor(), self.smbClient.getServerOSMinor(), self.smbClient.getServerOSBuild())) - 416 print(" ├─Server:") - 417 print(" │ ├─ Signing Required ──────── : %s" % (self.smbClient.isSigningRequired())) - 418 print(" │ ├─ Login Required ────────── : %s" % (self.smbClient.isLoginRequired())) - 419 print(" │ ├─ Supports NTLMv2 ───────── : %s" % (self.smbClient.doesSupportNTLMv2())) - 420 MaxReadSize = self.smbClient.getIOCapabilities()["MaxReadSize"] - 421 print(" │ ├─ Max size of read chunk ── : %d bytes (%s)" % (MaxReadSize, b_filesize(MaxReadSize))) - 422 MaxWriteSize = self.smbClient.getIOCapabilities()["MaxWriteSize"] - 423 print(" │ └─ Max size of write chunk ─ : %d bytes (%s)" % (MaxWriteSize, b_filesize(MaxWriteSize))) - 424 print(" └─") - 425 else: - 426 print("[+] Server:") - 427 print(" ├─NetBIOS:") - 428 print(" │ ├─ \x1b[94mNetBIOS Hostname\x1b[0m \x1b[90m────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerName())) - 429 print(" │ └─ \x1b[94mNetBIOS Domain\x1b[0m \x1b[90m──────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDomain())) - 430 print(" ├─DNS:") - 431 print(" │ ├─ \x1b[94mDNS Hostname\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDNSHostName())) - 432 print(" │ └─ \x1b[94mDNS Domain\x1b[0m \x1b[90m──────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDNSDomainName())) - 433 print(" ├─OS:") - 434 print(" │ ├─ \x1b[94mOS Name\x1b[0m \x1b[90m─────────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerOS())) - 435 print(" │ └─ \x1b[94mOS Version\x1b[0m \x1b[90m──────────────\x1b[0m : \x1b[93m%s.%s.%s\x1b[0m" % (self.smbClient.getServerOSMajor(), self.smbClient.getServerOSMinor(), self.smbClient.getServerOSBuild())) - 436 print(" ├─Server:") - 437 print(" │ ├─ \x1b[94mSigning Required\x1b[0m \x1b[90m────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.isSigningRequired())) - 438 print(" │ ├─ \x1b[94mLogin Required\x1b[0m \x1b[90m──────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.isLoginRequired())) - 439 print(" │ ├─ \x1b[94mSupports NTLMv2\x1b[0m \x1b[90m─────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.doesSupportNTLMv2())) - 440 MaxReadSize = self.smbClient.getIOCapabilities()["MaxReadSize"] - 441 print(" │ ├─ \x1b[94mMax size of read chunk\x1b[0m \x1b[90m──\x1b[0m : \x1b[93m%d bytes (%s)\x1b[0m" % (MaxReadSize, b_filesize(MaxReadSize))) - 442 MaxWriteSize = self.smbClient.getIOCapabilities()["MaxWriteSize"] - 443 print(" │ └─ \x1b[94mMax size of write chunk\x1b[0m \x1b[90m─\x1b[0m : \x1b[93m%d bytes (%s)\x1b[0m" % (MaxWriteSize, b_filesize(MaxWriteSize))) - 444 print(" └─") - 445 - 446 if share and self.smb_share is not None: - 447 share_name = self.available_shares.get(self.smb_share.lower(), "")["name"] - 448 share_comment = self.available_shares.get(self.smb_share.lower(), "")["comment"] - 449 share_type = self.available_shares.get(self.smb_share.lower(), "")["type"] - 450 share_type =', '.join([s.replace("STYPE_","") for s in share_type]) - 451 share_rawtype = self.available_shares.get(self.smb_share.lower(), "")["rawtype"] - 452 if self.config.no_colors: - 453 print("\n[+] Share:") - 454 print(" ├─ Name ──────────── : %s" % (share_name)) - 455 print(" ├─ Description ───── : %s" % (share_comment)) - 456 print(" ├─ Type ──────────── : %s" % (share_type)) - 457 print(" └─ Raw type value ── : %s" % (share_rawtype)) - 458 else: - 459 print("\n[+] Share:") - 460 print(" ├─ \x1b[94mName\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_name)) - 461 print(" ├─ \x1b[94mDescription\x1b[0m \x1b[90m─────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_comment)) - 462 print(" ├─ \x1b[94mType\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_type)) - 463 print(" └─ \x1b[94mRaw type value\x1b[0m \x1b[90m──\x1b[0m : \x1b[93m%s\x1b[0m" % (share_rawtype)) - 464 - 465 def list_contents(self, path=None): - 466 """ - 467 Lists the contents of a specified directory on the SMB share. - 468 - 469 This method retrieves the contents of a directory specified by `shareName` and `path`. If `shareName` or `path` - 470 is not provided, it defaults to the instance's current SMB share or path. The method returns a dictionary with - 471 the long names of the files and directories as keys and their respective SMB entry objects as values. - 472 - 473 Args: - 474 shareName (str, optional): The name of the SMB share. Defaults to the current SMB share if None. - 475 path (str, optional): The directory path to list contents from. Defaults to the current path if None. - 476 - 477 Returns: - 478 dict: A dictionary with file and directory names as keys and their SMB entry objects as values. - 479 """ - 480 - 481 dest_path = [self.smb_cwd.rstrip(ntpath.sep),] - 482 if path is not None and len(path) > 0: - 483 dest_path.append(path.rstrip(ntpath.sep)) - 484 dest_path.append('*') - 485 path = ntpath.sep.join(dest_path) - 486 - 487 contents = {} - 488 entries = self.smbClient.listPath( - 489 shareName=self.smb_share, - 490 path=path - 491 ) - 492 for entry in entries: - 493 contents[entry.get_longname()] = entry + 396 This method checks if the specified path exists on the SMB share. If the path exists, it retrieves the details of the entry at that path, including the directory name and file name. If the entry is found, it returns the entry object; otherwise, it returns None. + 397 + 398 Args: + 399 path (str): The path of the entry to retrieve information about. + 400 + 401 Returns: + 402 Entry: An object representing the entry at the specified path, or None if the entry is not found. + 403 """ + 404 + 405 if self.path_exists(path=path): + 406 matches = self.smbClient.listPath(shareName=self.smb_share, path=path) + 407 + 408 if len(matches) == 1: + 409 return matches[0] + 410 else: + 411 return None + 412 + 413 else: + 414 return None + 415 + 416 def info(self, share=True, server=True): + 417 """ + 418 Displays information about the server and optionally the shares. + 419 + 420 This method prints detailed information about the server's characteristics such as NetBIOS names, DNS details, OS information, and SMB capabilities. If the `share` parameter is set to True and a share is currently set, it will also attempt to display information about the share. + 421 + 422 Parameters: + 423 share (bool): If True, display information about the current share. + 424 server (bool): If True, display information about the server. + 425 + 426 Returns: + 427 None + 428 """ + 429 + 430 if server: + 431 if self.config.no_colors: + 432 print("[+] Server:") + 433 print(" ├─NetBIOS:") + 434 print(" │ ├─ NetBIOS Hostname ──────── : %s" % (self.smbClient.getServerName())) + 435 print(" │ └─ NetBIOS Domain ────────── : %s" % (self.smbClient.getServerDomain())) + 436 print(" ├─DNS:") + 437 print(" │ ├─ DNS Hostname ──────────── : %s" % (self.smbClient.getServerDNSHostName())) + 438 print(" │ └─ DNS Domain ────────────── : %s" % (self.smbClient.getServerDNSDomainName())) + 439 print(" ├─OS:") + 440 print(" │ ├─ OS Name ───────────────── : %s" % (self.smbClient.getServerOS())) + 441 print(" │ └─ OS Version ────────────── : %s.%s.%s" % (self.smbClient.getServerOSMajor(), self.smbClient.getServerOSMinor(), self.smbClient.getServerOSBuild())) + 442 print(" ├─Server:") + 443 print(" │ ├─ Signing Required ──────── : %s" % (self.smbClient.isSigningRequired())) + 444 print(" │ ├─ Login Required ────────── : %s" % (self.smbClient.isLoginRequired())) + 445 print(" │ ├─ Supports NTLMv2 ───────── : %s" % (self.smbClient.doesSupportNTLMv2())) + 446 MaxReadSize = self.smbClient.getIOCapabilities()["MaxReadSize"] + 447 print(" │ ├─ Max size of read chunk ── : %d bytes (%s)" % (MaxReadSize, b_filesize(MaxReadSize))) + 448 MaxWriteSize = self.smbClient.getIOCapabilities()["MaxWriteSize"] + 449 print(" │ └─ Max size of write chunk ─ : %d bytes (%s)" % (MaxWriteSize, b_filesize(MaxWriteSize))) + 450 print(" └─") + 451 else: + 452 print("[+] Server:") + 453 print(" ├─NetBIOS:") + 454 print(" │ ├─ \x1b[94mNetBIOS Hostname\x1b[0m \x1b[90m────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerName())) + 455 print(" │ └─ \x1b[94mNetBIOS Domain\x1b[0m \x1b[90m──────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDomain())) + 456 print(" ├─DNS:") + 457 print(" │ ├─ \x1b[94mDNS Hostname\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDNSHostName())) + 458 print(" │ └─ \x1b[94mDNS Domain\x1b[0m \x1b[90m──────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDNSDomainName())) + 459 print(" ├─OS:") + 460 print(" │ ├─ \x1b[94mOS Name\x1b[0m \x1b[90m─────────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerOS())) + 461 print(" │ └─ \x1b[94mOS Version\x1b[0m \x1b[90m──────────────\x1b[0m : \x1b[93m%s.%s.%s\x1b[0m" % (self.smbClient.getServerOSMajor(), self.smbClient.getServerOSMinor(), self.smbClient.getServerOSBuild())) + 462 print(" ├─Server:") + 463 print(" │ ├─ \x1b[94mSigning Required\x1b[0m \x1b[90m────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.isSigningRequired())) + 464 print(" │ ├─ \x1b[94mLogin Required\x1b[0m \x1b[90m──────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.isLoginRequired())) + 465 print(" │ ├─ \x1b[94mSupports NTLMv2\x1b[0m \x1b[90m─────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.doesSupportNTLMv2())) + 466 MaxReadSize = self.smbClient.getIOCapabilities()["MaxReadSize"] + 467 print(" │ ├─ \x1b[94mMax size of read chunk\x1b[0m \x1b[90m──\x1b[0m : \x1b[93m%d bytes (%s)\x1b[0m" % (MaxReadSize, b_filesize(MaxReadSize))) + 468 MaxWriteSize = self.smbClient.getIOCapabilities()["MaxWriteSize"] + 469 print(" │ └─ \x1b[94mMax size of write chunk\x1b[0m \x1b[90m─\x1b[0m : \x1b[93m%d bytes (%s)\x1b[0m" % (MaxWriteSize, b_filesize(MaxWriteSize))) + 470 print(" └─") + 471 + 472 if share and self.smb_share is not None: + 473 share_name = self.available_shares.get(self.smb_share.lower(), "")["name"] + 474 share_comment = self.available_shares.get(self.smb_share.lower(), "")["comment"] + 475 share_type = self.available_shares.get(self.smb_share.lower(), "")["type"] + 476 share_type =', '.join([s.replace("STYPE_","") for s in share_type]) + 477 share_rawtype = self.available_shares.get(self.smb_share.lower(), "")["rawtype"] + 478 if self.config.no_colors: + 479 print("\n[+] Share:") + 480 print(" ├─ Name ──────────── : %s" % (share_name)) + 481 print(" ├─ Description ───── : %s" % (share_comment)) + 482 print(" ├─ Type ──────────── : %s" % (share_type)) + 483 print(" └─ Raw type value ── : %s" % (share_rawtype)) + 484 else: + 485 print("\n[+] Share:") + 486 print(" ├─ \x1b[94mName\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_name)) + 487 print(" ├─ \x1b[94mDescription\x1b[0m \x1b[90m─────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_comment)) + 488 print(" ├─ \x1b[94mType\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_type)) + 489 print(" └─ \x1b[94mRaw type value\x1b[0m \x1b[90m──\x1b[0m : \x1b[93m%s\x1b[0m" % (share_rawtype)) + 490 + 491 def list_contents(self, path=None): + 492 """ + 493 Lists the contents of a specified directory on the SMB share. 494 - 495 return contents - 496 - 497 def list_shares(self): - 498 """ - 499 Lists all the shares available on the connected SMB server. - 500 - 501 This method queries the SMB server to retrieve a list of all available shares. It populates the `shares` dictionary - 502 with key-value pairs where the key is the share name and the value is a dictionary containing details about the share - 503 such as its name, type, raw type, and any comments associated with the share. - 504 - 505 Returns: - 506 dict: A dictionary containing information about each share available on the server. - 507 """ - 508 - 509 self.available_shares = {} - 510 - 511 if self.connected: - 512 if self.smbClient is not None: - 513 resp = self.smbClient.listShares() - 514 - 515 for share in resp: - 516 # SHARE_INFO_1 structure (lmshare.h) - 517 # https://learn.microsoft.com/en-us/windows/win32/api/lmshare/ns-lmshare-share_info_1 - 518 sharename = share["shi1_netname"][:-1] - 519 sharecomment = share["shi1_remark"][:-1] - 520 sharetype = share["shi1_type"] - 521 - 522 self.available_shares[sharename.lower()] = { - 523 "name": sharename, - 524 "type": STYPE_MASK(sharetype), - 525 "rawtype": sharetype, - 526 "comment": sharecomment - 527 } - 528 else: - 529 print("[!] Error: SMBSession.smbClient is None.") + 495 This method retrieves the contents of a directory specified by `shareName` and `path`. If `shareName` or `path` + 496 is not provided, it defaults to the instance's current SMB share or path. The method returns a dictionary with + 497 the long names of the files and directories as keys and their respective SMB entry objects as values. + 498 + 499 Args: + 500 shareName (str, optional): The name of the SMB share. Defaults to the current SMB share if None. + 501 path (str, optional): The directory path to list contents from. Defaults to the current path if None. + 502 + 503 Returns: + 504 dict: A dictionary with file and directory names as keys and their SMB entry objects as values. + 505 """ + 506 + 507 dest_path = [self.smb_cwd.rstrip(ntpath.sep),] + 508 if path is not None and len(path) > 0: + 509 dest_path.append(path.rstrip(ntpath.sep)) + 510 dest_path.append('*') + 511 path = ntpath.sep.join(dest_path) + 512 + 513 contents = {} + 514 entries = self.smbClient.listPath( + 515 shareName=self.smb_share, + 516 path=path + 517 ) + 518 for entry in entries: + 519 contents[entry.get_longname()] = entry + 520 + 521 return contents + 522 + 523 def list_shares(self): + 524 """ + 525 Lists all the shares available on the connected SMB server. + 526 + 527 This method queries the SMB server to retrieve a list of all available shares. It populates the `shares` dictionary + 528 with key-value pairs where the key is the share name and the value is a dictionary containing details about the share + 529 such as its name, type, raw type, and any comments associated with the share. 530 - 531 return self.available_shares - 532 - 533 def mkdir(self, path=None): - 534 """ - 535 Creates a directory at the specified path on the SMB share. + 531 Returns: + 532 dict: A dictionary containing information about each share available on the server. + 533 """ + 534 + 535 self.available_shares = {} 536 - 537 This method takes a path and attempts to create the directory structure on the SMB share. If the path includes - 538 nested directories, it will create each directory in the sequence. If a directory already exists, it will skip - 539 the creation for that directory without raising an error. + 537 if self.connected: + 538 if self.smbClient is not None: + 539 resp = self.smbClient.listShares() 540 - 541 Args: - 542 path (str, optional): The full path of the directory to create on the SMB share. Defaults to None. - 543 - 544 Note: - 545 The path should use forward slashes ('/') which will be converted to backslashes (ntpath.sep) for SMB compatibility. - 546 """ + 541 for share in resp: + 542 # SHARE_INFO_1 structure (lmshare.h) + 543 # https://learn.microsoft.com/en-us/windows/win32/api/lmshare/ns-lmshare-share_info_1 + 544 sharename = share["shi1_netname"][:-1] + 545 sharecomment = share["shi1_remark"][:-1] + 546 sharetype = share["shi1_type"] 547 - 548 if path is not None: - 549 # Prepare path - 550 path = path.replace('/',ntpath.sep) - 551 if ntpath.sep in path: - 552 path = path.strip(ntpath.sep).split(ntpath.sep) - 553 else: - 554 path = [path] - 555 - 556 # Create each dir in the path - 557 for depth in range(1, len(path)+1): - 558 tmp_path = ntpath.sep.join(path[:depth]) - 559 try: - 560 self.smbClient.createDirectory( - 561 shareName=self.smb_share, - 562 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + tmp_path + ntpath.sep) - 563 ) - 564 except impacket.smbconnection.SessionError as err: - 565 if err.getErrorCode() == 0xc0000035: - 566 # STATUS_OBJECT_NAME_COLLISION - 567 # Remote directory already created, this is normal - 568 # Src: https://github.com/fortra/impacket/blob/269ce69872f0e8f2188a80addb0c39fedfa6dcb8/impacket/nt_errors.py#L268C9-L268C19 - 569 pass - 570 else: - 571 print("[!] Failed to create directory '%s': %s" % (tmp_path, err)) - 572 if self.config.debug: - 573 traceback.print_exc() - 574 else: - 575 pass - 576 - 577 def mount(self, local_mount_point, remote_path): - 578 - 579 if not os.path.exists(local_mount_point): - 580 pass + 548 self.available_shares[sharename.lower()] = { + 549 "name": sharename, + 550 "type": STYPE_MASK(sharetype), + 551 "rawtype": sharetype, + 552 "comment": sharecomment + 553 } + 554 else: + 555 print("[!] Error: SMBSession.smbClient is None.") + 556 + 557 return self.available_shares + 558 + 559 def mkdir(self, path=None): + 560 """ + 561 Creates a directory at the specified path on the SMB share. + 562 + 563 This method takes a path and attempts to create the directory structure on the SMB share. If the path includes + 564 nested directories, it will create each directory in the sequence. If a directory already exists, it will skip + 565 the creation for that directory without raising an error. + 566 + 567 Args: + 568 path (str, optional): The full path of the directory to create on the SMB share. Defaults to None. + 569 + 570 Note: + 571 The path should use forward slashes ('/') which will be converted to backslashes (ntpath.sep) for SMB compatibility. + 572 """ + 573 + 574 if path is not None: + 575 # Prepare path + 576 path = path.replace('/',ntpath.sep) + 577 if ntpath.sep in path: + 578 path = path.strip(ntpath.sep).split(ntpath.sep) + 579 else: + 580 path = [path] 581 - 582 if sys.platform.startswith('win'): - 583 remote_path = remote_path.replace('/',ntpath.sep) - 584 command = f"net use {local_mount_point} \\\\{self.address}\\{self.smb_share}\\{remote_path}" - 585 - 586 elif sys.platform.startswith('linux'): - 587 remote_path = remote_path.replace(ntpath.sep,'/') - 588 command = f"mount -t cifs //{self.address}/{self.smb_share}/{remote_path} {local_mount_point} -o username={self.username},password={self.password}" - 589 - 590 elif sys.platform.startswith('darwin'): - 591 remote_path = remote_path.replace(ntpath.sep,'/') - 592 command = f"mount_smbfs //{self.username}:{self.password}@{self.address}/{self.smb_share}/{remote_path} {local_mount_point}" - 593 - 594 else: - 595 command = None - 596 print("[!] Unsupported platform for mounting SMB share.") - 597 - 598 if command is not None: - 599 if self.config.debug: - 600 print("[debug] Executing: %s" % command) - 601 os.system(command) + 582 # Create each dir in the path + 583 for depth in range(1, len(path)+1): + 584 tmp_path = ntpath.sep.join(path[:depth]) + 585 try: + 586 self.smbClient.createDirectory( + 587 shareName=self.smb_share, + 588 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + tmp_path + ntpath.sep) + 589 ) + 590 except impacket.smbconnection.SessionError as err: + 591 if err.getErrorCode() == 0xc0000035: + 592 # STATUS_OBJECT_NAME_COLLISION + 593 # Remote directory already created, this is normal + 594 # Src: https://github.com/fortra/impacket/blob/269ce69872f0e8f2188a80addb0c39fedfa6dcb8/impacket/nt_errors.py#L268C9-L268C19 + 595 pass + 596 else: + 597 print("[!] Failed to create directory '%s': %s" % (tmp_path, err)) + 598 if self.config.debug: + 599 traceback.print_exc() + 600 else: + 601 pass 602 - 603 def path_exists(self, path=None): + 603 def mount(self, local_mount_point, remote_path): 604 """ - 605 Checks if the specified path exists on the SMB share. + 605 Generates the command to mount an SMB share on different platforms. 606 - 607 This method determines if a given path exists on the SMB share by attempting to list the contents of the path. - 608 If the path listing is successful and returns one or more entries, the path is considered to exist. + 607 This method takes the local mount point and the remote path of the SMB share and generates the appropriate mount command based on the platform. + 608 It constructs the mount command using the provided parameters and executes it using the os.system() function. 609 610 Args: - 611 path (str, optional): The path to check on the SMB share. Defaults to None. - 612 - 613 Returns: - 614 bool: True if the path exists, False otherwise or if an error occurs. - 615 """ - 616 - 617 if path is not None: - 618 path = path.replace('*','') - 619 try: - 620 contents = self.smbClient.listPath( - 621 shareName=self.smb_share, - 622 path=ntpath.normpath(self.smb_cwd + ntpath.sep + path + ntpath.sep) - 623 ) - 624 return (len(contents) != 0) - 625 except Exception as e: - 626 return False - 627 else: - 628 return False - 629 - 630 def path_isdir(self, pathFromRoot=None): - 631 """ - 632 Checks if the specified path is a directory on the SMB share. - 633 - 634 This method determines if a given path corresponds to a directory on the SMB share. It does this by listing the - 635 contents of the path and filtering for entries that match the basename of the path and are marked as directories. - 636 - 637 Args: - 638 path (str, optional): The path to check on the SMB share. Defaults to None. - 639 - 640 Returns: - 641 bool: True if the path is a directory, False otherwise or if an error occurs. - 642 """ - 643 - 644 if pathFromRoot is not None: - 645 # Replace slashes if any - 646 path = pathFromRoot.replace('/', ntpath.sep) - 647 - 648 # Strip wildcards to avoid injections - 649 path = path.replace('*','') - 650 - 651 # Normalize path and strip leading backslash - 652 path = ntpath.normpath(path + ntpath.sep).lstrip(ntpath.sep) - 653 - 654 if path.strip() in ['', '.', '..']: - 655 # By defininition they exist on the filesystem - 656 return True - 657 else: - 658 try: - 659 contents = self.smbClient.listPath( - 660 shareName=self.smb_share, - 661 path=path+'*' - 662 ) - 663 # Filter on directories - 664 contents = [ - 665 c for c in contents - 666 if c.get_longname() == ntpath.basename(path) and c.is_directory() - 667 ] - 668 return (len(contents) != 0) - 669 except Exception as e: - 670 return False - 671 else: - 672 return False - 673 - 674 def path_isfile(self, path=None): - 675 """ - 676 Checks if the specified path is a file on the SMB share. - 677 - 678 This method determines if a given path corresponds to a file on the SMB share. It does this by listing the - 679 contents of the path and filtering for entries that match the basename of the path and are not marked as directories. - 680 - 681 Args: - 682 path (str, optional): The path to check on the SMB share. Defaults to None. - 683 - 684 Returns: - 685 bool: True if the path is a file, False otherwise or if an error occurs. - 686 """ - 687 - 688 if path is not None: - 689 path = path.replace('*','') - 690 search_dir = ntpath.normpath(self.smb_cwd + ntpath.sep + path) - 691 search_dir = ntpath.dirname(search_dir) + ntpath.sep + '*' - 692 try: - 693 contents = self.smbClient.listPath( - 694 shareName=self.smb_share, - 695 path=search_dir - 696 ) - 697 # Filter on files - 698 contents = [ - 699 c for c in contents - 700 if c.get_longname() == ntpath.basename(path) and not c.is_directory() - 701 ] - 702 return (len(contents) != 0) - 703 except Exception as e: - 704 return False - 705 else: - 706 return False - 707 - 708 def ping_smb_session(self): - 709 """ - 710 Tests the connectivity to the SMB server by sending an echo command. - 711 - 712 This method attempts to send an echo command to the SMB server to check if the session is still active. - 713 It updates the `connected` attribute of the class based on the success or failure of the echo command. - 714 - 715 Returns: - 716 bool: True if the echo command succeeds (indicating the session is active), False otherwise. - 717 """ + 611 local_mount_point (str): The local directory where the SMB share will be mounted. + 612 remote_path (str): The remote path on the SMB share to be mounted. + 613 + 614 Note: + 615 - For Windows platform, the command uses 'net use' to mount the share. + 616 - For Linux platform, the command uses 'mount' to mount the share. + 617 - For macOS platform, the command uses 'mount_smbfs' to mount the share. + 618 - If the platform is not supported, an error message is displayed. + 619 + 620 Returns: + 621 None + 622 """ + 623 + 624 if not os.path.exists(local_mount_point): + 625 pass + 626 + 627 if sys.platform.startswith('win'): + 628 remote_path = remote_path.replace('/',ntpath.sep) + 629 command = f"net use {local_mount_point} \\\\{self.address}\\{self.smb_share}\\{remote_path}" + 630 + 631 elif sys.platform.startswith('linux'): + 632 remote_path = remote_path.replace(ntpath.sep,'/') + 633 command = f"mount -t cifs //{self.address}/{self.smb_share}/{remote_path} {local_mount_point} -o username={self.username},password={self.password}" + 634 + 635 elif sys.platform.startswith('darwin'): + 636 remote_path = remote_path.replace(ntpath.sep,'/') + 637 command = f"mount_smbfs //{self.username}:{self.password}@{self.address}/{self.smb_share}/{remote_path} {local_mount_point}" + 638 + 639 else: + 640 command = None + 641 print("[!] Unsupported platform for mounting SMB share.") + 642 + 643 if command is not None: + 644 if self.config.debug: + 645 print("[debug] Executing: %s" % command) + 646 os.system(command) + 647 + 648 def path_exists(self, path=None): + 649 """ + 650 Checks if the specified path exists on the SMB share. + 651 + 652 This method determines if a given path exists on the SMB share by attempting to list the contents of the path. + 653 If the path listing is successful and returns one or more entries, the path is considered to exist. + 654 + 655 Args: + 656 path (str, optional): The path to check on the SMB share. Defaults to None. + 657 + 658 Returns: + 659 bool: True if the path exists, False otherwise or if an error occurs. + 660 """ + 661 + 662 if path is not None: + 663 path = path.replace('*','') + 664 try: + 665 contents = self.smbClient.listPath( + 666 shareName=self.smb_share, + 667 path=ntpath.normpath(self.smb_cwd + ntpath.sep + path + ntpath.sep) + 668 ) + 669 return (len(contents) != 0) + 670 except Exception as e: + 671 return False + 672 else: + 673 return False + 674 + 675 def path_isdir(self, pathFromRoot=None): + 676 """ + 677 Checks if the specified path is a directory on the SMB share. + 678 + 679 This method determines if a given path corresponds to a directory on the SMB share. It does this by listing the + 680 contents of the path and filtering for entries that match the basename of the path and are marked as directories. + 681 + 682 Args: + 683 path (str, optional): The path to check on the SMB share. Defaults to None. + 684 + 685 Returns: + 686 bool: True if the path is a directory, False otherwise or if an error occurs. + 687 """ + 688 + 689 if pathFromRoot is not None: + 690 # Replace slashes if any + 691 path = pathFromRoot.replace('/', ntpath.sep) + 692 + 693 # Strip wildcards to avoid injections + 694 path = path.replace('*','') + 695 + 696 # Normalize path and strip leading backslash + 697 path = ntpath.normpath(path + ntpath.sep).lstrip(ntpath.sep) + 698 + 699 if path.strip() in ['', '.', '..']: + 700 # By defininition they exist on the filesystem + 701 return True + 702 else: + 703 try: + 704 contents = self.smbClient.listPath( + 705 shareName=self.smb_share, + 706 path=path+'*' + 707 ) + 708 # Filter on directories + 709 contents = [ + 710 c for c in contents + 711 if c.get_longname() == ntpath.basename(path) and c.is_directory() + 712 ] + 713 return (len(contents) != 0) + 714 except Exception as e: + 715 return False + 716 else: + 717 return False 718 - 719 try: - 720 self.smbClient.getSMBServer().echo() - 721 except Exception as e: - 722 self.connected = False - 723 return self.connected - 724 - 725 def put_file(self, localpath=None): - 726 """ - 727 Uploads a single file to the SMB share. + 719 def path_isfile(self, path=None): + 720 """ + 721 Checks if the specified path is a file on the SMB share. + 722 + 723 This method determines if a given path corresponds to a file on the SMB share. It does this by listing the + 724 contents of the path and filtering for entries that match the basename of the path and are not marked as directories. + 725 + 726 Args: + 727 path (str, optional): The path to check on the SMB share. Defaults to None. 728 - 729 This method takes a local file path, opens the file, and uploads it to the SMB share at the specified path. - 730 It handles exceptions such as broken pipe errors or keyboard interrupts by closing and reinitializing the SMB session. - 731 General exceptions are caught and logged, with a traceback provided if debugging is enabled. + 729 Returns: + 730 bool: True if the path is a file, False otherwise or if an error occurs. + 731 """ 732 - 733 Args: - 734 localpath (str, optional): The local file path of the file to be uploaded. Defaults to None. - 735 """ - 736 - 737 if os.path.exists(localpath): - 738 if os.path.isfile(localpath): - 739 try: - 740 localfile = os.path.basename(localpath) - 741 f = LocalFileIO( - 742 mode="rb", - 743 path=localpath, - 744 debug=self.config.debug - 745 ) - 746 self.smbClient.putFile( - 747 shareName=self.smb_share, - 748 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + localfile + ntpath.sep), - 749 callback=f.read - 750 ) - 751 f.close() - 752 except (BrokenPipeError, KeyboardInterrupt) as err: - 753 print("[!] Interrupted.") - 754 self.close_smb_session() - 755 self.init_smb_session() - 756 except Exception as err: - 757 print("[!] Failed to upload '%s': %s" % (localfile, err)) - 758 if self.config.debug: - 759 traceback.print_exc() - 760 else: - 761 print("[!] The specified localpath is a directory. Use 'put -r <directory>' instead.") - 762 else: - 763 print("[!] The specified localpath does not exist.") - 764 - 765 def put_file_recursively(self, localpath=None): - 766 """ - 767 Recursively uploads files from a specified local directory to the SMB share. - 768 - 769 This method walks through the given local directory and all its subdirectories, uploading each file to the - 770 corresponding directory structure on the SMB share. It first checks if the local path is a directory. If it is, - 771 it iterates over all files and directories within the local path, creating necessary directories on the SMB share - 772 and uploading files. If the local path is not a directory, it prints an error message. + 733 if path is not None: + 734 path = path.replace('*','') + 735 search_dir = ntpath.normpath(self.smb_cwd + ntpath.sep + path) + 736 search_dir = ntpath.dirname(search_dir) + ntpath.sep + '*' + 737 try: + 738 contents = self.smbClient.listPath( + 739 shareName=self.smb_share, + 740 path=search_dir + 741 ) + 742 # Filter on files + 743 contents = [ + 744 c for c in contents + 745 if c.get_longname() == ntpath.basename(path) and not c.is_directory() + 746 ] + 747 return (len(contents) != 0) + 748 except Exception as e: + 749 return False + 750 else: + 751 return False + 752 + 753 def ping_smb_session(self): + 754 """ + 755 Tests the connectivity to the SMB server by sending an echo command. + 756 + 757 This method attempts to send an echo command to the SMB server to check if the session is still active. + 758 It updates the `connected` attribute of the class based on the success or failure of the echo command. + 759 + 760 Returns: + 761 bool: True if the echo command succeeds (indicating the session is active), False otherwise. + 762 """ + 763 + 764 try: + 765 self.smbClient.getSMBServer().echo() + 766 except Exception as e: + 767 self.connected = False + 768 return self.connected + 769 + 770 def put_file(self, localpath=None): + 771 """ + 772 Uploads a single file to the SMB share. 773 - 774 Args: - 775 localpath (str, optional): The local directory path from which files will be uploaded. Defaults to None. - 776 """ + 774 This method takes a local file path, opens the file, and uploads it to the SMB share at the specified path. + 775 It handles exceptions such as broken pipe errors or keyboard interrupts by closing and reinitializing the SMB session. + 776 General exceptions are caught and logged, with a traceback provided if debugging is enabled. 777 - 778 if os.path.exists(localpath): - 779 if os.path.isfile(localpath): - 780 # Iterate over all files and directories within the local path - 781 local_files = {} - 782 for root, dirs, files in os.walk(localpath): - 783 if len(files) != 0: - 784 local_files[root] = files - 785 - 786 # Iterate over the found files - 787 for local_dir_path in sorted(local_files.keys()): - 788 print("[>] Putting files of '%s'" % local_dir_path) - 789 - 790 # Create remote directory - 791 remote_dir_path = local_dir_path.replace(os.path.sep, ntpath.sep) - 792 self.mkdir( - 793 path=ntpath.normpath(self.smb_cwd + ntpath.sep + remote_dir_path + ntpath.sep) - 794 ) - 795 - 796 for local_file_path in local_files[local_dir_path]: - 797 try: - 798 f = LocalFileIO( - 799 mode="rb", - 800 path=local_dir_path + os.path.sep + local_file_path, - 801 debug=self.config.debug - 802 ) - 803 self.smbClient.putFile( - 804 shareName=self.smb_share, - 805 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + remote_dir_path + ntpath.sep + local_file_path), - 806 callback=f.read - 807 ) - 808 f.close() - 809 - 810 except BrokenPipeError as err: - 811 f.set_error(message="[bold red]Failed uploading '%s': %s" % (f.path, err)) - 812 f.close(remove=True) - 813 break - 814 except Exception as err: - 815 f.set_error(message="[bold red]Failed uploading '%s': %s" % (f.path, err)) - 816 f.close(remove=True) - 817 else: - 818 print("[!] The specified localpath is a file. Use 'put <file>' instead.") - 819 else: - 820 print("[!] The specified localpath does not exist.") - 821 - 822 def rmdir(self, path=None): - 823 """ - 824 Removes a directory from the SMB share at the specified path. - 825 - 826 This method attempts to delete a directory located at the given path on the SMB share. If the operation fails, - 827 it prints an error message indicating the failure and the reason. If debugging is enabled, it also prints - 828 the stack trace of the exception. - 829 - 830 Args: - 831 path (str, optional): The path of the directory to be removed on the SMB share. Defaults to None. - 832 """ - 833 try: - 834 self.smbClient.deleteDirectory( - 835 shareName=self.smb_share, - 836 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + path), - 837 ) - 838 except Exception as err: - 839 print("[!] Failed to remove directory '%s': %s" % (path, err)) - 840 if self.config.debug: - 841 traceback.print_exc() - 842 - 843 def rm(self, path=None): - 844 """ - 845 Removes a file from the SMB share at the specified path. - 846 - 847 This method attempts to delete a file located at the given path on the SMB share. If the operation fails, - 848 it prints an error message indicating the failure and the reason. If debugging is enabled, it also prints - 849 the stack trace of the exception. - 850 - 851 Args: - 852 path (str, optional): The path of the file to be removed on the SMB share. Defaults to None. - 853 """ - 854 try: - 855 self.smbClient.deleteFile( - 856 shareName=self.smb_share, - 857 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + path), - 858 ) - 859 except Exception as err: - 860 print("[!] Failed to remove file '%s': %s" % (path, err)) - 861 if self.config.debug: - 862 traceback.print_exc() - 863 - 864 def tree(self, path=None): - 865 """ - 866 Recursively lists the directory structure of the SMB share starting from the specified path. + 778 Args: + 779 localpath (str, optional): The local file path of the file to be uploaded. Defaults to None. + 780 """ + 781 + 782 # Parse path + 783 localpath = localpath.replace('/', os.path.sep) + 784 if os.path.sep in localpath: + 785 tmp_search_path = os.path.normpath(os.getcwd() + os.path.sep + os.path.dirname(localpath)) + 786 else: + 787 tmp_search_path = os.path.normpath(os.getcwd() + os.path.sep) + 788 # Parse filename + 789 filename = os.path.basename(localpath) + 790 + 791 # Search for the file + 792 matches = os.listdir(tmp_search_path) + 793 # Filter the entries + 794 matching_entries = [] + 795 for entry in matches: + 796 if entry == filename: + 797 matching_entries.append(entry) + 798 elif '*' in filename: + 799 regexp = filename.replace('.', '\\.').replace('*', '.*') + 800 if re.match(regexp, entry): + 801 matching_entries.append(entry) + 802 + 803 matching_entries = sorted(list(set(matching_entries))) + 804 + 805 # Loop and upload + 806 for localpath in matching_entries: + 807 if os.path.exists(localpath): + 808 if os.path.isfile(localpath): + 809 try: + 810 localfile = os.path.basename(localpath) + 811 f = LocalFileIO( + 812 mode="rb", + 813 path=localpath, + 814 debug=self.config.debug + 815 ) + 816 self.smbClient.putFile( + 817 shareName=self.smb_share, + 818 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + localfile + ntpath.sep), + 819 callback=f.read + 820 ) + 821 f.close() + 822 except (BrokenPipeError, KeyboardInterrupt) as err: + 823 print("[!] Interrupted.") + 824 self.close_smb_session() + 825 self.init_smb_session() + 826 except Exception as err: + 827 print("[!] Failed to upload '%s': %s" % (localfile, err)) + 828 if self.config.debug: + 829 traceback.print_exc() + 830 else: + 831 # [!] The specified localpath is a directory. Use 'put -r <directory>' instead. + 832 pass + 833 else: + 834 # [!] The specified localpath does not exist. + 835 pass + 836 + 837 def put_file_recursively(self, localpath=None): + 838 """ + 839 Recursively uploads files from a specified local directory to the SMB share. + 840 + 841 This method walks through the given local directory and all its subdirectories, uploading each file to the + 842 corresponding directory structure on the SMB share. It first checks if the local path is a directory. If it is, + 843 it iterates over all files and directories within the local path, creating necessary directories on the SMB share + 844 and uploading files. If the local path is not a directory, it prints an error message. + 845 + 846 Args: + 847 localpath (str, optional): The local directory path from which files will be uploaded. Defaults to None. + 848 """ + 849 + 850 if os.path.exists(localpath): + 851 if os.path.isfile(localpath): + 852 # Iterate over all files and directories within the local path + 853 local_files = {} + 854 for root, dirs, files in os.walk(localpath): + 855 if len(files) != 0: + 856 local_files[root] = files + 857 + 858 # Iterate over the found files + 859 for local_dir_path in sorted(local_files.keys()): + 860 print("[>] Putting files of '%s'" % local_dir_path) + 861 + 862 # Create remote directory + 863 remote_dir_path = local_dir_path.replace(os.path.sep, ntpath.sep) + 864 self.mkdir( + 865 path=ntpath.normpath(self.smb_cwd + ntpath.sep + remote_dir_path + ntpath.sep) + 866 ) 867 - 868 This function prints a visual representation of the directory tree of the remote SMB share. It uses - 869 recursion to navigate through directories and lists all files and subdirectories in each directory. - 870 The output is color-coded and formatted to enhance readability, with directories highlighted in cyan. - 871 - 872 Args: - 873 path (str, optional): The starting path on the SMB share from which to begin listing the tree. - 874 Defaults to the root of the current share. - 875 """ - 876 - 877 def recurse_action(base_dir="", path=[], prompt=[]): - 878 bars = ["│ ", "├── ", "└── "] - 879 - 880 remote_smb_path = ntpath.normpath(base_dir + ntpath.sep + ntpath.sep.join(path)) + 868 for local_file_path in local_files[local_dir_path]: + 869 try: + 870 f = LocalFileIO( + 871 mode="rb", + 872 path=local_dir_path + os.path.sep + local_file_path, + 873 debug=self.config.debug + 874 ) + 875 self.smbClient.putFile( + 876 shareName=self.smb_share, + 877 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + remote_dir_path + ntpath.sep + local_file_path), + 878 callback=f.read + 879 ) + 880 f.close() 881 - 882 entries = [] - 883 try: - 884 entries = self.smbClient.listPath( - 885 shareName=self.smb_share, - 886 path=remote_smb_path+'\\*' - 887 ) - 888 except impacket.smbconnection.SessionError as err: - 889 code, const, text = err.getErrorCode(), err.getErrorString()[0], err.getErrorString()[1] - 890 errmsg = "Error 0x%08x (%s): %s" % (code, const, text) - 891 if self.config.no_colors: - 892 print("%s%s" % (''.join(prompt+[bars[2]]), errmsg)) - 893 else: - 894 print("%s\x1b[1;91m%s\x1b[0m" % (''.join(prompt+[bars[2]]), errmsg)) - 895 return - 896 - 897 entries = [e for e in entries if e.get_longname() not in [".", ".."]] - 898 entries = sorted(entries, key=lambda x:x.get_longname()) - 899 - 900 # - 901 if len(entries) > 1: - 902 index = 0 - 903 for entry in entries: - 904 index += 1 - 905 # This is the first entry - 906 if index == 0: - 907 if entry.is_directory(): - 908 if self.config.no_colors: - 909 print("%s%s\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) - 910 else: - 911 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) - 912 recurse_action( - 913 base_dir=base_dir, - 914 path=path+[entry.get_longname()], - 915 prompt=prompt+["│ "] - 916 ) - 917 else: - 918 if self.config.no_colors: - 919 print("%s%s" % (''.join(prompt+[bars[1]]), entry.get_longname())) - 920 else: - 921 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[1]]), entry.get_longname())) + 882 except BrokenPipeError as err: + 883 f.set_error(message="[bold red]Failed uploading '%s': %s" % (f.path, err)) + 884 f.close(remove=True) + 885 break + 886 except Exception as err: + 887 f.set_error(message="[bold red]Failed uploading '%s': %s" % (f.path, err)) + 888 f.close(remove=True) + 889 else: + 890 print("[!] The specified localpath is a file. Use 'put <file>' instead.") + 891 else: + 892 print("[!] The specified localpath does not exist.") + 893 + 894 def rmdir(self, path=None): + 895 """ + 896 Removes a directory from the SMB share at the specified path. + 897 + 898 This method attempts to delete a directory located at the given path on the SMB share. If the operation fails, + 899 it prints an error message indicating the failure and the reason. If debugging is enabled, it also prints + 900 the stack trace of the exception. + 901 + 902 Args: + 903 path (str, optional): The path of the directory to be removed on the SMB share. Defaults to None. + 904 """ + 905 try: + 906 self.smbClient.deleteDirectory( + 907 shareName=self.smb_share, + 908 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + path), + 909 ) + 910 except Exception as err: + 911 print("[!] Failed to remove directory '%s': %s" % (path, err)) + 912 if self.config.debug: + 913 traceback.print_exc() + 914 + 915 def rm(self, path=None): + 916 """ + 917 Removes a file from the SMB share at the specified path. + 918 + 919 This method attempts to delete a file located at the given path on the SMB share. If the operation fails, + 920 it prints an error message indicating the failure and the reason. If debugging is enabled, it also prints + 921 the stack trace of the exception. 922 - 923 # This is the last entry - 924 elif index == len(entries): - 925 if entry.is_directory(): - 926 if self.config.no_colors: - 927 print("%s%s\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) - 928 else: - 929 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) - 930 recurse_action( - 931 base_dir=base_dir, - 932 path=path+[entry.get_longname()], - 933 prompt=prompt+[" "] - 934 ) - 935 else: - 936 if self.config.no_colors: - 937 print("%s%s" % (''.join(prompt+[bars[2]]), entry.get_longname())) - 938 else: - 939 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[2]]), entry.get_longname())) - 940 - 941 # These are entries in the middle - 942 else: - 943 if entry.is_directory(): - 944 if self.config.no_colors: - 945 print("%s%s\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) - 946 else: - 947 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) - 948 recurse_action( - 949 base_dir=base_dir, - 950 path=path+[entry.get_longname()], - 951 prompt=prompt+["│ "] - 952 ) - 953 else: - 954 if self.config.no_colors: - 955 print("%s%s" % (''.join(prompt+[bars[1]]), entry.get_longname())) - 956 else: - 957 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[1]]), entry.get_longname())) - 958 - 959 # - 960 elif len(entries) == 1: - 961 entry = entries[0] - 962 if entry.is_directory(): - 963 if self.config.no_colors: - 964 print("%s%s\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) - 965 else: - 966 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) - 967 recurse_action( - 968 base_dir=base_dir, - 969 path=path+[entry.get_longname()], - 970 prompt=prompt+[" "] - 971 ) - 972 else: - 973 if self.config.no_colors: - 974 print("%s%s" % (''.join(prompt+[bars[2]]), entry.get_longname())) - 975 else: - 976 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[2]]), entry.get_longname())) - 977 - 978 # Entrypoint - 979 try: - 980 if self.config.no_colors: - 981 print("%s\\" % path) - 982 else: - 983 print("\x1b[1;96m%s\x1b[0m\\" % path) - 984 recurse_action( - 985 base_dir=self.smb_cwd, - 986 path=[path], - 987 prompt=[""] - 988 ) - 989 except (BrokenPipeError, KeyboardInterrupt) as e: - 990 print("[!] Interrupted.") - 991 self.close_smb_session() - 992 self.init_smb_session() - 993 - 994 def umount(self, local_mount_point): - 995 if os.path.exists(local_mount_point): - 996 if sys.platform.startswith('win'): - 997 command = f"net use {local_mount_point} /delete" - 998 - 999 elif sys.platform.startswith('linux') or sys.platform.startswith('darwin'): -1000 command = f"umount {local_mount_point}" -1001 -1002 else: -1003 command = None -1004 print("[!] Unsupported platform for unmounting SMB share.") -1005 -1006 if command is not None: -1007 if self.config.debug: -1008 print("[debug] Executing: %s" % command) -1009 os.system(command) -1010 else: -1011 print("[!] Cannot unmount a non existing path.") -1012 -1013 # Setter / Getter -1014 -1015 def set_share(self, shareName): -1016 """ -1017 Sets the current SMB share to the specified share name. -1018 -1019 This method updates the SMB session to use the specified share name. It checks if the share name is valid -1020 and updates the smb_share attribute of the SMBSession instance. -1021 -1022 Parameters: -1023 shareName (str): The name of the share to set as the current SMB share. -1024 -1025 Raises: -1026 ValueError: If the shareName is None or an empty string. -1027 """ -1028 -1029 if shareName is not None: -1030 self.list_shares() -1031 if shareName.lower() in self.available_shares.keys(): -1032 # Doing this in order to keep the case of the share adevertised by the remote machine -1033 self.smb_share = self.available_shares[shareName.lower()]["name"] -1034 # Connects the tree -1035 self.smb_tree_id = self.smbClient.connectTree(self.smb_share) -1036 else: -1037 print("[!] Could not set share '%s', it does not exist remotely." % shareName) -1038 -1039 def set_cwd(self, path=None): -1040 """ -1041 Sets the current working directory on the SMB share to the specified path. -1042 -1043 This method updates the current working directory (cwd) of the SMB session to the given path if it is a valid directory. -1044 If the specified path is not a directory, the cwd remains unchanged. -1045 -1046 Parameters: -1047 path (str): The path to set as the current working directory. -1048 -1049 Raises: -1050 ValueError: If the specified path is not a directory. -1051 """ -1052 -1053 if path is not None: -1054 # Set path separators to ntpath sep -1055 if '/' in path: -1056 path = path.replace('/', ntpath.sep) -1057 -1058 if path.startswith(ntpath.sep): -1059 # Absolute path -1060 path = path + ntpath.sep -1061 else: -1062 # Relative path to the CWD -1063 if len(self.smb_cwd) == 0: -1064 path = path + ntpath.sep -1065 else: -1066 path = self.smb_cwd + ntpath.sep + path -1067 -1068 # Path normalization -1069 path = ntpath.normpath(path) -1070 path = re.sub(r'\\+', r'\\', path) -1071 -1072 if path in ["", ".", ".."]: -1073 self.smb_cwd = "" -1074 else: -1075 if self.path_isdir(pathFromRoot=path.strip(ntpath.sep)): -1076 # Path exists on the remote -1077 self.smb_cwd = ntpath.normpath(path) -1078 else: -1079 # Path does not exists or is not a directory on the remote -1080 print("[!] Remote directory '%s' does not exist." % path) + 923 Args: + 924 path (str, optional): The path of the file to be removed on the SMB share. Defaults to None. + 925 """ + 926 + 927 # Parse path + 928 path = path.replace('/', ntpath.sep) + 929 if ntpath.sep in path: + 930 tmp_search_path = ntpath.normpath(self.smb_cwd + ntpath.sep + ntpath.dirname(path)) + 931 else: + 932 tmp_search_path = ntpath.normpath(self.smb_cwd + ntpath.sep) + 933 # Parse filename + 934 filename = ntpath.basename(path) + 935 + 936 # Search for the file + 937 matches = self.smbClient.listPath( + 938 shareName=self.smb_share, + 939 path=tmp_search_path + ntpath.sep + '*' + 940 ) + 941 + 942 # Filter the entries + 943 matching_entries = [] + 944 for entry in matches: + 945 if entry.is_directory(): + 946 # Skip directories + 947 continue + 948 if entry.get_longname() == filename: + 949 matching_entries.append(entry) + 950 elif '*' in filename: + 951 regexp = filename.replace('.', '\\.').replace('*', '.*') + 952 if re.match(regexp, entry.get_longname()): + 953 matching_entries.append(entry) + 954 + 955 matching_entries = sorted(list(set(matching_entries)), key=lambda x: x.get_longname()) + 956 + 957 for entry in matching_entries: + 958 try: + 959 self.smbClient.deleteFile( + 960 shareName=self.smb_share, + 961 pathName=ntpath.normpath(tmp_search_path + ntpath.sep + entry.get_longname()), + 962 ) + 963 except Exception as err: + 964 print("[!] Failed to remove file '%s': %s" % (path, err)) + 965 if self.config.debug: + 966 traceback.print_exc() + 967 + 968 def tree(self, path=None): + 969 """ + 970 Recursively lists the directory structure of the SMB share starting from the specified path. + 971 + 972 This function prints a visual representation of the directory tree of the remote SMB share. It uses + 973 recursion to navigate through directories and lists all files and subdirectories in each directory. + 974 The output is color-coded and formatted to enhance readability, with directories highlighted in cyan. + 975 + 976 Args: + 977 path (str, optional): The starting path on the SMB share from which to begin listing the tree. + 978 Defaults to the root of the current share. + 979 """ + 980 + 981 def recurse_action(base_dir="", path=[], prompt=[]): + 982 bars = ["│ ", "├── ", "└── "] + 983 + 984 remote_smb_path = ntpath.normpath(base_dir + ntpath.sep + ntpath.sep.join(path)) + 985 + 986 entries = [] + 987 try: + 988 entries = self.smbClient.listPath( + 989 shareName=self.smb_share, + 990 path=remote_smb_path+'\\*' + 991 ) + 992 except impacket.smbconnection.SessionError as err: + 993 code, const, text = err.getErrorCode(), err.getErrorString()[0], err.getErrorString()[1] + 994 errmsg = "Error 0x%08x (%s): %s" % (code, const, text) + 995 if self.config.no_colors: + 996 print("%s%s" % (''.join(prompt+[bars[2]]), errmsg)) + 997 else: + 998 print("%s\x1b[1;91m%s\x1b[0m" % (''.join(prompt+[bars[2]]), errmsg)) + 999 return +1000 +1001 entries = [e for e in entries if e.get_longname() not in [".", ".."]] +1002 entries = sorted(entries, key=lambda x:x.get_longname()) +1003 +1004 # +1005 if len(entries) > 1: +1006 index = 0 +1007 for entry in entries: +1008 index += 1 +1009 # This is the first entry +1010 if index == 0: +1011 if entry.is_directory(): +1012 if self.config.no_colors: +1013 print("%s%s\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1014 else: +1015 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1016 recurse_action( +1017 base_dir=base_dir, +1018 path=path+[entry.get_longname()], +1019 prompt=prompt+["│ "] +1020 ) +1021 else: +1022 if self.config.no_colors: +1023 print("%s%s" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1024 else: +1025 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1026 +1027 # This is the last entry +1028 elif index == len(entries): +1029 if entry.is_directory(): +1030 if self.config.no_colors: +1031 print("%s%s\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1032 else: +1033 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1034 recurse_action( +1035 base_dir=base_dir, +1036 path=path+[entry.get_longname()], +1037 prompt=prompt+[" "] +1038 ) +1039 else: +1040 if self.config.no_colors: +1041 print("%s%s" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1042 else: +1043 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1044 +1045 # These are entries in the middle +1046 else: +1047 if entry.is_directory(): +1048 if self.config.no_colors: +1049 print("%s%s\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1050 else: +1051 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1052 recurse_action( +1053 base_dir=base_dir, +1054 path=path+[entry.get_longname()], +1055 prompt=prompt+["│ "] +1056 ) +1057 else: +1058 if self.config.no_colors: +1059 print("%s%s" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1060 else: +1061 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1062 +1063 # +1064 elif len(entries) == 1: +1065 entry = entries[0] +1066 if entry.is_directory(): +1067 if self.config.no_colors: +1068 print("%s%s\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1069 else: +1070 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1071 recurse_action( +1072 base_dir=base_dir, +1073 path=path+[entry.get_longname()], +1074 prompt=prompt+[" "] +1075 ) +1076 else: +1077 if self.config.no_colors: +1078 print("%s%s" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1079 else: +1080 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1081 +1082 # Entrypoint +1083 try: +1084 if self.config.no_colors: +1085 print("%s\\" % path) +1086 else: +1087 print("\x1b[1;96m%s\x1b[0m\\" % path) +1088 recurse_action( +1089 base_dir=self.smb_cwd, +1090 path=[path], +1091 prompt=[""] +1092 ) +1093 except (BrokenPipeError, KeyboardInterrupt) as e: +1094 print("[!] Interrupted.") +1095 self.close_smb_session() +1096 self.init_smb_session() +1097 +1098 def umount(self, local_mount_point): +1099 """ +1100 Unmounts the specified local mount point of the remote share. +1101 +1102 This method unmounts the specified local mount point of the remote share based on the platform. +1103 It supports Windows, Linux, and macOS platforms for unmounting. +1104 +1105 Parameters: +1106 local_mount_point (str): The local mount point to unmount. +1107 +1108 Raises: +1109 None +1110 """ +1111 +1112 if os.path.exists(local_mount_point): +1113 if sys.platform.startswith('win'): +1114 command = f"net use {local_mount_point} /delete" +1115 +1116 elif sys.platform.startswith('linux') or sys.platform.startswith('darwin'): +1117 command = f"umount {local_mount_point}" +1118 +1119 else: +1120 command = None +1121 print("[!] Unsupported platform for unmounting SMB share.") +1122 +1123 if command is not None: +1124 if self.config.debug: +1125 print("[debug] Executing: %s" % command) +1126 os.system(command) +1127 else: +1128 print("[!] Cannot unmount a non existing path.") +1129 +1130 # Other functions +1131 +1132 def test_rights(self, sharename): +1133 """ +1134 Tests the read and write access rights of the current SMB session. +1135 +1136 This method checks the read and write access rights of the current SMB session by attempting to list paths and create/delete temporary directories. +1137 +1138 Returns: +1139 dict: A dictionary containing the read and write access rights status. +1140 - "readable" (bool): Indicates if the session has read access rights. +1141 - "writable" (bool): Indicates if the session has write access rights. +1142 """ +1143 +1144 # Restore the current share +1145 current_share = self.smb_share +1146 self.set_share(shareName=sharename) +1147 +1148 access_rights = {"readable": False, "writable": False} +1149 try: +1150 self.smbClient.listPath(self.smb_share, '*', password=None) +1151 access_rights["readable"] = True +1152 except impacket.smbconnection.SessionError as e: +1153 access_rights["readable"] = False +1154 +1155 try: +1156 temp_dir = ntpath.normpath("\\" + ''.join([random.choice("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ0123456759") for k in range(16)])) +1157 self.smbClient.createDirectory(self.smb_share, temp_dir) +1158 self.smbClient.deleteDirectory(self.smb_share, temp_dir) +1159 access_rights["writable"] = True +1160 except impacket.smbconnection.SessionError as e: +1161 access_rights["writable"] = False +1162 +1163 # Restore the current share +1164 self.set_share(shareName=current_share) +1165 +1166 return access_rights +1167 +1168 # Setter / Getter +1169 +1170 def set_share(self, shareName): +1171 """ +1172 Sets the current SMB share to the specified share name. +1173 +1174 This method updates the SMB session to use the specified share name. It checks if the share name is valid +1175 and updates the smb_share attribute of the SMBSession instance. +1176 +1177 Parameters: +1178 shareName (str): The name of the share to set as the current SMB share. +1179 +1180 Raises: +1181 ValueError: If the shareName is None or an empty string. +1182 """ +1183 +1184 if shareName is not None: +1185 self.list_shares() +1186 if shareName.lower() in self.available_shares.keys(): +1187 # Doing this in order to keep the case of the share adevertised by the remote machine +1188 self.smb_share = self.available_shares[shareName.lower()]["name"] +1189 self.smb_cwd = "" +1190 # Connects the tree +1191 self.smb_tree_id = self.smbClient.connectTree(self.smb_share) +1192 else: +1193 print("[!] Could not set share '%s', it does not exist remotely." % shareName) +1194 else: +1195 self.smb_share = None +1196 +1197 def set_cwd(self, path=None): +1198 """ +1199 Sets the current working directory on the SMB share to the specified path. +1200 +1201 This method updates the current working directory (cwd) of the SMB session to the given path if it is a valid directory. +1202 If the specified path is not a directory, the cwd remains unchanged. +1203 +1204 Parameters: +1205 path (str): The path to set as the current working directory. +1206 +1207 Raises: +1208 ValueError: If the specified path is not a directory. +1209 """ +1210 +1211 if path is not None: +1212 # Set path separators to ntpath sep +1213 if '/' in path: +1214 path = path.replace('/', ntpath.sep) +1215 +1216 if path.startswith(ntpath.sep): +1217 # Absolute path +1218 path = path + ntpath.sep +1219 else: +1220 # Relative path to the CWD +1221 if len(self.smb_cwd) == 0: +1222 path = path + ntpath.sep +1223 else: +1224 path = self.smb_cwd + ntpath.sep + path +1225 +1226 # Path normalization +1227 path = ntpath.normpath(path) +1228 path = re.sub(r'\\+', r'\\', path) +1229 +1230 if path in ["", ".", ".."]: +1231 self.smb_cwd = "" +1232 else: +1233 if self.path_isdir(pathFromRoot=path.strip(ntpath.sep)): +1234 # Path exists on the remote +1235 self.smb_cwd = ntpath.normpath(path) +1236 else: +1237 # Path does not exists or is not a directory on the remote +1238 print("[!] Remote directory '%s' does not exist." % path)
47 def __init__(self, address, domain, username, password, lmhash, nthash, use_kerberos=False, kdcHost=None, config=None): -48 super(SMBSession, self).__init__() -49 # Objects -50 self.config = config -51 -52 # Target server -53 self.address = address -54 -55 # Credentials -56 self.domain = domain -57 self.username = username -58 self.password = password -59 self.lmhash = lmhash -60 self.nthash = nthash -61 self.use_kerberos = use_kerberos -62 self.kdcHost = kdcHost -63 -64 self.smbClient = None -65 self.connected = False -66 -67 self.available_shares = {} -68 self.smb_share = None -69 self.smb_cwd = "" -70 self.smb_tree_id = None -71 -72 self.list_shares() +@@ -2579,76 +2897,76 @@48 def __init__(self, address, domain, username, password, lmhash, nthash, use_kerberos=False, kdcHost=None, config=None): +49 super(SMBSession, self).__init__() +50 # Objects +51 self.config = config +52 +53 # Target server +54 self.address = address +55 +56 # Credentials +57 self.domain = domain +58 self.username = username +59 self.password = password +60 self.lmhash = lmhash +61 self.nthash = nthash +62 self.use_kerberos = use_kerberos +63 self.kdcHost = kdcHost +64 +65 self.smbClient = None +66 self.connected = False +67 +68 self.available_shares = {} +69 self.smb_share = None +70 self.smb_cwd = "" +71 self.smb_tree_id = None +72 +73 self.list_shares()
76 def init_smb_session(self): - 77 """ - 78 Initializes and establishes a session with the SMB server. - 79 - 80 This method sets up the SMB connection using either Kerberos or NTLM authentication based on the configuration. - 81 It attempts to connect to the SMB server specified by the `address` attribute and authenticate using the credentials provided during the object's initialization. - 82 - 83 The method will print debug information if the `debug` attribute is set to True. Upon successful connection and authentication, it sets the `connected` attribute to True. - 84 - 85 Returns: - 86 bool: True if the connection and authentication are successful, False otherwise. - 87 """ - 88 - 89 self.connected = False - 90 - 91 if self.config.debug: - 92 print("[debug] [>] Connecting to remote SMB server '%s' ... " % self.address) - 93 try: - 94 self.smbClient = impacket.smbconnection.SMBConnection( - 95 remoteName=self.address, - 96 remoteHost=self.address, - 97 sess_port=int(445) - 98 ) - 99 except OSError as err: -100 print("[!] %s" % err) -101 self.smbClient = None -102 -103 if self.smbClient is not None: -104 if self.use_kerberos: -105 if self.config.debug: -106 print("[debug] [>] Authenticating as '%s\\%s' with kerberos ... " % (self.domain, self.username)) -107 try: -108 self.connected = self.smbClient.kerberosLogin( -109 user=self.username, -110 password=self.password, -111 domain=self.domain, -112 lmhash=self.lmhash, -113 nthash=self.nthash, -114 aesKey=self.aesKey, -115 kdcHost=self.kdcHost -116 ) -117 except impacket.smbconnection.SessionError as err: -118 if self.config.debug: -119 traceback.print_exc() -120 print("[!] Could not login: %s" % err) -121 self.connected = False -122 -123 else: -124 if self.config.debug: -125 print("[debug] [>] Authenticating as '%s\\%s' with NTLM ... " % (self.domain, self.username)) -126 try: -127 self.connected = self.smbClient.login( -128 user=self.username, -129 password=self.password, -130 domain=self.domain, -131 lmhash=self.lmhash, -132 nthash=self.nthash -133 ) -134 except impacket.smbconnection.SessionError as err: -135 if self.config.debug: -136 traceback.print_exc() -137 print("[!] Could not login: %s" % err) -138 self.connected = False -139 -140 if self.connected: -141 print("[+] Successfully authenticated to '%s' as '%s\\%s'!" % (self.address, self.domain, self.username)) -142 else: -143 print("[!] Failed to authenticate to '%s' as '%s\\%s'!" % (self.address, self.domain, self.username)) -144 -145 return self.connected +@@ -2676,28 +2994,28 @@77 def init_smb_session(self): + 78 """ + 79 Initializes and establishes a session with the SMB server. + 80 + 81 This method sets up the SMB connection using either Kerberos or NTLM authentication based on the configuration. + 82 It attempts to connect to the SMB server specified by the `address` attribute and authenticate using the credentials provided during the object's initialization. + 83 + 84 The method will print debug information if the `debug` attribute is set to True. Upon successful connection and authentication, it sets the `connected` attribute to True. + 85 + 86 Returns: + 87 bool: True if the connection and authentication are successful, False otherwise. + 88 """ + 89 + 90 self.connected = False + 91 + 92 if self.config.debug: + 93 print("[debug] [>] Connecting to remote SMB server '%s' ... " % self.address) + 94 try: + 95 self.smbClient = impacket.smbconnection.SMBConnection( + 96 remoteName=self.address, + 97 remoteHost=self.address, + 98 sess_port=int(445) + 99 ) +100 except OSError as err: +101 print("[!] %s" % err) +102 self.smbClient = None +103 +104 if self.smbClient is not None: +105 if self.use_kerberos: +106 if self.config.debug: +107 print("[debug] [>] Authenticating as '%s\\%s' with kerberos ... " % (self.domain, self.username)) +108 try: +109 self.connected = self.smbClient.kerberosLogin( +110 user=self.username, +111 password=self.password, +112 domain=self.domain, +113 lmhash=self.lmhash, +114 nthash=self.nthash, +115 aesKey=self.aesKey, +116 kdcHost=self.kdcHost +117 ) +118 except impacket.smbconnection.SessionError as err: +119 if self.config.debug: +120 traceback.print_exc() +121 print("[!] Could not login: %s" % err) +122 self.connected = False +123 +124 else: +125 if self.config.debug: +126 print("[debug] [>] Authenticating as '%s\\%s' with NTLM ... " % (self.domain, self.username)) +127 try: +128 self.connected = self.smbClient.login( +129 user=self.username, +130 password=self.password, +131 domain=self.domain, +132 lmhash=self.lmhash, +133 nthash=self.nthash +134 ) +135 except impacket.smbconnection.SessionError as err: +136 if self.config.debug: +137 traceback.print_exc() +138 print("[!] Could not login: %s" % err) +139 self.connected = False +140 +141 if self.connected: +142 print("[+] Successfully authenticated to '%s' as '%s\\%s'!" % (self.address, self.domain, self.username)) +143 else: +144 print("[!] Failed to authenticate to '%s' as '%s\\%s'!" % (self.address, self.domain, self.username)) +145 +146 return self.connected
147 def close_smb_session(self): -148 """ -149 Closes the current SMB session by disconnecting the SMB client. -150 -151 This method ensures that the SMB client connection is properly closed. It checks if the client is connected -152 and if so, it closes the connection and resets the connection status. -153 -154 Raises: -155 Exception: If the SMB client is not initialized or if there's an error during the disconnection process. -156 """ -157 -158 if self.smbClient is not None: -159 if self.connected: -160 self.smbClient.close() -161 self.connected = False -162 if self.config.debug: -163 print("[+] SMB connection closed successfully.") -164 else: -165 if self.config.debug: -166 print("[!] No active SMB connection to close.") -167 else: -168 raise Exception("SMB client is not initialized.") +@@ -2723,26 +3041,26 @@148 def close_smb_session(self): +149 """ +150 Closes the current SMB session by disconnecting the SMB client. +151 +152 This method ensures that the SMB client connection is properly closed. It checks if the client is connected +153 and if so, it closes the connection and resets the connection status. +154 +155 Raises: +156 Exception: If the SMB client is not initialized or if there's an error during the disconnection process. +157 """ +158 +159 if self.smbClient is not None: +160 if self.connected: +161 self.smbClient.close() +162 self.connected = False +163 if self.config.debug: +164 print("[+] SMB connection closed successfully.") +165 else: +166 if self.config.debug: +167 print("[!] No active SMB connection to close.") +168 else: +169 raise Exception("SMB client is not initialized.")
172 def read_file(self, path=None): -173 if self.path_isfile(path=path): -174 tmp_file_path = self.smb_cwd + ntpath.sep + path -175 matches = self.smbClient.listPath( -176 shareName=self.smb_share, -177 path=tmp_file_path -178 ) -179 -180 fh = io.BytesIO() -181 try: -182 # opening the files in streams instead of mounting shares allows -183 # for running the script from unprivileged containers -184 self.smbClient.getFile(self.smb_share, tmp_file_path, fh.write) -185 except impacket.smbconnection.SessionError as e: -186 return None -187 rawdata = fh.getvalue() -188 fh.close() -189 return rawdata -190 else: -191 print("[!] Remote path '%s' is not a file." % path) +@@ -2760,53 +3078,53 @@173 def read_file(self, path=None): +174 if self.path_isfile(path=path): +175 tmp_file_path = self.smb_cwd + ntpath.sep + path +176 matches = self.smbClient.listPath( +177 shareName=self.smb_share, +178 path=tmp_file_path +179 ) +180 +181 fh = io.BytesIO() +182 try: +183 # opening the files in streams instead of mounting shares allows +184 # for running the script from unprivileged containers +185 self.smbClient.getFile(self.smb_share, tmp_file_path, fh.write) +186 except impacket.smbconnection.SessionError as e: +187 return None +188 rawdata = fh.getvalue() +189 fh.close() +190 return rawdata +191 else: +192 print("[!] Remote path '%s' is not a file." % path)
193 def find(self, paths=[], callback=None): -194 def recurse_action(paths=[], depth=0, callback=None): -195 if callback is None: -196 return [] -197 -198 next_directories_to_explore = [] -199 -200 for path in paths: -201 remote_smb_path = ntpath.normpath(self.smb_cwd + ntpath.sep + path) -202 entries = [] -203 -204 try: -205 entries = self.smbClient.listPath( -206 shareName=self.smb_share, -207 path=(remote_smb_path + ntpath.sep + '*') -208 ) -209 except impacket.smbconnection.SessionError as err: -210 continue -211 # Remove dot names -212 entries = [e for e in entries if e.get_longname() not in [".", ".."]] -213 # Sort the entries ignoring case -214 entries = sorted(entries, key=lambda x:x.get_longname().lower()) -215 -216 for entry in entries: -217 if entry.is_directory(): -218 callback(entry, path + ntpath.sep + entry.get_longname() + ntpath.sep, depth) -219 else: -220 callback(entry, path + ntpath.sep + entry.get_longname(), depth) -221 -222 # Next directories to explore -223 for entry in entries: -224 if entry.is_directory(): -225 next_directories_to_explore.append(path + ntpath.sep + entry.get_longname() + ntpath.sep) -226 -227 return next_directories_to_explore -228 # -229 if callback is not None: -230 depth = 0 -231 while len(paths) != 0: -232 paths = recurse_action( -233 paths=paths, -234 depth=depth, -235 callback=callback -236 ) -237 depth = depth + 1 -238 else: -239 print("[!] SMBSession.find(), callback function cannot be None.") +@@ -2824,56 +3142,81 @@194 def find(self, paths=[], callback=None): +195 def recurse_action(paths=[], depth=0, callback=None): +196 if callback is None: +197 return [] +198 +199 next_directories_to_explore = [] +200 +201 for path in paths: +202 remote_smb_path = ntpath.normpath(self.smb_cwd + ntpath.sep + path) +203 entries = [] +204 +205 try: +206 entries = self.smbClient.listPath( +207 shareName=self.smb_share, +208 path=(remote_smb_path + ntpath.sep + '*') +209 ) +210 except impacket.smbconnection.SessionError as err: +211 continue +212 # Remove dot names +213 entries = [e for e in entries if e.get_longname() not in [".", ".."]] +214 # Sort the entries ignoring case +215 entries = sorted(entries, key=lambda x:x.get_longname().lower()) +216 +217 for entry in entries: +218 if entry.is_directory(): +219 callback(entry, path + ntpath.sep + entry.get_longname() + ntpath.sep, depth) +220 else: +221 callback(entry, path + ntpath.sep + entry.get_longname(), depth) +222 +223 # Next directories to explore +224 for entry in entries: +225 if entry.is_directory(): +226 next_directories_to_explore.append(path + ntpath.sep + entry.get_longname() + ntpath.sep) +227 +228 return next_directories_to_explore +229 # +230 if callback is not None: +231 depth = 0 +232 while len(paths) != 0: +233 paths = recurse_action( +234 paths=paths, +235 depth=depth, +236 callback=callback +237 ) +238 depth = depth + 1 +239 else: +240 print("[!] SMBSession.find(), callback function cannot be None.")
241 def get_file(self, path=None, keepRemotePath=False): -242 """ -243 Retrieves a file from the specified path on the SMB share. -244 -245 This method attempts to retrieve a file from the given path within the currently connected SMB share. -246 If the path points to a directory, it skips the retrieval. It handles file retrieval by creating a local -247 file object and writing the contents of the remote file to it using the SMB client's getFile method. -248 -249 Parameters: -250 path (str): The path of the file to retrieve. If None, uses the current smb_path. -251 -252 Returns: -253 None -254 """ -255 -256 tmp_file_path = self.smb_cwd + ntpath.sep + path -257 matches = self.smbClient.listPath( -258 shareName=self.smb_share, -259 path=tmp_file_path -260 ) -261 -262 for entry in matches: -263 if entry.is_directory(): -264 print("[>] Skipping '%s' because it is a directory." % tmp_file_path) -265 else: -266 try: -267 if ntpath.sep in path: -268 outputfile = ntpath.dirname(path) + ntpath.sep + entry.get_longname() -269 else: -270 outputfile = entry.get_longname() -271 f = LocalFileIO( -272 mode="wb", -273 path=outputfile, -274 expected_size=entry.get_filesize(), -275 debug=self.config.debug, -276 keepRemotePath=keepRemotePath -277 ) -278 self.smbClient.getFile( -279 shareName=self.smb_share, -280 pathName=tmp_file_path, -281 callback=f.write -282 ) -283 f.close() -284 except (BrokenPipeError, KeyboardInterrupt) as e: -285 f.close() -286 print("\x1b[v\x1b[o\r[!] Interrupted.") -287 self.close_smb_session() -288 self.init_smb_session() -289 -290 return None +@@ -2903,79 +3246,79 @@242 def get_file(self, path=None, keepRemotePath=False): +243 """ +244 Retrieves a file from the specified path on the SMB share. +245 +246 This method attempts to retrieve a file from the given path within the currently connected SMB share. +247 If the path points to a directory, it skips the retrieval. It handles file retrieval by creating a local +248 file object and writing the contents of the remote file to it using the SMB client's getFile method. +249 +250 Parameters: +251 path (str): The path of the file to retrieve. If None, uses the current smb_path. +252 +253 Returns: +254 None +255 """ +256 +257 # Parse path +258 path = path.replace('/', ntpath.sep) +259 if ntpath.sep in path: +260 tmp_search_path = ntpath.normpath(self.smb_cwd + ntpath.sep + ntpath.dirname(path)) +261 else: +262 tmp_search_path = ntpath.normpath(self.smb_cwd + ntpath.sep) +263 # Parse filename +264 filename = ntpath.basename(path) +265 +266 # Search for the file +267 matches = self.smbClient.listPath( +268 shareName=self.smb_share, +269 path=tmp_search_path + ntpath.sep + '*' +270 ) +271 +272 # Filter the entries +273 matching_entries = [] +274 for entry in matches: +275 if entry.is_directory(): +276 # Skip directories +277 continue +278 if entry.get_longname() == filename: +279 matching_entries.append(entry) +280 elif '*' in filename: +281 regexp = filename.replace('.', '\\.').replace('*', '.*') +282 if re.match(regexp, entry.get_longname()): +283 matching_entries.append(entry) +284 +285 matching_entries = sorted(list(set(matching_entries)), key=lambda x: x.get_longname()) +286 +287 for entry in matching_entries: +288 if entry.is_directory(): +289 if self.config.debug: +290 print("[debug] [>] Skipping '%s' because it is a directory." % (tmp_search_path + ntpath.sep + entry.get_longname())) +291 else: +292 try: +293 if ntpath.sep in path: +294 outputfile = ntpath.dirname(path) + ntpath.sep + entry.get_longname() +295 else: +296 outputfile = entry.get_longname() +297 f = LocalFileIO( +298 mode="wb", +299 path=outputfile, +300 expected_size=entry.get_filesize(), +301 debug=self.config.debug, +302 keepRemotePath=keepRemotePath +303 ) +304 self.smbClient.getFile( +305 shareName=self.smb_share, +306 pathName=tmp_search_path + ntpath.sep + entry.get_longname(), +307 callback=f.write +308 ) +309 f.close() +310 except (BrokenPipeError, KeyboardInterrupt) as e: +311 f.close() +312 print("\x1b[v\x1b[o\r[!] Interrupted.") +313 self.close_smb_session() +314 self.init_smb_session() +315 +316 return None
292 def get_file_recursively(self, path=None): -293 """ -294 Recursively retrieves files from a specified path on the SMB share. -295 -296 This method navigates through all directories starting from the given path, -297 and downloads all files found. It handles directories recursively, ensuring -298 that all nested files are retrieved. The method skips over directory entries -299 and handles errors gracefully, attempting to continue the operation where possible. -300 -301 Parameters: -302 path (str): The initial directory path from which to start the recursive file retrieval. -303 If None, it starts from the root of the configured SMB share. -304 """ -305 -306 def recurse_action(base_dir="", path=[]): -307 if len(base_dir) == 0: -308 remote_smb_path = ntpath.sep.join(path) -309 else: -310 remote_smb_path = base_dir + ntpath.sep + ntpath.sep.join(path) -311 remote_smb_path = ntpath.normpath(remote_smb_path) -312 -313 entries = self.smbClient.listPath( -314 shareName=self.smb_share, -315 path=remote_smb_path + '\\*' -316 ) -317 if len(entries) != 0: -318 files = [entry for entry in entries if not entry.is_directory()] -319 directories = [entry for entry in entries if entry.is_directory() and entry.get_longname() not in [".", ".."]] -320 -321 # Files -322 if len(files) != 0: -323 print("[>] Retrieving files of '%s'" % remote_smb_path) -324 for entry_file in files: -325 if not entry_file.is_directory(): -326 f = LocalFileIO( -327 mode="wb", -328 path=remote_smb_path + ntpath.sep + entry_file.get_longname(), -329 expected_size=entry_file.get_filesize(), -330 keepRemotePath=True, -331 debug=self.config.debug -332 ) -333 try: -334 self.smbClient.getFile( -335 shareName=self.smb_share, -336 pathName=remote_smb_path + ntpath.sep + entry_file.get_longname(), -337 callback=f.write -338 ) -339 f.close() -340 except BrokenPipeError as err: -341 f.set_error(message="[bold red]Failed downloading '%s': %s" % (f.path, err)) -342 f.close(remove=True) -343 break -344 except Exception as err: -345 f.set_error(message="[bold red]Failed downloading '%s': %s" % (f.path, err)) -346 f.close(remove=True) -347 -348 # Directories -349 for entry_directory in directories: -350 if entry_directory.is_directory(): -351 recurse_action( -352 base_dir=self.smb_cwd, -353 path=path+[entry_directory.get_longname()] -354 ) -355 # Entrypoint -356 try: -357 recurse_action( -358 base_dir=self.smb_cwd, -359 path=[path] -360 ) -361 except (BrokenPipeError, KeyboardInterrupt) as e: -362 print("\x1b[v\x1b[o\r[!] Interrupted.") -363 self.close_smb_session() -364 self.init_smb_session() +@@ -3004,29 +3347,29 @@318 def get_file_recursively(self, path=None): +319 """ +320 Recursively retrieves files from a specified path on the SMB share. +321 +322 This method navigates through all directories starting from the given path, +323 and downloads all files found. It handles directories recursively, ensuring +324 that all nested files are retrieved. The method skips over directory entries +325 and handles errors gracefully, attempting to continue the operation where possible. +326 +327 Parameters: +328 path (str): The initial directory path from which to start the recursive file retrieval. +329 If None, it starts from the root of the configured SMB share. +330 """ +331 +332 def recurse_action(base_dir="", path=[]): +333 if len(base_dir) == 0: +334 remote_smb_path = ntpath.sep.join(path) +335 else: +336 remote_smb_path = base_dir + ntpath.sep + ntpath.sep.join(path) +337 remote_smb_path = ntpath.normpath(remote_smb_path) +338 +339 entries = self.smbClient.listPath( +340 shareName=self.smb_share, +341 path=remote_smb_path + '\\*' +342 ) +343 if len(entries) != 0: +344 files = [entry for entry in entries if not entry.is_directory()] +345 directories = [entry for entry in entries if entry.is_directory() and entry.get_longname() not in [".", ".."]] +346 +347 # Files +348 if len(files) != 0: +349 print("[>] Retrieving files of '%s'" % remote_smb_path) +350 for entry_file in files: +351 if not entry_file.is_directory(): +352 f = LocalFileIO( +353 mode="wb", +354 path=remote_smb_path + ntpath.sep + entry_file.get_longname(), +355 expected_size=entry_file.get_filesize(), +356 keepRemotePath=True, +357 debug=self.config.debug +358 ) +359 try: +360 self.smbClient.getFile( +361 shareName=self.smb_share, +362 pathName=remote_smb_path + ntpath.sep + entry_file.get_longname(), +363 callback=f.write +364 ) +365 f.close() +366 except BrokenPipeError as err: +367 f.set_error(message="[bold red]Failed downloading '%s': %s" % (f.path, err)) +368 f.close(remove=True) +369 break +370 except Exception as err: +371 f.set_error(message="[bold red]Failed downloading '%s': %s" % (f.path, err)) +372 f.close(remove=True) +373 +374 # Directories +375 for entry_directory in directories: +376 if entry_directory.is_directory(): +377 recurse_action( +378 base_dir=self.smb_cwd, +379 path=path+[entry_directory.get_longname()] +380 ) +381 # Entrypoint +382 try: +383 recurse_action( +384 base_dir=self.smb_cwd, +385 path=[path] +386 ) +387 except (BrokenPipeError, KeyboardInterrupt) as e: +388 print("\x1b[v\x1b[o\r[!] Interrupted.") +389 self.close_smb_session() +390 self.init_smb_session()
366 def get_entry(self, path=None): -367 """ -368 Retrieves information about a specific entry located at the provided path on the SMB share. -369 -370 This method checks if the specified path exists on the SMB share. If the path exists, it retrieves the details of the entry at that path, including the directory name and file name. If the entry is found, it returns the entry object; otherwise, it returns None. -371 -372 Args: -373 path (str): The path of the entry to retrieve information about. -374 -375 Returns: -376 Entry: An object representing the entry at the specified path, or None if the entry is not found. -377 """ -378 -379 if self.path_exists(path=path): -380 matches = self.smbClient.listPath(shareName=self.smb_share, path=path) -381 -382 if len(matches) == 1: -383 return matches[0] -384 else: -385 return None -386 -387 else: -388 return None +@@ -3054,80 +3397,80 @@392 def get_entry(self, path=None): +393 """ +394 Retrieves information about a specific entry located at the provided path on the SMB share. +395 +396 This method checks if the specified path exists on the SMB share. If the path exists, it retrieves the details of the entry at that path, including the directory name and file name. If the entry is found, it returns the entry object; otherwise, it returns None. +397 +398 Args: +399 path (str): The path of the entry to retrieve information about. +400 +401 Returns: +402 Entry: An object representing the entry at the specified path, or None if the entry is not found. +403 """ +404 +405 if self.path_exists(path=path): +406 matches = self.smbClient.listPath(shareName=self.smb_share, path=path) +407 +408 if len(matches) == 1: +409 return matches[0] +410 else: +411 return None +412 +413 else: +414 return None
390 def info(self, share=True, server=True): -391 """ -392 Displays information about the server and optionally the shares. -393 -394 This method prints detailed information about the server's characteristics such as NetBIOS names, DNS details, OS information, and SMB capabilities. If the `share` parameter is set to True and a share is currently set, it will also attempt to display information about the share. -395 -396 Parameters: -397 share (bool): If True, display information about the current share. -398 server (bool): If True, display information about the server. -399 -400 Returns: -401 None -402 """ -403 -404 if server: -405 if self.config.no_colors: -406 print("[+] Server:") -407 print(" ├─NetBIOS:") -408 print(" │ ├─ NetBIOS Hostname ──────── : %s" % (self.smbClient.getServerName())) -409 print(" │ └─ NetBIOS Domain ────────── : %s" % (self.smbClient.getServerDomain())) -410 print(" ├─DNS:") -411 print(" │ ├─ DNS Hostname ──────────── : %s" % (self.smbClient.getServerDNSHostName())) -412 print(" │ └─ DNS Domain ────────────── : %s" % (self.smbClient.getServerDNSDomainName())) -413 print(" ├─OS:") -414 print(" │ ├─ OS Name ───────────────── : %s" % (self.smbClient.getServerOS())) -415 print(" │ └─ OS Version ────────────── : %s.%s.%s" % (self.smbClient.getServerOSMajor(), self.smbClient.getServerOSMinor(), self.smbClient.getServerOSBuild())) -416 print(" ├─Server:") -417 print(" │ ├─ Signing Required ──────── : %s" % (self.smbClient.isSigningRequired())) -418 print(" │ ├─ Login Required ────────── : %s" % (self.smbClient.isLoginRequired())) -419 print(" │ ├─ Supports NTLMv2 ───────── : %s" % (self.smbClient.doesSupportNTLMv2())) -420 MaxReadSize = self.smbClient.getIOCapabilities()["MaxReadSize"] -421 print(" │ ├─ Max size of read chunk ── : %d bytes (%s)" % (MaxReadSize, b_filesize(MaxReadSize))) -422 MaxWriteSize = self.smbClient.getIOCapabilities()["MaxWriteSize"] -423 print(" │ └─ Max size of write chunk ─ : %d bytes (%s)" % (MaxWriteSize, b_filesize(MaxWriteSize))) -424 print(" └─") -425 else: -426 print("[+] Server:") -427 print(" ├─NetBIOS:") -428 print(" │ ├─ \x1b[94mNetBIOS Hostname\x1b[0m \x1b[90m────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerName())) -429 print(" │ └─ \x1b[94mNetBIOS Domain\x1b[0m \x1b[90m──────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDomain())) -430 print(" ├─DNS:") -431 print(" │ ├─ \x1b[94mDNS Hostname\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDNSHostName())) -432 print(" │ └─ \x1b[94mDNS Domain\x1b[0m \x1b[90m──────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDNSDomainName())) -433 print(" ├─OS:") -434 print(" │ ├─ \x1b[94mOS Name\x1b[0m \x1b[90m─────────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerOS())) -435 print(" │ └─ \x1b[94mOS Version\x1b[0m \x1b[90m──────────────\x1b[0m : \x1b[93m%s.%s.%s\x1b[0m" % (self.smbClient.getServerOSMajor(), self.smbClient.getServerOSMinor(), self.smbClient.getServerOSBuild())) -436 print(" ├─Server:") -437 print(" │ ├─ \x1b[94mSigning Required\x1b[0m \x1b[90m────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.isSigningRequired())) -438 print(" │ ├─ \x1b[94mLogin Required\x1b[0m \x1b[90m──────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.isLoginRequired())) -439 print(" │ ├─ \x1b[94mSupports NTLMv2\x1b[0m \x1b[90m─────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.doesSupportNTLMv2())) -440 MaxReadSize = self.smbClient.getIOCapabilities()["MaxReadSize"] -441 print(" │ ├─ \x1b[94mMax size of read chunk\x1b[0m \x1b[90m──\x1b[0m : \x1b[93m%d bytes (%s)\x1b[0m" % (MaxReadSize, b_filesize(MaxReadSize))) -442 MaxWriteSize = self.smbClient.getIOCapabilities()["MaxWriteSize"] -443 print(" │ └─ \x1b[94mMax size of write chunk\x1b[0m \x1b[90m─\x1b[0m : \x1b[93m%d bytes (%s)\x1b[0m" % (MaxWriteSize, b_filesize(MaxWriteSize))) -444 print(" └─") -445 -446 if share and self.smb_share is not None: -447 share_name = self.available_shares.get(self.smb_share.lower(), "")["name"] -448 share_comment = self.available_shares.get(self.smb_share.lower(), "")["comment"] -449 share_type = self.available_shares.get(self.smb_share.lower(), "")["type"] -450 share_type =', '.join([s.replace("STYPE_","") for s in share_type]) -451 share_rawtype = self.available_shares.get(self.smb_share.lower(), "")["rawtype"] -452 if self.config.no_colors: -453 print("\n[+] Share:") -454 print(" ├─ Name ──────────── : %s" % (share_name)) -455 print(" ├─ Description ───── : %s" % (share_comment)) -456 print(" ├─ Type ──────────── : %s" % (share_type)) -457 print(" └─ Raw type value ── : %s" % (share_rawtype)) -458 else: -459 print("\n[+] Share:") -460 print(" ├─ \x1b[94mName\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_name)) -461 print(" ├─ \x1b[94mDescription\x1b[0m \x1b[90m─────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_comment)) -462 print(" ├─ \x1b[94mType\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_type)) -463 print(" └─ \x1b[94mRaw type value\x1b[0m \x1b[90m──\x1b[0m : \x1b[93m%s\x1b[0m" % (share_rawtype)) +@@ -3156,37 +3499,37 @@416 def info(self, share=True, server=True): +417 """ +418 Displays information about the server and optionally the shares. +419 +420 This method prints detailed information about the server's characteristics such as NetBIOS names, DNS details, OS information, and SMB capabilities. If the `share` parameter is set to True and a share is currently set, it will also attempt to display information about the share. +421 +422 Parameters: +423 share (bool): If True, display information about the current share. +424 server (bool): If True, display information about the server. +425 +426 Returns: +427 None +428 """ +429 +430 if server: +431 if self.config.no_colors: +432 print("[+] Server:") +433 print(" ├─NetBIOS:") +434 print(" │ ├─ NetBIOS Hostname ──────── : %s" % (self.smbClient.getServerName())) +435 print(" │ └─ NetBIOS Domain ────────── : %s" % (self.smbClient.getServerDomain())) +436 print(" ├─DNS:") +437 print(" │ ├─ DNS Hostname ──────────── : %s" % (self.smbClient.getServerDNSHostName())) +438 print(" │ └─ DNS Domain ────────────── : %s" % (self.smbClient.getServerDNSDomainName())) +439 print(" ├─OS:") +440 print(" │ ├─ OS Name ───────────────── : %s" % (self.smbClient.getServerOS())) +441 print(" │ └─ OS Version ────────────── : %s.%s.%s" % (self.smbClient.getServerOSMajor(), self.smbClient.getServerOSMinor(), self.smbClient.getServerOSBuild())) +442 print(" ├─Server:") +443 print(" │ ├─ Signing Required ──────── : %s" % (self.smbClient.isSigningRequired())) +444 print(" │ ├─ Login Required ────────── : %s" % (self.smbClient.isLoginRequired())) +445 print(" │ ├─ Supports NTLMv2 ───────── : %s" % (self.smbClient.doesSupportNTLMv2())) +446 MaxReadSize = self.smbClient.getIOCapabilities()["MaxReadSize"] +447 print(" │ ├─ Max size of read chunk ── : %d bytes (%s)" % (MaxReadSize, b_filesize(MaxReadSize))) +448 MaxWriteSize = self.smbClient.getIOCapabilities()["MaxWriteSize"] +449 print(" │ └─ Max size of write chunk ─ : %d bytes (%s)" % (MaxWriteSize, b_filesize(MaxWriteSize))) +450 print(" └─") +451 else: +452 print("[+] Server:") +453 print(" ├─NetBIOS:") +454 print(" │ ├─ \x1b[94mNetBIOS Hostname\x1b[0m \x1b[90m────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerName())) +455 print(" │ └─ \x1b[94mNetBIOS Domain\x1b[0m \x1b[90m──────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDomain())) +456 print(" ├─DNS:") +457 print(" │ ├─ \x1b[94mDNS Hostname\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDNSHostName())) +458 print(" │ └─ \x1b[94mDNS Domain\x1b[0m \x1b[90m──────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerDNSDomainName())) +459 print(" ├─OS:") +460 print(" │ ├─ \x1b[94mOS Name\x1b[0m \x1b[90m─────────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.getServerOS())) +461 print(" │ └─ \x1b[94mOS Version\x1b[0m \x1b[90m──────────────\x1b[0m : \x1b[93m%s.%s.%s\x1b[0m" % (self.smbClient.getServerOSMajor(), self.smbClient.getServerOSMinor(), self.smbClient.getServerOSBuild())) +462 print(" ├─Server:") +463 print(" │ ├─ \x1b[94mSigning Required\x1b[0m \x1b[90m────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.isSigningRequired())) +464 print(" │ ├─ \x1b[94mLogin Required\x1b[0m \x1b[90m──────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.isLoginRequired())) +465 print(" │ ├─ \x1b[94mSupports NTLMv2\x1b[0m \x1b[90m─────────\x1b[0m : \x1b[93m%s\x1b[0m" % (self.smbClient.doesSupportNTLMv2())) +466 MaxReadSize = self.smbClient.getIOCapabilities()["MaxReadSize"] +467 print(" │ ├─ \x1b[94mMax size of read chunk\x1b[0m \x1b[90m──\x1b[0m : \x1b[93m%d bytes (%s)\x1b[0m" % (MaxReadSize, b_filesize(MaxReadSize))) +468 MaxWriteSize = self.smbClient.getIOCapabilities()["MaxWriteSize"] +469 print(" │ └─ \x1b[94mMax size of write chunk\x1b[0m \x1b[90m─\x1b[0m : \x1b[93m%d bytes (%s)\x1b[0m" % (MaxWriteSize, b_filesize(MaxWriteSize))) +470 print(" └─") +471 +472 if share and self.smb_share is not None: +473 share_name = self.available_shares.get(self.smb_share.lower(), "")["name"] +474 share_comment = self.available_shares.get(self.smb_share.lower(), "")["comment"] +475 share_type = self.available_shares.get(self.smb_share.lower(), "")["type"] +476 share_type =', '.join([s.replace("STYPE_","") for s in share_type]) +477 share_rawtype = self.available_shares.get(self.smb_share.lower(), "")["rawtype"] +478 if self.config.no_colors: +479 print("\n[+] Share:") +480 print(" ├─ Name ──────────── : %s" % (share_name)) +481 print(" ├─ Description ───── : %s" % (share_comment)) +482 print(" ├─ Type ──────────── : %s" % (share_type)) +483 print(" └─ Raw type value ── : %s" % (share_rawtype)) +484 else: +485 print("\n[+] Share:") +486 print(" ├─ \x1b[94mName\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_name)) +487 print(" ├─ \x1b[94mDescription\x1b[0m \x1b[90m─────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_comment)) +488 print(" ├─ \x1b[94mType\x1b[0m \x1b[90m────────────\x1b[0m : \x1b[93m%s\x1b[0m" % (share_type)) +489 print(" └─ \x1b[94mRaw type value\x1b[0m \x1b[90m──\x1b[0m : \x1b[93m%s\x1b[0m" % (share_rawtype))
465 def list_contents(self, path=None): -466 """ -467 Lists the contents of a specified directory on the SMB share. -468 -469 This method retrieves the contents of a directory specified by `shareName` and `path`. If `shareName` or `path` -470 is not provided, it defaults to the instance's current SMB share or path. The method returns a dictionary with -471 the long names of the files and directories as keys and their respective SMB entry objects as values. -472 -473 Args: -474 shareName (str, optional): The name of the SMB share. Defaults to the current SMB share if None. -475 path (str, optional): The directory path to list contents from. Defaults to the current path if None. -476 -477 Returns: -478 dict: A dictionary with file and directory names as keys and their SMB entry objects as values. -479 """ -480 -481 dest_path = [self.smb_cwd.rstrip(ntpath.sep),] -482 if path is not None and len(path) > 0: -483 dest_path.append(path.rstrip(ntpath.sep)) -484 dest_path.append('*') -485 path = ntpath.sep.join(dest_path) -486 -487 contents = {} -488 entries = self.smbClient.listPath( -489 shareName=self.smb_share, -490 path=path -491 ) -492 for entry in entries: -493 contents[entry.get_longname()] = entry +@@ -3217,41 +3560,41 @@491 def list_contents(self, path=None): +492 """ +493 Lists the contents of a specified directory on the SMB share. 494 -495 return contents +495 This method retrieves the contents of a directory specified by `shareName` and `path`. If `shareName` or `path` +496 is not provided, it defaults to the instance's current SMB share or path. The method returns a dictionary with +497 the long names of the files and directories as keys and their respective SMB entry objects as values. +498 +499 Args: +500 shareName (str, optional): The name of the SMB share. Defaults to the current SMB share if None. +501 path (str, optional): The directory path to list contents from. Defaults to the current path if None. +502 +503 Returns: +504 dict: A dictionary with file and directory names as keys and their SMB entry objects as values. +505 """ +506 +507 dest_path = [self.smb_cwd.rstrip(ntpath.sep),] +508 if path is not None and len(path) > 0: +509 dest_path.append(path.rstrip(ntpath.sep)) +510 dest_path.append('*') +511 path = ntpath.sep.join(dest_path) +512 +513 contents = {} +514 entries = self.smbClient.listPath( +515 shareName=self.smb_share, +516 path=path +517 ) +518 for entry in entries: +519 contents[entry.get_longname()] = entry +520 +521 return contents
533 def mkdir(self, path=None): -534 """ -535 Creates a directory at the specified path on the SMB share. -536 -537 This method takes a path and attempts to create the directory structure on the SMB share. If the path includes -538 nested directories, it will create each directory in the sequence. If a directory already exists, it will skip -539 the creation for that directory without raising an error. -540 -541 Args: -542 path (str, optional): The full path of the directory to create on the SMB share. Defaults to None. -543 -544 Note: -545 The path should use forward slashes ('/') which will be converted to backslashes (ntpath.sep) for SMB compatibility. -546 """ -547 -548 if path is not None: -549 # Prepare path -550 path = path.replace('/',ntpath.sep) -551 if ntpath.sep in path: -552 path = path.strip(ntpath.sep).split(ntpath.sep) -553 else: -554 path = [path] -555 -556 # Create each dir in the path -557 for depth in range(1, len(path)+1): -558 tmp_path = ntpath.sep.join(path[:depth]) -559 try: -560 self.smbClient.createDirectory( -561 shareName=self.smb_share, -562 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + tmp_path + ntpath.sep) -563 ) -564 except impacket.smbconnection.SessionError as err: -565 if err.getErrorCode() == 0xc0000035: -566 # STATUS_OBJECT_NAME_COLLISION -567 # Remote directory already created, this is normal -568 # Src: https://github.com/fortra/impacket/blob/269ce69872f0e8f2188a80addb0c39fedfa6dcb8/impacket/nt_errors.py#L268C9-L268C19 -569 pass -570 else: -571 print("[!] Failed to create directory '%s': %s" % (tmp_path, err)) -572 if self.config.debug: -573 traceback.print_exc() -574 else: -575 pass +@@ -3350,35 +3693,72 @@559 def mkdir(self, path=None): +560 """ +561 Creates a directory at the specified path on the SMB share. +562 +563 This method takes a path and attempts to create the directory structure on the SMB share. If the path includes +564 nested directories, it will create each directory in the sequence. If a directory already exists, it will skip +565 the creation for that directory without raising an error. +566 +567 Args: +568 path (str, optional): The full path of the directory to create on the SMB share. Defaults to None. +569 +570 Note: +571 The path should use forward slashes ('/') which will be converted to backslashes (ntpath.sep) for SMB compatibility. +572 """ +573 +574 if path is not None: +575 # Prepare path +576 path = path.replace('/',ntpath.sep) +577 if ntpath.sep in path: +578 path = path.strip(ntpath.sep).split(ntpath.sep) +579 else: +580 path = [path] +581 +582 # Create each dir in the path +583 for depth in range(1, len(path)+1): +584 tmp_path = ntpath.sep.join(path[:depth]) +585 try: +586 self.smbClient.createDirectory( +587 shareName=self.smb_share, +588 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + tmp_path + ntpath.sep) +589 ) +590 except impacket.smbconnection.SessionError as err: +591 if err.getErrorCode() == 0xc0000035: +592 # STATUS_OBJECT_NAME_COLLISION +593 # Remote directory already created, this is normal +594 # Src: https://github.com/fortra/impacket/blob/269ce69872f0e8f2188a80addb0c39fedfa6dcb8/impacket/nt_errors.py#L268C9-L268C19 +595 pass +596 else: +597 print("[!] Failed to create directory '%s': %s" % (tmp_path, err)) +598 if self.config.debug: +599 traceback.print_exc() +600 else: +601 pass
577 def mount(self, local_mount_point, remote_path): -578 -579 if not os.path.exists(local_mount_point): -580 pass -581 -582 if sys.platform.startswith('win'): -583 remote_path = remote_path.replace('/',ntpath.sep) -584 command = f"net use {local_mount_point} \\\\{self.address}\\{self.smb_share}\\{remote_path}" -585 -586 elif sys.platform.startswith('linux'): -587 remote_path = remote_path.replace(ntpath.sep,'/') -588 command = f"mount -t cifs //{self.address}/{self.smb_share}/{remote_path} {local_mount_point} -o username={self.username},password={self.password}" -589 -590 elif sys.platform.startswith('darwin'): -591 remote_path = remote_path.replace(ntpath.sep,'/') -592 command = f"mount_smbfs //{self.username}:{self.password}@{self.address}/{self.smb_share}/{remote_path} {local_mount_point}" -593 -594 else: -595 command = None -596 print("[!] Unsupported platform for mounting SMB share.") -597 -598 if command is not None: -599 if self.config.debug: -600 print("[debug] Executing: %s" % command) -601 os.system(command) +- +603 def mount(self, local_mount_point, remote_path): +604 """ +605 Generates the command to mount an SMB share on different platforms. +606 +607 This method takes the local mount point and the remote path of the SMB share and generates the appropriate mount command based on the platform. +608 It constructs the mount command using the provided parameters and executes it using the os.system() function. +609 +610 Args: +611 local_mount_point (str): The local directory where the SMB share will be mounted. +612 remote_path (str): The remote path on the SMB share to be mounted. +613 +614 Note: +615 - For Windows platform, the command uses 'net use' to mount the share. +616 - For Linux platform, the command uses 'mount' to mount the share. +617 - For macOS platform, the command uses 'mount_smbfs' to mount the share. +618 - If the platform is not supported, an error message is displayed. +619 +620 Returns: +621 None +622 """ +623 +624 if not os.path.exists(local_mount_point): +625 pass +626 +627 if sys.platform.startswith('win'): +628 remote_path = remote_path.replace('/',ntpath.sep) +629 command = f"net use {local_mount_point} \\\\{self.address}\\{self.smb_share}\\{remote_path}" +630 +631 elif sys.platform.startswith('linux'): +632 remote_path = remote_path.replace(ntpath.sep,'/') +633 command = f"mount -t cifs //{self.address}/{self.smb_share}/{remote_path} {local_mount_point} -o username={self.username},password={self.password}" +634 +635 elif sys.platform.startswith('darwin'): +636 remote_path = remote_path.replace(ntpath.sep,'/') +637 command = f"mount_smbfs //{self.username}:{self.password}@{self.address}/{self.smb_share}/{remote_path} {local_mount_point}" +638 +639 else: +640 command = None +641 print("[!] Unsupported platform for mounting SMB share.") +642 +643 if command is not None: +644 if self.config.debug: +645 print("[debug] Executing: %s" % command) +646 os.system(command)+Generates the command to mount an SMB share on different platforms.
+ +This method takes the local mount point and the remote path of the SMB share and generates the appropriate mount command based on the platform. +It constructs the mount command using the provided parameters and executes it using the os.system() function.
+ +Args: + local_mount_point (str): The local directory where the SMB share will be mounted. + remote_path (str): The remote path on the SMB share to be mounted.
+ +Note: + - For Windows platform, the command uses 'net use' to mount the share. + - For Linux platform, the command uses 'mount' to mount the share. + - For macOS platform, the command uses 'mount_smbfs' to mount the share. + - If the platform is not supported, an error message is displayed.
+ +Returns: + None
+
603 def path_exists(self, path=None): -604 """ -605 Checks if the specified path exists on the SMB share. -606 -607 This method determines if a given path exists on the SMB share by attempting to list the contents of the path. -608 If the path listing is successful and returns one or more entries, the path is considered to exist. -609 -610 Args: -611 path (str, optional): The path to check on the SMB share. Defaults to None. -612 -613 Returns: -614 bool: True if the path exists, False otherwise or if an error occurs. -615 """ -616 -617 if path is not None: -618 path = path.replace('*','') -619 try: -620 contents = self.smbClient.listPath( -621 shareName=self.smb_share, -622 path=ntpath.normpath(self.smb_cwd + ntpath.sep + path + ntpath.sep) -623 ) -624 return (len(contents) != 0) -625 except Exception as e: -626 return False -627 else: -628 return False +@@ -3446,49 +3826,49 @@648 def path_exists(self, path=None): +649 """ +650 Checks if the specified path exists on the SMB share. +651 +652 This method determines if a given path exists on the SMB share by attempting to list the contents of the path. +653 If the path listing is successful and returns one or more entries, the path is considered to exist. +654 +655 Args: +656 path (str, optional): The path to check on the SMB share. Defaults to None. +657 +658 Returns: +659 bool: True if the path exists, False otherwise or if an error occurs. +660 """ +661 +662 if path is not None: +663 path = path.replace('*','') +664 try: +665 contents = self.smbClient.listPath( +666 shareName=self.smb_share, +667 path=ntpath.normpath(self.smb_cwd + ntpath.sep + path + ntpath.sep) +668 ) +669 return (len(contents) != 0) +670 except Exception as e: +671 return False +672 else: +673 return False
630 def path_isdir(self, pathFromRoot=None): -631 """ -632 Checks if the specified path is a directory on the SMB share. -633 -634 This method determines if a given path corresponds to a directory on the SMB share. It does this by listing the -635 contents of the path and filtering for entries that match the basename of the path and are marked as directories. -636 -637 Args: -638 path (str, optional): The path to check on the SMB share. Defaults to None. -639 -640 Returns: -641 bool: True if the path is a directory, False otherwise or if an error occurs. -642 """ -643 -644 if pathFromRoot is not None: -645 # Replace slashes if any -646 path = pathFromRoot.replace('/', ntpath.sep) -647 -648 # Strip wildcards to avoid injections -649 path = path.replace('*','') -650 -651 # Normalize path and strip leading backslash -652 path = ntpath.normpath(path + ntpath.sep).lstrip(ntpath.sep) -653 -654 if path.strip() in ['', '.', '..']: -655 # By defininition they exist on the filesystem -656 return True -657 else: -658 try: -659 contents = self.smbClient.listPath( -660 shareName=self.smb_share, -661 path=path+'*' -662 ) -663 # Filter on directories -664 contents = [ -665 c for c in contents -666 if c.get_longname() == ntpath.basename(path) and c.is_directory() -667 ] -668 return (len(contents) != 0) -669 except Exception as e: -670 return False -671 else: -672 return False +@@ -3517,39 +3897,39 @@675 def path_isdir(self, pathFromRoot=None): +676 """ +677 Checks if the specified path is a directory on the SMB share. +678 +679 This method determines if a given path corresponds to a directory on the SMB share. It does this by listing the +680 contents of the path and filtering for entries that match the basename of the path and are marked as directories. +681 +682 Args: +683 path (str, optional): The path to check on the SMB share. Defaults to None. +684 +685 Returns: +686 bool: True if the path is a directory, False otherwise or if an error occurs. +687 """ +688 +689 if pathFromRoot is not None: +690 # Replace slashes if any +691 path = pathFromRoot.replace('/', ntpath.sep) +692 +693 # Strip wildcards to avoid injections +694 path = path.replace('*','') +695 +696 # Normalize path and strip leading backslash +697 path = ntpath.normpath(path + ntpath.sep).lstrip(ntpath.sep) +698 +699 if path.strip() in ['', '.', '..']: +700 # By defininition they exist on the filesystem +701 return True +702 else: +703 try: +704 contents = self.smbClient.listPath( +705 shareName=self.smb_share, +706 path=path+'*' +707 ) +708 # Filter on directories +709 contents = [ +710 c for c in contents +711 if c.get_longname() == ntpath.basename(path) and c.is_directory() +712 ] +713 return (len(contents) != 0) +714 except Exception as e: +715 return False +716 else: +717 return False
674 def path_isfile(self, path=None): -675 """ -676 Checks if the specified path is a file on the SMB share. -677 -678 This method determines if a given path corresponds to a file on the SMB share. It does this by listing the -679 contents of the path and filtering for entries that match the basename of the path and are not marked as directories. -680 -681 Args: -682 path (str, optional): The path to check on the SMB share. Defaults to None. -683 -684 Returns: -685 bool: True if the path is a file, False otherwise or if an error occurs. -686 """ -687 -688 if path is not None: -689 path = path.replace('*','') -690 search_dir = ntpath.normpath(self.smb_cwd + ntpath.sep + path) -691 search_dir = ntpath.dirname(search_dir) + ntpath.sep + '*' -692 try: -693 contents = self.smbClient.listPath( -694 shareName=self.smb_share, -695 path=search_dir -696 ) -697 # Filter on files -698 contents = [ -699 c for c in contents -700 if c.get_longname() == ntpath.basename(path) and not c.is_directory() -701 ] -702 return (len(contents) != 0) -703 except Exception as e: -704 return False -705 else: -706 return False +@@ -3578,22 +3958,22 @@719 def path_isfile(self, path=None): +720 """ +721 Checks if the specified path is a file on the SMB share. +722 +723 This method determines if a given path corresponds to a file on the SMB share. It does this by listing the +724 contents of the path and filtering for entries that match the basename of the path and are not marked as directories. +725 +726 Args: +727 path (str, optional): The path to check on the SMB share. Defaults to None. +728 +729 Returns: +730 bool: True if the path is a file, False otherwise or if an error occurs. +731 """ +732 +733 if path is not None: +734 path = path.replace('*','') +735 search_dir = ntpath.normpath(self.smb_cwd + ntpath.sep + path) +736 search_dir = ntpath.dirname(search_dir) + ntpath.sep + '*' +737 try: +738 contents = self.smbClient.listPath( +739 shareName=self.smb_share, +740 path=search_dir +741 ) +742 # Filter on files +743 contents = [ +744 c for c in contents +745 if c.get_longname() == ntpath.basename(path) and not c.is_directory() +746 ] +747 return (len(contents) != 0) +748 except Exception as e: +749 return False +750 else: +751 return False
708 def ping_smb_session(self): -709 """ -710 Tests the connectivity to the SMB server by sending an echo command. -711 -712 This method attempts to send an echo command to the SMB server to check if the session is still active. -713 It updates the `connected` attribute of the class based on the success or failure of the echo command. -714 -715 Returns: -716 bool: True if the echo command succeeds (indicating the session is active), False otherwise. -717 """ -718 -719 try: -720 self.smbClient.getSMBServer().echo() -721 except Exception as e: -722 self.connected = False -723 return self.connected +@@ -3619,45 +3999,72 @@753 def ping_smb_session(self): +754 """ +755 Tests the connectivity to the SMB server by sending an echo command. +756 +757 This method attempts to send an echo command to the SMB server to check if the session is still active. +758 It updates the `connected` attribute of the class based on the success or failure of the echo command. +759 +760 Returns: +761 bool: True if the echo command succeeds (indicating the session is active), False otherwise. +762 """ +763 +764 try: +765 self.smbClient.getSMBServer().echo() +766 except Exception as e: +767 self.connected = False +768 return self.connected
725 def put_file(self, localpath=None): -726 """ -727 Uploads a single file to the SMB share. -728 -729 This method takes a local file path, opens the file, and uploads it to the SMB share at the specified path. -730 It handles exceptions such as broken pipe errors or keyboard interrupts by closing and reinitializing the SMB session. -731 General exceptions are caught and logged, with a traceback provided if debugging is enabled. -732 -733 Args: -734 localpath (str, optional): The local file path of the file to be uploaded. Defaults to None. -735 """ -736 -737 if os.path.exists(localpath): -738 if os.path.isfile(localpath): -739 try: -740 localfile = os.path.basename(localpath) -741 f = LocalFileIO( -742 mode="rb", -743 path=localpath, -744 debug=self.config.debug -745 ) -746 self.smbClient.putFile( -747 shareName=self.smb_share, -748 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + localfile + ntpath.sep), -749 callback=f.read -750 ) -751 f.close() -752 except (BrokenPipeError, KeyboardInterrupt) as err: -753 print("[!] Interrupted.") -754 self.close_smb_session() -755 self.init_smb_session() -756 except Exception as err: -757 print("[!] Failed to upload '%s': %s" % (localfile, err)) -758 if self.config.debug: -759 traceback.print_exc() -760 else: -761 print("[!] The specified localpath is a directory. Use 'put -r <directory>' instead.") -762 else: -763 print("[!] The specified localpath does not exist.") +@@ -3684,62 +4091,62 @@770 def put_file(self, localpath=None): +771 """ +772 Uploads a single file to the SMB share. +773 +774 This method takes a local file path, opens the file, and uploads it to the SMB share at the specified path. +775 It handles exceptions such as broken pipe errors or keyboard interrupts by closing and reinitializing the SMB session. +776 General exceptions are caught and logged, with a traceback provided if debugging is enabled. +777 +778 Args: +779 localpath (str, optional): The local file path of the file to be uploaded. Defaults to None. +780 """ +781 +782 # Parse path +783 localpath = localpath.replace('/', os.path.sep) +784 if os.path.sep in localpath: +785 tmp_search_path = os.path.normpath(os.getcwd() + os.path.sep + os.path.dirname(localpath)) +786 else: +787 tmp_search_path = os.path.normpath(os.getcwd() + os.path.sep) +788 # Parse filename +789 filename = os.path.basename(localpath) +790 +791 # Search for the file +792 matches = os.listdir(tmp_search_path) +793 # Filter the entries +794 matching_entries = [] +795 for entry in matches: +796 if entry == filename: +797 matching_entries.append(entry) +798 elif '*' in filename: +799 regexp = filename.replace('.', '\\.').replace('*', '.*') +800 if re.match(regexp, entry): +801 matching_entries.append(entry) +802 +803 matching_entries = sorted(list(set(matching_entries))) +804 +805 # Loop and upload +806 for localpath in matching_entries: +807 if os.path.exists(localpath): +808 if os.path.isfile(localpath): +809 try: +810 localfile = os.path.basename(localpath) +811 f = LocalFileIO( +812 mode="rb", +813 path=localpath, +814 debug=self.config.debug +815 ) +816 self.smbClient.putFile( +817 shareName=self.smb_share, +818 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + localfile + ntpath.sep), +819 callback=f.read +820 ) +821 f.close() +822 except (BrokenPipeError, KeyboardInterrupt) as err: +823 print("[!] Interrupted.") +824 self.close_smb_session() +825 self.init_smb_session() +826 except Exception as err: +827 print("[!] Failed to upload '%s': %s" % (localfile, err)) +828 if self.config.debug: +829 traceback.print_exc() +830 else: +831 # [!] The specified localpath is a directory. Use 'put -r <directory>' instead. +832 pass +833 else: +834 # [!] The specified localpath does not exist. +835 pass
765 def put_file_recursively(self, localpath=None): -766 """ -767 Recursively uploads files from a specified local directory to the SMB share. -768 -769 This method walks through the given local directory and all its subdirectories, uploading each file to the -770 corresponding directory structure on the SMB share. It first checks if the local path is a directory. If it is, -771 it iterates over all files and directories within the local path, creating necessary directories on the SMB share -772 and uploading files. If the local path is not a directory, it prints an error message. -773 -774 Args: -775 localpath (str, optional): The local directory path from which files will be uploaded. Defaults to None. -776 """ -777 -778 if os.path.exists(localpath): -779 if os.path.isfile(localpath): -780 # Iterate over all files and directories within the local path -781 local_files = {} -782 for root, dirs, files in os.walk(localpath): -783 if len(files) != 0: -784 local_files[root] = files -785 -786 # Iterate over the found files -787 for local_dir_path in sorted(local_files.keys()): -788 print("[>] Putting files of '%s'" % local_dir_path) -789 -790 # Create remote directory -791 remote_dir_path = local_dir_path.replace(os.path.sep, ntpath.sep) -792 self.mkdir( -793 path=ntpath.normpath(self.smb_cwd + ntpath.sep + remote_dir_path + ntpath.sep) -794 ) -795 -796 for local_file_path in local_files[local_dir_path]: -797 try: -798 f = LocalFileIO( -799 mode="rb", -800 path=local_dir_path + os.path.sep + local_file_path, -801 debug=self.config.debug -802 ) -803 self.smbClient.putFile( -804 shareName=self.smb_share, -805 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + remote_dir_path + ntpath.sep + local_file_path), -806 callback=f.read -807 ) -808 f.close() -809 -810 except BrokenPipeError as err: -811 f.set_error(message="[bold red]Failed uploading '%s': %s" % (f.path, err)) -812 f.close(remove=True) -813 break -814 except Exception as err: -815 f.set_error(message="[bold red]Failed uploading '%s': %s" % (f.path, err)) -816 f.close(remove=True) -817 else: -818 print("[!] The specified localpath is a file. Use 'put <file>' instead.") -819 else: -820 print("[!] The specified localpath does not exist.") +@@ -3767,26 +4174,26 @@837 def put_file_recursively(self, localpath=None): +838 """ +839 Recursively uploads files from a specified local directory to the SMB share. +840 +841 This method walks through the given local directory and all its subdirectories, uploading each file to the +842 corresponding directory structure on the SMB share. It first checks if the local path is a directory. If it is, +843 it iterates over all files and directories within the local path, creating necessary directories on the SMB share +844 and uploading files. If the local path is not a directory, it prints an error message. +845 +846 Args: +847 localpath (str, optional): The local directory path from which files will be uploaded. Defaults to None. +848 """ +849 +850 if os.path.exists(localpath): +851 if os.path.isfile(localpath): +852 # Iterate over all files and directories within the local path +853 local_files = {} +854 for root, dirs, files in os.walk(localpath): +855 if len(files) != 0: +856 local_files[root] = files +857 +858 # Iterate over the found files +859 for local_dir_path in sorted(local_files.keys()): +860 print("[>] Putting files of '%s'" % local_dir_path) +861 +862 # Create remote directory +863 remote_dir_path = local_dir_path.replace(os.path.sep, ntpath.sep) +864 self.mkdir( +865 path=ntpath.normpath(self.smb_cwd + ntpath.sep + remote_dir_path + ntpath.sep) +866 ) +867 +868 for local_file_path in local_files[local_dir_path]: +869 try: +870 f = LocalFileIO( +871 mode="rb", +872 path=local_dir_path + os.path.sep + local_file_path, +873 debug=self.config.debug +874 ) +875 self.smbClient.putFile( +876 shareName=self.smb_share, +877 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + remote_dir_path + ntpath.sep + local_file_path), +878 callback=f.read +879 ) +880 f.close() +881 +882 except BrokenPipeError as err: +883 f.set_error(message="[bold red]Failed uploading '%s': %s" % (f.path, err)) +884 f.close(remove=True) +885 break +886 except Exception as err: +887 f.set_error(message="[bold red]Failed uploading '%s': %s" % (f.path, err)) +888 f.close(remove=True) +889 else: +890 print("[!] The specified localpath is a file. Use 'put <file>' instead.") +891 else: +892 print("[!] The specified localpath does not exist.")
822 def rmdir(self, path=None): -823 """ -824 Removes a directory from the SMB share at the specified path. -825 -826 This method attempts to delete a directory located at the given path on the SMB share. If the operation fails, -827 it prints an error message indicating the failure and the reason. If debugging is enabled, it also prints -828 the stack trace of the exception. -829 -830 Args: -831 path (str, optional): The path of the directory to be removed on the SMB share. Defaults to None. -832 """ -833 try: -834 self.smbClient.deleteDirectory( -835 shareName=self.smb_share, -836 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + path), -837 ) -838 except Exception as err: -839 print("[!] Failed to remove directory '%s': %s" % (path, err)) -840 if self.config.debug: -841 traceback.print_exc() +@@ -3813,26 +4220,58 @@894 def rmdir(self, path=None): +895 """ +896 Removes a directory from the SMB share at the specified path. +897 +898 This method attempts to delete a directory located at the given path on the SMB share. If the operation fails, +899 it prints an error message indicating the failure and the reason. If debugging is enabled, it also prints +900 the stack trace of the exception. +901 +902 Args: +903 path (str, optional): The path of the directory to be removed on the SMB share. Defaults to None. +904 """ +905 try: +906 self.smbClient.deleteDirectory( +907 shareName=self.smb_share, +908 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + path), +909 ) +910 except Exception as err: +911 print("[!] Failed to remove directory '%s': %s" % (path, err)) +912 if self.config.debug: +913 traceback.print_exc()
843 def rm(self, path=None): -844 """ -845 Removes a file from the SMB share at the specified path. -846 -847 This method attempts to delete a file located at the given path on the SMB share. If the operation fails, -848 it prints an error message indicating the failure and the reason. If debugging is enabled, it also prints -849 the stack trace of the exception. -850 -851 Args: -852 path (str, optional): The path of the file to be removed on the SMB share. Defaults to None. -853 """ -854 try: -855 self.smbClient.deleteFile( -856 shareName=self.smb_share, -857 pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + path), -858 ) -859 except Exception as err: -860 print("[!] Failed to remove file '%s': %s" % (path, err)) -861 if self.config.debug: -862 traceback.print_exc() +@@ -3859,135 +4298,135 @@915 def rm(self, path=None): +916 """ +917 Removes a file from the SMB share at the specified path. +918 +919 This method attempts to delete a file located at the given path on the SMB share. If the operation fails, +920 it prints an error message indicating the failure and the reason. If debugging is enabled, it also prints +921 the stack trace of the exception. +922 +923 Args: +924 path (str, optional): The path of the file to be removed on the SMB share. Defaults to None. +925 """ +926 +927 # Parse path +928 path = path.replace('/', ntpath.sep) +929 if ntpath.sep in path: +930 tmp_search_path = ntpath.normpath(self.smb_cwd + ntpath.sep + ntpath.dirname(path)) +931 else: +932 tmp_search_path = ntpath.normpath(self.smb_cwd + ntpath.sep) +933 # Parse filename +934 filename = ntpath.basename(path) +935 +936 # Search for the file +937 matches = self.smbClient.listPath( +938 shareName=self.smb_share, +939 path=tmp_search_path + ntpath.sep + '*' +940 ) +941 +942 # Filter the entries +943 matching_entries = [] +944 for entry in matches: +945 if entry.is_directory(): +946 # Skip directories +947 continue +948 if entry.get_longname() == filename: +949 matching_entries.append(entry) +950 elif '*' in filename: +951 regexp = filename.replace('.', '\\.').replace('*', '.*') +952 if re.match(regexp, entry.get_longname()): +953 matching_entries.append(entry) +954 +955 matching_entries = sorted(list(set(matching_entries)), key=lambda x: x.get_longname()) +956 +957 for entry in matching_entries: +958 try: +959 self.smbClient.deleteFile( +960 shareName=self.smb_share, +961 pathName=ntpath.normpath(tmp_search_path + ntpath.sep + entry.get_longname()), +962 ) +963 except Exception as err: +964 print("[!] Failed to remove file '%s': %s" % (path, err)) +965 if self.config.debug: +966 traceback.print_exc()
864 def tree(self, path=None): -865 """ -866 Recursively lists the directory structure of the SMB share starting from the specified path. -867 -868 This function prints a visual representation of the directory tree of the remote SMB share. It uses -869 recursion to navigate through directories and lists all files and subdirectories in each directory. -870 The output is color-coded and formatted to enhance readability, with directories highlighted in cyan. -871 -872 Args: -873 path (str, optional): The starting path on the SMB share from which to begin listing the tree. -874 Defaults to the root of the current share. -875 """ -876 -877 def recurse_action(base_dir="", path=[], prompt=[]): -878 bars = ["│ ", "├── ", "└── "] -879 -880 remote_smb_path = ntpath.normpath(base_dir + ntpath.sep + ntpath.sep.join(path)) -881 -882 entries = [] -883 try: -884 entries = self.smbClient.listPath( -885 shareName=self.smb_share, -886 path=remote_smb_path+'\\*' -887 ) -888 except impacket.smbconnection.SessionError as err: -889 code, const, text = err.getErrorCode(), err.getErrorString()[0], err.getErrorString()[1] -890 errmsg = "Error 0x%08x (%s): %s" % (code, const, text) -891 if self.config.no_colors: -892 print("%s%s" % (''.join(prompt+[bars[2]]), errmsg)) -893 else: -894 print("%s\x1b[1;91m%s\x1b[0m" % (''.join(prompt+[bars[2]]), errmsg)) -895 return -896 -897 entries = [e for e in entries if e.get_longname() not in [".", ".."]] -898 entries = sorted(entries, key=lambda x:x.get_longname()) -899 -900 # -901 if len(entries) > 1: -902 index = 0 -903 for entry in entries: -904 index += 1 -905 # This is the first entry -906 if index == 0: -907 if entry.is_directory(): -908 if self.config.no_colors: -909 print("%s%s\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) -910 else: -911 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) -912 recurse_action( -913 base_dir=base_dir, -914 path=path+[entry.get_longname()], -915 prompt=prompt+["│ "] -916 ) -917 else: -918 if self.config.no_colors: -919 print("%s%s" % (''.join(prompt+[bars[1]]), entry.get_longname())) -920 else: -921 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[1]]), entry.get_longname())) -922 -923 # This is the last entry -924 elif index == len(entries): -925 if entry.is_directory(): -926 if self.config.no_colors: -927 print("%s%s\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) -928 else: -929 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) -930 recurse_action( -931 base_dir=base_dir, -932 path=path+[entry.get_longname()], -933 prompt=prompt+[" "] -934 ) -935 else: -936 if self.config.no_colors: -937 print("%s%s" % (''.join(prompt+[bars[2]]), entry.get_longname())) -938 else: -939 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[2]]), entry.get_longname())) -940 -941 # These are entries in the middle -942 else: -943 if entry.is_directory(): -944 if self.config.no_colors: -945 print("%s%s\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) -946 else: -947 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) -948 recurse_action( -949 base_dir=base_dir, -950 path=path+[entry.get_longname()], -951 prompt=prompt+["│ "] -952 ) -953 else: -954 if self.config.no_colors: -955 print("%s%s" % (''.join(prompt+[bars[1]]), entry.get_longname())) -956 else: -957 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[1]]), entry.get_longname())) -958 -959 # -960 elif len(entries) == 1: -961 entry = entries[0] -962 if entry.is_directory(): -963 if self.config.no_colors: -964 print("%s%s\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) -965 else: -966 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) -967 recurse_action( -968 base_dir=base_dir, -969 path=path+[entry.get_longname()], -970 prompt=prompt+[" "] -971 ) -972 else: -973 if self.config.no_colors: -974 print("%s%s" % (''.join(prompt+[bars[2]]), entry.get_longname())) -975 else: -976 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[2]]), entry.get_longname())) -977 -978 # Entrypoint -979 try: -980 if self.config.no_colors: -981 print("%s\\" % path) -982 else: -983 print("\x1b[1;96m%s\x1b[0m\\" % path) -984 recurse_action( -985 base_dir=self.smb_cwd, -986 path=[path], -987 prompt=[""] -988 ) -989 except (BrokenPipeError, KeyboardInterrupt) as e: -990 print("[!] Interrupted.") -991 self.close_smb_session() -992 self.init_smb_session() +@@ -4015,28 +4454,113 @@968 def tree(self, path=None): + 969 """ + 970 Recursively lists the directory structure of the SMB share starting from the specified path. + 971 + 972 This function prints a visual representation of the directory tree of the remote SMB share. It uses + 973 recursion to navigate through directories and lists all files and subdirectories in each directory. + 974 The output is color-coded and formatted to enhance readability, with directories highlighted in cyan. + 975 + 976 Args: + 977 path (str, optional): The starting path on the SMB share from which to begin listing the tree. + 978 Defaults to the root of the current share. + 979 """ + 980 + 981 def recurse_action(base_dir="", path=[], prompt=[]): + 982 bars = ["│ ", "├── ", "└── "] + 983 + 984 remote_smb_path = ntpath.normpath(base_dir + ntpath.sep + ntpath.sep.join(path)) + 985 + 986 entries = [] + 987 try: + 988 entries = self.smbClient.listPath( + 989 shareName=self.smb_share, + 990 path=remote_smb_path+'\\*' + 991 ) + 992 except impacket.smbconnection.SessionError as err: + 993 code, const, text = err.getErrorCode(), err.getErrorString()[0], err.getErrorString()[1] + 994 errmsg = "Error 0x%08x (%s): %s" % (code, const, text) + 995 if self.config.no_colors: + 996 print("%s%s" % (''.join(prompt+[bars[2]]), errmsg)) + 997 else: + 998 print("%s\x1b[1;91m%s\x1b[0m" % (''.join(prompt+[bars[2]]), errmsg)) + 999 return +1000 +1001 entries = [e for e in entries if e.get_longname() not in [".", ".."]] +1002 entries = sorted(entries, key=lambda x:x.get_longname()) +1003 +1004 # +1005 if len(entries) > 1: +1006 index = 0 +1007 for entry in entries: +1008 index += 1 +1009 # This is the first entry +1010 if index == 0: +1011 if entry.is_directory(): +1012 if self.config.no_colors: +1013 print("%s%s\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1014 else: +1015 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1016 recurse_action( +1017 base_dir=base_dir, +1018 path=path+[entry.get_longname()], +1019 prompt=prompt+["│ "] +1020 ) +1021 else: +1022 if self.config.no_colors: +1023 print("%s%s" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1024 else: +1025 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1026 +1027 # This is the last entry +1028 elif index == len(entries): +1029 if entry.is_directory(): +1030 if self.config.no_colors: +1031 print("%s%s\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1032 else: +1033 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1034 recurse_action( +1035 base_dir=base_dir, +1036 path=path+[entry.get_longname()], +1037 prompt=prompt+[" "] +1038 ) +1039 else: +1040 if self.config.no_colors: +1041 print("%s%s" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1042 else: +1043 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1044 +1045 # These are entries in the middle +1046 else: +1047 if entry.is_directory(): +1048 if self.config.no_colors: +1049 print("%s%s\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1050 else: +1051 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1052 recurse_action( +1053 base_dir=base_dir, +1054 path=path+[entry.get_longname()], +1055 prompt=prompt+["│ "] +1056 ) +1057 else: +1058 if self.config.no_colors: +1059 print("%s%s" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1060 else: +1061 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[1]]), entry.get_longname())) +1062 +1063 # +1064 elif len(entries) == 1: +1065 entry = entries[0] +1066 if entry.is_directory(): +1067 if self.config.no_colors: +1068 print("%s%s\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1069 else: +1070 print("%s\x1b[1;96m%s\x1b[0m\\" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1071 recurse_action( +1072 base_dir=base_dir, +1073 path=path+[entry.get_longname()], +1074 prompt=prompt+[" "] +1075 ) +1076 else: +1077 if self.config.no_colors: +1078 print("%s%s" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1079 else: +1080 print("%s\x1b[1m%s\x1b[0m" % (''.join(prompt+[bars[2]]), entry.get_longname())) +1081 +1082 # Entrypoint +1083 try: +1084 if self.config.no_colors: +1085 print("%s\\" % path) +1086 else: +1087 print("\x1b[1;96m%s\x1b[0m\\" % path) +1088 recurse_action( +1089 base_dir=self.smb_cwd, +1090 path=[path], +1091 prompt=[""] +1092 ) +1093 except (BrokenPipeError, KeyboardInterrupt) as e: +1094 print("[!] Interrupted.") +1095 self.close_smb_session() +1096 self.init_smb_session()
994 def umount(self, local_mount_point): - 995 if os.path.exists(local_mount_point): - 996 if sys.platform.startswith('win'): - 997 command = f"net use {local_mount_point} /delete" - 998 - 999 elif sys.platform.startswith('linux') or sys.platform.startswith('darwin'): -1000 command = f"umount {local_mount_point}" -1001 -1002 else: -1003 command = None -1004 print("[!] Unsupported platform for unmounting SMB share.") -1005 -1006 if command is not None: -1007 if self.config.debug: -1008 print("[debug] Executing: %s" % command) -1009 os.system(command) -1010 else: -1011 print("[!] Cannot unmount a non existing path.") +- +1098 def umount(self, local_mount_point): +1099 """ +1100 Unmounts the specified local mount point of the remote share. +1101 +1102 This method unmounts the specified local mount point of the remote share based on the platform. +1103 It supports Windows, Linux, and macOS platforms for unmounting. +1104 +1105 Parameters: +1106 local_mount_point (str): The local mount point to unmount. +1107 +1108 Raises: +1109 None +1110 """ +1111 +1112 if os.path.exists(local_mount_point): +1113 if sys.platform.startswith('win'): +1114 command = f"net use {local_mount_point} /delete" +1115 +1116 elif sys.platform.startswith('linux') or sys.platform.startswith('darwin'): +1117 command = f"umount {local_mount_point}" +1118 +1119 else: +1120 command = None +1121 print("[!] Unsupported platform for unmounting SMB share.") +1122 +1123 if command is not None: +1124 if self.config.debug: +1125 print("[debug] Executing: %s" % command) +1126 os.system(command) +1127 else: +1128 print("[!] Cannot unmount a non existing path.")+ + +Unmounts the specified local mount point of the remote share.
+ +This method unmounts the specified local mount point of the remote share based on the platform. +It supports Windows, Linux, and macOS platforms for unmounting.
+ +Parameters: + local_mount_point (str): The local mount point to unmount.
+ +Raises: + None
+
1132 def test_rights(self, sharename): +1133 """ +1134 Tests the read and write access rights of the current SMB session. +1135 +1136 This method checks the read and write access rights of the current SMB session by attempting to list paths and create/delete temporary directories. +1137 +1138 Returns: +1139 dict: A dictionary containing the read and write access rights status. +1140 - "readable" (bool): Indicates if the session has read access rights. +1141 - "writable" (bool): Indicates if the session has write access rights. +1142 """ +1143 +1144 # Restore the current share +1145 current_share = self.smb_share +1146 self.set_share(shareName=sharename) +1147 +1148 access_rights = {"readable": False, "writable": False} +1149 try: +1150 self.smbClient.listPath(self.smb_share, '*', password=None) +1151 access_rights["readable"] = True +1152 except impacket.smbconnection.SessionError as e: +1153 access_rights["readable"] = False +1154 +1155 try: +1156 temp_dir = ntpath.normpath("\\" + ''.join([random.choice("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ0123456759") for k in range(16)])) +1157 self.smbClient.createDirectory(self.smb_share, temp_dir) +1158 self.smbClient.deleteDirectory(self.smb_share, temp_dir) +1159 access_rights["writable"] = True +1160 except impacket.smbconnection.SessionError as e: +1161 access_rights["writable"] = False +1162 +1163 # Restore the current share +1164 self.set_share(shareName=current_share) +1165 +1166 return access_rights +
Tests the read and write access rights of the current SMB session.
+ +This method checks the read and write access rights of the current SMB session by attempting to list paths and create/delete temporary directories.
+ +Returns: + dict: A dictionary containing the read and write access rights status. + - "readable" (bool): Indicates if the session has read access rights. + - "writable" (bool): Indicates if the session has write access rights.
+1039 def set_cwd(self, path=None): -1040 """ -1041 Sets the current working directory on the SMB share to the specified path. -1042 -1043 This method updates the current working directory (cwd) of the SMB session to the given path if it is a valid directory. -1044 If the specified path is not a directory, the cwd remains unchanged. -1045 -1046 Parameters: -1047 path (str): The path to set as the current working directory. -1048 -1049 Raises: -1050 ValueError: If the specified path is not a directory. -1051 """ -1052 -1053 if path is not None: -1054 # Set path separators to ntpath sep -1055 if '/' in path: -1056 path = path.replace('/', ntpath.sep) -1057 -1058 if path.startswith(ntpath.sep): -1059 # Absolute path -1060 path = path + ntpath.sep -1061 else: -1062 # Relative path to the CWD -1063 if len(self.smb_cwd) == 0: -1064 path = path + ntpath.sep -1065 else: -1066 path = self.smb_cwd + ntpath.sep + path -1067 -1068 # Path normalization -1069 path = ntpath.normpath(path) -1070 path = re.sub(r'\\+', r'\\', path) -1071 -1072 if path in ["", ".", ".."]: -1073 self.smb_cwd = "" -1074 else: -1075 if self.path_isdir(pathFromRoot=path.strip(ntpath.sep)): -1076 # Path exists on the remote -1077 self.smb_cwd = ntpath.normpath(path) -1078 else: -1079 # Path does not exists or is not a directory on the remote -1080 print("[!] Remote directory '%s' does not exist." % path) +diff --git a/smbclientng/core/InteractiveShell.py b/smbclientng/core/InteractiveShell.py index 9a0e275..c691b2a 100644 --- a/smbclientng/core/InteractiveShell.py +++ b/smbclientng/core/InteractiveShell.py @@ -723,7 +723,9 @@ def command_rm(self, arguments, command): # SMB share needed : Yes path = ' '.join(arguments) - if self.smbSession.path_exists(path): + if '*' in path: + self.smbSession.rm(path=path) + elif self.smbSession.path_exists(path): if self.smbSession.path_isfile(path): try: self.smbSession.rm(path=path) diff --git a/smbclientng/core/SMBSession.py b/smbclientng/core/SMBSession.py index a95680b..9378d70 100644 --- a/smbclientng/core/SMBSession.py +++ b/smbclientng/core/SMBSession.py @@ -271,6 +271,9 @@ def get_file(self, path=None, keepRemotePath=False): # Filter the entries matching_entries = [] for entry in matches: + if entry.is_directory(): + # Skip directories + continue if entry.get_longname() == filename: matching_entries.append(entry) elif '*' in filename: @@ -278,7 +281,7 @@ def get_file(self, path=None, keepRemotePath=False): if re.match(regexp, entry.get_longname()): matching_entries.append(entry) - matching_entries = sorted(list(set(matching_entries))) + matching_entries = sorted(list(set(matching_entries)), key=lambda x: x.get_longname()) for entry in matching_entries: if entry.is_directory(): @@ -919,15 +922,47 @@ def rm(self, path=None): Args: path (str, optional): The path of the file to be removed on the SMB share. Defaults to None. """ - try: - self.smbClient.deleteFile( - shareName=self.smb_share, - pathName=ntpath.normpath(self.smb_cwd + ntpath.sep + path), - ) - except Exception as err: - print("[!] Failed to remove file '%s': %s" % (path, err)) - if self.config.debug: - traceback.print_exc() + + # Parse path + path = path.replace('/', ntpath.sep) + if ntpath.sep in path: + tmp_search_path = ntpath.normpath(self.smb_cwd + ntpath.sep + ntpath.dirname(path)) + else: + tmp_search_path = ntpath.normpath(self.smb_cwd + ntpath.sep) + # Parse filename + filename = ntpath.basename(path) + + # Search for the file + matches = self.smbClient.listPath( + shareName=self.smb_share, + path=tmp_search_path + ntpath.sep + '*' + ) + + # Filter the entries + matching_entries = [] + for entry in matches: + if entry.is_directory(): + # Skip directories + continue + if entry.get_longname() == filename: + matching_entries.append(entry) + elif '*' in filename: + regexp = filename.replace('.', '\\.').replace('*', '.*') + if re.match(regexp, entry.get_longname()): + matching_entries.append(entry) + + matching_entries = sorted(list(set(matching_entries)), key=lambda x: x.get_longname()) + + for entry in matching_entries: + try: + self.smbClient.deleteFile( + shareName=self.smb_share, + pathName=ntpath.normpath(tmp_search_path + ntpath.sep + entry.get_longname()), + ) + except Exception as err: + print("[!] Failed to remove file '%s': %s" % (path, err)) + if self.config.debug: + traceback.print_exc() def tree(self, path=None): """1197 def set_cwd(self, path=None): +1198 """ +1199 Sets the current working directory on the SMB share to the specified path. +1200 +1201 This method updates the current working directory (cwd) of the SMB session to the given path if it is a valid directory. +1202 If the specified path is not a directory, the cwd remains unchanged. +1203 +1204 Parameters: +1205 path (str): The path to set as the current working directory. +1206 +1207 Raises: +1208 ValueError: If the specified path is not a directory. +1209 """ +1210 +1211 if path is not None: +1212 # Set path separators to ntpath sep +1213 if '/' in path: +1214 path = path.replace('/', ntpath.sep) +1215 +1216 if path.startswith(ntpath.sep): +1217 # Absolute path +1218 path = path + ntpath.sep +1219 else: +1220 # Relative path to the CWD +1221 if len(self.smb_cwd) == 0: +1222 path = path + ntpath.sep +1223 else: +1224 path = self.smb_cwd + ntpath.sep + path +1225 +1226 # Path normalization +1227 path = ntpath.normpath(path) +1228 path = re.sub(r'\\+', r'\\', path) +1229 +1230 if path in ["", ".", ".."]: +1231 self.smb_cwd = "" +1232 else: +1233 if self.path_isdir(pathFromRoot=path.strip(ntpath.sep)): +1234 # Path exists on the remote +1235 self.smb_cwd = ntpath.normpath(path) +1236 else: +1237 # Path does not exists or is not a directory on the remote +1238 print("[!] Remote directory '%s' does not exist." % path)