From 2741a930e6a5bafafb7b6be4777e8d9fb16877f0 Mon Sep 17 00:00:00 2001 From: skuom Date: Wed, 2 Jul 2014 20:24:45 +0200 Subject: [PATCH 01/17] Updated standard port --- src/metasploit/msfrpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index 025b978..b143551 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -196,7 +196,7 @@ def __init__(self, password, **kwargs): - ssl : if true uses SSL else regular HTTP (default: SSL enabled) """ self.uri = kwargs.get('uri', '/api/') - self.port = kwargs.get('port', 55553) + self.port = kwargs.get('port', 55552) self.server = kwargs.get('server', '127.0.0.1') self.ssl = kwargs.get('ssl', True) self.sessionid = kwargs.get('token') From f2a77fd87bc7f8858ca54a13be59913eefbf8c90 Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 3 Dec 2015 04:10:20 +0000 Subject: [PATCH 02/17] fix bad chars in prompt --- src/scripts/pymsfconsole | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/scripts/pymsfconsole b/src/scripts/pymsfconsole index 0ae0c2a..8822f72 100755 --- a/src/scripts/pymsfconsole +++ b/src/scripts/pymsfconsole @@ -50,12 +50,11 @@ class MsfConsole(InteractiveConsole): def callback(self, d): stdout.write('\n%s' % d['data']) if not self.fl: - stdout.write('\n%s' % d['prompt']) + stdout.write('\n%s' % d['prompt'].replace("\x01\x02", "")) stdout.flush() else: self.fl = False - if __name__ == '__main__': o = parseargs() try: From d021b554de13b46469ee988f8fcbb16b13b58a93 Mon Sep 17 00:00:00 2001 From: Kyle Date: Thu, 26 May 2016 08:41:54 +1000 Subject: [PATCH 03/17] Create msfrpcdHandler.py --- src/metasploit/msfrpcdHandler.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/metasploit/msfrpcdHandler.py diff --git a/src/metasploit/msfrpcdHandler.py b/src/metasploit/msfrpcdHandler.py new file mode 100644 index 0000000..015dadf --- /dev/null +++ b/src/metasploit/msfrpcdHandler.py @@ -0,0 +1,28 @@ +# Handles the MetaSploit Framework Remote Procedure Call Daemon (MSFRPCD) for *nix machines + +import os, psutil, signal, time + +def msfrpcdStart(password): + if checkMsfrpcdRunning(): return "MetaSploit Framework Remote Procedure Call Daemon is already running." + else: + response = os.system("msfrpcd -P "+password+" -n -a 127.0.0.1") + time.sleep(10) + if checkMsfrpcdRunning(): return "MetaSploit Framework Remote Procedure Call Daemon running." + else: return "There was an issue: MetaSploit Framework Remote Procedure Call Daemon did not start." + +def checkMsfrpcdRunning(): + for socket in psutil.net_connections(): + if socket.laddr[1] == 55553: return socket.pid + +def msfrpcdRestart(password): + pid = checkMsfrpcdRunning() + if pid: + os.kill(socket.pid, signal.SIGKILL) + print "Old MSFRPCD process killed." + response = os.system("msfrpcd -P "+password+" -n -a 127.0.0.1") + time.sleep(10) + if checkMsfrpcdRunning(): return "MetaSploit Framework Remote Procedure Call Daemon running." + else: return "There was an issue: MetaSploit Framework Remote Procedure Call Daemon did not start." + +if __name__ == "__main__": + print msfrpcdStart('pass123') From bb87472600c86cc08a02c7387570f61565ffed26 Mon Sep 17 00:00:00 2001 From: Kyle Date: Thu, 26 May 2016 14:08:31 +1000 Subject: [PATCH 04/17] Update msfrpc.py Add functionality to allow additional run time options for payloads. Useful for Reverse_TCP --- src/metasploit/msfrpc.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index c005b5e..38c02a6 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -1450,6 +1450,15 @@ def execute(self, **kwargs): if isinstance(self, ExploitModule): payload = kwargs.get('payload') runopts['TARGET'] = self.target + """ + Define Runtime Options set as part of the execution argument + - For use when a payload requires additional options that can + - not be set as part of the exploit, for instance LHOST and LPORT + - for a meterpreter/reverse_tcp session. Add more lines for extra + - options + """ + if kwargs.get('LHOST'): runopts['LHOST'] = kwargs.get('LHOST') + if kwargs.get('LPORT'): runopts['LPORT'] = kwargs.get('LPORT') if 'DisablePayloadHandler' in runopts and runopts['DisablePayloadHandler']: pass elif payload is None: From 9e65d75ce41006795173fd03851543d1aa2a2f11 Mon Sep 17 00:00:00 2001 From: amon Date: Sun, 5 Jun 2016 06:30:18 +0000 Subject: [PATCH 05/17] Python 3 compatibility --- src/metasploit/msfconsole.py | 6 +- src/metasploit/msfconsole.py.bak | 96 + src/metasploit/msfrpc.py | 3522 +++++++++++++++--------------- src/metasploit/msfrpc.py.bak | 1971 +++++++++++++++++ src/metasploit/utils.py | 2 +- src/metasploit/utils.py.bak | 32 + 6 files changed, 3875 insertions(+), 1754 deletions(-) create mode 100644 src/metasploit/msfconsole.py.bak create mode 100644 src/metasploit/msfrpc.py.bak create mode 100644 src/metasploit/utils.py.bak diff --git a/src/metasploit/msfconsole.py b/src/metasploit/msfconsole.py index b8e7294..33544f7 100644 --- a/src/metasploit/msfconsole.py +++ b/src/metasploit/msfconsole.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from threading import Timer, Lock -from msfrpc import ShellSession +from .msfrpc import ShellSession __author__ = 'Nadeem Douba' __copyright__ = 'Copyright 2012, PyMetasploit Project' @@ -66,13 +66,13 @@ def _poller(self): if self.callback is not None: self.callback(d) else: - print d['data'] + print(d['data']) else: if d: if self.callback is not None: self.callback(dict(data=d, prompt=self.prompt)) else: - print d + print(d) Timer(0.5, self._poller).start() def execute(self, command): diff --git a/src/metasploit/msfconsole.py.bak b/src/metasploit/msfconsole.py.bak new file mode 100644 index 0000000..b8e7294 --- /dev/null +++ b/src/metasploit/msfconsole.py.bak @@ -0,0 +1,96 @@ +#!/usr/bin/env python + +from threading import Timer, Lock +from msfrpc import ShellSession + +__author__ = 'Nadeem Douba' +__copyright__ = 'Copyright 2012, PyMetasploit Project' +__credits__ = [] + +__license__ = 'GPL' +__version__ = '0.3' +__maintainer__ = 'Nadeem Douba' +__email__ = 'ndouba@cygnos.com' +__status__ = 'Development' + +__all__ = [ + 'MsfRpcConsole' +] + + +class MsfRpcConsoleType: + Console = 0 + Meterpreter = 1 + Shell = 2 + + +class MsfRpcConsole(object): + + def __init__(self, rpc, sessionid=None, cb=None): + """ + Emulates the msfconsole in msf except over RPC. + + Mandatory Arguments: + - rpc : an msfrpc client object + + Optional Arguments: + - cb : a callback function that gets called when data is received from the console. + """ + + self.callback = cb + + if sessionid is not None: + self.console = rpc.sessions.session(sessionid) + self.type_ = MsfRpcConsoleType.Shell if isinstance(self.console, ShellSession) else MsfRpcConsoleType.Meterpreter + self.prompt = '>>> ' + self.callback(dict(data='', prompt=self.prompt)) + else: + self.console = rpc.consoles.console() + self.type_ = MsfRpcConsoleType.Console + self.prompt = '' + + self.lock = Lock() + self.running = True + self._poller() + + def _poller(self): + self.lock.acquire() + if not self.running: + return + d = self.console.read() + self.lock.release() + + if self.type_ == MsfRpcConsoleType.Console: + if d['data'] or self.prompt != d['prompt']: + self.prompt = d['prompt'] + if self.callback is not None: + self.callback(d) + else: + print d['data'] + else: + if d: + if self.callback is not None: + self.callback(dict(data=d, prompt=self.prompt)) + else: + print d + Timer(0.5, self._poller).start() + + def execute(self, command): + """ + Execute a command on the console. + + Mandatory Arguments: + - command : the command to execute + """ + if not command.endswith('\n'): + command += '\n' + self.lock.acquire() + self.console.write(command) + self.lock.release() + + def __del__(self): + self.lock.acquire() + if self.type_ == MsfRpcConsoleType.Console: + self.console.destroy() + self.running = False + self.lock.release() diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index c005b5e..245ae86 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from httplib import HTTPConnection, HTTPSConnection +from http.client import HTTPConnection, HTTPSConnection import ssl from numbers import Number @@ -17,1955 +17,1977 @@ __status__ = 'Development' __all__ = [ - 'MsfRpcError', - 'MsfRpcMethod', - 'MsfPlugins', - 'MsfRpcClient', - 'MsfTable', - 'NotesTable', - 'LootsTable', - 'CredsTable', - 'AuthInfoTable', - 'HostsTable', - 'ServicesTable', - 'VulnsTable', - 'EventsTable', - 'ClientsTable', - 'Workspace', - 'MsfManager', - 'WorkspaceManager', - 'DbManager', - 'AuthManager', - 'PluginManager', - 'JobManager', - 'CoreManager', - 'MsfModule', - 'ExploitModule', - 'PostModule', - 'EncoderModule', - 'AuxiliaryModule', - 'PayloadModule', - 'NopModule', - 'ModuleManager', - 'MsfSession', - 'MeterpreterSession', - 'ShellSession', - 'SessionManager', - 'MsfConsole', - 'ConsoleManager', - 'ReportFilter', - 'ReportFilterQuery' + 'MsfRpcError', + 'MsfRpcMethod', + 'MsfPlugins', + 'MsfRpcClient', + 'MsfTable', + 'NotesTable', + 'LootsTable', + 'CredsTable', + 'AuthInfoTable', + 'HostsTable', + 'ServicesTable', + 'VulnsTable', + 'EventsTable', + 'ClientsTable', + 'Workspace', + 'MsfManager', + 'WorkspaceManager', + 'DbManager', + 'AuthManager', + 'PluginManager', + 'JobManager', + 'CoreManager', + 'MsfModule', + 'ExploitModule', + 'PostModule', + 'EncoderModule', + 'AuxiliaryModule', + 'PayloadModule', + 'NopModule', + 'ModuleManager', + 'MsfSession', + 'MeterpreterSession', + 'ShellSession', + 'SessionManager', + 'MsfConsole', + 'ConsoleManager', + 'ReportFilter', + 'ReportFilterQuery' ] class MsfRpcError(Exception): - pass + pass class MsfRpcMethod(object): - AuthLogin = 'auth.login' - AuthLogout = 'auth.logout' - AuthTokenList = 'auth.token_list' - AuthTokenAdd = 'auth.token_add' - AuthTokenGenerate = 'auth.token_generate' - AuthTokenRemove = 'auth.token_remove' - ConsoleCreate = 'console.create' - ConsoleList = 'console.list' - ConsoleDestroy = 'console.destroy' - ConsoleRead = 'console.read' - ConsoleWrite = 'console.write' - ConsoleTabs = 'console.tabs' - ConsoleSessionKill = 'console.session_kill' - ConsoleSessionDetach = 'console.session_detach' - CoreVersion = 'core.version' - CoreStop = 'core.stop' - CoreSetG = 'core.setg' - CoreUnsetG = 'core.unsetg' - CoreSave = 'core.save' - CoreReloadModules = 'core.reload_modules' - CoreModuleStats = 'core.module_stats' - CoreAddModulePath = 'core.add_module_path' - CoreThreadList = 'core.thread_list' - CoreThreadKill = 'core.thread_kill' - DbHosts = 'db.hosts' - DbServices = 'db.services' - DbVulns = 'db.vulns' - DbWorkspaces = 'db.workspaces' - DbCurrentWorkspace = 'db.current_workspace' - DbGetWorkspace = 'db.get_workspace' - DbSetWorkspace = 'db.set_workspace' - DbDelWorkspace = 'db.del_workspace' - DbAddWorkspace = 'db.add_workspace' - DbGetHost = 'db.get_host' - DbReportHost = 'db.report_host' - DbReportService = 'db.report_service' - DbGetService = 'db.get_service' - DbGetNote = 'db.get_note' - DbGetClient = 'db.get_client' - DbReportClient = 'db.report_client' - DbReportNote = 'db.report_note' - DbNotes = 'db.notes' - DbReportAuthInfo = 'db.report_auth_info' - DbGetAuthInfo = 'db.get_auth_info' - DbGetRef = 'db.get_ref' - DbDelVuln = 'db.del_vuln' - DbDelNote = 'db.del_note' - DbDelService = 'db.del_service' - DbDelHost = 'db.del_host' - DbReportVuln = 'db.report_vuln' - DbEvents = 'db.events' - DbReportEvent = 'db.report_event' - DbReportLoot = 'db.report_loot' - DbLoots = 'db.loots' - DbReportCred = 'db.report_cred' - DbCreds = 'db.creds' - DbImportData = 'db.import_data' - DbGetVuln = 'db.get_vuln' - DbClients = 'db.clients' - DbDelClient = 'db.del_client' - DbDriver = 'db.driver' - DbConnect = 'db.connect' - DbStatus = 'db.status' - DbDisconnect = 'db.disconnect' - JobList = 'job.list' - JobStop = 'job.stop' - JobInfo = 'job.info' - ModuleExploits = 'module.exploits' - ModuleAuxiliary = 'module.auxiliary' - ModulePayloads = 'module.payloads' - ModuleEncoders = 'module.encoders' - ModuleNops = 'module.nops' - ModulePost = 'module.post' - ModuleInfo = 'module.info' - ModuleCompatiblePayloads = 'module.compatible_payloads' - ModuleCompatibleSessions = 'module.compatible_sessions' - ModuleTargetCompatiblePayloads = 'module.target_compatible_payloads' - ModuleOptions = 'module.options' - ModuleExecute = 'module.execute' - ModuleEncodeFormats = 'module.encode_formats' - ModuleEncode = 'module.encode' - PluginLoad = 'plugin.load' - PluginUnload = 'plugin.unload' - PluginLoaded = 'plugin.loaded' - SessionList = 'session.list' - SessionStop = 'session.stop' - SessionShellRead = 'session.shell_read' - SessionShellWrite = 'session.shell_write' - SessionShellUpgrade = 'session.shell_upgrade' - SessionMeterpreterRead = 'session.meterpreter_read' - SessionRingRead = 'session.ring_read' - SessionRingPut = 'session.ring_put' - SessionRingLast = 'session.ring_last' - SessionRingClear = 'session.ring_clear' - SessionMeterpreterWrite = 'session.meterpreter_write' - SessionMeterpreterSessionDetach = 'session.meterpreter_session_detach' - SessionMeterpreterSessionKill = 'session.meterpreter_session_kill' - SessionMeterpreterTabs = 'session.meterpreter_tabs' - SessionMeterpreterRunSingle = 'session.meterpreter_run_single' - SessionMeterpreterScript = 'session.meterpreter_script' - SessionMeterpreterDirectorySeparator = 'session.meterpreter_directory_separator' - SessionCompatibleModules = 'session.compatible_modules' + AuthLogin = 'auth.login' + AuthLogout = 'auth.logout' + AuthTokenList = 'auth.token_list' + AuthTokenAdd = 'auth.token_add' + AuthTokenGenerate = 'auth.token_generate' + AuthTokenRemove = 'auth.token_remove' + ConsoleCreate = 'console.create' + ConsoleList = 'console.list' + ConsoleDestroy = 'console.destroy' + ConsoleRead = 'console.read' + ConsoleWrite = 'console.write' + ConsoleTabs = 'console.tabs' + ConsoleSessionKill = 'console.session_kill' + ConsoleSessionDetach = 'console.session_detach' + CoreVersion = 'core.version' + CoreStop = 'core.stop' + CoreSetG = 'core.setg' + CoreUnsetG = 'core.unsetg' + CoreSave = 'core.save' + CoreReloadModules = 'core.reload_modules' + CoreModuleStats = 'core.module_stats' + CoreAddModulePath = 'core.add_module_path' + CoreThreadList = 'core.thread_list' + CoreThreadKill = 'core.thread_kill' + DbHosts = 'db.hosts' + DbServices = 'db.services' + DbVulns = 'db.vulns' + DbWorkspaces = 'db.workspaces' + DbCurrentWorkspace = 'db.current_workspace' + DbGetWorkspace = 'db.get_workspace' + DbSetWorkspace = 'db.set_workspace' + DbDelWorkspace = 'db.del_workspace' + DbAddWorkspace = 'db.add_workspace' + DbGetHost = 'db.get_host' + DbReportHost = 'db.report_host' + DbReportService = 'db.report_service' + DbGetService = 'db.get_service' + DbGetNote = 'db.get_note' + DbGetClient = 'db.get_client' + DbReportClient = 'db.report_client' + DbReportNote = 'db.report_note' + DbNotes = 'db.notes' + DbReportAuthInfo = 'db.report_auth_info' + DbGetAuthInfo = 'db.get_auth_info' + DbGetRef = 'db.get_ref' + DbDelVuln = 'db.del_vuln' + DbDelNote = 'db.del_note' + DbDelService = 'db.del_service' + DbDelHost = 'db.del_host' + DbReportVuln = 'db.report_vuln' + DbEvents = 'db.events' + DbReportEvent = 'db.report_event' + DbReportLoot = 'db.report_loot' + DbLoots = 'db.loots' + DbReportCred = 'db.report_cred' + DbCreds = 'db.creds' + DbImportData = 'db.import_data' + DbGetVuln = 'db.get_vuln' + DbClients = 'db.clients' + DbDelClient = 'db.del_client' + DbDriver = 'db.driver' + DbConnect = 'db.connect' + DbStatus = 'db.status' + DbDisconnect = 'db.disconnect' + JobList = 'job.list' + JobStop = 'job.stop' + JobInfo = 'job.info' + ModuleExploits = 'module.exploits' + ModuleAuxiliary = 'module.auxiliary' + ModulePayloads = 'module.payloads' + ModuleEncoders = 'module.encoders' + ModuleNops = 'module.nops' + ModulePost = 'module.post' + ModuleInfo = 'module.info' + ModuleCompatiblePayloads = 'module.compatible_payloads' + ModuleCompatibleSessions = 'module.compatible_sessions' + ModuleTargetCompatiblePayloads = 'module.target_compatible_payloads' + ModuleOptions = 'module.options' + ModuleExecute = 'module.execute' + ModuleEncodeFormats = 'module.encode_formats' + ModuleEncode = 'module.encode' + PluginLoad = 'plugin.load' + PluginUnload = 'plugin.unload' + PluginLoaded = 'plugin.loaded' + SessionList = 'session.list' + SessionStop = 'session.stop' + SessionShellRead = 'session.shell_read' + SessionShellWrite = 'session.shell_write' + SessionShellUpgrade = 'session.shell_upgrade' + SessionMeterpreterRead = 'session.meterpreter_read' + SessionRingRead = 'session.ring_read' + SessionRingPut = 'session.ring_put' + SessionRingLast = 'session.ring_last' + SessionRingClear = 'session.ring_clear' + SessionMeterpreterWrite = 'session.meterpreter_write' + SessionMeterpreterSessionDetach = 'session.meterpreter_session_detach' + SessionMeterpreterSessionKill = 'session.meterpreter_session_kill' + SessionMeterpreterTabs = 'session.meterpreter_tabs' + SessionMeterpreterRunSingle = 'session.meterpreter_run_single' + SessionMeterpreterScript = 'session.meterpreter_script' + SessionMeterpreterDirectorySeparator = 'session.meterpreter_directory_separator' + SessionCompatibleModules = 'session.compatible_modules' class MsfPlugins(object): - IpsFilter = "ips_filter" - SocketLogger = "socket_logger" - DbTracker = "db_tracker" - Sounds = "sounds" - AutoAddRoute = "auto_add_route" - DbCredCollect = "db_credcollect" + IpsFilter = "ips_filter" + SocketLogger = "socket_logger" + DbTracker = "db_tracker" + Sounds = "sounds" + AutoAddRoute = "auto_add_route" + DbCredCollect = "db_credcollect" class MsfRpcClient(object): - _headers = { - 'Content-Type' : 'binary/message-pack' - } - - def __init__(self, password, **kwargs): - """ - Connects and authenticates to a Metasploit RPC daemon. - - Mandatory Arguments: - - password : the password used to authenticate to msfrpcd - - Optional Keyword Arguments: - - username : the username used to authenticate to msfrpcd (default: msf) - - uri : the msfrpcd URI (default: /api/) - - port : the remote msfrpcd port to connect to (default: 55553) - - server : the remote server IP address hosting msfrpcd (default: localhost) - - ssl : if true uses SSL else regular HTTP (default: SSL enabled) - - verify : if true, verify SSL cert when using SSL (default: False) - """ - self.uri = kwargs.get('uri', '/api/') - self.port = kwargs.get('port', 55553) - self.server = kwargs.get('server', '127.0.0.1') - self.ssl = kwargs.get('ssl', True) - self.verify_ssl = kwargs.get('verify', False) - self.sessionid = kwargs.get('token') - if self.ssl: - if self.verify_ssl: - self.client = HTTPSConnection(self.server, self.port) - else: - self.client = HTTPSConnection(self.server, self.port, context=ssl._create_unverified_context()) - else: - self.client = HTTPConnection(self.server, self.port) - self.login(kwargs.get('username', 'msf'), password) - - def call(self, method, *args): - """ - Builds an RPC request and retrieves the result. - - Mandatory Arguments: - - method : the RPC call method name (e.g. db.clients) - - Optional Arguments: - - *args : the RPC method's parameters if necessary - - Returns : RPC call result - """ - l = [ method ] - l.extend(args) - if method == MsfRpcMethod.AuthLogin: - self.client.request('POST', self.uri, packb(l), self._headers) - r = self.client.getresponse() - if r.status == 200: - return unpackb(r.read()) - raise MsfRpcError('An unknown error has occurred while logging in.') - elif self.authenticated: - l.insert(1, self.sessionid) - self.client.request('POST', self.uri, packb(l), self._headers) - r = self.client.getresponse() - if r.status == 200: - result = unpackb(r.read()) - if 'error' in result: - raise MsfRpcError(result['error_message']) - return result - raise MsfRpcError('An unknown error has occurred while performing the RPC call.') - raise MsfRpcError('You cannot perform this call because you are not authenticated.') - - @property - def core(self): - """ - The msf RPC core manager. - """ - return CoreManager(self) - - @property - def modules(self): - """ - The msf RPC modules RPC manager. - """ - return ModuleManager(self) - - @property - def sessions(self): - """ - The msf RPC sessions (meterpreter & shell) manager. - """ - return SessionManager(self) - - @property - def jobs(self): - """ - The msf RPC jobs manager. - """ - return JobManager(self) - - @property - def consoles(self): - """ - The msf RPC consoles manager - """ - return ConsoleManager(self) - - @property - def authenticated(self): - """ - Whether or not this client is authenticated. - """ - return self.sessionid is not None - - @property - def plugins(self): - """ - The msf RPC plugins manager. - """ - return PluginManager(self) - - @property - def db(self): - """ - The msf RPC database manager. - """ - return DbManager(self) - - @property - def auth(self): - """ - The msf authentication manager. - """ - return AuthManager(self) - - def login(self, username, password): - """ - Authenticates and reauthenticates the user to msfrpcd. - """ - if self.sessionid is None: - r = self.call(MsfRpcMethod.AuthLogin, username, password) - try: - if r['result'] == 'success': - self.sessionid = r['token'] - except KeyError: - raise MsfRpcError('Login failed.') - else: - try: - r = self.call(MsfRpcMethod.DbStatus) - except MsfRpcError: - raise MsfRpcError('Login failed.') - - def logout(self): - """ - Logs the current user out. Note: do not call directly. - """ - self.call(MsfRpcMethod.AuthLogout, self.sessionid) + _headers = { + 'Content-Type' : 'binary/message-pack' + } + + def __init__(self, password, **kwargs): + """ + Connects and authenticates to a Metasploit RPC daemon. + + Mandatory Arguments: + - password : the password used to authenticate to msfrpcd + + Optional Keyword Arguments: + - username : the username used to authenticate to msfrpcd (default: msf) + - uri : the msfrpcd URI (default: /api/) + - port : the remote msfrpcd port to connect to (default: 55553) + - server : the remote server IP address hosting msfrpcd (default: localhost) + - ssl : if true uses SSL else regular HTTP (default: SSL enabled) + - verify : if true, verify SSL cert when using SSL (default: False) + """ + self.uri = kwargs.get('uri', '/api/') + self.port = kwargs.get('port', 55553) + self.server = kwargs.get('server', '127.0.0.1') + self.ssl = kwargs.get('ssl', True) + self.verify_ssl = kwargs.get('verify', False) + self.sessionid = kwargs.get('token') + if self.ssl: + if self.verify_ssl: + self.client = HTTPSConnection(self.server, self.port) + else: + self.client = HTTPSConnection(self.server, self.port, context=ssl._create_unverified_context()) + else: + self.client = HTTPConnection(self.server, self.port) + self.login(kwargs.get('username', 'msf'), password) + + def unpackb_wrapper(self, data): + return self.unpackb_wrapf(data) + + def unpackb_wrapf(self, item): + if type(item) == bytes: + return item.decode('ascii') + if type(item) == list: + nl = [] + for j in item: + nl.append(self.unpackb_wrapf(j)) + return nl + if type(item) == dict: + nd = {} + for j in item: + k = j + if type(k) == bytes: + k = j.decode('ascii') + nd[k] = self.unpackb_wrapf(item[j]) + return nd + return item + + + def call(self, method, *args): + """ + Builds an RPC request and retrieves the result. + + Mandatory Arguments: + - method : the RPC call method name (e.g. db.clients) + + Optional Arguments: + - *args : the RPC method's parameters if necessary + + Returns : RPC call result + """ + l = [ method ] + l.extend(args) + if method == MsfRpcMethod.AuthLogin: + self.client.request('POST', self.uri, packb(l), self._headers) + r = self.client.getresponse() + if r.status == 200: + return self.unpackb_wrapper(unpackb(r.read())) + raise MsfRpcError('An unknown error has occurred while logging in.') + elif self.authenticated: + l.insert(1, self.sessionid) + self.client.request('POST', self.uri, packb(l), self._headers) + r = self.client.getresponse() + if r.status == 200: + result = self.unpackb_wrapper(unpackb(r.read())) + if 'error' in result: + raise MsfRpcError(result['error_message']) + return result + raise MsfRpcError('An unknown error has occurred while performing the RPC call.') + raise MsfRpcError('You cannot perform this call because you are not authenticated.') + + @property + def core(self): + """ + The msf RPC core manager. + """ + return CoreManager(self) + + @property + def modules(self): + """ + The msf RPC modules RPC manager. + """ + return ModuleManager(self) + + @property + def sessions(self): + """ + The msf RPC sessions (meterpreter & shell) manager. + """ + return SessionManager(self) + + @property + def jobs(self): + """ + The msf RPC jobs manager. + """ + return JobManager(self) + + @property + def consoles(self): + """ + The msf RPC consoles manager + """ + return ConsoleManager(self) + + @property + def authenticated(self): + """ + Whether or not this client is authenticated. + """ + return self.sessionid is not None + + @property + def plugins(self): + """ + The msf RPC plugins manager. + """ + return PluginManager(self) + + @property + def db(self): + """ + The msf RPC database manager. + """ + return DbManager(self) + + @property + def auth(self): + """ + The msf authentication manager. + """ + return AuthManager(self) + + def login(self, username, password): + """ + Authenticates and reauthenticates the user to msfrpcd. + """ + if self.sessionid is None: + r = self.call(MsfRpcMethod.AuthLogin, username, password);print(r) + try: + if r['result'] == 'success': + self.sessionid = r['token'] + except KeyError: + raise MsfRpcError('Login failed.') + else: + try: + r = self.call(MsfRpcMethod.DbStatus) + except MsfRpcError: + raise MsfRpcError('Login failed.') + + def logout(self): + """ + Logs the current user out. Note: do not call directly. + """ + self.call(MsfRpcMethod.AuthLogout, self.sessionid) class MsfTable(object): - def __init__(self, rpc, wname): - self.rpc = rpc - self.name = wname + def __init__(self, rpc, wname): + self.rpc = rpc + self.name = wname - def dbreport(self, atype, attrs): - attrs.update({ 'workspace' : self.name }) - return self.rpc.call('db.report_%s' % atype, attrs) + def dbreport(self, atype, attrs): + attrs.update({ 'workspace' : self.name }) + return self.rpc.call('db.report_%s' % atype, attrs) - def dbdel(self, atype, attrs): - attrs.update({ 'workspace' : self.name }) - return self.rpc.call('db.del_%s' % atype, attrs) + def dbdel(self, atype, attrs): + attrs.update({ 'workspace' : self.name }) + return self.rpc.call('db.del_%s' % atype, attrs) - def dbget(self, atype, attrs): - attrs.update({ 'workspace' : self.name }) - return self.rpc.call('db.get_%s' % atype, attrs)[atype] + def dbget(self, atype, attrs): + attrs.update({ 'workspace' : self.name }) + return self.rpc.call('db.get_%s' % atype, attrs)[atype] - def records(self, atypes, **kwargs): - kwargs.update({'workspace' : self.name}) - return self.rpc.call('db.%s' % atypes, kwargs)[atypes] + def records(self, atypes, **kwargs): + kwargs.update({'workspace' : self.name}) + return self.rpc.call('db.%s' % atypes, kwargs)[atypes] - @property - def list(self): - raise NotImplementedError + @property + def list(self): + raise NotImplementedError - def report(self, *args, **kwargs): - raise NotImplementedError + def report(self, *args, **kwargs): + raise NotImplementedError - def delete(self, *args, **kwargs): - raise NotImplementedError + def delete(self, *args, **kwargs): + raise NotImplementedError - def find(self, **kwargs): - raise NotImplementedError + def find(self, **kwargs): + raise NotImplementedError - update = report + update = report class NotesTable(MsfTable): - @property - def list(self): - return super(NotesTable, self).records('notes') - - def find(self, **kwargs): - """ - Find notes based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - addresses : a list of addresses to search for. - - names : comma separated string of service names. - - ntype : the note type. - - ports : the port associated with the note. - - proto : the protocol associated with the note. - """ - if 'ports' in kwargs: - kwargs['port'] = True - return super(NotesTable, self).records('notes', **kwargs) - - def report(self, type, data, **kwargs): - """ - Report a Note to the database. Notes can be tied to a Workspace, Host, or Service. - - Mandatory Arguments: - - type : The type of note, e.g. 'smb_peer_os'. - - data : whatever it is you're making a note of. - - Optional Keyword Arguments: - - host : an IP address or a Host object to associate with this Note. - - service : a dict containing 'host', 'port', 'proto' and optionally 'name' keys. - - port : along with 'host' and 'proto', a service to associate with this Note. - - proto : along with 'host' and 'port', a service to associate with this Note. - - update : what to do in case a similar Note exists, see below. - - The 'update' option can have the following values: - - unique : allow only a single Note per host/type pair. - - unique_data : like 'unique', but also compare 'data'. - - insert : always insert a new Note even if one with identical values exists. - - If the provided 'host' is an IP address and does not exist in the database, - it will be created. If 'host' and 'service' are all omitted, the new Note - will be associated with the current 'workspace'. - """ - kwargs.update({ 'data' : data, 'type' : type }) - kwargs.update(kwargs.pop('service', {})) - self.dbreport('note', kwargs) - - def delete(self, **kwargs): - """ - Delete one or more notes based on a search criteria. - - Optional Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - - port : the port associated with a Note. - - proto : the protocol associated with a Note. - - ntype : the note type, e.g. 'smb_peer_os'. - """ - self.dbdel('note', kwargs) - - def get(self, **kwargs): - """ - Get a Note from the database based on the specifications of one or more keyword arguments. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - address : the address associated with a Note, not required if 'host' or 'addr' is specified. - - addr : same as 'address', not required if 'host' or 'address' is specified. - - Optional Keyword Arguments: - - proto : the protocol associated with the Note. - - port : the port associated with the Note. - - ntype : the type of Note. - """ - if not any([i in kwargs for i in ('host', 'address', 'addr')]): - raise TypeError('Expected a host, address, or addr.') - return self.dbget('note', kwargs) - - update = report + @property + def list(self): + return super(NotesTable, self).records('notes') + + def find(self, **kwargs): + """ + Find notes based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - addresses : a list of addresses to search for. + - names : comma separated string of service names. + - ntype : the note type. + - ports : the port associated with the note. + - proto : the protocol associated with the note. + """ + if 'ports' in kwargs: + kwargs['port'] = True + return super(NotesTable, self).records('notes', **kwargs) + + def report(self, type, data, **kwargs): + """ + Report a Note to the database. Notes can be tied to a Workspace, Host, or Service. + + Mandatory Arguments: + - type : The type of note, e.g. 'smb_peer_os'. + - data : whatever it is you're making a note of. + + Optional Keyword Arguments: + - host : an IP address or a Host object to associate with this Note. + - service : a dict containing 'host', 'port', 'proto' and optionally 'name' keys. + - port : along with 'host' and 'proto', a service to associate with this Note. + - proto : along with 'host' and 'port', a service to associate with this Note. + - update : what to do in case a similar Note exists, see below. + + The 'update' option can have the following values: + - unique : allow only a single Note per host/type pair. + - unique_data : like 'unique', but also compare 'data'. + - insert : always insert a new Note even if one with identical values exists. + + If the provided 'host' is an IP address and does not exist in the database, + it will be created. If 'host' and 'service' are all omitted, the new Note + will be associated with the current 'workspace'. + """ + kwargs.update({ 'data' : data, 'type' : type }) + kwargs.update(kwargs.pop('service', {})) + self.dbreport('note', kwargs) + + def delete(self, **kwargs): + """ + Delete one or more notes based on a search criteria. + + Optional Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + - port : the port associated with a Note. + - proto : the protocol associated with a Note. + - ntype : the note type, e.g. 'smb_peer_os'. + """ + self.dbdel('note', kwargs) + + def get(self, **kwargs): + """ + Get a Note from the database based on the specifications of one or more keyword arguments. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - address : the address associated with a Note, not required if 'host' or 'addr' is specified. + - addr : same as 'address', not required if 'host' or 'address' is specified. + + Optional Keyword Arguments: + - proto : the protocol associated with the Note. + - port : the port associated with the Note. + - ntype : the type of Note. + """ + if not any([i in kwargs for i in ('host', 'address', 'addr')]): + raise TypeError('Expected a host, address, or addr.') + return self.dbget('note', kwargs) + + update = report class LootsTable(MsfTable): - @property - def list(self): - return super(LootsTable, self).records('loots') + @property + def list(self): + return super(LootsTable, self).records('loots') - def find(self, **kwargs): - """ - Find loot based on search criteria. + def find(self, **kwargs): + """ + Find loot based on search criteria. - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - """ - return super(LootsTable, self).records('loots', **kwargs) + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + """ + return super(LootsTable, self).records('loots', **kwargs) - def report(self, path, type, **kwargs): - """ - Report Loot to the database + def report(self, path, type, **kwargs): + """ + Report Loot to the database - Mandatory Arguments: - - path : the filesystem path to the Loot - - type : the type of Loot - - ltype : the same as 'type', not required if 'type' is specified. + Mandatory Arguments: + - path : the filesystem path to the Loot + - type : the type of Loot + - ltype : the same as 'type', not required if 'type' is specified. - Optional Keyword Arguments: - - host : an IP address or a Host object to associate with this Note - - ctype : the content type of the loot, e.g. 'text/plain' - - content_type : same as 'ctype'. - - service : a service to associate Loot with. - - name : a name to associate with this Loot. - - info : additional information about this Loot. - - data : the data within the Loot. - """ - kwargs.update({ 'path' : path, 'type' : type }) - self.dbreport('loot', kwargs) + Optional Keyword Arguments: + - host : an IP address or a Host object to associate with this Note + - ctype : the content type of the loot, e.g. 'text/plain' + - content_type : same as 'ctype'. + - service : a service to associate Loot with. + - name : a name to associate with this Loot. + - info : additional information about this Loot. + - data : the data within the Loot. + """ + kwargs.update({ 'path' : path, 'type' : type }) + self.dbreport('loot', kwargs) - update = report + update = report class CredsTable(MsfTable): - @property - def list(self): - return super(CredsTable, self).records('creds') + @property + def list(self): + return super(CredsTable, self).records('creds') - def find(self, **kwargs): - """ - Find creds based on search criteria. + def find(self, **kwargs): + """ + Find creds based on search criteria. - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - """ - return super(CredsTable, self).records('creds', **kwargs) + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + """ + return super(CredsTable, self).records('creds', **kwargs) - def report(self, host, port, **kwargs): - """ - Store a set of credentials in the database. + def report(self, host, port, **kwargs): + """ + Store a set of credentials in the database. - Mandatory Arguments: - - host : an IP address or Host object reference - - port : a port number + Mandatory Arguments: + - host : an IP address or Host object reference + - port : a port number - Optional Keyword Arguments: - - user : the username. - - password : the password, or path to ssh_key. - - ptype : the type of password (password(ish), hash, or ssh_key). - - proto : a transport name for the port. - - sname : service name. - - active : by default, a cred is active, unless explicitly false. - - proof : data used to prove the account is actually active. + Optional Keyword Arguments: + - user : the username. + - password : the password, or path to ssh_key. + - ptype : the type of password (password(ish), hash, or ssh_key). + - proto : a transport name for the port. + - sname : service name. + - active : by default, a cred is active, unless explicitly false. + - proof : data used to prove the account is actually active. - Sources: Credentials can be sourced from another credential, or from - a vulnerability. For example, if an exploit was used to dump the - smb_hashes, and this credential comes from there, the source_id would - be the Vuln id (as reported by report_vuln) and the type would be "Vuln". + Sources: Credentials can be sourced from another credential, or from + a vulnerability. For example, if an exploit was used to dump the + smb_hashes, and this credential comes from there, the source_id would + be the Vuln id (as reported by report_vuln) and the type would be "Vuln". - - source_id : The Vuln or Cred id of the source of this cred. - - source_type : Either Vuln or Cred. - """ - kwargs.update({'host' : host, 'port' : port}) - kwargs['pass'] = kwargs.get('password') - self.dbreport('cred', kwargs) + - source_id : The Vuln or Cred id of the source of this cred. + - source_type : Either Vuln or Cred. + """ + kwargs.update({'host' : host, 'port' : port}) + kwargs['pass'] = kwargs.get('password') + self.dbreport('cred', kwargs) - update = report + update = report class AuthInfoTable(MsfTable): - def report(self, host, port, **kwargs): - """ - Store a set of credentials in the database. + def report(self, host, port, **kwargs): + """ + Store a set of credentials in the database. - Mandatory Arguments: - - host : an IP address or Host object reference - - port : a port number + Mandatory Arguments: + - host : an IP address or Host object reference + - port : a port number - Optional Keyword Arguments: - - user : the username. - - pass : the password, or path to ssh_key. - - ptype : the type of password (password(ish), hash, or ssh_key). - - proto : a transport name for the port. - - sname : service name. - - active : by default, a cred is active, unless explicitly false. - - proof : data used to prove the account is actually active. + Optional Keyword Arguments: + - user : the username. + - pass : the password, or path to ssh_key. + - ptype : the type of password (password(ish), hash, or ssh_key). + - proto : a transport name for the port. + - sname : service name. + - active : by default, a cred is active, unless explicitly false. + - proof : data used to prove the account is actually active. - Sources: Credentials can be sourced from another credential, or from - a vulnerability. For example, if an exploit was used to dump the - smb_hashes, and this credential comes from there, the source_id would - be the Vuln id (as reported by report_vuln) and the type would be "Vuln". + Sources: Credentials can be sourced from another credential, or from + a vulnerability. For example, if an exploit was used to dump the + smb_hashes, and this credential comes from there, the source_id would + be the Vuln id (as reported by report_vuln) and the type would be "Vuln". - - source_id : The Vuln or Cred id of the source of this cred. - - source_type : Either Vuln or Cred. - """ - kwargs.update({'host' : host, 'port' : port}) - self.dbreport('auth_info', kwargs) + - source_id : The Vuln or Cred id of the source of this cred. + - source_type : Either Vuln or Cred. + """ + kwargs.update({'host' : host, 'port' : port}) + self.dbreport('auth_info', kwargs) - update = report + update = report class HostsTable(MsfTable): - @property - def list(self): - return super(HostsTable, self).records('hosts') - - def find(self, **kwargs): - """ - Find hosts based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - only_up : find only hosts that are alive. - - addresses : find hosts based on a list of addresses. - """ - return super(HostsTable, self).records('hosts', **kwargs) - - def report(self, host, **kwargs): - """ - Store a host in the database. - - Mandatory Keyword Arguments: - - host : an IP address or Host object reference. - - Optional Keyword Arguments: - - state : a host state. - - os_name : an operating system. - - os_flavor : something like 'XP or 'Gentoo'. - - os_sp : something like 'SP2'. - - os_lang : something like 'English', 'French', or 'en-US'. - - arch : an architecture. - - mac : the host's MAC address. - - scope : interface identifier for link-local IPv6. - - virtual_host : the name of the VM host software, e.g. 'VMWare', 'QEMU', 'Xen', etc. - """ - kwargs.update({'host' : host}) - self.dbreport('host', kwargs) - - def delete(self, **kwargs): - """ - Deletes a host and associated data matching this address/comm. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): - raise TypeError('Expected host, address, or addresses.') - self.dbdel('host', kwargs) - - def get(self, **kwargs): - """ - Get a host in the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - address : the address associated with a Note, not required if 'host' or 'addr' is specified. - - addr : same as 'address', not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('addr', 'address', 'host')]): - raise TypeError('Expected addr, address, or host.') - return self.dbget('host', kwargs) - - update = report + @property + def list(self): + return super(HostsTable, self).records('hosts') + + def find(self, **kwargs): + """ + Find hosts based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - only_up : find only hosts that are alive. + - addresses : find hosts based on a list of addresses. + """ + return super(HostsTable, self).records('hosts', **kwargs) + + def report(self, host, **kwargs): + """ + Store a host in the database. + + Mandatory Keyword Arguments: + - host : an IP address or Host object reference. + + Optional Keyword Arguments: + - state : a host state. + - os_name : an operating system. + - os_flavor : something like 'XP or 'Gentoo'. + - os_sp : something like 'SP2'. + - os_lang : something like 'English', 'French', or 'en-US'. + - arch : an architecture. + - mac : the host's MAC address. + - scope : interface identifier for link-local IPv6. + - virtual_host : the name of the VM host software, e.g. 'VMWare', 'QEMU', 'Xen', etc. + """ + kwargs.update({'host' : host}) + self.dbreport('host', kwargs) + + def delete(self, **kwargs): + """ + Deletes a host and associated data matching this address/comm. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): + raise TypeError('Expected host, address, or addresses.') + self.dbdel('host', kwargs) + + def get(self, **kwargs): + """ + Get a host in the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - address : the address associated with a Note, not required if 'host' or 'addr' is specified. + - addr : same as 'address', not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('addr', 'address', 'host')]): + raise TypeError('Expected addr, address, or host.') + return self.dbget('host', kwargs) + + update = report class ServicesTable(MsfTable): - @property - def list(self): - return super(ServicesTable, self).records('services') - - def find(self, **kwargs): - """ - Find hosts based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - only_up : find only hosts that are alive. - - addresses : find hosts based on a list of addresses. - - proto : the protocol of the service. - - ports : a comma separated string of ports. - - names : a comma separated string of service names. - """ - return super(ServicesTable, self).records('services', **kwargs) - - def report(self, host, port, proto, **kwargs): - """ - Record a service in the database. - - Mandatory Arguments: - - host : the host where this service is running. - - port : the port where this service listens. - - proto : the transport layer protocol (e.g. tcp, udp). - - Optional Keyword Arguments: - - name : the application layer protocol (e.g. ssh, mssql, smb) - - sname : an alias for the above - """ - kwargs.update({'host' : host, 'port' : port, 'proto' : proto}) - self.dbreport('service', kwargs) - - def delete(self, **kwargs): - """ - Deletes a port and associated vulns matching this port. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - - or - - - port : used along with 'proto', specifies a service. - - proto : used along with 'port', specifies a service. - """ - if not any([i in kwargs for i in ('host', 'address', 'addresses')]) and \ - not all([i in kwargs for i in ('proto', 'port')]): - raise TypeError('Expected host or port/proto pair.') - self.dbdel('service', kwargs) - - def get(self, **kwargs): - """ - Get a service record from the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - - or - - - port : used along with 'proto', specifies a service. - - proto : used along with 'port', specifies a service. - - Optional Keyword Arguments: - - up : specifies whether or not the service is alive. - - names : a comma separated string of service names. - """ - if not any([i in kwargs for i in ('host', 'addr', 'address')]) and \ - not all([i in kwargs for i in ('proto', 'port')]): - raise TypeError('Expected host or port/proto pair.') - return self.dbget('service', kwargs) - - update = report + @property + def list(self): + return super(ServicesTable, self).records('services') + + def find(self, **kwargs): + """ + Find hosts based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - only_up : find only hosts that are alive. + - addresses : find hosts based on a list of addresses. + - proto : the protocol of the service. + - ports : a comma separated string of ports. + - names : a comma separated string of service names. + """ + return super(ServicesTable, self).records('services', **kwargs) + + def report(self, host, port, proto, **kwargs): + """ + Record a service in the database. + + Mandatory Arguments: + - host : the host where this service is running. + - port : the port where this service listens. + - proto : the transport layer protocol (e.g. tcp, udp). + + Optional Keyword Arguments: + - name : the application layer protocol (e.g. ssh, mssql, smb) + - sname : an alias for the above + """ + kwargs.update({'host' : host, 'port' : port, 'proto' : proto}) + self.dbreport('service', kwargs) + + def delete(self, **kwargs): + """ + Deletes a port and associated vulns matching this port. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + + or + + - port : used along with 'proto', specifies a service. + - proto : used along with 'port', specifies a service. + """ + if not any([i in kwargs for i in ('host', 'address', 'addresses')]) and \ + not all([i in kwargs for i in ('proto', 'port')]): + raise TypeError('Expected host or port/proto pair.') + self.dbdel('service', kwargs) + + def get(self, **kwargs): + """ + Get a service record from the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + + or + + - port : used along with 'proto', specifies a service. + - proto : used along with 'port', specifies a service. + + Optional Keyword Arguments: + - up : specifies whether or not the service is alive. + - names : a comma separated string of service names. + """ + if not any([i in kwargs for i in ('host', 'addr', 'address')]) and \ + not all([i in kwargs for i in ('proto', 'port')]): + raise TypeError('Expected host or port/proto pair.') + return self.dbget('service', kwargs) + + update = report class VulnsTable(MsfTable): - @property - def list(self): - return super(VulnsTable, self).records('vulns') - - def find(self, **kwargs): - """ - Find vulns based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - addresses : find hosts based on a list of addresses. - - proto : the protocol of the service. - - ports : a comma separated string of ports. - - names : a comma separated string of service names. - """ - return super(VulnsTable, self).records('vulns', **kwargs) - - def report(self, host, name, **kwargs): - """ - Record a Vuln in the database. - - Mandatory Arguments: - - host : the host where this vulnerability resides. - - name : the scanner-specific id of the vuln (e.g. NEXPOSE-cifs-acct-password-never-expires). - - Optional Keyword Arguments: - - info : a human readable description of the vuln, free-form text. - - refs : an array of Ref objects or string names of references. - """ - kwargs.update({'host' : host, 'name' : name}) - self.dbreport('vuln', kwargs) - - def delete(self, **kwargs): - """ - Deletes a vuln and associated data matching this address/comm. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): - raise TypeError('Expected host, address, or addresses.') - self.dbdel('vuln', kwargs) - - def get(self, **kwargs): - """ - Get a vuln in the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - address : the address associated with a Note, not required if 'host' or 'addr' is specified. - - addr : same as 'address', not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('addr', 'address', 'host')]): - raise TypeError('Expected addr, address, or host.') - return self.dbreport('vuln', kwargs) - - update = report + @property + def list(self): + return super(VulnsTable, self).records('vulns') + + def find(self, **kwargs): + """ + Find vulns based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - addresses : find hosts based on a list of addresses. + - proto : the protocol of the service. + - ports : a comma separated string of ports. + - names : a comma separated string of service names. + """ + return super(VulnsTable, self).records('vulns', **kwargs) + + def report(self, host, name, **kwargs): + """ + Record a Vuln in the database. + + Mandatory Arguments: + - host : the host where this vulnerability resides. + - name : the scanner-specific id of the vuln (e.g. NEXPOSE-cifs-acct-password-never-expires). + + Optional Keyword Arguments: + - info : a human readable description of the vuln, free-form text. + - refs : an array of Ref objects or string names of references. + """ + kwargs.update({'host' : host, 'name' : name}) + self.dbreport('vuln', kwargs) + + def delete(self, **kwargs): + """ + Deletes a vuln and associated data matching this address/comm. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): + raise TypeError('Expected host, address, or addresses.') + self.dbdel('vuln', kwargs) + + def get(self, **kwargs): + """ + Get a vuln in the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - address : the address associated with a Note, not required if 'host' or 'addr' is specified. + - addr : same as 'address', not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('addr', 'address', 'host')]): + raise TypeError('Expected addr, address, or host.') + return self.dbreport('vuln', kwargs) + + update = report class EventsTable(MsfTable): - @property - def list(self): - return super(EventsTable, self).records('events') + @property + def list(self): + return super(EventsTable, self).records('events') - def find(self, **kwargs): - """ - Find events based on search criteria. + def find(self, **kwargs): + """ + Find events based on search criteria. - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - """ - return super(EventsTable, self).records('events', **kwargs) + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + """ + return super(EventsTable, self).records('events', **kwargs) - def report(self, **kwargs): - """ - Record a Vuln in the database. + def report(self, **kwargs): + """ + Record a Vuln in the database. - Mandatory Arguments: - - username : user that invoked the event. - - host : host that invoked the event. - """ - if not any([i in kwargs for i in ('username', 'host')]): - raise TypeError('Expected either username or host') - self.dbreport('vuln', kwargs) + Mandatory Arguments: + - username : user that invoked the event. + - host : host that invoked the event. + """ + if not any([i in kwargs for i in ('username', 'host')]): + raise TypeError('Expected either username or host') + self.dbreport('vuln', kwargs) - update = report + update = report class ClientsTable(MsfTable): - @property - def list(self): - return super(ClientsTable, self).records('clients') - - def find(self, **kwargs): - """ - Find clients based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - ua_name : a user-agent string. - - ua_ver : the user-agent version. - - addresses : a list of IP addresses. - """ - return super(ClientsTable, self).records('clients', **kwargs) - - def report(self, ua_string, host, **kwargs): - """ - Report a client running on a host. - - Mandatory Arguments: - - ua_string : the value of the User-Agent header - - host : the host where this client connected from, can be an ip address or a Host object - - Optional Keyword Arguments - - ua_name : one of the user agent name constants - - ua_ver : detected version of the given client - - campaign : an id or Campaign object - - Returns a Client. - """ - kwargs.update({'host' : host, 'ua_string' : ua_string}) - self.dbreport('client', kwargs) - - def delete(self, **kwargs): - """ - Deletes a client and associated data matching this address/comm. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - """ - self.dbdel('client', kwargs) - - def get(self, **kwargs): - """ - Get a client in the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - ua_string : the value of the User-Agent header - """ - if not any([ i in kwargs for i in ('host', 'ua_string')]): - raise TypeError('Expected host or ua_string.') - return self.dbreport('client', kwargs) - - update = report + @property + def list(self): + return super(ClientsTable, self).records('clients') + + def find(self, **kwargs): + """ + Find clients based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - ua_name : a user-agent string. + - ua_ver : the user-agent version. + - addresses : a list of IP addresses. + """ + return super(ClientsTable, self).records('clients', **kwargs) + + def report(self, ua_string, host, **kwargs): + """ + Report a client running on a host. + + Mandatory Arguments: + - ua_string : the value of the User-Agent header + - host : the host where this client connected from, can be an ip address or a Host object + + Optional Keyword Arguments + - ua_name : one of the user agent name constants + - ua_ver : detected version of the given client + - campaign : an id or Campaign object + + Returns a Client. + """ + kwargs.update({'host' : host, 'ua_string' : ua_string}) + self.dbreport('client', kwargs) + + def delete(self, **kwargs): + """ + Deletes a client and associated data matching this address/comm. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + """ + self.dbdel('client', kwargs) + + def get(self, **kwargs): + """ + Get a client in the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - ua_string : the value of the User-Agent header + """ + if not any([ i in kwargs for i in ('host', 'ua_string')]): + raise TypeError('Expected host or ua_string.') + return self.dbreport('client', kwargs) + + update = report class Workspace(object): - def __init__(self, rpc, name): - """ - Initializes a workspace object. - - Mandatory Arguments: - - rpc : the msfrpc client object - - name : the name of the workspace - """ - self.rpc = rpc - self.name = name - - @property - def current(self): - """ - The name of the current workspace. - """ - return self.name - - @current.setter - def current(self, name): - self.name = name - - @property - def notes(self): - """ - Returns the notes table for the current workspace. - """ - return NotesTable(self.rpc, self.name) - - @property - def hosts(self): - """ - Returns the hosts table for the current workspace. - """ - return HostsTable(self.rpc, self.name) - - @property - def services(self): - """ - Returns the services table for the current workspace. - """ - return ServicesTable(self.rpc, self.name) - - @property - def vulns(self): - """ - Returns the vulns table for the current workspace. - """ - return VulnsTable(self.rpc, self.name) - - @property - def events(self): - """ - Returns the events table for the current workspace. - """ - return EventsTable(self.rpc, self.name) - - @property - def loots(self): - """ - Returns the loots table for the current workspace. - """ - return LootsTable(self.rpc, self.name) - - @property - def creds(self): - """ - Returns the creds table for the current workspace. - """ - return CredsTable(self.rpc, self.name) - - @property - def clients(self): - """ - Returns the clients table for the current workspace. - """ - return ClientsTable(self.rpc, self.name) - - def delete(self): - """ - Delete the current workspace. - """ - self.rpc.call(MsfRpcMethod.DbDelWorkspace, {'workspace' : self.name}) - - def importdata(self, data): - self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : data}) - - def importfile(self, fname): - r = file(fname, mode='rb') - self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : r.read()}) - r.close() + def __init__(self, rpc, name): + """ + Initializes a workspace object. + + Mandatory Arguments: + - rpc : the msfrpc client object + - name : the name of the workspace + """ + self.rpc = rpc + self.name = name + + @property + def current(self): + """ + The name of the current workspace. + """ + return self.name + + @current.setter + def current(self, name): + self.name = name + + @property + def notes(self): + """ + Returns the notes table for the current workspace. + """ + return NotesTable(self.rpc, self.name) + + @property + def hosts(self): + """ + Returns the hosts table for the current workspace. + """ + return HostsTable(self.rpc, self.name) + + @property + def services(self): + """ + Returns the services table for the current workspace. + """ + return ServicesTable(self.rpc, self.name) + + @property + def vulns(self): + """ + Returns the vulns table for the current workspace. + """ + return VulnsTable(self.rpc, self.name) + + @property + def events(self): + """ + Returns the events table for the current workspace. + """ + return EventsTable(self.rpc, self.name) + + @property + def loots(self): + """ + Returns the loots table for the current workspace. + """ + return LootsTable(self.rpc, self.name) + + @property + def creds(self): + """ + Returns the creds table for the current workspace. + """ + return CredsTable(self.rpc, self.name) + + @property + def clients(self): + """ + Returns the clients table for the current workspace. + """ + return ClientsTable(self.rpc, self.name) + + def delete(self): + """ + Delete the current workspace. + """ + self.rpc.call(MsfRpcMethod.DbDelWorkspace, {'workspace' : self.name}) + + def importdata(self, data): + self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : data}) + + def importfile(self, fname): + r = file(fname, mode='rb') + self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : r.read()}) + r.close() class MsfManager(object): - def __init__(self, rpc): - """ - Initialize a msf component manager. + def __init__(self, rpc): + """ + Initialize a msf component manager. - Mandatory Arguments: - - rpc : the msfrpc client object. - """ - self.rpc = rpc + Mandatory Arguments: + - rpc : the msfrpc client object. + """ + self.rpc = rpc class WorkspaceManager(MsfManager): - @property - def list(self): - """ - The list of all workspaces in the current msf database. - """ - return self.rpc.call(MsfRpcMethod.DbWorkspaces)['workspaces'] - - def workspace(self, name='default'): - """ - Returns a Workspace object for the given workspace name. - - Optional Arguments: - - name : the name of the workspace - """ - w = self.list - if name not in w: - self.add(name) - return Workspace(self.rpc, name) - - def add(self, name): - """ - Adds a workspace with the given name. - - Mandatory Arguments: - - name : the name of the workspace - """ - self.rpc.call(MsfRpcMethod.DbAddWorkspace, name) - - def get(self, name): - """ - Get a workspace with the given name. - - Mandatory Arguments: - - name : the name of the workspace - """ - return self.rpc.call(MsfRpcMethod.DbGetWorkspace, name)['workspace'] - - def remove(self, name): - """ - Adds a workspace with the given name. - - Mandatory Arguments: - - name : the name of the workspace - """ - self.rpc.call(MsfRpcMethod.DbDelWorkspace, name) - - def set(self, name): - """ - Sets the current workspace. - - Mandatory Arguments: - - name : the name of the workspace - """ - self.rpc.call(MsfRpcMethod.DbSetWorkspace, name) - - @property - def current(self): - """ - The current workspace. - """ - return self.workspace(self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace']) + @property + def list(self): + """ + The list of all workspaces in the current msf database. + """ + return self.rpc.call(MsfRpcMethod.DbWorkspaces)['workspaces'] + + def workspace(self, name='default'): + """ + Returns a Workspace object for the given workspace name. + + Optional Arguments: + - name : the name of the workspace + """ + w = self.list + if name not in w: + self.add(name) + return Workspace(self.rpc, name) + + def add(self, name): + """ + Adds a workspace with the given name. + + Mandatory Arguments: + - name : the name of the workspace + """ + self.rpc.call(MsfRpcMethod.DbAddWorkspace, name) + + def get(self, name): + """ + Get a workspace with the given name. + + Mandatory Arguments: + - name : the name of the workspace + """ + return self.rpc.call(MsfRpcMethod.DbGetWorkspace, name)['workspace'] + + def remove(self, name): + """ + Adds a workspace with the given name. + + Mandatory Arguments: + - name : the name of the workspace + """ + self.rpc.call(MsfRpcMethod.DbDelWorkspace, name) + + def set(self, name): + """ + Sets the current workspace. + + Mandatory Arguments: + - name : the name of the workspace + """ + self.rpc.call(MsfRpcMethod.DbSetWorkspace, name) + + @property + def current(self): + """ + The current workspace. + """ + return self.workspace(self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace']) class DbManager(MsfManager): - def connect(self, username, database='msf', **kwargs): - """ - Connects to a database and creates the msf schema if necessary. - - Mandatory Arguments: - - username : the username for the database connection - - Optional Keyword Arguments: - - host : the IP or hostname of the database server (default: 'localhost') - - driver : the driver to use for the database connection (default: 'postgresql') - - password : the password for the database connection - - database : the database name (default: 'msf') - - port : the port that the server is running on (default: 5432) - """ - runopts = { 'username': username, 'database' : database } - runopts.update(kwargs) - return self.rpc.call(MsfRpcMethod.DbConnect, runopts)['result'] == 'success' - - @property - def driver(self): - """ - The current database driver in use. - """ - return self.rpc.call(MsfRpcMethod.DbDriver, {})['driver'] - - @driver.setter - def driver(self, d): - self.rpc.call(MsfRpcMethod.DbDriver, {'driver' : d}) - - @property - def status(self): - """ - The status of the database connection. - """ - return self.rpc.call(MsfRpcMethod.DbStatus) - - def disconnect(self): - """ - Disconnect from the database. - """ - self.rpc.call(MsfRpcMethod.DbDisconnect) - - @property - def workspaces(self): - """ - A WorkspaceManager object. - """ - return WorkspaceManager(self.rpc) - - @property - def workspace(self): - """ - The name of the current workspace. - """ - return self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace'] - - @workspace.setter - def workspace(self, w): - self.rpc.call(MsfRpcMethod.DbSetWorkspace, w) + def connect(self, username, database='msf', **kwargs): + """ + Connects to a database and creates the msf schema if necessary. + + Mandatory Arguments: + - username : the username for the database connection + + Optional Keyword Arguments: + - host : the IP or hostname of the database server (default: 'localhost') + - driver : the driver to use for the database connection (default: 'postgresql') + - password : the password for the database connection + - database : the database name (default: 'msf') + - port : the port that the server is running on (default: 5432) + """ + runopts = { 'username': username, 'database' : database } + runopts.update(kwargs) + return self.rpc.call(MsfRpcMethod.DbConnect, runopts)['result'] == 'success' + + @property + def driver(self): + """ + The current database driver in use. + """ + return self.rpc.call(MsfRpcMethod.DbDriver, {})['driver'] + + @driver.setter + def driver(self, d): + self.rpc.call(MsfRpcMethod.DbDriver, {'driver' : d}) + + @property + def status(self): + """ + The status of the database connection. + """ + return self.rpc.call(MsfRpcMethod.DbStatus) + + def disconnect(self): + """ + Disconnect from the database. + """ + self.rpc.call(MsfRpcMethod.DbDisconnect) + + @property + def workspaces(self): + """ + A WorkspaceManager object. + """ + return WorkspaceManager(self.rpc) + + @property + def workspace(self): + """ + The name of the current workspace. + """ + return self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace'] + + @workspace.setter + def workspace(self, w): + self.rpc.call(MsfRpcMethod.DbSetWorkspace, w) class AuthManager(MsfManager): - def login(self, password, **kwargs): - """ - Login to the msfrpc daemon. - - Mandatory Arguments: - - password : the password used to login to msfrpc - - Optional Keyword Arguments: - - username : the username used to authenticate to msfrpcd (default: msf) - - uri : the msfrpcd URI (default: /api/) - - port : the remote msfrpcd port to connect to (default: 55553) - - server : the remote server IP address hosting msfrpcd (default: localhost) - - ssl : if true uses SSL else regular HTTP (default: SSL enabled) - """ - return MsfRpcClient(password, **kwargs) - - def logout(self, sid): - """ - Logs out a user for a given session ID. - - Mandatory Arguments: - - sid : a session ID that is active. - """ - return self.rpc.call(MsfRpcMethod.AuthLogout, sid) - - @property - def tokens(self): - """ - The current list of active session IDs. - """ - return self.rpc.call(MsfRpcMethod.AuthTokenList)['tokens'] - - def add(self, token): - """ - Add a session ID or token. - - Mandatory Argument: - - token : a random string used as a session identifier. - """ - self.rpc.call(MsfRpcMethod.AuthTokenAdd, token) - - def remove(self, token): - """ - Remove a session ID or token. - - Mandatory Argument: - - token : a session ID or token that is active. - """ - self.rpc.call(MsfRpcMethod.AuthTokenRemove, token) - - def generate(self): - """ - Generate a session ID or token. - """ - return self.rpc.call(MsfRpcMethod.AuthTokenGenerate)['token'] + def login(self, password, **kwargs): + """ + Login to the msfrpc daemon. + + Mandatory Arguments: + - password : the password used to login to msfrpc + + Optional Keyword Arguments: + - username : the username used to authenticate to msfrpcd (default: msf) + - uri : the msfrpcd URI (default: /api/) + - port : the remote msfrpcd port to connect to (default: 55553) + - server : the remote server IP address hosting msfrpcd (default: localhost) + - ssl : if true uses SSL else regular HTTP (default: SSL enabled) + """ + return MsfRpcClient(password, **kwargs) + + def logout(self, sid): + """ + Logs out a user for a given session ID. + + Mandatory Arguments: + - sid : a session ID that is active. + """ + return self.rpc.call(MsfRpcMethod.AuthLogout, sid) + + @property + def tokens(self): + """ + The current list of active session IDs. + """ + return self.rpc.call(MsfRpcMethod.AuthTokenList)['tokens'] + + def add(self, token): + """ + Add a session ID or token. + + Mandatory Argument: + - token : a random string used as a session identifier. + """ + self.rpc.call(MsfRpcMethod.AuthTokenAdd, token) + + def remove(self, token): + """ + Remove a session ID or token. + + Mandatory Argument: + - token : a session ID or token that is active. + """ + self.rpc.call(MsfRpcMethod.AuthTokenRemove, token) + + def generate(self): + """ + Generate a session ID or token. + """ + return self.rpc.call(MsfRpcMethod.AuthTokenGenerate)['token'] class PluginManager(MsfManager): - @property - def list(self): - """ - A list of loaded plugins. - """ - return self.rpc.call(MsfRpcMethod.PluginLoaded)['plugins'] + @property + def list(self): + """ + A list of loaded plugins. + """ + return self.rpc.call(MsfRpcMethod.PluginLoaded)['plugins'] - def load(self, plugin): - """ - Load a plugin of a given name. + def load(self, plugin): + """ + Load a plugin of a given name. - Mandatory Arguments: - - plugin : a name of a plugin to load. - """ - self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginLoad, plugin) + Mandatory Arguments: + - plugin : a name of a plugin to load. + """ + self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginLoad, plugin) - def unload(self, plugin): - """ - Unload a plugin of a given name. + def unload(self, plugin): + """ + Unload a plugin of a given name. - Mandatory Arguments: - - plugin : a name of a loaded plugin to unload. - """ - self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginUnload, plugin) + Mandatory Arguments: + - plugin : a name of a loaded plugin to unload. + """ + self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginUnload, plugin) class JobManager(MsfManager): - @property - def list(self): - """ - A list of currently running jobs. - """ - return self.rpc.call(MsfRpcMethod.JobList) + @property + def list(self): + """ + A list of currently running jobs. + """ + return self.rpc.call(MsfRpcMethod.JobList) - def stop(self, jobid): - """ - Stop a job. + def stop(self, jobid): + """ + Stop a job. - Mandatory Argument: - - jobid : the ID of the job. - """ - self.rpc.call(MsfRpcMethod.JobStop, jobid) + Mandatory Argument: + - jobid : the ID of the job. + """ + self.rpc.call(MsfRpcMethod.JobStop, jobid) - def info(self, jobid): - """ - Get job information for a particular job. + def info(self, jobid): + """ + Get job information for a particular job. - Mandatory Argument: - - jobid : the ID of the job. - """ - return self.rpc.call(MsfRpcMethod.JobInfo, jobid) + Mandatory Argument: + - jobid : the ID of the job. + """ + return self.rpc.call(MsfRpcMethod.JobInfo, jobid) class CoreManager(MsfManager): - @property - def version(self): - """ - The version of msf core. - """ - return self.rpc.call(MsfRpcMethod.CoreVersion) - - def stop(self): - """ - Stop the core. - """ - self.rpc.call(MsfRpcMethod.CoreStop) - - def setg(self, var, val): - """ - Set a global variable - - Mandatory Arguments: - - var : the variable name - - val : the variable value - """ - self.rpc.call(MsfRpcMethod.CoreSetG, var, val) - - def unsetg(self, var): - """ - Unset a global variable - - Mandatory Arguments: - - var : the variable name - """ - self.rpc.call(MsfRpcMethod.CoreUnsetG, var) - - def save(self): - """ - Save the core state. - """ - self.rpc.call(MsfRpcMethod.CoreSave) - - def reload(self): - """ - Reload all modules in the core. - """ - self.rpc.call(MsfRpcMethod.CoreReloadModules) - - @property - def stats(self): - """ - Get module statistics from the core. - """ - return self.rpc.call(MsfRpcMethod.CoreModuleStats) - - def addmodulepath(self, path): - """ - Add a search path for additional modules. - - Mandatory Arguments: - - path : the path to search for modules. - """ - return self.rpc.call(MsfRpcMethod.CoreAddModulePath, path) - - @property - def threads(self): - """ - The current threads running in the core. - """ - return self.rpc.call(MsfRpcMethod.CoreThreadList) - - def kill(self, threadid): - """ - Kill a thread running in the core. - - Mandatory Arguments: - - threadid : the thread ID. - """ - self.rpc.call(MsfRpcMethod.CoreThreadKill, threadid) + @property + def version(self): + """ + The version of msf core. + """ + return self.rpc.call(MsfRpcMethod.CoreVersion) + + def stop(self): + """ + Stop the core. + """ + self.rpc.call(MsfRpcMethod.CoreStop) + + def setg(self, var, val): + """ + Set a global variable + + Mandatory Arguments: + - var : the variable name + - val : the variable value + """ + self.rpc.call(MsfRpcMethod.CoreSetG, var, val) + + def unsetg(self, var): + """ + Unset a global variable + + Mandatory Arguments: + - var : the variable name + """ + self.rpc.call(MsfRpcMethod.CoreUnsetG, var) + + def save(self): + """ + Save the core state. + """ + self.rpc.call(MsfRpcMethod.CoreSave) + + def reload(self): + """ + Reload all modules in the core. + """ + self.rpc.call(MsfRpcMethod.CoreReloadModules) + + @property + def stats(self): + """ + Get module statistics from the core. + """ + return self.rpc.call(MsfRpcMethod.CoreModuleStats) + + def addmodulepath(self, path): + """ + Add a search path for additional modules. + + Mandatory Arguments: + - path : the path to search for modules. + """ + return self.rpc.call(MsfRpcMethod.CoreAddModulePath, path) + + @property + def threads(self): + """ + The current threads running in the core. + """ + return self.rpc.call(MsfRpcMethod.CoreThreadList) + + def kill(self, threadid): + """ + Kill a thread running in the core. + + Mandatory Arguments: + - threadid : the thread ID. + """ + self.rpc.call(MsfRpcMethod.CoreThreadKill, threadid) class MsfModule(object): - def __init__(self, rpc, mtype, mname): - """ - Initializes an msf module object. - - Mandatory Arguments: - - rpc : the msfrpc client object. - - mtype : the module type (e.g. 'exploit') - - mname : the module name (e.g. 'exploits/windows/http/icecast_header') - """ - self.moduletype = mtype - self.modulename = mname - self.rpc = rpc - self._info = rpc.call(MsfRpcMethod.ModuleInfo, mtype, mname) - for k in self._info: - setattr(self, k, self._info.get(k)) - self._moptions = rpc.call(MsfRpcMethod.ModuleOptions, mtype, mname) - self._roptions = [] - self._aoptions = [] - self._eoptions = [] - self._runopts = {} - for o in self._moptions: - if self._moptions[o]['required']: - self._roptions.append(o) - if self._moptions[o]['advanced']: - self._aoptions.append(o) - if self._moptions[o]['evasion']: - self._eoptions.append(o) - if 'default' in self._moptions[o]: - self._runopts[o] = self._moptions[o]['default'] - - @property - def options(self): - """ - All the module options. - """ - return self._moptions.keys() - - @property - def required(self): - """ - The required module options. - """ - return self._roptions - - @property - def evasion(self): - """ - Module options that are used for evasion. - """ - return self._eoptions - - @property - def advanced(self): - """ - Advanced module options. - """ - return self._aoptions - - @property - def runoptions(self): - """ - The running (currently set) options for a module. This will raise an error - if some of the required options are missing. - """ - outstanding = set(self.required).difference(self._runopts.keys()) - if outstanding: - raise TypeError('Module missing required parameter: %s' % ', '.join(outstanding)) - return self._runopts - - def optioninfo(self, option): - """ - Get information about the module option - - Mandatory Argument: - - option : the option name. - """ - return self._moptions[option] - - def __getitem__(self, item): - """ - Get the current option value. - - Mandatory Arguments: - - item : the option name. - """ - if item not in self._moptions: - raise KeyError("Invalid option '%s'." % item) - return self._runopts.get(item) - - def __setitem__(self, key, value): - """ - Set the current option value. - - Mandatory Arguments: - - key : the option name. - - value : the option value. - """ - if key not in self.options: - raise KeyError("Invalid option '%s'." % key) - elif 'enums' in self._moptions[key] and value not in self._moptions[key]['enums']: - raise ValueError("Value ('%s') is not one of %s" % (value, repr(self._moptions[key]['enums']))) - elif self._moptions[key]['type'] == 'bool' and not isinstance(value, bool): - raise TypeError("Value must be a boolean not '%s'" % type(value).__name__) - elif self._moptions[key]['type'] in ['integer', 'float'] and not isinstance(value, Number): - raise TypeError("Value must be an integer not '%s'" % type(value).__name__) - self._runopts[key] = value - - def __delitem__(self, key): - del self._runopts[key] - - def __contains__(self, item): - return item in self._runopts - - def update(self, d): - """ - Update a set of options. - - Mandatory Arguments: - - d : a dictionary of options - """ - for k in d: - self[k] = d[k] - - def execute(self, **kwargs): - """ - Executes the module with its run options as parameters. - - Optional Keyword Arguments: - - payload : the payload of an exploit module (this is mandatory if the module is an exploit). - - **kwargs : can contain any module options. - """ - runopts = self.runoptions.copy() - if isinstance(self, ExploitModule): - payload = kwargs.get('payload') - runopts['TARGET'] = self.target - if 'DisablePayloadHandler' in runopts and runopts['DisablePayloadHandler']: - pass - elif payload is None: - runopts['DisablePayloadHandler'] = True - else: - if isinstance(payload, PayloadModule): - if payload.modulename not in self.payloads: - raise ValueError( - 'Invalid payload (%s) for given target (%d).' % (payload.modulename, self.target) - ) - runopts['PAYLOAD'] = payload.modulename - for k, v in payload.runoptions.iteritems(): - if v is None or (isinstance(v, basestring) and not v): - continue - if k not in runopts or runopts[k] is None or \ - (isinstance(runopts[k], basestring) and not runopts[k]): - runopts[k] = v -# runopts.update(payload.runoptions) - elif isinstance(payload, basestring): - if payload not in self.payloads: - raise ValueError('Invalid payload (%s) for given target (%d).' % (payload, self.target)) - runopts['PAYLOAD'] = payload - else: - raise TypeError("Expected type str or PayloadModule not '%s'" % type(kwargs['payload']).__name__) - - return self.rpc.call(MsfRpcMethod.ModuleExecute, self.moduletype, self.modulename, runopts) + def __init__(self, rpc, mtype, mname): + """ + Initializes an msf module object. + + Mandatory Arguments: + - rpc : the msfrpc client object. + - mtype : the module type (e.g. 'exploit') + - mname : the module name (e.g. 'exploits/windows/http/icecast_header') + """ + self.moduletype = mtype + self.modulename = mname + self.rpc = rpc + self._info = rpc.call(MsfRpcMethod.ModuleInfo, mtype, mname) + for k in self._info: + setattr(self, k, self._info.get(k)) + self._moptions = rpc.call(MsfRpcMethod.ModuleOptions, mtype, mname) + self._roptions = [] + self._aoptions = [] + self._eoptions = [] + self._runopts = {} + for o in self._moptions: + if self._moptions[o]['required']: + self._roptions.append(o) + if self._moptions[o]['advanced']: + self._aoptions.append(o) + if self._moptions[o]['evasion']: + self._eoptions.append(o) + if 'default' in self._moptions[o]: + self._runopts[o] = self._moptions[o]['default'] + + @property + def options(self): + """ + All the module options. + """ + return list(self._moptions.keys()) + + @property + def required(self): + """ + The required module options. + """ + return self._roptions + + @property + def evasion(self): + """ + Module options that are used for evasion. + """ + return self._eoptions + + @property + def advanced(self): + """ + Advanced module options. + """ + return self._aoptions + + @property + def runoptions(self): + """ + The running (currently set) options for a module. This will raise an error + if some of the required options are missing. + """ + outstanding = set(self.required).difference(list(self._runopts.keys())) + if outstanding: + raise TypeError('Module missing required parameter: %s' % ', '.join(outstanding)) + return self._runopts + + def optioninfo(self, option): + """ + Get information about the module option + + Mandatory Argument: + - option : the option name. + """ + return self._moptions[option] + + def __getitem__(self, item): + """ + Get the current option value. + + Mandatory Arguments: + - item : the option name. + """ + if item not in self._moptions: + raise KeyError("Invalid option '%s'." % item) + return self._runopts.get(item) + + def __setitem__(self, key, value): + """ + Set the current option value. + + Mandatory Arguments: + - key : the option name. + - value : the option value. + """ + if key not in self.options: + raise KeyError("Invalid option '%s'." % key) + elif 'enums' in self._moptions[key] and value not in self._moptions[key]['enums']: + raise ValueError("Value ('%s') is not one of %s" % (value, repr(self._moptions[key]['enums']))) + elif self._moptions[key]['type'] == 'bool' and not isinstance(value, bool): + raise TypeError("Value must be a boolean not '%s'" % type(value).__name__) + elif self._moptions[key]['type'] in ['integer', 'float'] and not isinstance(value, Number): + raise TypeError("Value must be an integer not '%s'" % type(value).__name__) + self._runopts[key] = value + + def __delitem__(self, key): + del self._runopts[key] + + def __contains__(self, item): + return item in self._runopts + + def update(self, d): + """ + Update a set of options. + + Mandatory Arguments: + - d : a dictionary of options + """ + for k in d: + self[k] = d[k] + + def execute(self, **kwargs): + """ + Executes the module with its run options as parameters. + + Optional Keyword Arguments: + - payload : the payload of an exploit module (this is mandatory if the module is an exploit). + - **kwargs : can contain any module options. + """ + runopts = self.runoptions.copy() + if isinstance(self, ExploitModule): + payload = kwargs.get('payload') + runopts['TARGET'] = self.target + if 'DisablePayloadHandler' in runopts and runopts['DisablePayloadHandler']: + pass + elif payload is None: + runopts['DisablePayloadHandler'] = True + else: + if isinstance(payload, PayloadModule): + if payload.modulename not in self.payloads: + raise ValueError( + 'Invalid payload (%s) for given target (%d).' % (payload.modulename, self.target) + ) + runopts['PAYLOAD'] = payload.modulename + for k, v in payload.runoptions.items(): + if v is None or (isinstance(v, str) and not v): + continue + if k not in runopts or runopts[k] is None or \ + (isinstance(runopts[k], str) and not runopts[k]): + runopts[k] = v +# runopts.update(payload.runoptions) + elif isinstance(payload, str): + if payload not in self.payloads: + raise ValueError('Invalid payload (%s) for given target (%d).' % (payload, self.target)) + runopts['PAYLOAD'] = payload + else: + raise TypeError("Expected type str or PayloadModule not '%s'" % type(kwargs['payload']).__name__) + + return self.rpc.call(MsfRpcMethod.ModuleExecute, self.moduletype, self.modulename, runopts) class ExploitModule(MsfModule): - def __init__(self, rpc, exploit): - """ - Initializes the use of an exploit module. - - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - exploit : the name of the exploit module. - """ - super(ExploitModule, self).__init__(rpc, 'exploit', exploit) - self._target = self._info.get('default_target', 0) - - @property - def payloads(self): - """ - A list of compatible payloads. - """ -# return self.rpc.call(MsfRpcMethod.ModuleCompatiblePayloads, self.modulename)['payloads'] - return self.targetpayloads(self.target) - - @property - def target(self): - return self._target - - @target.setter - def target(self, target): - if target not in self.targets: - raise ValueError('Target must be one of %s' % repr(self.targets.keys())) - self._target = target - - def targetpayloads(self, t=0): - """ - Returns a list of compatible payloads for a given target ID. - - Optional Keyword Arguments: - - t : the target ID (default: 0, e.g. 'Automatic') - """ - return self.rpc.call(MsfRpcMethod.ModuleTargetCompatiblePayloads, self.modulename, t)['payloads'] + def __init__(self, rpc, exploit): + """ + Initializes the use of an exploit module. + + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - exploit : the name of the exploit module. + """ + super(ExploitModule, self).__init__(rpc, 'exploit', exploit) + self._target = self._info.get('default_target', 0) + + @property + def payloads(self): + """ + A list of compatible payloads. + """ +# return self.rpc.call(MsfRpcMethod.ModuleCompatiblePayloads, self.modulename)['payloads'] + return self.targetpayloads(self.target) + + @property + def target(self): + return self._target + + @target.setter + def target(self, target): + if target not in self.targets: + raise ValueError('Target must be one of %s' % repr(list(self.targets.keys()))) + self._target = target + + def targetpayloads(self, t=0): + """ + Returns a list of compatible payloads for a given target ID. + + Optional Keyword Arguments: + - t : the target ID (default: 0, e.g. 'Automatic') + """ + return self.rpc.call(MsfRpcMethod.ModuleTargetCompatiblePayloads, self.modulename, t)['payloads'] class PostModule(MsfModule): - def __init__(self, rpc, post): - """ - Initializes the use of a post exploitation module. + def __init__(self, rpc, post): + """ + Initializes the use of a post exploitation module. - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - post : the name of the post exploitation module. - """ - super(PostModule, self).__init__(rpc, 'post', post) + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - post : the name of the post exploitation module. + """ + super(PostModule, self).__init__(rpc, 'post', post) - @property - def sessions(self): - """ - A list of compatible shell/meterpreter sessions. - """ - return self.rpc.compatiblesessions(self.modulename) + @property + def sessions(self): + """ + A list of compatible shell/meterpreter sessions. + """ + return self.rpc.compatiblesessions(self.modulename) class EncoderModule(MsfModule): - def __init__(self, rpc, encoder): - """ - Initializes the use of an encoder module. + def __init__(self, rpc, encoder): + """ + Initializes the use of an encoder module. - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - encoder : the name of the encoder module. - """ - super(EncoderModule, self).__init__(rpc, 'encoder', encoder) + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - encoder : the name of the encoder module. + """ + super(EncoderModule, self).__init__(rpc, 'encoder', encoder) class AuxiliaryModule(MsfModule): - def __init__(self, rpc, auxiliary): - """ - Initializes the use of an auxiliary module. + def __init__(self, rpc, auxiliary): + """ + Initializes the use of an auxiliary module. - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - auxiliary : the name of the auxiliary module. - """ - super(AuxiliaryModule, self).__init__(rpc, 'auxiliary', auxiliary) + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - auxiliary : the name of the auxiliary module. + """ + super(AuxiliaryModule, self).__init__(rpc, 'auxiliary', auxiliary) class PayloadModule(MsfModule): - def __init__(self, rpc, payload): - """ - Initializes the use of a payload module. + def __init__(self, rpc, payload): + """ + Initializes the use of a payload module. - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - payload : the name of the payload module. - """ - super(PayloadModule, self).__init__(rpc, 'payload', payload) + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - payload : the name of the payload module. + """ + super(PayloadModule, self).__init__(rpc, 'payload', payload) class NopModule(MsfModule): - def __init__(self, rpc, nop): - """ - Initializes the use of a nop module. + def __init__(self, rpc, nop): + """ + Initializes the use of a nop module. - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - nop : the name of the nop module. - """ - super(NopModule, self).__init__(rpc, 'nop', nop) + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - nop : the name of the nop module. + """ + super(NopModule, self).__init__(rpc, 'nop', nop) class ModuleManager(MsfManager): - def execute(self, modtype, modname, **kwargs): - """ - Execute the module. - - Mandatory Arguments: - - modtype : the module type (e.g. 'exploit') - - modname : the module name (e.g. 'exploits/windows/http/icecast_header') - - Optional Keyword Arguments: - - **kwargs : the module's run options - """ - return self.rpc.call(MsfRpcMethod.ModuleExecute, modtype, modname, kwargs) - - @property - def exploits(self): - """ - A list of exploit modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleExploits)['modules'] - - @property - def payloads(self): - """ - A list of payload modules. - """ - return self.rpc.call(MsfRpcMethod.ModulePayloads)['modules'] - - @property - def auxiliary(self): - """ - A list of auxiliary modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleAuxiliary)['modules'] - - @property - def post(self): - """ - A list of post modules. - """ - return self.rpc.call(MsfRpcMethod.ModulePost)['modules'] - - @property - def encodeformats(self): - """ - A list of encoding formats. - """ - return self.rpc.call(MsfRpcMethod.ModuleEncodeFormats) - - @property - def encoders(self): - """ - A list of encoder modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleEncoders)['modules'] - - @property - def nops(self): - """ - A list of nop modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleNops)['modules'] - - def use(self, mtype, mname): - """ - Returns a module object. - - Mandatory Arguments: - - mname : the module name (e.g. 'exploits/windows/http/icecast_header') - """ - if mtype == 'exploit': - return ExploitModule(self.rpc, mname) - elif mtype == 'post': - return PostModule(self.rpc, mname) - elif mtype == 'encoder': - return EncoderModule(self.rpc, mname) - elif mtype == 'auxiliary': - return AuxiliaryModule(self.rpc, mname) - elif mtype == 'nop': - return NopModule(self.rpc, mname) - elif mtype == 'payload': - return PayloadModule(self.rpc, mname) - raise MsfRpcError('Unknown module type %s not: exploit, post, encoder, auxiliary, nop, or payload' % mname) + def execute(self, modtype, modname, **kwargs): + """ + Execute the module. + + Mandatory Arguments: + - modtype : the module type (e.g. 'exploit') + - modname : the module name (e.g. 'exploits/windows/http/icecast_header') + + Optional Keyword Arguments: + - **kwargs : the module's run options + """ + return self.rpc.call(MsfRpcMethod.ModuleExecute, modtype, modname, kwargs) + + @property + def exploits(self): + """ + A list of exploit modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleExploits)['modules'] + + @property + def payloads(self): + """ + A list of payload modules. + """ + return self.rpc.call(MsfRpcMethod.ModulePayloads)['modules'] + + @property + def auxiliary(self): + """ + A list of auxiliary modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleAuxiliary)['modules'] + + @property + def post(self): + """ + A list of post modules. + """ + return self.rpc.call(MsfRpcMethod.ModulePost)['modules'] + + @property + def encodeformats(self): + """ + A list of encoding formats. + """ + return self.rpc.call(MsfRpcMethod.ModuleEncodeFormats) + + @property + def encoders(self): + """ + A list of encoder modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleEncoders)['modules'] + + @property + def nops(self): + """ + A list of nop modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleNops)['modules'] + + def use(self, mtype, mname): + """ + Returns a module object. + + Mandatory Arguments: + - mname : the module name (e.g. 'exploits/windows/http/icecast_header') + """ + if mtype == 'exploit': + return ExploitModule(self.rpc, mname) + elif mtype == 'post': + return PostModule(self.rpc, mname) + elif mtype == 'encoder': + return EncoderModule(self.rpc, mname) + elif mtype == 'auxiliary': + return AuxiliaryModule(self.rpc, mname) + elif mtype == 'nop': + return NopModule(self.rpc, mname) + elif mtype == 'payload': + return PayloadModule(self.rpc, mname) + raise MsfRpcError('Unknown module type %s not: exploit, post, encoder, auxiliary, nop, or payload' % mname) class MsfSession(object): - def __init__(self, id, rpc, sd): - """ - Initialize a meterpreter or shell session. - - Mandatory Arguments: - - id : the session identifier. - - rpc : the msfrpc client object. - - sd : the session description - """ - self.id = id - self.rpc = rpc - self.__dict__.update(sd) - - def stop(self): - """ - Stop a meterpreter or shell session. - """ - return self.rpc.call(MsfRpcMethod.SessionStop, self.id) - - @property - def modules(self): - """ - A list of compatible session modules. - """ - return self.rpc.call(MsfRpcMethod.SessionCompatibleModules, self.id)['modules'] - - @property - def ring(self): - return SessionRing(self.rpc, self.id) + def __init__(self, id, rpc, sd): + """ + Initialize a meterpreter or shell session. + + Mandatory Arguments: + - id : the session identifier. + - rpc : the msfrpc client object. + - sd : the session description + """ + self.id = id + self.rpc = rpc + self.__dict__.update(sd) + + def stop(self): + """ + Stop a meterpreter or shell session. + """ + return self.rpc.call(MsfRpcMethod.SessionStop, self.id) + + @property + def modules(self): + """ + A list of compatible session modules. + """ + return self.rpc.call(MsfRpcMethod.SessionCompatibleModules, self.id)['modules'] + + @property + def ring(self): + return SessionRing(self.rpc, self.id) class SessionRing(object): - def __init__(self, rpc, sessionid): - self.rpc = rpc - self.id = sessionid + def __init__(self, rpc, sessionid): + self.rpc = rpc + self.id = sessionid - def read(self, seq=None): - """ - Reads the session ring. + def read(self, seq=None): + """ + Reads the session ring. - Optional Keyword Arguments: - - seq : the sequence ID of the ring (default: 0) - """ - if seq is not None: - return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id, seq) - return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id) + Optional Keyword Arguments: + - seq : the sequence ID of the ring (default: 0) + """ + if seq is not None: + return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id, seq) + return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id) - def put(self, line): - """ - Add a command to the session history. + def put(self, line): + """ + Add a command to the session history. - Mandatory Arguments: - - line : arbitrary data. - """ - self.rpc.call(MsfRpcMethod.SessionRingPut, self.id, line) + Mandatory Arguments: + - line : arbitrary data. + """ + self.rpc.call(MsfRpcMethod.SessionRingPut, self.id, line) - @property - def last(self): - """ - Returns the last sequence ID in the session ring. - """ - return int(self.rpc.call(MsfRpcMethod.SessionRingLast, self.id)['seq']) + @property + def last(self): + """ + Returns the last sequence ID in the session ring. + """ + return int(self.rpc.call(MsfRpcMethod.SessionRingLast, self.id)['seq']) - def clear(self): - """ - Clear the session ring. - """ - return self.rpc.call(MsfRpcMethod.SessionRingClear, self.id) + def clear(self): + """ + Clear the session ring. + """ + return self.rpc.call(MsfRpcMethod.SessionRingClear, self.id) class MeterpreterSession(MsfSession): - def read(self): - """ - Read data from the meterpreter session. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterRead, self.id)['data'] - - def write(self, data): - """ - Write data to the meterpreter session. - - Mandatory Arguments: - - data : arbitrary data or commands - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterWrite, self.id, data) - - def runsingle(self, data): - """ - Run a single meterpreter command - - Mandatory Arguments: - - data : arbitrary data or command - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterRunSingle, self.id, data) - return self.read() - - def runscript(self, path): - """ - Run a meterpreter script - - Mandatory Arguments: - - path : path to a meterpreter script on the msfrpcd host. - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterScript, self.id, path) - return self.read() - - @property - def sep(self): - """ - The operating system path separator. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterDirectorySeparator, self.id)['separator'] - - def detach(self): - """ - Detach the meterpreter session. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionDetach, self.id) - - def kill(self): - """ - Kill the meterpreter session. - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionKill, self.id) - - def tabs(self, line): - """ - Return a list of commands for a partial command line (tab completion). - - Mandatory Arguments: - - line : a partial command line for completion. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterTabs, self.id, line)['tabs'] + def read(self): + """ + Read data from the meterpreter session. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterRead, self.id)['data'] + + def write(self, data): + """ + Write data to the meterpreter session. + + Mandatory Arguments: + - data : arbitrary data or commands + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterWrite, self.id, data) + + def runsingle(self, data): + """ + Run a single meterpreter command + + Mandatory Arguments: + - data : arbitrary data or command + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterRunSingle, self.id, data) + return self.read() + + def runscript(self, path): + """ + Run a meterpreter script + + Mandatory Arguments: + - path : path to a meterpreter script on the msfrpcd host. + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterScript, self.id, path) + return self.read() + + @property + def sep(self): + """ + The operating system path separator. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterDirectorySeparator, self.id)['separator'] + + def detach(self): + """ + Detach the meterpreter session. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionDetach, self.id) + + def kill(self): + """ + Kill the meterpreter session. + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionKill, self.id) + + def tabs(self, line): + """ + Return a list of commands for a partial command line (tab completion). + + Mandatory Arguments: + - line : a partial command line for completion. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterTabs, self.id, line)['tabs'] class ShellSession(MsfSession): - def read(self): - """ - Read data from the shell session. - """ - return self.rpc.call(MsfRpcMethod.SessionShellRead, self.id)['data'] + def read(self): + """ + Read data from the shell session. + """ + return self.rpc.call(MsfRpcMethod.SessionShellRead, self.id)['data'] - def write(self, data): - """ - Write data to the shell session. + def write(self, data): + """ + Write data to the shell session. - Mandatory Arguments: - - data : arbitrary data or commands - """ - self.rpc.call(MsfRpcMethod.SessionShellWrite, self.id, data) + Mandatory Arguments: + - data : arbitrary data or commands + """ + self.rpc.call(MsfRpcMethod.SessionShellWrite, self.id, data) - def upgrade(self, lhost, lport): - """ - Upgrade the current shell session. - """ - self.rpc.call(MsfRpcMethod.SessionShellUpgrade, self.id, lhost, lport) - return self.read() + def upgrade(self, lhost, lport): + """ + Upgrade the current shell session. + """ + self.rpc.call(MsfRpcMethod.SessionShellUpgrade, self.id, lhost, lport) + return self.read() class SessionManager(MsfManager): - @property - def list(self): - """ - A list of active sessions. - """ - return self.rpc.call(MsfRpcMethod.SessionList) - - def session(self, id): - """ - Returns a session object for meterpreter or shell sessions. - - Mandatory Arguments: - - id : the session identifier. - """ - s = self.list - if id not in s: - for k in s: - if s[k]['uuid'] == id: - if s[id]['type'] == 'meterpreter': - return MeterpreterSession(id, self.rpc, s) - elif s[id]['type'] == 'shell': - return ShellSession(id, self.rpc, s) - raise KeyError('Session ID (%s) does not exist' % id) - if s[id]['type'] == 'meterpreter': - return MeterpreterSession(id, self.rpc, s) - elif s[id]['type'] == 'shell': - return ShellSession(id, self.rpc, s) - raise NotImplementedError('Could not determine session type: %s' % s[id]['type']) + @property + def list(self): + """ + A list of active sessions. + """ + return self.rpc.call(MsfRpcMethod.SessionList) + + def session(self, id): + """ + Returns a session object for meterpreter or shell sessions. + + Mandatory Arguments: + - id : the session identifier. + """ + s = self.list + if id not in s: + for k in s: + if s[k]['uuid'] == id: + if s[id]['type'] == 'meterpreter': + return MeterpreterSession(id, self.rpc, s) + elif s[id]['type'] == 'shell': + return ShellSession(id, self.rpc, s) + raise KeyError('Session ID (%s) does not exist' % id) + if s[id]['type'] == 'meterpreter': + return MeterpreterSession(id, self.rpc, s) + elif s[id]['type'] == 'shell': + return ShellSession(id, self.rpc, s) + raise NotImplementedError('Could not determine session type: %s' % s[id]['type']) class MsfConsole(object): - def __init__(self, rpc, cid=None): - """ - Initializes an msf console. - - Mandatory Arguments: - - rpc : the msfrpc client object. - - Optional Keyword Arguments: - - cid : the console identifier if it exists already otherwise a new one will be created. - """ - self.rpc = rpc - if cid is None: - r = self.rpc.call(MsfRpcMethod.ConsoleCreate) - if 'id' in r: - self.cid = r['id'] - else: - raise MsfRpcError('Unable to create a new console.') - else: - self.cid = cid - - def read(self): - """ - Read data from the console. - """ - return self.rpc.call(MsfRpcMethod.ConsoleRead, self.cid) - - def write(self, command): - """ - Write data to the console. - """ - if not command.endswith('\n'): - command += '\n' - self.rpc.call(MsfRpcMethod.ConsoleWrite, self.cid, command) - - def sessionkill(self): - """ - Kill all active meterpreter or shell sessions. - """ - self.rpc.call(MsfRpcMethod.ConsoleSessionKill, self.cid) - - def sessiondetach(self): - """ - Detach the current meterpreter or shell session. - """ - self.rpc.call(MsfRpcMethod.ConsoleSessionDetach, self.cid) - - def tabs(self, line): - """ - Tab completion for console commands. - - Mandatory Arguments: - - line : a partial command to be completed. - """ - return self.rpc.call(MsfRpcMethod.ConsoleTabs, self.cid, line)['tabs'] - - def destroy(self): - """ - Destroy the console. - """ - self.rpc.call(MsfRpcMethod.ConsoleDestroy, self.cid) + def __init__(self, rpc, cid=None): + """ + Initializes an msf console. + + Mandatory Arguments: + - rpc : the msfrpc client object. + + Optional Keyword Arguments: + - cid : the console identifier if it exists already otherwise a new one will be created. + """ + self.rpc = rpc + if cid is None: + r = self.rpc.call(MsfRpcMethod.ConsoleCreate) + if 'id' in r: + self.cid = r['id'] + else: + raise MsfRpcError('Unable to create a new console.') + else: + self.cid = cid + + def read(self): + """ + Read data from the console. + """ + return self.rpc.call(MsfRpcMethod.ConsoleRead, self.cid) + + def write(self, command): + """ + Write data to the console. + """ + if not command.endswith('\n'): + command += '\n' + self.rpc.call(MsfRpcMethod.ConsoleWrite, self.cid, command) + + def sessionkill(self): + """ + Kill all active meterpreter or shell sessions. + """ + self.rpc.call(MsfRpcMethod.ConsoleSessionKill, self.cid) + + def sessiondetach(self): + """ + Detach the current meterpreter or shell session. + """ + self.rpc.call(MsfRpcMethod.ConsoleSessionDetach, self.cid) + + def tabs(self, line): + """ + Tab completion for console commands. + + Mandatory Arguments: + - line : a partial command to be completed. + """ + return self.rpc.call(MsfRpcMethod.ConsoleTabs, self.cid, line)['tabs'] + + def destroy(self): + """ + Destroy the console. + """ + self.rpc.call(MsfRpcMethod.ConsoleDestroy, self.cid) class ConsoleManager(MsfManager): - @property - def list(self): - """ - A list of active consoles. - """ - return self.rpc.call(MsfRpcMethod.ConsoleList) - - def console(self, cid=None): - """ - Connect to an active console otherwise create a new console. - - Optional Keyword Arguments: - - cid : the console identifier. - """ - s = self.list - if cid is None: - return MsfConsole(self.rpc) - if cid not in s: - raise KeyError('Console ID (%s) does not exist' % cid) - else: - return MsfConsole(self.rpc, cid=cid) - - def destroy(self, cid): - """ - Destory an active console. - - Mandatory Arguments: - - cid : the console identifier. - """ - self.rpc.call(MsfRpcMethod.ConsoleDestroy, cid) + @property + def list(self): + """ + A list of active consoles. + """ + return self.rpc.call(MsfRpcMethod.ConsoleList) + + def console(self, cid=None): + """ + Connect to an active console otherwise create a new console. + + Optional Keyword Arguments: + - cid : the console identifier. + """ + s = self.list + if cid is None: + return MsfConsole(self.rpc) + if cid not in s: + raise KeyError('Console ID (%s) does not exist' % cid) + else: + return MsfConsole(self.rpc, cid=cid) + + def destroy(self, cid): + """ + Destory an active console. + + Mandatory Arguments: + - cid : the console identifier. + """ + self.rpc.call(MsfRpcMethod.ConsoleDestroy, cid) diff --git a/src/metasploit/msfrpc.py.bak b/src/metasploit/msfrpc.py.bak new file mode 100644 index 0000000..c005b5e --- /dev/null +++ b/src/metasploit/msfrpc.py.bak @@ -0,0 +1,1971 @@ +#!/usr/bin/env python + +from httplib import HTTPConnection, HTTPSConnection +import ssl +from numbers import Number + +from msgpack import packb, unpackb + +__author__ = 'Nadeem Douba' +__copyright__ = 'Copyright 2012, PyMetasploit Project' +__credits__ = [] + +__license__ = 'GPL' +__version__ = '0.4' +__maintainer__ = 'Nadeem Douba' +__email__ = 'ndouba@gmail.com' +__status__ = 'Development' + +__all__ = [ + 'MsfRpcError', + 'MsfRpcMethod', + 'MsfPlugins', + 'MsfRpcClient', + 'MsfTable', + 'NotesTable', + 'LootsTable', + 'CredsTable', + 'AuthInfoTable', + 'HostsTable', + 'ServicesTable', + 'VulnsTable', + 'EventsTable', + 'ClientsTable', + 'Workspace', + 'MsfManager', + 'WorkspaceManager', + 'DbManager', + 'AuthManager', + 'PluginManager', + 'JobManager', + 'CoreManager', + 'MsfModule', + 'ExploitModule', + 'PostModule', + 'EncoderModule', + 'AuxiliaryModule', + 'PayloadModule', + 'NopModule', + 'ModuleManager', + 'MsfSession', + 'MeterpreterSession', + 'ShellSession', + 'SessionManager', + 'MsfConsole', + 'ConsoleManager', + 'ReportFilter', + 'ReportFilterQuery' +] + + +class MsfRpcError(Exception): + pass + + +class MsfRpcMethod(object): + AuthLogin = 'auth.login' + AuthLogout = 'auth.logout' + AuthTokenList = 'auth.token_list' + AuthTokenAdd = 'auth.token_add' + AuthTokenGenerate = 'auth.token_generate' + AuthTokenRemove = 'auth.token_remove' + ConsoleCreate = 'console.create' + ConsoleList = 'console.list' + ConsoleDestroy = 'console.destroy' + ConsoleRead = 'console.read' + ConsoleWrite = 'console.write' + ConsoleTabs = 'console.tabs' + ConsoleSessionKill = 'console.session_kill' + ConsoleSessionDetach = 'console.session_detach' + CoreVersion = 'core.version' + CoreStop = 'core.stop' + CoreSetG = 'core.setg' + CoreUnsetG = 'core.unsetg' + CoreSave = 'core.save' + CoreReloadModules = 'core.reload_modules' + CoreModuleStats = 'core.module_stats' + CoreAddModulePath = 'core.add_module_path' + CoreThreadList = 'core.thread_list' + CoreThreadKill = 'core.thread_kill' + DbHosts = 'db.hosts' + DbServices = 'db.services' + DbVulns = 'db.vulns' + DbWorkspaces = 'db.workspaces' + DbCurrentWorkspace = 'db.current_workspace' + DbGetWorkspace = 'db.get_workspace' + DbSetWorkspace = 'db.set_workspace' + DbDelWorkspace = 'db.del_workspace' + DbAddWorkspace = 'db.add_workspace' + DbGetHost = 'db.get_host' + DbReportHost = 'db.report_host' + DbReportService = 'db.report_service' + DbGetService = 'db.get_service' + DbGetNote = 'db.get_note' + DbGetClient = 'db.get_client' + DbReportClient = 'db.report_client' + DbReportNote = 'db.report_note' + DbNotes = 'db.notes' + DbReportAuthInfo = 'db.report_auth_info' + DbGetAuthInfo = 'db.get_auth_info' + DbGetRef = 'db.get_ref' + DbDelVuln = 'db.del_vuln' + DbDelNote = 'db.del_note' + DbDelService = 'db.del_service' + DbDelHost = 'db.del_host' + DbReportVuln = 'db.report_vuln' + DbEvents = 'db.events' + DbReportEvent = 'db.report_event' + DbReportLoot = 'db.report_loot' + DbLoots = 'db.loots' + DbReportCred = 'db.report_cred' + DbCreds = 'db.creds' + DbImportData = 'db.import_data' + DbGetVuln = 'db.get_vuln' + DbClients = 'db.clients' + DbDelClient = 'db.del_client' + DbDriver = 'db.driver' + DbConnect = 'db.connect' + DbStatus = 'db.status' + DbDisconnect = 'db.disconnect' + JobList = 'job.list' + JobStop = 'job.stop' + JobInfo = 'job.info' + ModuleExploits = 'module.exploits' + ModuleAuxiliary = 'module.auxiliary' + ModulePayloads = 'module.payloads' + ModuleEncoders = 'module.encoders' + ModuleNops = 'module.nops' + ModulePost = 'module.post' + ModuleInfo = 'module.info' + ModuleCompatiblePayloads = 'module.compatible_payloads' + ModuleCompatibleSessions = 'module.compatible_sessions' + ModuleTargetCompatiblePayloads = 'module.target_compatible_payloads' + ModuleOptions = 'module.options' + ModuleExecute = 'module.execute' + ModuleEncodeFormats = 'module.encode_formats' + ModuleEncode = 'module.encode' + PluginLoad = 'plugin.load' + PluginUnload = 'plugin.unload' + PluginLoaded = 'plugin.loaded' + SessionList = 'session.list' + SessionStop = 'session.stop' + SessionShellRead = 'session.shell_read' + SessionShellWrite = 'session.shell_write' + SessionShellUpgrade = 'session.shell_upgrade' + SessionMeterpreterRead = 'session.meterpreter_read' + SessionRingRead = 'session.ring_read' + SessionRingPut = 'session.ring_put' + SessionRingLast = 'session.ring_last' + SessionRingClear = 'session.ring_clear' + SessionMeterpreterWrite = 'session.meterpreter_write' + SessionMeterpreterSessionDetach = 'session.meterpreter_session_detach' + SessionMeterpreterSessionKill = 'session.meterpreter_session_kill' + SessionMeterpreterTabs = 'session.meterpreter_tabs' + SessionMeterpreterRunSingle = 'session.meterpreter_run_single' + SessionMeterpreterScript = 'session.meterpreter_script' + SessionMeterpreterDirectorySeparator = 'session.meterpreter_directory_separator' + SessionCompatibleModules = 'session.compatible_modules' + + +class MsfPlugins(object): + IpsFilter = "ips_filter" + SocketLogger = "socket_logger" + DbTracker = "db_tracker" + Sounds = "sounds" + AutoAddRoute = "auto_add_route" + DbCredCollect = "db_credcollect" + + +class MsfRpcClient(object): + + _headers = { + 'Content-Type' : 'binary/message-pack' + } + + def __init__(self, password, **kwargs): + """ + Connects and authenticates to a Metasploit RPC daemon. + + Mandatory Arguments: + - password : the password used to authenticate to msfrpcd + + Optional Keyword Arguments: + - username : the username used to authenticate to msfrpcd (default: msf) + - uri : the msfrpcd URI (default: /api/) + - port : the remote msfrpcd port to connect to (default: 55553) + - server : the remote server IP address hosting msfrpcd (default: localhost) + - ssl : if true uses SSL else regular HTTP (default: SSL enabled) + - verify : if true, verify SSL cert when using SSL (default: False) + """ + self.uri = kwargs.get('uri', '/api/') + self.port = kwargs.get('port', 55553) + self.server = kwargs.get('server', '127.0.0.1') + self.ssl = kwargs.get('ssl', True) + self.verify_ssl = kwargs.get('verify', False) + self.sessionid = kwargs.get('token') + if self.ssl: + if self.verify_ssl: + self.client = HTTPSConnection(self.server, self.port) + else: + self.client = HTTPSConnection(self.server, self.port, context=ssl._create_unverified_context()) + else: + self.client = HTTPConnection(self.server, self.port) + self.login(kwargs.get('username', 'msf'), password) + + def call(self, method, *args): + """ + Builds an RPC request and retrieves the result. + + Mandatory Arguments: + - method : the RPC call method name (e.g. db.clients) + + Optional Arguments: + - *args : the RPC method's parameters if necessary + + Returns : RPC call result + """ + l = [ method ] + l.extend(args) + if method == MsfRpcMethod.AuthLogin: + self.client.request('POST', self.uri, packb(l), self._headers) + r = self.client.getresponse() + if r.status == 200: + return unpackb(r.read()) + raise MsfRpcError('An unknown error has occurred while logging in.') + elif self.authenticated: + l.insert(1, self.sessionid) + self.client.request('POST', self.uri, packb(l), self._headers) + r = self.client.getresponse() + if r.status == 200: + result = unpackb(r.read()) + if 'error' in result: + raise MsfRpcError(result['error_message']) + return result + raise MsfRpcError('An unknown error has occurred while performing the RPC call.') + raise MsfRpcError('You cannot perform this call because you are not authenticated.') + + @property + def core(self): + """ + The msf RPC core manager. + """ + return CoreManager(self) + + @property + def modules(self): + """ + The msf RPC modules RPC manager. + """ + return ModuleManager(self) + + @property + def sessions(self): + """ + The msf RPC sessions (meterpreter & shell) manager. + """ + return SessionManager(self) + + @property + def jobs(self): + """ + The msf RPC jobs manager. + """ + return JobManager(self) + + @property + def consoles(self): + """ + The msf RPC consoles manager + """ + return ConsoleManager(self) + + @property + def authenticated(self): + """ + Whether or not this client is authenticated. + """ + return self.sessionid is not None + + @property + def plugins(self): + """ + The msf RPC plugins manager. + """ + return PluginManager(self) + + @property + def db(self): + """ + The msf RPC database manager. + """ + return DbManager(self) + + @property + def auth(self): + """ + The msf authentication manager. + """ + return AuthManager(self) + + def login(self, username, password): + """ + Authenticates and reauthenticates the user to msfrpcd. + """ + if self.sessionid is None: + r = self.call(MsfRpcMethod.AuthLogin, username, password) + try: + if r['result'] == 'success': + self.sessionid = r['token'] + except KeyError: + raise MsfRpcError('Login failed.') + else: + try: + r = self.call(MsfRpcMethod.DbStatus) + except MsfRpcError: + raise MsfRpcError('Login failed.') + + def logout(self): + """ + Logs the current user out. Note: do not call directly. + """ + self.call(MsfRpcMethod.AuthLogout, self.sessionid) + + +class MsfTable(object): + + def __init__(self, rpc, wname): + self.rpc = rpc + self.name = wname + + def dbreport(self, atype, attrs): + attrs.update({ 'workspace' : self.name }) + return self.rpc.call('db.report_%s' % atype, attrs) + + def dbdel(self, atype, attrs): + attrs.update({ 'workspace' : self.name }) + return self.rpc.call('db.del_%s' % atype, attrs) + + def dbget(self, atype, attrs): + attrs.update({ 'workspace' : self.name }) + return self.rpc.call('db.get_%s' % atype, attrs)[atype] + + def records(self, atypes, **kwargs): + kwargs.update({'workspace' : self.name}) + return self.rpc.call('db.%s' % atypes, kwargs)[atypes] + + @property + def list(self): + raise NotImplementedError + + def report(self, *args, **kwargs): + raise NotImplementedError + + def delete(self, *args, **kwargs): + raise NotImplementedError + + def find(self, **kwargs): + raise NotImplementedError + + update = report + + +class NotesTable(MsfTable): + + @property + def list(self): + return super(NotesTable, self).records('notes') + + def find(self, **kwargs): + """ + Find notes based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - addresses : a list of addresses to search for. + - names : comma separated string of service names. + - ntype : the note type. + - ports : the port associated with the note. + - proto : the protocol associated with the note. + """ + if 'ports' in kwargs: + kwargs['port'] = True + return super(NotesTable, self).records('notes', **kwargs) + + def report(self, type, data, **kwargs): + """ + Report a Note to the database. Notes can be tied to a Workspace, Host, or Service. + + Mandatory Arguments: + - type : The type of note, e.g. 'smb_peer_os'. + - data : whatever it is you're making a note of. + + Optional Keyword Arguments: + - host : an IP address or a Host object to associate with this Note. + - service : a dict containing 'host', 'port', 'proto' and optionally 'name' keys. + - port : along with 'host' and 'proto', a service to associate with this Note. + - proto : along with 'host' and 'port', a service to associate with this Note. + - update : what to do in case a similar Note exists, see below. + + The 'update' option can have the following values: + - unique : allow only a single Note per host/type pair. + - unique_data : like 'unique', but also compare 'data'. + - insert : always insert a new Note even if one with identical values exists. + + If the provided 'host' is an IP address and does not exist in the database, + it will be created. If 'host' and 'service' are all omitted, the new Note + will be associated with the current 'workspace'. + """ + kwargs.update({ 'data' : data, 'type' : type }) + kwargs.update(kwargs.pop('service', {})) + self.dbreport('note', kwargs) + + def delete(self, **kwargs): + """ + Delete one or more notes based on a search criteria. + + Optional Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + - port : the port associated with a Note. + - proto : the protocol associated with a Note. + - ntype : the note type, e.g. 'smb_peer_os'. + """ + self.dbdel('note', kwargs) + + def get(self, **kwargs): + """ + Get a Note from the database based on the specifications of one or more keyword arguments. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - address : the address associated with a Note, not required if 'host' or 'addr' is specified. + - addr : same as 'address', not required if 'host' or 'address' is specified. + + Optional Keyword Arguments: + - proto : the protocol associated with the Note. + - port : the port associated with the Note. + - ntype : the type of Note. + """ + if not any([i in kwargs for i in ('host', 'address', 'addr')]): + raise TypeError('Expected a host, address, or addr.') + return self.dbget('note', kwargs) + + update = report + + +class LootsTable(MsfTable): + + @property + def list(self): + return super(LootsTable, self).records('loots') + + def find(self, **kwargs): + """ + Find loot based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + """ + return super(LootsTable, self).records('loots', **kwargs) + + def report(self, path, type, **kwargs): + """ + Report Loot to the database + + Mandatory Arguments: + - path : the filesystem path to the Loot + - type : the type of Loot + - ltype : the same as 'type', not required if 'type' is specified. + + Optional Keyword Arguments: + - host : an IP address or a Host object to associate with this Note + - ctype : the content type of the loot, e.g. 'text/plain' + - content_type : same as 'ctype'. + - service : a service to associate Loot with. + - name : a name to associate with this Loot. + - info : additional information about this Loot. + - data : the data within the Loot. + """ + kwargs.update({ 'path' : path, 'type' : type }) + self.dbreport('loot', kwargs) + + update = report + + +class CredsTable(MsfTable): + + @property + def list(self): + return super(CredsTable, self).records('creds') + + def find(self, **kwargs): + """ + Find creds based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + """ + return super(CredsTable, self).records('creds', **kwargs) + + def report(self, host, port, **kwargs): + """ + Store a set of credentials in the database. + + Mandatory Arguments: + - host : an IP address or Host object reference + - port : a port number + + Optional Keyword Arguments: + - user : the username. + - password : the password, or path to ssh_key. + - ptype : the type of password (password(ish), hash, or ssh_key). + - proto : a transport name for the port. + - sname : service name. + - active : by default, a cred is active, unless explicitly false. + - proof : data used to prove the account is actually active. + + Sources: Credentials can be sourced from another credential, or from + a vulnerability. For example, if an exploit was used to dump the + smb_hashes, and this credential comes from there, the source_id would + be the Vuln id (as reported by report_vuln) and the type would be "Vuln". + + - source_id : The Vuln or Cred id of the source of this cred. + - source_type : Either Vuln or Cred. + """ + kwargs.update({'host' : host, 'port' : port}) + kwargs['pass'] = kwargs.get('password') + self.dbreport('cred', kwargs) + + update = report + + +class AuthInfoTable(MsfTable): + + def report(self, host, port, **kwargs): + """ + Store a set of credentials in the database. + + Mandatory Arguments: + - host : an IP address or Host object reference + - port : a port number + + Optional Keyword Arguments: + - user : the username. + - pass : the password, or path to ssh_key. + - ptype : the type of password (password(ish), hash, or ssh_key). + - proto : a transport name for the port. + - sname : service name. + - active : by default, a cred is active, unless explicitly false. + - proof : data used to prove the account is actually active. + + Sources: Credentials can be sourced from another credential, or from + a vulnerability. For example, if an exploit was used to dump the + smb_hashes, and this credential comes from there, the source_id would + be the Vuln id (as reported by report_vuln) and the type would be "Vuln". + + - source_id : The Vuln or Cred id of the source of this cred. + - source_type : Either Vuln or Cred. + """ + kwargs.update({'host' : host, 'port' : port}) + self.dbreport('auth_info', kwargs) + + update = report + + +class HostsTable(MsfTable): + + @property + def list(self): + return super(HostsTable, self).records('hosts') + + def find(self, **kwargs): + """ + Find hosts based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - only_up : find only hosts that are alive. + - addresses : find hosts based on a list of addresses. + """ + return super(HostsTable, self).records('hosts', **kwargs) + + def report(self, host, **kwargs): + """ + Store a host in the database. + + Mandatory Keyword Arguments: + - host : an IP address or Host object reference. + + Optional Keyword Arguments: + - state : a host state. + - os_name : an operating system. + - os_flavor : something like 'XP or 'Gentoo'. + - os_sp : something like 'SP2'. + - os_lang : something like 'English', 'French', or 'en-US'. + - arch : an architecture. + - mac : the host's MAC address. + - scope : interface identifier for link-local IPv6. + - virtual_host : the name of the VM host software, e.g. 'VMWare', 'QEMU', 'Xen', etc. + """ + kwargs.update({'host' : host}) + self.dbreport('host', kwargs) + + def delete(self, **kwargs): + """ + Deletes a host and associated data matching this address/comm. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): + raise TypeError('Expected host, address, or addresses.') + self.dbdel('host', kwargs) + + def get(self, **kwargs): + """ + Get a host in the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - address : the address associated with a Note, not required if 'host' or 'addr' is specified. + - addr : same as 'address', not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('addr', 'address', 'host')]): + raise TypeError('Expected addr, address, or host.') + return self.dbget('host', kwargs) + + update = report + + +class ServicesTable(MsfTable): + + @property + def list(self): + return super(ServicesTable, self).records('services') + + def find(self, **kwargs): + """ + Find hosts based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - only_up : find only hosts that are alive. + - addresses : find hosts based on a list of addresses. + - proto : the protocol of the service. + - ports : a comma separated string of ports. + - names : a comma separated string of service names. + """ + return super(ServicesTable, self).records('services', **kwargs) + + def report(self, host, port, proto, **kwargs): + """ + Record a service in the database. + + Mandatory Arguments: + - host : the host where this service is running. + - port : the port where this service listens. + - proto : the transport layer protocol (e.g. tcp, udp). + + Optional Keyword Arguments: + - name : the application layer protocol (e.g. ssh, mssql, smb) + - sname : an alias for the above + """ + kwargs.update({'host' : host, 'port' : port, 'proto' : proto}) + self.dbreport('service', kwargs) + + def delete(self, **kwargs): + """ + Deletes a port and associated vulns matching this port. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + + or + + - port : used along with 'proto', specifies a service. + - proto : used along with 'port', specifies a service. + """ + if not any([i in kwargs for i in ('host', 'address', 'addresses')]) and \ + not all([i in kwargs for i in ('proto', 'port')]): + raise TypeError('Expected host or port/proto pair.') + self.dbdel('service', kwargs) + + def get(self, **kwargs): + """ + Get a service record from the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + + or + + - port : used along with 'proto', specifies a service. + - proto : used along with 'port', specifies a service. + + Optional Keyword Arguments: + - up : specifies whether or not the service is alive. + - names : a comma separated string of service names. + """ + if not any([i in kwargs for i in ('host', 'addr', 'address')]) and \ + not all([i in kwargs for i in ('proto', 'port')]): + raise TypeError('Expected host or port/proto pair.') + return self.dbget('service', kwargs) + + update = report + + +class VulnsTable(MsfTable): + + @property + def list(self): + return super(VulnsTable, self).records('vulns') + + def find(self, **kwargs): + """ + Find vulns based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - addresses : find hosts based on a list of addresses. + - proto : the protocol of the service. + - ports : a comma separated string of ports. + - names : a comma separated string of service names. + """ + return super(VulnsTable, self).records('vulns', **kwargs) + + def report(self, host, name, **kwargs): + """ + Record a Vuln in the database. + + Mandatory Arguments: + - host : the host where this vulnerability resides. + - name : the scanner-specific id of the vuln (e.g. NEXPOSE-cifs-acct-password-never-expires). + + Optional Keyword Arguments: + - info : a human readable description of the vuln, free-form text. + - refs : an array of Ref objects or string names of references. + """ + kwargs.update({'host' : host, 'name' : name}) + self.dbreport('vuln', kwargs) + + def delete(self, **kwargs): + """ + Deletes a vuln and associated data matching this address/comm. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): + raise TypeError('Expected host, address, or addresses.') + self.dbdel('vuln', kwargs) + + def get(self, **kwargs): + """ + Get a vuln in the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - address : the address associated with a Note, not required if 'host' or 'addr' is specified. + - addr : same as 'address', not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('addr', 'address', 'host')]): + raise TypeError('Expected addr, address, or host.') + return self.dbreport('vuln', kwargs) + + update = report + + +class EventsTable(MsfTable): + + @property + def list(self): + return super(EventsTable, self).records('events') + + def find(self, **kwargs): + """ + Find events based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + """ + return super(EventsTable, self).records('events', **kwargs) + + def report(self, **kwargs): + """ + Record a Vuln in the database. + + Mandatory Arguments: + - username : user that invoked the event. + - host : host that invoked the event. + """ + if not any([i in kwargs for i in ('username', 'host')]): + raise TypeError('Expected either username or host') + self.dbreport('vuln', kwargs) + + update = report + + +class ClientsTable(MsfTable): + + @property + def list(self): + return super(ClientsTable, self).records('clients') + + def find(self, **kwargs): + """ + Find clients based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - ua_name : a user-agent string. + - ua_ver : the user-agent version. + - addresses : a list of IP addresses. + """ + return super(ClientsTable, self).records('clients', **kwargs) + + def report(self, ua_string, host, **kwargs): + """ + Report a client running on a host. + + Mandatory Arguments: + - ua_string : the value of the User-Agent header + - host : the host where this client connected from, can be an ip address or a Host object + + Optional Keyword Arguments + - ua_name : one of the user agent name constants + - ua_ver : detected version of the given client + - campaign : an id or Campaign object + + Returns a Client. + """ + kwargs.update({'host' : host, 'ua_string' : ua_string}) + self.dbreport('client', kwargs) + + def delete(self, **kwargs): + """ + Deletes a client and associated data matching this address/comm. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + """ + self.dbdel('client', kwargs) + + def get(self, **kwargs): + """ + Get a client in the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - ua_string : the value of the User-Agent header + """ + if not any([ i in kwargs for i in ('host', 'ua_string')]): + raise TypeError('Expected host or ua_string.') + return self.dbreport('client', kwargs) + + update = report + + +class Workspace(object): + + def __init__(self, rpc, name): + """ + Initializes a workspace object. + + Mandatory Arguments: + - rpc : the msfrpc client object + - name : the name of the workspace + """ + self.rpc = rpc + self.name = name + + @property + def current(self): + """ + The name of the current workspace. + """ + return self.name + + @current.setter + def current(self, name): + self.name = name + + @property + def notes(self): + """ + Returns the notes table for the current workspace. + """ + return NotesTable(self.rpc, self.name) + + @property + def hosts(self): + """ + Returns the hosts table for the current workspace. + """ + return HostsTable(self.rpc, self.name) + + @property + def services(self): + """ + Returns the services table for the current workspace. + """ + return ServicesTable(self.rpc, self.name) + + @property + def vulns(self): + """ + Returns the vulns table for the current workspace. + """ + return VulnsTable(self.rpc, self.name) + + @property + def events(self): + """ + Returns the events table for the current workspace. + """ + return EventsTable(self.rpc, self.name) + + @property + def loots(self): + """ + Returns the loots table for the current workspace. + """ + return LootsTable(self.rpc, self.name) + + @property + def creds(self): + """ + Returns the creds table for the current workspace. + """ + return CredsTable(self.rpc, self.name) + + @property + def clients(self): + """ + Returns the clients table for the current workspace. + """ + return ClientsTable(self.rpc, self.name) + + def delete(self): + """ + Delete the current workspace. + """ + self.rpc.call(MsfRpcMethod.DbDelWorkspace, {'workspace' : self.name}) + + def importdata(self, data): + self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : data}) + + def importfile(self, fname): + r = file(fname, mode='rb') + self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : r.read()}) + r.close() + + +class MsfManager(object): + + def __init__(self, rpc): + """ + Initialize a msf component manager. + + Mandatory Arguments: + - rpc : the msfrpc client object. + """ + self.rpc = rpc + + +class WorkspaceManager(MsfManager): + + @property + def list(self): + """ + The list of all workspaces in the current msf database. + """ + return self.rpc.call(MsfRpcMethod.DbWorkspaces)['workspaces'] + + def workspace(self, name='default'): + """ + Returns a Workspace object for the given workspace name. + + Optional Arguments: + - name : the name of the workspace + """ + w = self.list + if name not in w: + self.add(name) + return Workspace(self.rpc, name) + + def add(self, name): + """ + Adds a workspace with the given name. + + Mandatory Arguments: + - name : the name of the workspace + """ + self.rpc.call(MsfRpcMethod.DbAddWorkspace, name) + + def get(self, name): + """ + Get a workspace with the given name. + + Mandatory Arguments: + - name : the name of the workspace + """ + return self.rpc.call(MsfRpcMethod.DbGetWorkspace, name)['workspace'] + + def remove(self, name): + """ + Adds a workspace with the given name. + + Mandatory Arguments: + - name : the name of the workspace + """ + self.rpc.call(MsfRpcMethod.DbDelWorkspace, name) + + def set(self, name): + """ + Sets the current workspace. + + Mandatory Arguments: + - name : the name of the workspace + """ + self.rpc.call(MsfRpcMethod.DbSetWorkspace, name) + + @property + def current(self): + """ + The current workspace. + """ + return self.workspace(self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace']) + + +class DbManager(MsfManager): + + def connect(self, username, database='msf', **kwargs): + """ + Connects to a database and creates the msf schema if necessary. + + Mandatory Arguments: + - username : the username for the database connection + + Optional Keyword Arguments: + - host : the IP or hostname of the database server (default: 'localhost') + - driver : the driver to use for the database connection (default: 'postgresql') + - password : the password for the database connection + - database : the database name (default: 'msf') + - port : the port that the server is running on (default: 5432) + """ + runopts = { 'username': username, 'database' : database } + runopts.update(kwargs) + return self.rpc.call(MsfRpcMethod.DbConnect, runopts)['result'] == 'success' + + @property + def driver(self): + """ + The current database driver in use. + """ + return self.rpc.call(MsfRpcMethod.DbDriver, {})['driver'] + + @driver.setter + def driver(self, d): + self.rpc.call(MsfRpcMethod.DbDriver, {'driver' : d}) + + @property + def status(self): + """ + The status of the database connection. + """ + return self.rpc.call(MsfRpcMethod.DbStatus) + + def disconnect(self): + """ + Disconnect from the database. + """ + self.rpc.call(MsfRpcMethod.DbDisconnect) + + @property + def workspaces(self): + """ + A WorkspaceManager object. + """ + return WorkspaceManager(self.rpc) + + @property + def workspace(self): + """ + The name of the current workspace. + """ + return self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace'] + + @workspace.setter + def workspace(self, w): + self.rpc.call(MsfRpcMethod.DbSetWorkspace, w) + + +class AuthManager(MsfManager): + + def login(self, password, **kwargs): + """ + Login to the msfrpc daemon. + + Mandatory Arguments: + - password : the password used to login to msfrpc + + Optional Keyword Arguments: + - username : the username used to authenticate to msfrpcd (default: msf) + - uri : the msfrpcd URI (default: /api/) + - port : the remote msfrpcd port to connect to (default: 55553) + - server : the remote server IP address hosting msfrpcd (default: localhost) + - ssl : if true uses SSL else regular HTTP (default: SSL enabled) + """ + return MsfRpcClient(password, **kwargs) + + def logout(self, sid): + """ + Logs out a user for a given session ID. + + Mandatory Arguments: + - sid : a session ID that is active. + """ + return self.rpc.call(MsfRpcMethod.AuthLogout, sid) + + @property + def tokens(self): + """ + The current list of active session IDs. + """ + return self.rpc.call(MsfRpcMethod.AuthTokenList)['tokens'] + + def add(self, token): + """ + Add a session ID or token. + + Mandatory Argument: + - token : a random string used as a session identifier. + """ + self.rpc.call(MsfRpcMethod.AuthTokenAdd, token) + + def remove(self, token): + """ + Remove a session ID or token. + + Mandatory Argument: + - token : a session ID or token that is active. + """ + self.rpc.call(MsfRpcMethod.AuthTokenRemove, token) + + def generate(self): + """ + Generate a session ID or token. + """ + return self.rpc.call(MsfRpcMethod.AuthTokenGenerate)['token'] + + +class PluginManager(MsfManager): + + @property + def list(self): + """ + A list of loaded plugins. + """ + return self.rpc.call(MsfRpcMethod.PluginLoaded)['plugins'] + + def load(self, plugin): + """ + Load a plugin of a given name. + + Mandatory Arguments: + - plugin : a name of a plugin to load. + """ + self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginLoad, plugin) + + def unload(self, plugin): + """ + Unload a plugin of a given name. + + Mandatory Arguments: + - plugin : a name of a loaded plugin to unload. + """ + self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginUnload, plugin) + + +class JobManager(MsfManager): + + @property + def list(self): + """ + A list of currently running jobs. + """ + return self.rpc.call(MsfRpcMethod.JobList) + + def stop(self, jobid): + """ + Stop a job. + + Mandatory Argument: + - jobid : the ID of the job. + """ + self.rpc.call(MsfRpcMethod.JobStop, jobid) + + def info(self, jobid): + """ + Get job information for a particular job. + + Mandatory Argument: + - jobid : the ID of the job. + """ + return self.rpc.call(MsfRpcMethod.JobInfo, jobid) + + +class CoreManager(MsfManager): + + @property + def version(self): + """ + The version of msf core. + """ + return self.rpc.call(MsfRpcMethod.CoreVersion) + + def stop(self): + """ + Stop the core. + """ + self.rpc.call(MsfRpcMethod.CoreStop) + + def setg(self, var, val): + """ + Set a global variable + + Mandatory Arguments: + - var : the variable name + - val : the variable value + """ + self.rpc.call(MsfRpcMethod.CoreSetG, var, val) + + def unsetg(self, var): + """ + Unset a global variable + + Mandatory Arguments: + - var : the variable name + """ + self.rpc.call(MsfRpcMethod.CoreUnsetG, var) + + def save(self): + """ + Save the core state. + """ + self.rpc.call(MsfRpcMethod.CoreSave) + + def reload(self): + """ + Reload all modules in the core. + """ + self.rpc.call(MsfRpcMethod.CoreReloadModules) + + @property + def stats(self): + """ + Get module statistics from the core. + """ + return self.rpc.call(MsfRpcMethod.CoreModuleStats) + + def addmodulepath(self, path): + """ + Add a search path for additional modules. + + Mandatory Arguments: + - path : the path to search for modules. + """ + return self.rpc.call(MsfRpcMethod.CoreAddModulePath, path) + + @property + def threads(self): + """ + The current threads running in the core. + """ + return self.rpc.call(MsfRpcMethod.CoreThreadList) + + def kill(self, threadid): + """ + Kill a thread running in the core. + + Mandatory Arguments: + - threadid : the thread ID. + """ + self.rpc.call(MsfRpcMethod.CoreThreadKill, threadid) + + +class MsfModule(object): + + def __init__(self, rpc, mtype, mname): + """ + Initializes an msf module object. + + Mandatory Arguments: + - rpc : the msfrpc client object. + - mtype : the module type (e.g. 'exploit') + - mname : the module name (e.g. 'exploits/windows/http/icecast_header') + """ + self.moduletype = mtype + self.modulename = mname + self.rpc = rpc + self._info = rpc.call(MsfRpcMethod.ModuleInfo, mtype, mname) + for k in self._info: + setattr(self, k, self._info.get(k)) + self._moptions = rpc.call(MsfRpcMethod.ModuleOptions, mtype, mname) + self._roptions = [] + self._aoptions = [] + self._eoptions = [] + self._runopts = {} + for o in self._moptions: + if self._moptions[o]['required']: + self._roptions.append(o) + if self._moptions[o]['advanced']: + self._aoptions.append(o) + if self._moptions[o]['evasion']: + self._eoptions.append(o) + if 'default' in self._moptions[o]: + self._runopts[o] = self._moptions[o]['default'] + + @property + def options(self): + """ + All the module options. + """ + return self._moptions.keys() + + @property + def required(self): + """ + The required module options. + """ + return self._roptions + + @property + def evasion(self): + """ + Module options that are used for evasion. + """ + return self._eoptions + + @property + def advanced(self): + """ + Advanced module options. + """ + return self._aoptions + + @property + def runoptions(self): + """ + The running (currently set) options for a module. This will raise an error + if some of the required options are missing. + """ + outstanding = set(self.required).difference(self._runopts.keys()) + if outstanding: + raise TypeError('Module missing required parameter: %s' % ', '.join(outstanding)) + return self._runopts + + def optioninfo(self, option): + """ + Get information about the module option + + Mandatory Argument: + - option : the option name. + """ + return self._moptions[option] + + def __getitem__(self, item): + """ + Get the current option value. + + Mandatory Arguments: + - item : the option name. + """ + if item not in self._moptions: + raise KeyError("Invalid option '%s'." % item) + return self._runopts.get(item) + + def __setitem__(self, key, value): + """ + Set the current option value. + + Mandatory Arguments: + - key : the option name. + - value : the option value. + """ + if key not in self.options: + raise KeyError("Invalid option '%s'." % key) + elif 'enums' in self._moptions[key] and value not in self._moptions[key]['enums']: + raise ValueError("Value ('%s') is not one of %s" % (value, repr(self._moptions[key]['enums']))) + elif self._moptions[key]['type'] == 'bool' and not isinstance(value, bool): + raise TypeError("Value must be a boolean not '%s'" % type(value).__name__) + elif self._moptions[key]['type'] in ['integer', 'float'] and not isinstance(value, Number): + raise TypeError("Value must be an integer not '%s'" % type(value).__name__) + self._runopts[key] = value + + def __delitem__(self, key): + del self._runopts[key] + + def __contains__(self, item): + return item in self._runopts + + def update(self, d): + """ + Update a set of options. + + Mandatory Arguments: + - d : a dictionary of options + """ + for k in d: + self[k] = d[k] + + def execute(self, **kwargs): + """ + Executes the module with its run options as parameters. + + Optional Keyword Arguments: + - payload : the payload of an exploit module (this is mandatory if the module is an exploit). + - **kwargs : can contain any module options. + """ + runopts = self.runoptions.copy() + if isinstance(self, ExploitModule): + payload = kwargs.get('payload') + runopts['TARGET'] = self.target + if 'DisablePayloadHandler' in runopts and runopts['DisablePayloadHandler']: + pass + elif payload is None: + runopts['DisablePayloadHandler'] = True + else: + if isinstance(payload, PayloadModule): + if payload.modulename not in self.payloads: + raise ValueError( + 'Invalid payload (%s) for given target (%d).' % (payload.modulename, self.target) + ) + runopts['PAYLOAD'] = payload.modulename + for k, v in payload.runoptions.iteritems(): + if v is None or (isinstance(v, basestring) and not v): + continue + if k not in runopts or runopts[k] is None or \ + (isinstance(runopts[k], basestring) and not runopts[k]): + runopts[k] = v +# runopts.update(payload.runoptions) + elif isinstance(payload, basestring): + if payload not in self.payloads: + raise ValueError('Invalid payload (%s) for given target (%d).' % (payload, self.target)) + runopts['PAYLOAD'] = payload + else: + raise TypeError("Expected type str or PayloadModule not '%s'" % type(kwargs['payload']).__name__) + + return self.rpc.call(MsfRpcMethod.ModuleExecute, self.moduletype, self.modulename, runopts) + + +class ExploitModule(MsfModule): + + def __init__(self, rpc, exploit): + """ + Initializes the use of an exploit module. + + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - exploit : the name of the exploit module. + """ + super(ExploitModule, self).__init__(rpc, 'exploit', exploit) + self._target = self._info.get('default_target', 0) + + @property + def payloads(self): + """ + A list of compatible payloads. + """ +# return self.rpc.call(MsfRpcMethod.ModuleCompatiblePayloads, self.modulename)['payloads'] + return self.targetpayloads(self.target) + + @property + def target(self): + return self._target + + @target.setter + def target(self, target): + if target not in self.targets: + raise ValueError('Target must be one of %s' % repr(self.targets.keys())) + self._target = target + + def targetpayloads(self, t=0): + """ + Returns a list of compatible payloads for a given target ID. + + Optional Keyword Arguments: + - t : the target ID (default: 0, e.g. 'Automatic') + """ + return self.rpc.call(MsfRpcMethod.ModuleTargetCompatiblePayloads, self.modulename, t)['payloads'] + + +class PostModule(MsfModule): + + def __init__(self, rpc, post): + """ + Initializes the use of a post exploitation module. + + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - post : the name of the post exploitation module. + """ + super(PostModule, self).__init__(rpc, 'post', post) + + @property + def sessions(self): + """ + A list of compatible shell/meterpreter sessions. + """ + return self.rpc.compatiblesessions(self.modulename) + + +class EncoderModule(MsfModule): + + def __init__(self, rpc, encoder): + """ + Initializes the use of an encoder module. + + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - encoder : the name of the encoder module. + """ + super(EncoderModule, self).__init__(rpc, 'encoder', encoder) + + +class AuxiliaryModule(MsfModule): + + def __init__(self, rpc, auxiliary): + """ + Initializes the use of an auxiliary module. + + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - auxiliary : the name of the auxiliary module. + """ + super(AuxiliaryModule, self).__init__(rpc, 'auxiliary', auxiliary) + + +class PayloadModule(MsfModule): + + def __init__(self, rpc, payload): + """ + Initializes the use of a payload module. + + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - payload : the name of the payload module. + """ + super(PayloadModule, self).__init__(rpc, 'payload', payload) + + +class NopModule(MsfModule): + + def __init__(self, rpc, nop): + """ + Initializes the use of a nop module. + + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - nop : the name of the nop module. + """ + super(NopModule, self).__init__(rpc, 'nop', nop) + + +class ModuleManager(MsfManager): + + def execute(self, modtype, modname, **kwargs): + """ + Execute the module. + + Mandatory Arguments: + - modtype : the module type (e.g. 'exploit') + - modname : the module name (e.g. 'exploits/windows/http/icecast_header') + + Optional Keyword Arguments: + - **kwargs : the module's run options + """ + return self.rpc.call(MsfRpcMethod.ModuleExecute, modtype, modname, kwargs) + + @property + def exploits(self): + """ + A list of exploit modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleExploits)['modules'] + + @property + def payloads(self): + """ + A list of payload modules. + """ + return self.rpc.call(MsfRpcMethod.ModulePayloads)['modules'] + + @property + def auxiliary(self): + """ + A list of auxiliary modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleAuxiliary)['modules'] + + @property + def post(self): + """ + A list of post modules. + """ + return self.rpc.call(MsfRpcMethod.ModulePost)['modules'] + + @property + def encodeformats(self): + """ + A list of encoding formats. + """ + return self.rpc.call(MsfRpcMethod.ModuleEncodeFormats) + + @property + def encoders(self): + """ + A list of encoder modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleEncoders)['modules'] + + @property + def nops(self): + """ + A list of nop modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleNops)['modules'] + + def use(self, mtype, mname): + """ + Returns a module object. + + Mandatory Arguments: + - mname : the module name (e.g. 'exploits/windows/http/icecast_header') + """ + if mtype == 'exploit': + return ExploitModule(self.rpc, mname) + elif mtype == 'post': + return PostModule(self.rpc, mname) + elif mtype == 'encoder': + return EncoderModule(self.rpc, mname) + elif mtype == 'auxiliary': + return AuxiliaryModule(self.rpc, mname) + elif mtype == 'nop': + return NopModule(self.rpc, mname) + elif mtype == 'payload': + return PayloadModule(self.rpc, mname) + raise MsfRpcError('Unknown module type %s not: exploit, post, encoder, auxiliary, nop, or payload' % mname) + + +class MsfSession(object): + + def __init__(self, id, rpc, sd): + """ + Initialize a meterpreter or shell session. + + Mandatory Arguments: + - id : the session identifier. + - rpc : the msfrpc client object. + - sd : the session description + """ + self.id = id + self.rpc = rpc + self.__dict__.update(sd) + + def stop(self): + """ + Stop a meterpreter or shell session. + """ + return self.rpc.call(MsfRpcMethod.SessionStop, self.id) + + @property + def modules(self): + """ + A list of compatible session modules. + """ + return self.rpc.call(MsfRpcMethod.SessionCompatibleModules, self.id)['modules'] + + @property + def ring(self): + return SessionRing(self.rpc, self.id) + + +class SessionRing(object): + + def __init__(self, rpc, sessionid): + self.rpc = rpc + self.id = sessionid + + def read(self, seq=None): + """ + Reads the session ring. + + Optional Keyword Arguments: + - seq : the sequence ID of the ring (default: 0) + """ + if seq is not None: + return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id, seq) + return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id) + + def put(self, line): + """ + Add a command to the session history. + + Mandatory Arguments: + - line : arbitrary data. + """ + self.rpc.call(MsfRpcMethod.SessionRingPut, self.id, line) + + @property + def last(self): + """ + Returns the last sequence ID in the session ring. + """ + return int(self.rpc.call(MsfRpcMethod.SessionRingLast, self.id)['seq']) + + def clear(self): + """ + Clear the session ring. + """ + return self.rpc.call(MsfRpcMethod.SessionRingClear, self.id) + + +class MeterpreterSession(MsfSession): + + def read(self): + """ + Read data from the meterpreter session. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterRead, self.id)['data'] + + def write(self, data): + """ + Write data to the meterpreter session. + + Mandatory Arguments: + - data : arbitrary data or commands + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterWrite, self.id, data) + + def runsingle(self, data): + """ + Run a single meterpreter command + + Mandatory Arguments: + - data : arbitrary data or command + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterRunSingle, self.id, data) + return self.read() + + def runscript(self, path): + """ + Run a meterpreter script + + Mandatory Arguments: + - path : path to a meterpreter script on the msfrpcd host. + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterScript, self.id, path) + return self.read() + + @property + def sep(self): + """ + The operating system path separator. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterDirectorySeparator, self.id)['separator'] + + def detach(self): + """ + Detach the meterpreter session. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionDetach, self.id) + + def kill(self): + """ + Kill the meterpreter session. + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionKill, self.id) + + def tabs(self, line): + """ + Return a list of commands for a partial command line (tab completion). + + Mandatory Arguments: + - line : a partial command line for completion. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterTabs, self.id, line)['tabs'] + + +class ShellSession(MsfSession): + + def read(self): + """ + Read data from the shell session. + """ + return self.rpc.call(MsfRpcMethod.SessionShellRead, self.id)['data'] + + def write(self, data): + """ + Write data to the shell session. + + Mandatory Arguments: + - data : arbitrary data or commands + """ + self.rpc.call(MsfRpcMethod.SessionShellWrite, self.id, data) + + def upgrade(self, lhost, lport): + """ + Upgrade the current shell session. + """ + self.rpc.call(MsfRpcMethod.SessionShellUpgrade, self.id, lhost, lport) + return self.read() + + +class SessionManager(MsfManager): + + @property + def list(self): + """ + A list of active sessions. + """ + return self.rpc.call(MsfRpcMethod.SessionList) + + def session(self, id): + """ + Returns a session object for meterpreter or shell sessions. + + Mandatory Arguments: + - id : the session identifier. + """ + s = self.list + if id not in s: + for k in s: + if s[k]['uuid'] == id: + if s[id]['type'] == 'meterpreter': + return MeterpreterSession(id, self.rpc, s) + elif s[id]['type'] == 'shell': + return ShellSession(id, self.rpc, s) + raise KeyError('Session ID (%s) does not exist' % id) + if s[id]['type'] == 'meterpreter': + return MeterpreterSession(id, self.rpc, s) + elif s[id]['type'] == 'shell': + return ShellSession(id, self.rpc, s) + raise NotImplementedError('Could not determine session type: %s' % s[id]['type']) + + +class MsfConsole(object): + + def __init__(self, rpc, cid=None): + """ + Initializes an msf console. + + Mandatory Arguments: + - rpc : the msfrpc client object. + + Optional Keyword Arguments: + - cid : the console identifier if it exists already otherwise a new one will be created. + """ + self.rpc = rpc + if cid is None: + r = self.rpc.call(MsfRpcMethod.ConsoleCreate) + if 'id' in r: + self.cid = r['id'] + else: + raise MsfRpcError('Unable to create a new console.') + else: + self.cid = cid + + def read(self): + """ + Read data from the console. + """ + return self.rpc.call(MsfRpcMethod.ConsoleRead, self.cid) + + def write(self, command): + """ + Write data to the console. + """ + if not command.endswith('\n'): + command += '\n' + self.rpc.call(MsfRpcMethod.ConsoleWrite, self.cid, command) + + def sessionkill(self): + """ + Kill all active meterpreter or shell sessions. + """ + self.rpc.call(MsfRpcMethod.ConsoleSessionKill, self.cid) + + def sessiondetach(self): + """ + Detach the current meterpreter or shell session. + """ + self.rpc.call(MsfRpcMethod.ConsoleSessionDetach, self.cid) + + def tabs(self, line): + """ + Tab completion for console commands. + + Mandatory Arguments: + - line : a partial command to be completed. + """ + return self.rpc.call(MsfRpcMethod.ConsoleTabs, self.cid, line)['tabs'] + + def destroy(self): + """ + Destroy the console. + """ + self.rpc.call(MsfRpcMethod.ConsoleDestroy, self.cid) + + +class ConsoleManager(MsfManager): + + @property + def list(self): + """ + A list of active consoles. + """ + return self.rpc.call(MsfRpcMethod.ConsoleList) + + def console(self, cid=None): + """ + Connect to an active console otherwise create a new console. + + Optional Keyword Arguments: + - cid : the console identifier. + """ + s = self.list + if cid is None: + return MsfConsole(self.rpc) + if cid not in s: + raise KeyError('Console ID (%s) does not exist' % cid) + else: + return MsfConsole(self.rpc, cid=cid) + + def destroy(self, cid): + """ + Destory an active console. + + Mandatory Arguments: + - cid : the console identifier. + """ + self.rpc.call(MsfRpcMethod.ConsoleDestroy, cid) diff --git a/src/metasploit/utils.py b/src/metasploit/utils.py index d7cffa5..570b6cb 100644 --- a/src/metasploit/utils.py +++ b/src/metasploit/utils.py @@ -26,7 +26,7 @@ def parseargs(): p.add_option("-p", dest="port", help="Connect to the specified port instead of 55553", metavar="opt", default=55553) o, a = p.parse_args() if o.password is None: - print '[-] Error: a password must be specified (-P)\n' + print('[-] Error: a password must be specified (-P)\n') p.print_help() exit(-1) return o \ No newline at end of file diff --git a/src/metasploit/utils.py.bak b/src/metasploit/utils.py.bak new file mode 100644 index 0000000..d7cffa5 --- /dev/null +++ b/src/metasploit/utils.py.bak @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +from optparse import OptionParser + +__author__ = 'Nadeem Douba' +__copyright__ = 'Copyright 2012, PyMetasploit Project' +__credits__ = [] + +__license__ = 'GPL' +__version__ = '0.1' +__maintainer__ = 'Nadeem Douba' +__email__ = 'ndouba@gmail.com' +__status__ = 'Development' + +__all__ = [ + 'parseargs' +] + + +def parseargs(): + p = OptionParser() + p.add_option("-P", dest="password", help="Specify the password to access msfrpcd", metavar="opt") + p.add_option("-S", dest="ssl", help="Disable SSL on the RPC socket", action="store_false", default=True) + p.add_option("-U", dest="username", help="Specify the username to access msfrpcd", metavar="opt", default="msf") + p.add_option("-a", dest="server", help="Connect to this IP address", metavar="host", default="127.0.0.1") + p.add_option("-p", dest="port", help="Connect to the specified port instead of 55553", metavar="opt", default=55553) + o, a = p.parse_args() + if o.password is None: + print '[-] Error: a password must be specified (-P)\n' + p.print_help() + exit(-1) + return o \ No newline at end of file From 4aac15d460f98dfdf91a27ee7c8daf17fb217317 Mon Sep 17 00:00:00 2001 From: amon Date: Sun, 5 Jun 2016 06:45:09 +0000 Subject: [PATCH 06/17] Removed print --- src/metasploit/msfrpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index 245ae86..3ab3c82 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -334,7 +334,7 @@ def login(self, username, password): Authenticates and reauthenticates the user to msfrpcd. """ if self.sessionid is None: - r = self.call(MsfRpcMethod.AuthLogin, username, password);print(r) + r = self.call(MsfRpcMethod.AuthLogin, username, password); try: if r['result'] == 'success': self.sessionid = r['token'] From deeee191b31708a9d1bbfd15676faa9fd635a4d1 Mon Sep 17 00:00:00 2001 From: Niels Fallenbeck Date: Fri, 15 Jul 2016 11:25:18 +0200 Subject: [PATCH 07/17] changed httplib to http.client for python3 --- src/metasploit/msfrpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index c005b5e..1f9e3a4 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from httplib import HTTPConnection, HTTPSConnection +from http.client import HTTPConnection, HTTPSConnection import ssl from numbers import Number From 0a9b41e507dbd082dd4b9242a6a4fa5b8cff40d1 Mon Sep 17 00:00:00 2001 From: 72616e646f6d <72616e646f6d@users.noreply.github.com> Date: Mon, 5 Sep 2016 09:45:14 +0200 Subject: [PATCH 08/17] Removed check for DisablePayloadHandler in msfrpc. --- src/metasploit/msfrpc.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index c005b5e..23033e6 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -1450,9 +1450,7 @@ def execute(self, **kwargs): if isinstance(self, ExploitModule): payload = kwargs.get('payload') runopts['TARGET'] = self.target - if 'DisablePayloadHandler' in runopts and runopts['DisablePayloadHandler']: - pass - elif payload is None: + if payload is None: runopts['DisablePayloadHandler'] = True else: if isinstance(payload, PayloadModule): From 71f70bb171807772445ae1b4fd5f6703f5b8db6e Mon Sep 17 00:00:00 2001 From: aoighost Date: Wed, 26 Apr 2017 19:43:48 -0400 Subject: [PATCH 09/17] deleted bak files --- src/metasploit/msfrpc.py.bak | 1971 ---------------------------------- src/metasploit/utils.py.bak | 32 - 2 files changed, 2003 deletions(-) delete mode 100644 src/metasploit/msfrpc.py.bak delete mode 100644 src/metasploit/utils.py.bak diff --git a/src/metasploit/msfrpc.py.bak b/src/metasploit/msfrpc.py.bak deleted file mode 100644 index c005b5e..0000000 --- a/src/metasploit/msfrpc.py.bak +++ /dev/null @@ -1,1971 +0,0 @@ -#!/usr/bin/env python - -from httplib import HTTPConnection, HTTPSConnection -import ssl -from numbers import Number - -from msgpack import packb, unpackb - -__author__ = 'Nadeem Douba' -__copyright__ = 'Copyright 2012, PyMetasploit Project' -__credits__ = [] - -__license__ = 'GPL' -__version__ = '0.4' -__maintainer__ = 'Nadeem Douba' -__email__ = 'ndouba@gmail.com' -__status__ = 'Development' - -__all__ = [ - 'MsfRpcError', - 'MsfRpcMethod', - 'MsfPlugins', - 'MsfRpcClient', - 'MsfTable', - 'NotesTable', - 'LootsTable', - 'CredsTable', - 'AuthInfoTable', - 'HostsTable', - 'ServicesTable', - 'VulnsTable', - 'EventsTable', - 'ClientsTable', - 'Workspace', - 'MsfManager', - 'WorkspaceManager', - 'DbManager', - 'AuthManager', - 'PluginManager', - 'JobManager', - 'CoreManager', - 'MsfModule', - 'ExploitModule', - 'PostModule', - 'EncoderModule', - 'AuxiliaryModule', - 'PayloadModule', - 'NopModule', - 'ModuleManager', - 'MsfSession', - 'MeterpreterSession', - 'ShellSession', - 'SessionManager', - 'MsfConsole', - 'ConsoleManager', - 'ReportFilter', - 'ReportFilterQuery' -] - - -class MsfRpcError(Exception): - pass - - -class MsfRpcMethod(object): - AuthLogin = 'auth.login' - AuthLogout = 'auth.logout' - AuthTokenList = 'auth.token_list' - AuthTokenAdd = 'auth.token_add' - AuthTokenGenerate = 'auth.token_generate' - AuthTokenRemove = 'auth.token_remove' - ConsoleCreate = 'console.create' - ConsoleList = 'console.list' - ConsoleDestroy = 'console.destroy' - ConsoleRead = 'console.read' - ConsoleWrite = 'console.write' - ConsoleTabs = 'console.tabs' - ConsoleSessionKill = 'console.session_kill' - ConsoleSessionDetach = 'console.session_detach' - CoreVersion = 'core.version' - CoreStop = 'core.stop' - CoreSetG = 'core.setg' - CoreUnsetG = 'core.unsetg' - CoreSave = 'core.save' - CoreReloadModules = 'core.reload_modules' - CoreModuleStats = 'core.module_stats' - CoreAddModulePath = 'core.add_module_path' - CoreThreadList = 'core.thread_list' - CoreThreadKill = 'core.thread_kill' - DbHosts = 'db.hosts' - DbServices = 'db.services' - DbVulns = 'db.vulns' - DbWorkspaces = 'db.workspaces' - DbCurrentWorkspace = 'db.current_workspace' - DbGetWorkspace = 'db.get_workspace' - DbSetWorkspace = 'db.set_workspace' - DbDelWorkspace = 'db.del_workspace' - DbAddWorkspace = 'db.add_workspace' - DbGetHost = 'db.get_host' - DbReportHost = 'db.report_host' - DbReportService = 'db.report_service' - DbGetService = 'db.get_service' - DbGetNote = 'db.get_note' - DbGetClient = 'db.get_client' - DbReportClient = 'db.report_client' - DbReportNote = 'db.report_note' - DbNotes = 'db.notes' - DbReportAuthInfo = 'db.report_auth_info' - DbGetAuthInfo = 'db.get_auth_info' - DbGetRef = 'db.get_ref' - DbDelVuln = 'db.del_vuln' - DbDelNote = 'db.del_note' - DbDelService = 'db.del_service' - DbDelHost = 'db.del_host' - DbReportVuln = 'db.report_vuln' - DbEvents = 'db.events' - DbReportEvent = 'db.report_event' - DbReportLoot = 'db.report_loot' - DbLoots = 'db.loots' - DbReportCred = 'db.report_cred' - DbCreds = 'db.creds' - DbImportData = 'db.import_data' - DbGetVuln = 'db.get_vuln' - DbClients = 'db.clients' - DbDelClient = 'db.del_client' - DbDriver = 'db.driver' - DbConnect = 'db.connect' - DbStatus = 'db.status' - DbDisconnect = 'db.disconnect' - JobList = 'job.list' - JobStop = 'job.stop' - JobInfo = 'job.info' - ModuleExploits = 'module.exploits' - ModuleAuxiliary = 'module.auxiliary' - ModulePayloads = 'module.payloads' - ModuleEncoders = 'module.encoders' - ModuleNops = 'module.nops' - ModulePost = 'module.post' - ModuleInfo = 'module.info' - ModuleCompatiblePayloads = 'module.compatible_payloads' - ModuleCompatibleSessions = 'module.compatible_sessions' - ModuleTargetCompatiblePayloads = 'module.target_compatible_payloads' - ModuleOptions = 'module.options' - ModuleExecute = 'module.execute' - ModuleEncodeFormats = 'module.encode_formats' - ModuleEncode = 'module.encode' - PluginLoad = 'plugin.load' - PluginUnload = 'plugin.unload' - PluginLoaded = 'plugin.loaded' - SessionList = 'session.list' - SessionStop = 'session.stop' - SessionShellRead = 'session.shell_read' - SessionShellWrite = 'session.shell_write' - SessionShellUpgrade = 'session.shell_upgrade' - SessionMeterpreterRead = 'session.meterpreter_read' - SessionRingRead = 'session.ring_read' - SessionRingPut = 'session.ring_put' - SessionRingLast = 'session.ring_last' - SessionRingClear = 'session.ring_clear' - SessionMeterpreterWrite = 'session.meterpreter_write' - SessionMeterpreterSessionDetach = 'session.meterpreter_session_detach' - SessionMeterpreterSessionKill = 'session.meterpreter_session_kill' - SessionMeterpreterTabs = 'session.meterpreter_tabs' - SessionMeterpreterRunSingle = 'session.meterpreter_run_single' - SessionMeterpreterScript = 'session.meterpreter_script' - SessionMeterpreterDirectorySeparator = 'session.meterpreter_directory_separator' - SessionCompatibleModules = 'session.compatible_modules' - - -class MsfPlugins(object): - IpsFilter = "ips_filter" - SocketLogger = "socket_logger" - DbTracker = "db_tracker" - Sounds = "sounds" - AutoAddRoute = "auto_add_route" - DbCredCollect = "db_credcollect" - - -class MsfRpcClient(object): - - _headers = { - 'Content-Type' : 'binary/message-pack' - } - - def __init__(self, password, **kwargs): - """ - Connects and authenticates to a Metasploit RPC daemon. - - Mandatory Arguments: - - password : the password used to authenticate to msfrpcd - - Optional Keyword Arguments: - - username : the username used to authenticate to msfrpcd (default: msf) - - uri : the msfrpcd URI (default: /api/) - - port : the remote msfrpcd port to connect to (default: 55553) - - server : the remote server IP address hosting msfrpcd (default: localhost) - - ssl : if true uses SSL else regular HTTP (default: SSL enabled) - - verify : if true, verify SSL cert when using SSL (default: False) - """ - self.uri = kwargs.get('uri', '/api/') - self.port = kwargs.get('port', 55553) - self.server = kwargs.get('server', '127.0.0.1') - self.ssl = kwargs.get('ssl', True) - self.verify_ssl = kwargs.get('verify', False) - self.sessionid = kwargs.get('token') - if self.ssl: - if self.verify_ssl: - self.client = HTTPSConnection(self.server, self.port) - else: - self.client = HTTPSConnection(self.server, self.port, context=ssl._create_unverified_context()) - else: - self.client = HTTPConnection(self.server, self.port) - self.login(kwargs.get('username', 'msf'), password) - - def call(self, method, *args): - """ - Builds an RPC request and retrieves the result. - - Mandatory Arguments: - - method : the RPC call method name (e.g. db.clients) - - Optional Arguments: - - *args : the RPC method's parameters if necessary - - Returns : RPC call result - """ - l = [ method ] - l.extend(args) - if method == MsfRpcMethod.AuthLogin: - self.client.request('POST', self.uri, packb(l), self._headers) - r = self.client.getresponse() - if r.status == 200: - return unpackb(r.read()) - raise MsfRpcError('An unknown error has occurred while logging in.') - elif self.authenticated: - l.insert(1, self.sessionid) - self.client.request('POST', self.uri, packb(l), self._headers) - r = self.client.getresponse() - if r.status == 200: - result = unpackb(r.read()) - if 'error' in result: - raise MsfRpcError(result['error_message']) - return result - raise MsfRpcError('An unknown error has occurred while performing the RPC call.') - raise MsfRpcError('You cannot perform this call because you are not authenticated.') - - @property - def core(self): - """ - The msf RPC core manager. - """ - return CoreManager(self) - - @property - def modules(self): - """ - The msf RPC modules RPC manager. - """ - return ModuleManager(self) - - @property - def sessions(self): - """ - The msf RPC sessions (meterpreter & shell) manager. - """ - return SessionManager(self) - - @property - def jobs(self): - """ - The msf RPC jobs manager. - """ - return JobManager(self) - - @property - def consoles(self): - """ - The msf RPC consoles manager - """ - return ConsoleManager(self) - - @property - def authenticated(self): - """ - Whether or not this client is authenticated. - """ - return self.sessionid is not None - - @property - def plugins(self): - """ - The msf RPC plugins manager. - """ - return PluginManager(self) - - @property - def db(self): - """ - The msf RPC database manager. - """ - return DbManager(self) - - @property - def auth(self): - """ - The msf authentication manager. - """ - return AuthManager(self) - - def login(self, username, password): - """ - Authenticates and reauthenticates the user to msfrpcd. - """ - if self.sessionid is None: - r = self.call(MsfRpcMethod.AuthLogin, username, password) - try: - if r['result'] == 'success': - self.sessionid = r['token'] - except KeyError: - raise MsfRpcError('Login failed.') - else: - try: - r = self.call(MsfRpcMethod.DbStatus) - except MsfRpcError: - raise MsfRpcError('Login failed.') - - def logout(self): - """ - Logs the current user out. Note: do not call directly. - """ - self.call(MsfRpcMethod.AuthLogout, self.sessionid) - - -class MsfTable(object): - - def __init__(self, rpc, wname): - self.rpc = rpc - self.name = wname - - def dbreport(self, atype, attrs): - attrs.update({ 'workspace' : self.name }) - return self.rpc.call('db.report_%s' % atype, attrs) - - def dbdel(self, atype, attrs): - attrs.update({ 'workspace' : self.name }) - return self.rpc.call('db.del_%s' % atype, attrs) - - def dbget(self, atype, attrs): - attrs.update({ 'workspace' : self.name }) - return self.rpc.call('db.get_%s' % atype, attrs)[atype] - - def records(self, atypes, **kwargs): - kwargs.update({'workspace' : self.name}) - return self.rpc.call('db.%s' % atypes, kwargs)[atypes] - - @property - def list(self): - raise NotImplementedError - - def report(self, *args, **kwargs): - raise NotImplementedError - - def delete(self, *args, **kwargs): - raise NotImplementedError - - def find(self, **kwargs): - raise NotImplementedError - - update = report - - -class NotesTable(MsfTable): - - @property - def list(self): - return super(NotesTable, self).records('notes') - - def find(self, **kwargs): - """ - Find notes based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - addresses : a list of addresses to search for. - - names : comma separated string of service names. - - ntype : the note type. - - ports : the port associated with the note. - - proto : the protocol associated with the note. - """ - if 'ports' in kwargs: - kwargs['port'] = True - return super(NotesTable, self).records('notes', **kwargs) - - def report(self, type, data, **kwargs): - """ - Report a Note to the database. Notes can be tied to a Workspace, Host, or Service. - - Mandatory Arguments: - - type : The type of note, e.g. 'smb_peer_os'. - - data : whatever it is you're making a note of. - - Optional Keyword Arguments: - - host : an IP address or a Host object to associate with this Note. - - service : a dict containing 'host', 'port', 'proto' and optionally 'name' keys. - - port : along with 'host' and 'proto', a service to associate with this Note. - - proto : along with 'host' and 'port', a service to associate with this Note. - - update : what to do in case a similar Note exists, see below. - - The 'update' option can have the following values: - - unique : allow only a single Note per host/type pair. - - unique_data : like 'unique', but also compare 'data'. - - insert : always insert a new Note even if one with identical values exists. - - If the provided 'host' is an IP address and does not exist in the database, - it will be created. If 'host' and 'service' are all omitted, the new Note - will be associated with the current 'workspace'. - """ - kwargs.update({ 'data' : data, 'type' : type }) - kwargs.update(kwargs.pop('service', {})) - self.dbreport('note', kwargs) - - def delete(self, **kwargs): - """ - Delete one or more notes based on a search criteria. - - Optional Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - - port : the port associated with a Note. - - proto : the protocol associated with a Note. - - ntype : the note type, e.g. 'smb_peer_os'. - """ - self.dbdel('note', kwargs) - - def get(self, **kwargs): - """ - Get a Note from the database based on the specifications of one or more keyword arguments. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - address : the address associated with a Note, not required if 'host' or 'addr' is specified. - - addr : same as 'address', not required if 'host' or 'address' is specified. - - Optional Keyword Arguments: - - proto : the protocol associated with the Note. - - port : the port associated with the Note. - - ntype : the type of Note. - """ - if not any([i in kwargs for i in ('host', 'address', 'addr')]): - raise TypeError('Expected a host, address, or addr.') - return self.dbget('note', kwargs) - - update = report - - -class LootsTable(MsfTable): - - @property - def list(self): - return super(LootsTable, self).records('loots') - - def find(self, **kwargs): - """ - Find loot based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - """ - return super(LootsTable, self).records('loots', **kwargs) - - def report(self, path, type, **kwargs): - """ - Report Loot to the database - - Mandatory Arguments: - - path : the filesystem path to the Loot - - type : the type of Loot - - ltype : the same as 'type', not required if 'type' is specified. - - Optional Keyword Arguments: - - host : an IP address or a Host object to associate with this Note - - ctype : the content type of the loot, e.g. 'text/plain' - - content_type : same as 'ctype'. - - service : a service to associate Loot with. - - name : a name to associate with this Loot. - - info : additional information about this Loot. - - data : the data within the Loot. - """ - kwargs.update({ 'path' : path, 'type' : type }) - self.dbreport('loot', kwargs) - - update = report - - -class CredsTable(MsfTable): - - @property - def list(self): - return super(CredsTable, self).records('creds') - - def find(self, **kwargs): - """ - Find creds based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - """ - return super(CredsTable, self).records('creds', **kwargs) - - def report(self, host, port, **kwargs): - """ - Store a set of credentials in the database. - - Mandatory Arguments: - - host : an IP address or Host object reference - - port : a port number - - Optional Keyword Arguments: - - user : the username. - - password : the password, or path to ssh_key. - - ptype : the type of password (password(ish), hash, or ssh_key). - - proto : a transport name for the port. - - sname : service name. - - active : by default, a cred is active, unless explicitly false. - - proof : data used to prove the account is actually active. - - Sources: Credentials can be sourced from another credential, or from - a vulnerability. For example, if an exploit was used to dump the - smb_hashes, and this credential comes from there, the source_id would - be the Vuln id (as reported by report_vuln) and the type would be "Vuln". - - - source_id : The Vuln or Cred id of the source of this cred. - - source_type : Either Vuln or Cred. - """ - kwargs.update({'host' : host, 'port' : port}) - kwargs['pass'] = kwargs.get('password') - self.dbreport('cred', kwargs) - - update = report - - -class AuthInfoTable(MsfTable): - - def report(self, host, port, **kwargs): - """ - Store a set of credentials in the database. - - Mandatory Arguments: - - host : an IP address or Host object reference - - port : a port number - - Optional Keyword Arguments: - - user : the username. - - pass : the password, or path to ssh_key. - - ptype : the type of password (password(ish), hash, or ssh_key). - - proto : a transport name for the port. - - sname : service name. - - active : by default, a cred is active, unless explicitly false. - - proof : data used to prove the account is actually active. - - Sources: Credentials can be sourced from another credential, or from - a vulnerability. For example, if an exploit was used to dump the - smb_hashes, and this credential comes from there, the source_id would - be the Vuln id (as reported by report_vuln) and the type would be "Vuln". - - - source_id : The Vuln or Cred id of the source of this cred. - - source_type : Either Vuln or Cred. - """ - kwargs.update({'host' : host, 'port' : port}) - self.dbreport('auth_info', kwargs) - - update = report - - -class HostsTable(MsfTable): - - @property - def list(self): - return super(HostsTable, self).records('hosts') - - def find(self, **kwargs): - """ - Find hosts based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - only_up : find only hosts that are alive. - - addresses : find hosts based on a list of addresses. - """ - return super(HostsTable, self).records('hosts', **kwargs) - - def report(self, host, **kwargs): - """ - Store a host in the database. - - Mandatory Keyword Arguments: - - host : an IP address or Host object reference. - - Optional Keyword Arguments: - - state : a host state. - - os_name : an operating system. - - os_flavor : something like 'XP or 'Gentoo'. - - os_sp : something like 'SP2'. - - os_lang : something like 'English', 'French', or 'en-US'. - - arch : an architecture. - - mac : the host's MAC address. - - scope : interface identifier for link-local IPv6. - - virtual_host : the name of the VM host software, e.g. 'VMWare', 'QEMU', 'Xen', etc. - """ - kwargs.update({'host' : host}) - self.dbreport('host', kwargs) - - def delete(self, **kwargs): - """ - Deletes a host and associated data matching this address/comm. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): - raise TypeError('Expected host, address, or addresses.') - self.dbdel('host', kwargs) - - def get(self, **kwargs): - """ - Get a host in the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - address : the address associated with a Note, not required if 'host' or 'addr' is specified. - - addr : same as 'address', not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('addr', 'address', 'host')]): - raise TypeError('Expected addr, address, or host.') - return self.dbget('host', kwargs) - - update = report - - -class ServicesTable(MsfTable): - - @property - def list(self): - return super(ServicesTable, self).records('services') - - def find(self, **kwargs): - """ - Find hosts based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - only_up : find only hosts that are alive. - - addresses : find hosts based on a list of addresses. - - proto : the protocol of the service. - - ports : a comma separated string of ports. - - names : a comma separated string of service names. - """ - return super(ServicesTable, self).records('services', **kwargs) - - def report(self, host, port, proto, **kwargs): - """ - Record a service in the database. - - Mandatory Arguments: - - host : the host where this service is running. - - port : the port where this service listens. - - proto : the transport layer protocol (e.g. tcp, udp). - - Optional Keyword Arguments: - - name : the application layer protocol (e.g. ssh, mssql, smb) - - sname : an alias for the above - """ - kwargs.update({'host' : host, 'port' : port, 'proto' : proto}) - self.dbreport('service', kwargs) - - def delete(self, **kwargs): - """ - Deletes a port and associated vulns matching this port. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - - or - - - port : used along with 'proto', specifies a service. - - proto : used along with 'port', specifies a service. - """ - if not any([i in kwargs for i in ('host', 'address', 'addresses')]) and \ - not all([i in kwargs for i in ('proto', 'port')]): - raise TypeError('Expected host or port/proto pair.') - self.dbdel('service', kwargs) - - def get(self, **kwargs): - """ - Get a service record from the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - - or - - - port : used along with 'proto', specifies a service. - - proto : used along with 'port', specifies a service. - - Optional Keyword Arguments: - - up : specifies whether or not the service is alive. - - names : a comma separated string of service names. - """ - if not any([i in kwargs for i in ('host', 'addr', 'address')]) and \ - not all([i in kwargs for i in ('proto', 'port')]): - raise TypeError('Expected host or port/proto pair.') - return self.dbget('service', kwargs) - - update = report - - -class VulnsTable(MsfTable): - - @property - def list(self): - return super(VulnsTable, self).records('vulns') - - def find(self, **kwargs): - """ - Find vulns based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - addresses : find hosts based on a list of addresses. - - proto : the protocol of the service. - - ports : a comma separated string of ports. - - names : a comma separated string of service names. - """ - return super(VulnsTable, self).records('vulns', **kwargs) - - def report(self, host, name, **kwargs): - """ - Record a Vuln in the database. - - Mandatory Arguments: - - host : the host where this vulnerability resides. - - name : the scanner-specific id of the vuln (e.g. NEXPOSE-cifs-acct-password-never-expires). - - Optional Keyword Arguments: - - info : a human readable description of the vuln, free-form text. - - refs : an array of Ref objects or string names of references. - """ - kwargs.update({'host' : host, 'name' : name}) - self.dbreport('vuln', kwargs) - - def delete(self, **kwargs): - """ - Deletes a vuln and associated data matching this address/comm. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): - raise TypeError('Expected host, address, or addresses.') - self.dbdel('vuln', kwargs) - - def get(self, **kwargs): - """ - Get a vuln in the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - address : the address associated with a Note, not required if 'host' or 'addr' is specified. - - addr : same as 'address', not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('addr', 'address', 'host')]): - raise TypeError('Expected addr, address, or host.') - return self.dbreport('vuln', kwargs) - - update = report - - -class EventsTable(MsfTable): - - @property - def list(self): - return super(EventsTable, self).records('events') - - def find(self, **kwargs): - """ - Find events based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - """ - return super(EventsTable, self).records('events', **kwargs) - - def report(self, **kwargs): - """ - Record a Vuln in the database. - - Mandatory Arguments: - - username : user that invoked the event. - - host : host that invoked the event. - """ - if not any([i in kwargs for i in ('username', 'host')]): - raise TypeError('Expected either username or host') - self.dbreport('vuln', kwargs) - - update = report - - -class ClientsTable(MsfTable): - - @property - def list(self): - return super(ClientsTable, self).records('clients') - - def find(self, **kwargs): - """ - Find clients based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - ua_name : a user-agent string. - - ua_ver : the user-agent version. - - addresses : a list of IP addresses. - """ - return super(ClientsTable, self).records('clients', **kwargs) - - def report(self, ua_string, host, **kwargs): - """ - Report a client running on a host. - - Mandatory Arguments: - - ua_string : the value of the User-Agent header - - host : the host where this client connected from, can be an ip address or a Host object - - Optional Keyword Arguments - - ua_name : one of the user agent name constants - - ua_ver : detected version of the given client - - campaign : an id or Campaign object - - Returns a Client. - """ - kwargs.update({'host' : host, 'ua_string' : ua_string}) - self.dbreport('client', kwargs) - - def delete(self, **kwargs): - """ - Deletes a client and associated data matching this address/comm. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - """ - self.dbdel('client', kwargs) - - def get(self, **kwargs): - """ - Get a client in the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - ua_string : the value of the User-Agent header - """ - if not any([ i in kwargs for i in ('host', 'ua_string')]): - raise TypeError('Expected host or ua_string.') - return self.dbreport('client', kwargs) - - update = report - - -class Workspace(object): - - def __init__(self, rpc, name): - """ - Initializes a workspace object. - - Mandatory Arguments: - - rpc : the msfrpc client object - - name : the name of the workspace - """ - self.rpc = rpc - self.name = name - - @property - def current(self): - """ - The name of the current workspace. - """ - return self.name - - @current.setter - def current(self, name): - self.name = name - - @property - def notes(self): - """ - Returns the notes table for the current workspace. - """ - return NotesTable(self.rpc, self.name) - - @property - def hosts(self): - """ - Returns the hosts table for the current workspace. - """ - return HostsTable(self.rpc, self.name) - - @property - def services(self): - """ - Returns the services table for the current workspace. - """ - return ServicesTable(self.rpc, self.name) - - @property - def vulns(self): - """ - Returns the vulns table for the current workspace. - """ - return VulnsTable(self.rpc, self.name) - - @property - def events(self): - """ - Returns the events table for the current workspace. - """ - return EventsTable(self.rpc, self.name) - - @property - def loots(self): - """ - Returns the loots table for the current workspace. - """ - return LootsTable(self.rpc, self.name) - - @property - def creds(self): - """ - Returns the creds table for the current workspace. - """ - return CredsTable(self.rpc, self.name) - - @property - def clients(self): - """ - Returns the clients table for the current workspace. - """ - return ClientsTable(self.rpc, self.name) - - def delete(self): - """ - Delete the current workspace. - """ - self.rpc.call(MsfRpcMethod.DbDelWorkspace, {'workspace' : self.name}) - - def importdata(self, data): - self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : data}) - - def importfile(self, fname): - r = file(fname, mode='rb') - self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : r.read()}) - r.close() - - -class MsfManager(object): - - def __init__(self, rpc): - """ - Initialize a msf component manager. - - Mandatory Arguments: - - rpc : the msfrpc client object. - """ - self.rpc = rpc - - -class WorkspaceManager(MsfManager): - - @property - def list(self): - """ - The list of all workspaces in the current msf database. - """ - return self.rpc.call(MsfRpcMethod.DbWorkspaces)['workspaces'] - - def workspace(self, name='default'): - """ - Returns a Workspace object for the given workspace name. - - Optional Arguments: - - name : the name of the workspace - """ - w = self.list - if name not in w: - self.add(name) - return Workspace(self.rpc, name) - - def add(self, name): - """ - Adds a workspace with the given name. - - Mandatory Arguments: - - name : the name of the workspace - """ - self.rpc.call(MsfRpcMethod.DbAddWorkspace, name) - - def get(self, name): - """ - Get a workspace with the given name. - - Mandatory Arguments: - - name : the name of the workspace - """ - return self.rpc.call(MsfRpcMethod.DbGetWorkspace, name)['workspace'] - - def remove(self, name): - """ - Adds a workspace with the given name. - - Mandatory Arguments: - - name : the name of the workspace - """ - self.rpc.call(MsfRpcMethod.DbDelWorkspace, name) - - def set(self, name): - """ - Sets the current workspace. - - Mandatory Arguments: - - name : the name of the workspace - """ - self.rpc.call(MsfRpcMethod.DbSetWorkspace, name) - - @property - def current(self): - """ - The current workspace. - """ - return self.workspace(self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace']) - - -class DbManager(MsfManager): - - def connect(self, username, database='msf', **kwargs): - """ - Connects to a database and creates the msf schema if necessary. - - Mandatory Arguments: - - username : the username for the database connection - - Optional Keyword Arguments: - - host : the IP or hostname of the database server (default: 'localhost') - - driver : the driver to use for the database connection (default: 'postgresql') - - password : the password for the database connection - - database : the database name (default: 'msf') - - port : the port that the server is running on (default: 5432) - """ - runopts = { 'username': username, 'database' : database } - runopts.update(kwargs) - return self.rpc.call(MsfRpcMethod.DbConnect, runopts)['result'] == 'success' - - @property - def driver(self): - """ - The current database driver in use. - """ - return self.rpc.call(MsfRpcMethod.DbDriver, {})['driver'] - - @driver.setter - def driver(self, d): - self.rpc.call(MsfRpcMethod.DbDriver, {'driver' : d}) - - @property - def status(self): - """ - The status of the database connection. - """ - return self.rpc.call(MsfRpcMethod.DbStatus) - - def disconnect(self): - """ - Disconnect from the database. - """ - self.rpc.call(MsfRpcMethod.DbDisconnect) - - @property - def workspaces(self): - """ - A WorkspaceManager object. - """ - return WorkspaceManager(self.rpc) - - @property - def workspace(self): - """ - The name of the current workspace. - """ - return self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace'] - - @workspace.setter - def workspace(self, w): - self.rpc.call(MsfRpcMethod.DbSetWorkspace, w) - - -class AuthManager(MsfManager): - - def login(self, password, **kwargs): - """ - Login to the msfrpc daemon. - - Mandatory Arguments: - - password : the password used to login to msfrpc - - Optional Keyword Arguments: - - username : the username used to authenticate to msfrpcd (default: msf) - - uri : the msfrpcd URI (default: /api/) - - port : the remote msfrpcd port to connect to (default: 55553) - - server : the remote server IP address hosting msfrpcd (default: localhost) - - ssl : if true uses SSL else regular HTTP (default: SSL enabled) - """ - return MsfRpcClient(password, **kwargs) - - def logout(self, sid): - """ - Logs out a user for a given session ID. - - Mandatory Arguments: - - sid : a session ID that is active. - """ - return self.rpc.call(MsfRpcMethod.AuthLogout, sid) - - @property - def tokens(self): - """ - The current list of active session IDs. - """ - return self.rpc.call(MsfRpcMethod.AuthTokenList)['tokens'] - - def add(self, token): - """ - Add a session ID or token. - - Mandatory Argument: - - token : a random string used as a session identifier. - """ - self.rpc.call(MsfRpcMethod.AuthTokenAdd, token) - - def remove(self, token): - """ - Remove a session ID or token. - - Mandatory Argument: - - token : a session ID or token that is active. - """ - self.rpc.call(MsfRpcMethod.AuthTokenRemove, token) - - def generate(self): - """ - Generate a session ID or token. - """ - return self.rpc.call(MsfRpcMethod.AuthTokenGenerate)['token'] - - -class PluginManager(MsfManager): - - @property - def list(self): - """ - A list of loaded plugins. - """ - return self.rpc.call(MsfRpcMethod.PluginLoaded)['plugins'] - - def load(self, plugin): - """ - Load a plugin of a given name. - - Mandatory Arguments: - - plugin : a name of a plugin to load. - """ - self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginLoad, plugin) - - def unload(self, plugin): - """ - Unload a plugin of a given name. - - Mandatory Arguments: - - plugin : a name of a loaded plugin to unload. - """ - self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginUnload, plugin) - - -class JobManager(MsfManager): - - @property - def list(self): - """ - A list of currently running jobs. - """ - return self.rpc.call(MsfRpcMethod.JobList) - - def stop(self, jobid): - """ - Stop a job. - - Mandatory Argument: - - jobid : the ID of the job. - """ - self.rpc.call(MsfRpcMethod.JobStop, jobid) - - def info(self, jobid): - """ - Get job information for a particular job. - - Mandatory Argument: - - jobid : the ID of the job. - """ - return self.rpc.call(MsfRpcMethod.JobInfo, jobid) - - -class CoreManager(MsfManager): - - @property - def version(self): - """ - The version of msf core. - """ - return self.rpc.call(MsfRpcMethod.CoreVersion) - - def stop(self): - """ - Stop the core. - """ - self.rpc.call(MsfRpcMethod.CoreStop) - - def setg(self, var, val): - """ - Set a global variable - - Mandatory Arguments: - - var : the variable name - - val : the variable value - """ - self.rpc.call(MsfRpcMethod.CoreSetG, var, val) - - def unsetg(self, var): - """ - Unset a global variable - - Mandatory Arguments: - - var : the variable name - """ - self.rpc.call(MsfRpcMethod.CoreUnsetG, var) - - def save(self): - """ - Save the core state. - """ - self.rpc.call(MsfRpcMethod.CoreSave) - - def reload(self): - """ - Reload all modules in the core. - """ - self.rpc.call(MsfRpcMethod.CoreReloadModules) - - @property - def stats(self): - """ - Get module statistics from the core. - """ - return self.rpc.call(MsfRpcMethod.CoreModuleStats) - - def addmodulepath(self, path): - """ - Add a search path for additional modules. - - Mandatory Arguments: - - path : the path to search for modules. - """ - return self.rpc.call(MsfRpcMethod.CoreAddModulePath, path) - - @property - def threads(self): - """ - The current threads running in the core. - """ - return self.rpc.call(MsfRpcMethod.CoreThreadList) - - def kill(self, threadid): - """ - Kill a thread running in the core. - - Mandatory Arguments: - - threadid : the thread ID. - """ - self.rpc.call(MsfRpcMethod.CoreThreadKill, threadid) - - -class MsfModule(object): - - def __init__(self, rpc, mtype, mname): - """ - Initializes an msf module object. - - Mandatory Arguments: - - rpc : the msfrpc client object. - - mtype : the module type (e.g. 'exploit') - - mname : the module name (e.g. 'exploits/windows/http/icecast_header') - """ - self.moduletype = mtype - self.modulename = mname - self.rpc = rpc - self._info = rpc.call(MsfRpcMethod.ModuleInfo, mtype, mname) - for k in self._info: - setattr(self, k, self._info.get(k)) - self._moptions = rpc.call(MsfRpcMethod.ModuleOptions, mtype, mname) - self._roptions = [] - self._aoptions = [] - self._eoptions = [] - self._runopts = {} - for o in self._moptions: - if self._moptions[o]['required']: - self._roptions.append(o) - if self._moptions[o]['advanced']: - self._aoptions.append(o) - if self._moptions[o]['evasion']: - self._eoptions.append(o) - if 'default' in self._moptions[o]: - self._runopts[o] = self._moptions[o]['default'] - - @property - def options(self): - """ - All the module options. - """ - return self._moptions.keys() - - @property - def required(self): - """ - The required module options. - """ - return self._roptions - - @property - def evasion(self): - """ - Module options that are used for evasion. - """ - return self._eoptions - - @property - def advanced(self): - """ - Advanced module options. - """ - return self._aoptions - - @property - def runoptions(self): - """ - The running (currently set) options for a module. This will raise an error - if some of the required options are missing. - """ - outstanding = set(self.required).difference(self._runopts.keys()) - if outstanding: - raise TypeError('Module missing required parameter: %s' % ', '.join(outstanding)) - return self._runopts - - def optioninfo(self, option): - """ - Get information about the module option - - Mandatory Argument: - - option : the option name. - """ - return self._moptions[option] - - def __getitem__(self, item): - """ - Get the current option value. - - Mandatory Arguments: - - item : the option name. - """ - if item not in self._moptions: - raise KeyError("Invalid option '%s'." % item) - return self._runopts.get(item) - - def __setitem__(self, key, value): - """ - Set the current option value. - - Mandatory Arguments: - - key : the option name. - - value : the option value. - """ - if key not in self.options: - raise KeyError("Invalid option '%s'." % key) - elif 'enums' in self._moptions[key] and value not in self._moptions[key]['enums']: - raise ValueError("Value ('%s') is not one of %s" % (value, repr(self._moptions[key]['enums']))) - elif self._moptions[key]['type'] == 'bool' and not isinstance(value, bool): - raise TypeError("Value must be a boolean not '%s'" % type(value).__name__) - elif self._moptions[key]['type'] in ['integer', 'float'] and not isinstance(value, Number): - raise TypeError("Value must be an integer not '%s'" % type(value).__name__) - self._runopts[key] = value - - def __delitem__(self, key): - del self._runopts[key] - - def __contains__(self, item): - return item in self._runopts - - def update(self, d): - """ - Update a set of options. - - Mandatory Arguments: - - d : a dictionary of options - """ - for k in d: - self[k] = d[k] - - def execute(self, **kwargs): - """ - Executes the module with its run options as parameters. - - Optional Keyword Arguments: - - payload : the payload of an exploit module (this is mandatory if the module is an exploit). - - **kwargs : can contain any module options. - """ - runopts = self.runoptions.copy() - if isinstance(self, ExploitModule): - payload = kwargs.get('payload') - runopts['TARGET'] = self.target - if 'DisablePayloadHandler' in runopts and runopts['DisablePayloadHandler']: - pass - elif payload is None: - runopts['DisablePayloadHandler'] = True - else: - if isinstance(payload, PayloadModule): - if payload.modulename not in self.payloads: - raise ValueError( - 'Invalid payload (%s) for given target (%d).' % (payload.modulename, self.target) - ) - runopts['PAYLOAD'] = payload.modulename - for k, v in payload.runoptions.iteritems(): - if v is None or (isinstance(v, basestring) and not v): - continue - if k not in runopts or runopts[k] is None or \ - (isinstance(runopts[k], basestring) and not runopts[k]): - runopts[k] = v -# runopts.update(payload.runoptions) - elif isinstance(payload, basestring): - if payload not in self.payloads: - raise ValueError('Invalid payload (%s) for given target (%d).' % (payload, self.target)) - runopts['PAYLOAD'] = payload - else: - raise TypeError("Expected type str or PayloadModule not '%s'" % type(kwargs['payload']).__name__) - - return self.rpc.call(MsfRpcMethod.ModuleExecute, self.moduletype, self.modulename, runopts) - - -class ExploitModule(MsfModule): - - def __init__(self, rpc, exploit): - """ - Initializes the use of an exploit module. - - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - exploit : the name of the exploit module. - """ - super(ExploitModule, self).__init__(rpc, 'exploit', exploit) - self._target = self._info.get('default_target', 0) - - @property - def payloads(self): - """ - A list of compatible payloads. - """ -# return self.rpc.call(MsfRpcMethod.ModuleCompatiblePayloads, self.modulename)['payloads'] - return self.targetpayloads(self.target) - - @property - def target(self): - return self._target - - @target.setter - def target(self, target): - if target not in self.targets: - raise ValueError('Target must be one of %s' % repr(self.targets.keys())) - self._target = target - - def targetpayloads(self, t=0): - """ - Returns a list of compatible payloads for a given target ID. - - Optional Keyword Arguments: - - t : the target ID (default: 0, e.g. 'Automatic') - """ - return self.rpc.call(MsfRpcMethod.ModuleTargetCompatiblePayloads, self.modulename, t)['payloads'] - - -class PostModule(MsfModule): - - def __init__(self, rpc, post): - """ - Initializes the use of a post exploitation module. - - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - post : the name of the post exploitation module. - """ - super(PostModule, self).__init__(rpc, 'post', post) - - @property - def sessions(self): - """ - A list of compatible shell/meterpreter sessions. - """ - return self.rpc.compatiblesessions(self.modulename) - - -class EncoderModule(MsfModule): - - def __init__(self, rpc, encoder): - """ - Initializes the use of an encoder module. - - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - encoder : the name of the encoder module. - """ - super(EncoderModule, self).__init__(rpc, 'encoder', encoder) - - -class AuxiliaryModule(MsfModule): - - def __init__(self, rpc, auxiliary): - """ - Initializes the use of an auxiliary module. - - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - auxiliary : the name of the auxiliary module. - """ - super(AuxiliaryModule, self).__init__(rpc, 'auxiliary', auxiliary) - - -class PayloadModule(MsfModule): - - def __init__(self, rpc, payload): - """ - Initializes the use of a payload module. - - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - payload : the name of the payload module. - """ - super(PayloadModule, self).__init__(rpc, 'payload', payload) - - -class NopModule(MsfModule): - - def __init__(self, rpc, nop): - """ - Initializes the use of a nop module. - - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - nop : the name of the nop module. - """ - super(NopModule, self).__init__(rpc, 'nop', nop) - - -class ModuleManager(MsfManager): - - def execute(self, modtype, modname, **kwargs): - """ - Execute the module. - - Mandatory Arguments: - - modtype : the module type (e.g. 'exploit') - - modname : the module name (e.g. 'exploits/windows/http/icecast_header') - - Optional Keyword Arguments: - - **kwargs : the module's run options - """ - return self.rpc.call(MsfRpcMethod.ModuleExecute, modtype, modname, kwargs) - - @property - def exploits(self): - """ - A list of exploit modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleExploits)['modules'] - - @property - def payloads(self): - """ - A list of payload modules. - """ - return self.rpc.call(MsfRpcMethod.ModulePayloads)['modules'] - - @property - def auxiliary(self): - """ - A list of auxiliary modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleAuxiliary)['modules'] - - @property - def post(self): - """ - A list of post modules. - """ - return self.rpc.call(MsfRpcMethod.ModulePost)['modules'] - - @property - def encodeformats(self): - """ - A list of encoding formats. - """ - return self.rpc.call(MsfRpcMethod.ModuleEncodeFormats) - - @property - def encoders(self): - """ - A list of encoder modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleEncoders)['modules'] - - @property - def nops(self): - """ - A list of nop modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleNops)['modules'] - - def use(self, mtype, mname): - """ - Returns a module object. - - Mandatory Arguments: - - mname : the module name (e.g. 'exploits/windows/http/icecast_header') - """ - if mtype == 'exploit': - return ExploitModule(self.rpc, mname) - elif mtype == 'post': - return PostModule(self.rpc, mname) - elif mtype == 'encoder': - return EncoderModule(self.rpc, mname) - elif mtype == 'auxiliary': - return AuxiliaryModule(self.rpc, mname) - elif mtype == 'nop': - return NopModule(self.rpc, mname) - elif mtype == 'payload': - return PayloadModule(self.rpc, mname) - raise MsfRpcError('Unknown module type %s not: exploit, post, encoder, auxiliary, nop, or payload' % mname) - - -class MsfSession(object): - - def __init__(self, id, rpc, sd): - """ - Initialize a meterpreter or shell session. - - Mandatory Arguments: - - id : the session identifier. - - rpc : the msfrpc client object. - - sd : the session description - """ - self.id = id - self.rpc = rpc - self.__dict__.update(sd) - - def stop(self): - """ - Stop a meterpreter or shell session. - """ - return self.rpc.call(MsfRpcMethod.SessionStop, self.id) - - @property - def modules(self): - """ - A list of compatible session modules. - """ - return self.rpc.call(MsfRpcMethod.SessionCompatibleModules, self.id)['modules'] - - @property - def ring(self): - return SessionRing(self.rpc, self.id) - - -class SessionRing(object): - - def __init__(self, rpc, sessionid): - self.rpc = rpc - self.id = sessionid - - def read(self, seq=None): - """ - Reads the session ring. - - Optional Keyword Arguments: - - seq : the sequence ID of the ring (default: 0) - """ - if seq is not None: - return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id, seq) - return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id) - - def put(self, line): - """ - Add a command to the session history. - - Mandatory Arguments: - - line : arbitrary data. - """ - self.rpc.call(MsfRpcMethod.SessionRingPut, self.id, line) - - @property - def last(self): - """ - Returns the last sequence ID in the session ring. - """ - return int(self.rpc.call(MsfRpcMethod.SessionRingLast, self.id)['seq']) - - def clear(self): - """ - Clear the session ring. - """ - return self.rpc.call(MsfRpcMethod.SessionRingClear, self.id) - - -class MeterpreterSession(MsfSession): - - def read(self): - """ - Read data from the meterpreter session. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterRead, self.id)['data'] - - def write(self, data): - """ - Write data to the meterpreter session. - - Mandatory Arguments: - - data : arbitrary data or commands - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterWrite, self.id, data) - - def runsingle(self, data): - """ - Run a single meterpreter command - - Mandatory Arguments: - - data : arbitrary data or command - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterRunSingle, self.id, data) - return self.read() - - def runscript(self, path): - """ - Run a meterpreter script - - Mandatory Arguments: - - path : path to a meterpreter script on the msfrpcd host. - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterScript, self.id, path) - return self.read() - - @property - def sep(self): - """ - The operating system path separator. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterDirectorySeparator, self.id)['separator'] - - def detach(self): - """ - Detach the meterpreter session. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionDetach, self.id) - - def kill(self): - """ - Kill the meterpreter session. - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionKill, self.id) - - def tabs(self, line): - """ - Return a list of commands for a partial command line (tab completion). - - Mandatory Arguments: - - line : a partial command line for completion. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterTabs, self.id, line)['tabs'] - - -class ShellSession(MsfSession): - - def read(self): - """ - Read data from the shell session. - """ - return self.rpc.call(MsfRpcMethod.SessionShellRead, self.id)['data'] - - def write(self, data): - """ - Write data to the shell session. - - Mandatory Arguments: - - data : arbitrary data or commands - """ - self.rpc.call(MsfRpcMethod.SessionShellWrite, self.id, data) - - def upgrade(self, lhost, lport): - """ - Upgrade the current shell session. - """ - self.rpc.call(MsfRpcMethod.SessionShellUpgrade, self.id, lhost, lport) - return self.read() - - -class SessionManager(MsfManager): - - @property - def list(self): - """ - A list of active sessions. - """ - return self.rpc.call(MsfRpcMethod.SessionList) - - def session(self, id): - """ - Returns a session object for meterpreter or shell sessions. - - Mandatory Arguments: - - id : the session identifier. - """ - s = self.list - if id not in s: - for k in s: - if s[k]['uuid'] == id: - if s[id]['type'] == 'meterpreter': - return MeterpreterSession(id, self.rpc, s) - elif s[id]['type'] == 'shell': - return ShellSession(id, self.rpc, s) - raise KeyError('Session ID (%s) does not exist' % id) - if s[id]['type'] == 'meterpreter': - return MeterpreterSession(id, self.rpc, s) - elif s[id]['type'] == 'shell': - return ShellSession(id, self.rpc, s) - raise NotImplementedError('Could not determine session type: %s' % s[id]['type']) - - -class MsfConsole(object): - - def __init__(self, rpc, cid=None): - """ - Initializes an msf console. - - Mandatory Arguments: - - rpc : the msfrpc client object. - - Optional Keyword Arguments: - - cid : the console identifier if it exists already otherwise a new one will be created. - """ - self.rpc = rpc - if cid is None: - r = self.rpc.call(MsfRpcMethod.ConsoleCreate) - if 'id' in r: - self.cid = r['id'] - else: - raise MsfRpcError('Unable to create a new console.') - else: - self.cid = cid - - def read(self): - """ - Read data from the console. - """ - return self.rpc.call(MsfRpcMethod.ConsoleRead, self.cid) - - def write(self, command): - """ - Write data to the console. - """ - if not command.endswith('\n'): - command += '\n' - self.rpc.call(MsfRpcMethod.ConsoleWrite, self.cid, command) - - def sessionkill(self): - """ - Kill all active meterpreter or shell sessions. - """ - self.rpc.call(MsfRpcMethod.ConsoleSessionKill, self.cid) - - def sessiondetach(self): - """ - Detach the current meterpreter or shell session. - """ - self.rpc.call(MsfRpcMethod.ConsoleSessionDetach, self.cid) - - def tabs(self, line): - """ - Tab completion for console commands. - - Mandatory Arguments: - - line : a partial command to be completed. - """ - return self.rpc.call(MsfRpcMethod.ConsoleTabs, self.cid, line)['tabs'] - - def destroy(self): - """ - Destroy the console. - """ - self.rpc.call(MsfRpcMethod.ConsoleDestroy, self.cid) - - -class ConsoleManager(MsfManager): - - @property - def list(self): - """ - A list of active consoles. - """ - return self.rpc.call(MsfRpcMethod.ConsoleList) - - def console(self, cid=None): - """ - Connect to an active console otherwise create a new console. - - Optional Keyword Arguments: - - cid : the console identifier. - """ - s = self.list - if cid is None: - return MsfConsole(self.rpc) - if cid not in s: - raise KeyError('Console ID (%s) does not exist' % cid) - else: - return MsfConsole(self.rpc, cid=cid) - - def destroy(self, cid): - """ - Destory an active console. - - Mandatory Arguments: - - cid : the console identifier. - """ - self.rpc.call(MsfRpcMethod.ConsoleDestroy, cid) diff --git a/src/metasploit/utils.py.bak b/src/metasploit/utils.py.bak deleted file mode 100644 index d7cffa5..0000000 --- a/src/metasploit/utils.py.bak +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python - -from optparse import OptionParser - -__author__ = 'Nadeem Douba' -__copyright__ = 'Copyright 2012, PyMetasploit Project' -__credits__ = [] - -__license__ = 'GPL' -__version__ = '0.1' -__maintainer__ = 'Nadeem Douba' -__email__ = 'ndouba@gmail.com' -__status__ = 'Development' - -__all__ = [ - 'parseargs' -] - - -def parseargs(): - p = OptionParser() - p.add_option("-P", dest="password", help="Specify the password to access msfrpcd", metavar="opt") - p.add_option("-S", dest="ssl", help="Disable SSL on the RPC socket", action="store_false", default=True) - p.add_option("-U", dest="username", help="Specify the username to access msfrpcd", metavar="opt", default="msf") - p.add_option("-a", dest="server", help="Connect to this IP address", metavar="host", default="127.0.0.1") - p.add_option("-p", dest="port", help="Connect to the specified port instead of 55553", metavar="opt", default=55553) - o, a = p.parse_args() - if o.password is None: - print '[-] Error: a password must be specified (-P)\n' - p.print_help() - exit(-1) - return o \ No newline at end of file From 5aca68cc6d7bbce297bd4ca86a6ee0263bafa970 Mon Sep 17 00:00:00 2001 From: aoighost Date: Mon, 17 Jul 2017 09:07:09 -0400 Subject: [PATCH 10/17] fixed whitespace mismatch --- src/metasploit/msfrpc.py | 50 ++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index 92960df..0bfbad8 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -1,5 +1,4 @@ #!/usr/bin/env python - from http.client import HTTPConnection, HTTPSConnection import ssl from numbers import Number @@ -16,8 +15,7 @@ __email__ = 'ndouba@gmail.com' __status__ = 'Development' -__all__ = [ - 'MsfRpcError', +__all__ = ['MsfRpcError', 'MsfRpcMethod', 'MsfPlugins', 'MsfRpcClient', @@ -54,8 +52,7 @@ 'MsfConsole', 'ConsoleManager', 'ReportFilter', - 'ReportFilterQuery' -] + 'ReportFilterQuery'] class MsfRpcError(Exception): @@ -197,20 +194,20 @@ def __init__(self, password, **kwargs): - ssl : if true uses SSL else regular HTTP (default: SSL enabled) - verify : if true, verify SSL cert when using SSL (default: False) """ - self.uri = kwargs.get('uri', '/api/') - self.port = kwargs.get('port', 55552) - self.server = kwargs.get('server', '127.0.0.1') - self.ssl = kwargs.get('ssl', True) - self.verify_ssl = kwargs.get('verify', False) - self.sessionid = kwargs.get('token') - if self.ssl: - if self.verify_ssl: - self.client = HTTPSConnection(self.server, self.port) - else: - self.client = HTTPSConnection(self.server, self.port, context=ssl._create_unverified_context()) - else: - self.client = HTTPConnection(self.server, self.port) - self.login(kwargs.get('username', 'msf'), password) + self.uri = kwargs.get('uri', '/api/') + self.port = kwargs.get('port', 55552) + self.server = kwargs.get('server', '127.0.0.1') + self.ssl = kwargs.get('ssl', True) + self.verify_ssl = kwargs.get('verify', False) + self.sessionid = kwargs.get('token') + if self.ssl: + if self.verify_ssl: + self.client = HTTPSConnection(self.server, self.port) + else: + self.client = HTTPSConnection(self.server, self.port, context=ssl._create_unverified_context()) + else: + self.client = HTTPConnection(self.server, self.port) + self.login(kwargs.get('username', 'msf'), password) def unpackb_wrapper(self, data): return self.unpackb_wrapf(data) @@ -246,7 +243,7 @@ def call(self, method, *args): Returns : RPC call result """ - l = [ method ] + l = [method] l.extend(args) if method == MsfRpcMethod.AuthLogin: self.client.request('POST', self.uri, packb(l), self._headers) @@ -334,7 +331,7 @@ def login(self, username, password): Authenticates and reauthenticates the user to msfrpcd. """ if self.sessionid is None: - r = self.call(MsfRpcMethod.AuthLogin, username, password); + r = self.call(MsfRpcMethod.AuthLogin, username, password) try: if r['result'] == 'success': self.sessionid = r['token'] @@ -1479,9 +1476,7 @@ def execute(self, **kwargs): else: if isinstance(payload, PayloadModule): if payload.modulename not in self.payloads: - raise ValueError( - 'Invalid payload (%s) for given target (%d).' % (payload.modulename, self.target) - ) + raise ValueError('Invalid payload (%s) for given target (%d).' % (payload.modulename, self.target)) runopts['PAYLOAD'] = payload.modulename for k, v in payload.runoptions.items(): if v is None or (isinstance(v, str) and not v): @@ -1518,7 +1513,8 @@ def payloads(self): """ A list of compatible payloads. """ -# return self.rpc.call(MsfRpcMethod.ModuleCompatiblePayloads, self.modulename)['payloads'] +# return self.rpc.call(MsfRpcMethod.ModuleCompatiblePayloads, +# self.modulename)['payloads'] return self.targetpayloads(self.target) @property @@ -1885,12 +1881,12 @@ def session(self, id): if s[k]['uuid'] == id: if s[id]['type'] == 'meterpreter': return MeterpreterSession(id, self.rpc, s) - elif s[id]['type'] == 'shell': + elif s[id]['type'] == 'shell': return ShellSession(id, self.rpc, s) raise KeyError('Session ID (%s) does not exist' % id) if s[id]['type'] == 'meterpreter': return MeterpreterSession(id, self.rpc, s) - elif s[id]['type'] == 'shell': + elif s[id]['type'] == 'shell': return ShellSession(id, self.rpc, s) raise NotImplementedError('Could not determine session type: %s' % s[id]['type']) From e493c36ebae079e55aad343346a55b6240c56fb2 Mon Sep 17 00:00:00 2001 From: Mika Ayenson Date: Mon, 17 Jul 2017 16:08:00 -0400 Subject: [PATCH 11/17] Don't try to set property attributes. Bug Fix: https://github.com/allfro/pymetasploit/issues/11 --- .DS_Store | Bin 0 -> 6148 bytes src/.DS_Store | Bin 0 -> 6148 bytes src/metasploit/msfrpc.py | 6 +++++- 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .DS_Store create mode 100644 src/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..81229e8d26382bd3469cb3d9bb2de3f1954844ac GIT binary patch literal 6148 zcmeH~Jqp4=5QS&dB4Cr!avKle4VIuM@B*S@B?yZB9^E%TjnP_yyn&f-XEsBUS7b9H zqQmpN5$Q#wgBxXSVPuMYE)TiO>2iLYjtb*@FJ*K=2U&T%hcRwa*e@u>x3=Er<$CqZN!+^)bZi z-VT<$t|nVB+C_8t(7dzS6a&*}7cEF&S{)2jfC`Khm`C2*`M-mIoBu~GOsN1B_%j7` zvE6S6yi}g8AFpTiLso6w;GkcQ@b(jc#E#+>+ztE17GO=bASy8a2)GOkRN$uyya2`( B5q1Co literal 0 HcmV?d00001 diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a8aa742f92d36262077612c7ad68e8d708e861a8 GIT binary patch literal 6148 zcmeHKJ5EC}5S)b+5i}_&eFbh{Md1WofKNa|3VKL^{#7|wj>hb#AbLp`nrK#9kG4F-JRdy;)T;M^O0;*E^wzx?<0 z_Vr~LHl84p0#ZN Date: Mon, 17 Jul 2017 16:15:07 -0400 Subject: [PATCH 12/17] remove ds store files --- .DS_Store | Bin 6148 -> 0 bytes src/.DS_Store | Bin 6148 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store delete mode 100644 src/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 81229e8d26382bd3469cb3d9bb2de3f1954844ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jqp4=5QS&dB4Cr!avKle4VIuM@B*S@B?yZB9^E%TjnP_yyn&f-XEsBUS7b9H zqQmpN5$Q#wgBxXSVPuMYE)TiO>2iLYjtb*@FJ*K=2U&T%hcRwa*e@u>x3=Er<$CqZN!+^)bZi z-VT<$t|nVB+C_8t(7dzS6a&*}7cEF&S{)2jfC`Khm`C2*`M-mIoBu~GOsN1B_%j7` zvE6S6yi}g8AFpTiLso6w;GkcQ@b(jc#E#+>+ztE17GO=bASy8a2)GOkRN$uyya2`( B5q1Co diff --git a/src/.DS_Store b/src/.DS_Store deleted file mode 100644 index a8aa742f92d36262077612c7ad68e8d708e861a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ5EC}5S)b+5i}_&eFbh{Md1WofKNa|3VKL^{#7|wj>hb#AbLp`nrK#9kG4F-JRdy;)T;M^O0;*E^wzx?<0 z_Vr~LHl84p0#ZN Date: Fri, 4 Aug 2017 22:05:19 -0400 Subject: [PATCH 13/17] removing github desktop garbage --- src/metasploit/msfrpc.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index 2c575c6..9854374 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -1,6 +1,4 @@ #!/usr/bin/env python - -from httplib import HTTPConnection, HTTPSConnection from http.client import HTTPConnection, HTTPSConnection import ssl from numbers import Number @@ -1336,7 +1334,6 @@ def kill(self, threadid): class MsfModule(object): -<<<<<<< HEAD def __init__(self, rpc, mtype, mname): """ Initializes an msf module object. @@ -1662,7 +1659,6 @@ def execute(self, **kwargs): raise TypeError("Expected type str or PayloadModule not '%s'" % type(kwargs['payload']).__name__) return self.rpc.call(MsfRpcMethod.ModuleExecute, self.moduletype, self.modulename, runopts) ->>>>>>> pr/3 class ExploitModule(MsfModule): From 3aef4ce43e02553fa8db0152c4abdbd668a1976b Mon Sep 17 00:00:00 2001 From: Mika Ayenson Date: Fri, 4 Aug 2017 22:14:20 -0400 Subject: [PATCH 14/17] remove ds --- .DS_Store | Bin 6148 -> 0 bytes src/.DS_Store | Bin 6148 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store delete mode 100644 src/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 5172429f264de2441865cb4700216d4256da9242..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~J!%6%427R!7lt%jx}3%b$PET#pTHLgIFQEJ;E>dF^gR7ES*H$5cmnB-G%I%Z zD|S`@Z2$T80!#olbXV*=%*>dt@PRwdU#I)^a=X5>;#J@&VrHyNnC;iLL0pQvfVyTmjO&;ssLc!1UOG})p;=82 zR;?Ceh}WZ?+UmMqI#RP8R>OzYoz15hnq@nzF`-!xQ4j$Um=RcIKKc27r2jVm&svm< zfC&6E0=7P!4tu^-ovjbA=k?dB`g+i*aXG_}p8zI)6mRKa+;6_1_R^8c3Qa!(fk8n8 H{*=HsM+*^= diff --git a/src/.DS_Store b/src/.DS_Store deleted file mode 100644 index b2a6b3e6c870dde3f033c72e8cfe8a9aab8f5326..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKOG-mQ5UkdK0XJD@IalxoLx?BH1p*O5K%yk-`mJ&$ zdAwS@eht7D?@tfF48WA`h?9r0`MLYZZYpC$I`4SJ8;&2V!~XeYRDC(&+&dhx!2!FU z{QWj>y-ZV93P=GdAO)m=6!@hA-g{}&`$R=4AO)nrw*vlsXmrP3I3&iWgCRx$;)Lli zu49%UHct?H;gHA-&5}w?s?~^LNoT%QT`wFGlMbul!|KUa6N<&td4G#?SWi@x0#e{y zf!o~9y#GJaugw4FB<-Yt6!=#P*krj{F8E5-TSqVFy|&TUbg%iOyKx;9hG@scXvf@m fJDx{T)-_-AycZ6ML1#YbMEwl7E;1?b*9v?AELauN From 7ebfeb5a1d5ca0a7b58b09debc487c92f55033b6 Mon Sep 17 00:00:00 2001 From: Mika Ayenson Date: Fri, 4 Aug 2017 22:18:04 -0400 Subject: [PATCH 15/17] remove github desktop garbage --- src/metasploit/msfrpc.py | 160 --------------------------------------- 1 file changed, 160 deletions(-) diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index 9854374..e35e219 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -1499,166 +1499,6 @@ def execute(self, **kwargs): raise TypeError("Expected type str or PayloadModule not '%s'" % type(kwargs['payload']).__name__) return self.rpc.call(MsfRpcMethod.ModuleExecute, self.moduletype, self.modulename, runopts) -======= - def __init__(self, rpc, mtype, mname): - """ - Initializes an msf module object. - - Mandatory Arguments: - - rpc : the msfrpc client object. - - mtype : the module type (e.g. 'exploit') - - mname : the module name (e.g. 'exploits/windows/http/icecast_header') - """ - self.moduletype = mtype - self.modulename = mname - self.rpc = rpc - self._info = rpc.call(MsfRpcMethod.ModuleInfo, mtype, mname) - for k in self._info: - setattr(self, k, self._info.get(k)) - self._moptions = rpc.call(MsfRpcMethod.ModuleOptions, mtype, mname) - self._roptions = [] - self._aoptions = [] - self._eoptions = [] - self._runopts = {} - for o in self._moptions: - if self._moptions[o]['required']: - self._roptions.append(o) - if self._moptions[o]['advanced']: - self._aoptions.append(o) - if self._moptions[o]['evasion']: - self._eoptions.append(o) - if 'default' in self._moptions[o]: - self._runopts[o] = self._moptions[o]['default'] - - @property - def options(self): - """ - All the module options. - """ - return list(self._moptions.keys()) - - @property - def required(self): - """ - The required module options. - """ - return self._roptions - - @property - def evasion(self): - """ - Module options that are used for evasion. - """ - return self._eoptions - - @property - def advanced(self): - """ - Advanced module options. - """ - return self._aoptions - - @property - def runoptions(self): - """ - The running (currently set) options for a module. This will raise an error - if some of the required options are missing. - """ - outstanding = set(self.required).difference(list(self._runopts.keys())) - if outstanding: - raise TypeError('Module missing required parameter: %s' % ', '.join(outstanding)) - return self._runopts - - def optioninfo(self, option): - """ - Get information about the module option - - Mandatory Argument: - - option : the option name. - """ - return self._moptions[option] - - def __getitem__(self, item): - """ - Get the current option value. - - Mandatory Arguments: - - item : the option name. - """ - if item not in self._moptions: - raise KeyError("Invalid option '%s'." % item) - return self._runopts.get(item) - - def __setitem__(self, key, value): - """ - Set the current option value. - - Mandatory Arguments: - - key : the option name. - - value : the option value. - """ - if key not in self.options: - raise KeyError("Invalid option '%s'." % key) - elif 'enums' in self._moptions[key] and value not in self._moptions[key]['enums']: - raise ValueError("Value ('%s') is not one of %s" % (value, repr(self._moptions[key]['enums']))) - elif self._moptions[key]['type'] == 'bool' and not isinstance(value, bool): - raise TypeError("Value must be a boolean not '%s'" % type(value).__name__) - elif self._moptions[key]['type'] in ['integer', 'float'] and not isinstance(value, Number): - raise TypeError("Value must be an integer not '%s'" % type(value).__name__) - self._runopts[key] = value - - def __delitem__(self, key): - del self._runopts[key] - - def __contains__(self, item): - return item in self._runopts - - def update(self, d): - """ - Update a set of options. - - Mandatory Arguments: - - d : a dictionary of options - """ - for k in d: - self[k] = d[k] - - def execute(self, **kwargs): - """ - Executes the module with its run options as parameters. - - Optional Keyword Arguments: - - payload : the payload of an exploit module (this is mandatory if the module is an exploit). - - **kwargs : can contain any module options. - """ - runopts = self.runoptions.copy() - if isinstance(self, ExploitModule): - payload = kwargs.get('payload') - runopts['TARGET'] = self.target - if 'DisablePayloadHandler' in runopts and runopts['DisablePayloadHandler']: - pass - elif payload is None: - runopts['DisablePayloadHandler'] = True - else: - if isinstance(payload, PayloadModule): - if payload.modulename not in self.payloads: - raise ValueError('Invalid payload (%s) for given target (%d).' % (payload.modulename, self.target)) - runopts['PAYLOAD'] = payload.modulename - for k, v in payload.runoptions.items(): - if v is None or (isinstance(v, str) and not v): - continue - if k not in runopts or runopts[k] is None or \ - (isinstance(runopts[k], str) and not runopts[k]): - runopts[k] = v -# runopts.update(payload.runoptions) - elif isinstance(payload, str): - if payload not in self.payloads: - raise ValueError('Invalid payload (%s) for given target (%d).' % (payload, self.target)) - runopts['PAYLOAD'] = payload - else: - raise TypeError("Expected type str or PayloadModule not '%s'" % type(kwargs['payload']).__name__) - - return self.rpc.call(MsfRpcMethod.ModuleExecute, self.moduletype, self.modulename, runopts) class ExploitModule(MsfModule): From d5c827fe1badf1b8a91aafa16731d4f4dfa1280e Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 2 Mar 2018 18:49:53 -0700 Subject: [PATCH 16/17] changed http.client to httplib for py2 --- src/metasploit/msfrpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index e35e219..f489276 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from http.client import HTTPConnection, HTTPSConnection +from httplib import HTTPConnection, HTTPSConnection import ssl from numbers import Number From f3a082bf1b86df051aaaabc021cac8b408e0de89 Mon Sep 17 00:00:00 2001 From: Dan Date: Sat, 3 Mar 2018 15:49:21 -0700 Subject: [PATCH 17/17] fixed attributeerror and console listings --- src/metasploit/msfrpc.py | 3208 +++++++++++++++++++------------------- 1 file changed, 1593 insertions(+), 1615 deletions(-) diff --git a/src/metasploit/msfrpc.py b/src/metasploit/msfrpc.py index f489276..ba10f31 100644 --- a/src/metasploit/msfrpc.py +++ b/src/metasploit/msfrpc.py @@ -1,4 +1,5 @@ #!/usr/bin/env python + from httplib import HTTPConnection, HTTPSConnection import ssl from numbers import Number @@ -15,176 +16,178 @@ __email__ = 'ndouba@gmail.com' __status__ = 'Development' -__all__ = ['MsfRpcError', - 'MsfRpcMethod', - 'MsfPlugins', - 'MsfRpcClient', - 'MsfTable', - 'NotesTable', - 'LootsTable', - 'CredsTable', - 'AuthInfoTable', - 'HostsTable', - 'ServicesTable', - 'VulnsTable', - 'EventsTable', - 'ClientsTable', - 'Workspace', - 'MsfManager', - 'WorkspaceManager', - 'DbManager', - 'AuthManager', - 'PluginManager', - 'JobManager', - 'CoreManager', - 'MsfModule', - 'ExploitModule', - 'PostModule', - 'EncoderModule', - 'AuxiliaryModule', - 'PayloadModule', - 'NopModule', - 'ModuleManager', - 'MsfSession', - 'MeterpreterSession', - 'ShellSession', - 'SessionManager', - 'MsfConsole', - 'ConsoleManager', - 'ReportFilter', - 'ReportFilterQuery'] +__all__ = [ + 'MsfRpcError', + 'MsfRpcMethod', + 'MsfPlugins', + 'MsfRpcClient', + 'MsfTable', + 'NotesTable', + 'LootsTable', + 'CredsTable', + 'AuthInfoTable', + 'HostsTable', + 'ServicesTable', + 'VulnsTable', + 'EventsTable', + 'ClientsTable', + 'Workspace', + 'MsfManager', + 'WorkspaceManager', + 'DbManager', + 'AuthManager', + 'PluginManager', + 'JobManager', + 'CoreManager', + 'MsfModule', + 'ExploitModule', + 'PostModule', + 'EncoderModule', + 'AuxiliaryModule', + 'PayloadModule', + 'NopModule', + 'ModuleManager', + 'MsfSession', + 'MeterpreterSession', + 'ShellSession', + 'SessionManager', + 'MsfConsole', + 'ConsoleManager', + 'ReportFilter', + 'ReportFilterQuery' +] class MsfRpcError(Exception): - pass + pass class MsfRpcMethod(object): - AuthLogin = 'auth.login' - AuthLogout = 'auth.logout' - AuthTokenList = 'auth.token_list' - AuthTokenAdd = 'auth.token_add' - AuthTokenGenerate = 'auth.token_generate' - AuthTokenRemove = 'auth.token_remove' - ConsoleCreate = 'console.create' - ConsoleList = 'console.list' - ConsoleDestroy = 'console.destroy' - ConsoleRead = 'console.read' - ConsoleWrite = 'console.write' - ConsoleTabs = 'console.tabs' - ConsoleSessionKill = 'console.session_kill' - ConsoleSessionDetach = 'console.session_detach' - CoreVersion = 'core.version' - CoreStop = 'core.stop' - CoreSetG = 'core.setg' - CoreUnsetG = 'core.unsetg' - CoreSave = 'core.save' - CoreReloadModules = 'core.reload_modules' - CoreModuleStats = 'core.module_stats' - CoreAddModulePath = 'core.add_module_path' - CoreThreadList = 'core.thread_list' - CoreThreadKill = 'core.thread_kill' - DbHosts = 'db.hosts' - DbServices = 'db.services' - DbVulns = 'db.vulns' - DbWorkspaces = 'db.workspaces' - DbCurrentWorkspace = 'db.current_workspace' - DbGetWorkspace = 'db.get_workspace' - DbSetWorkspace = 'db.set_workspace' - DbDelWorkspace = 'db.del_workspace' - DbAddWorkspace = 'db.add_workspace' - DbGetHost = 'db.get_host' - DbReportHost = 'db.report_host' - DbReportService = 'db.report_service' - DbGetService = 'db.get_service' - DbGetNote = 'db.get_note' - DbGetClient = 'db.get_client' - DbReportClient = 'db.report_client' - DbReportNote = 'db.report_note' - DbNotes = 'db.notes' - DbReportAuthInfo = 'db.report_auth_info' - DbGetAuthInfo = 'db.get_auth_info' - DbGetRef = 'db.get_ref' - DbDelVuln = 'db.del_vuln' - DbDelNote = 'db.del_note' - DbDelService = 'db.del_service' - DbDelHost = 'db.del_host' - DbReportVuln = 'db.report_vuln' - DbEvents = 'db.events' - DbReportEvent = 'db.report_event' - DbReportLoot = 'db.report_loot' - DbLoots = 'db.loots' - DbReportCred = 'db.report_cred' - DbCreds = 'db.creds' - DbImportData = 'db.import_data' - DbGetVuln = 'db.get_vuln' - DbClients = 'db.clients' - DbDelClient = 'db.del_client' - DbDriver = 'db.driver' - DbConnect = 'db.connect' - DbStatus = 'db.status' - DbDisconnect = 'db.disconnect' - JobList = 'job.list' - JobStop = 'job.stop' - JobInfo = 'job.info' - ModuleExploits = 'module.exploits' - ModuleAuxiliary = 'module.auxiliary' - ModulePayloads = 'module.payloads' - ModuleEncoders = 'module.encoders' - ModuleNops = 'module.nops' - ModulePost = 'module.post' - ModuleInfo = 'module.info' - ModuleCompatiblePayloads = 'module.compatible_payloads' - ModuleCompatibleSessions = 'module.compatible_sessions' - ModuleTargetCompatiblePayloads = 'module.target_compatible_payloads' - ModuleOptions = 'module.options' - ModuleExecute = 'module.execute' - ModuleEncodeFormats = 'module.encode_formats' - ModuleEncode = 'module.encode' - PluginLoad = 'plugin.load' - PluginUnload = 'plugin.unload' - PluginLoaded = 'plugin.loaded' - SessionList = 'session.list' - SessionStop = 'session.stop' - SessionShellRead = 'session.shell_read' - SessionShellWrite = 'session.shell_write' - SessionShellUpgrade = 'session.shell_upgrade' - SessionMeterpreterRead = 'session.meterpreter_read' - SessionRingRead = 'session.ring_read' - SessionRingPut = 'session.ring_put' - SessionRingLast = 'session.ring_last' - SessionRingClear = 'session.ring_clear' - SessionMeterpreterWrite = 'session.meterpreter_write' - SessionMeterpreterSessionDetach = 'session.meterpreter_session_detach' - SessionMeterpreterSessionKill = 'session.meterpreter_session_kill' - SessionMeterpreterTabs = 'session.meterpreter_tabs' - SessionMeterpreterRunSingle = 'session.meterpreter_run_single' - SessionMeterpreterScript = 'session.meterpreter_script' - SessionMeterpreterDirectorySeparator = 'session.meterpreter_directory_separator' - SessionCompatibleModules = 'session.compatible_modules' + AuthLogin = 'auth.login' + AuthLogout = 'auth.logout' + AuthTokenList = 'auth.token_list' + AuthTokenAdd = 'auth.token_add' + AuthTokenGenerate = 'auth.token_generate' + AuthTokenRemove = 'auth.token_remove' + ConsoleCreate = 'console.create' + ConsoleList = 'console.list' + ConsoleDestroy = 'console.destroy' + ConsoleRead = 'console.read' + ConsoleWrite = 'console.write' + ConsoleTabs = 'console.tabs' + ConsoleSessionKill = 'console.session_kill' + ConsoleSessionDetach = 'console.session_detach' + CoreVersion = 'core.version' + CoreStop = 'core.stop' + CoreSetG = 'core.setg' + CoreUnsetG = 'core.unsetg' + CoreSave = 'core.save' + CoreReloadModules = 'core.reload_modules' + CoreModuleStats = 'core.module_stats' + CoreAddModulePath = 'core.add_module_path' + CoreThreadList = 'core.thread_list' + CoreThreadKill = 'core.thread_kill' + DbHosts = 'db.hosts' + DbServices = 'db.services' + DbVulns = 'db.vulns' + DbWorkspaces = 'db.workspaces' + DbCurrentWorkspace = 'db.current_workspace' + DbGetWorkspace = 'db.get_workspace' + DbSetWorkspace = 'db.set_workspace' + DbDelWorkspace = 'db.del_workspace' + DbAddWorkspace = 'db.add_workspace' + DbGetHost = 'db.get_host' + DbReportHost = 'db.report_host' + DbReportService = 'db.report_service' + DbGetService = 'db.get_service' + DbGetNote = 'db.get_note' + DbGetClient = 'db.get_client' + DbReportClient = 'db.report_client' + DbReportNote = 'db.report_note' + DbNotes = 'db.notes' + DbReportAuthInfo = 'db.report_auth_info' + DbGetAuthInfo = 'db.get_auth_info' + DbGetRef = 'db.get_ref' + DbDelVuln = 'db.del_vuln' + DbDelNote = 'db.del_note' + DbDelService = 'db.del_service' + DbDelHost = 'db.del_host' + DbReportVuln = 'db.report_vuln' + DbEvents = 'db.events' + DbReportEvent = 'db.report_event' + DbReportLoot = 'db.report_loot' + DbLoots = 'db.loots' + DbReportCred = 'db.report_cred' + DbCreds = 'db.creds' + DbImportData = 'db.import_data' + DbGetVuln = 'db.get_vuln' + DbClients = 'db.clients' + DbDelClient = 'db.del_client' + DbDriver = 'db.driver' + DbConnect = 'db.connect' + DbStatus = 'db.status' + DbDisconnect = 'db.disconnect' + JobList = 'job.list' + JobStop = 'job.stop' + JobInfo = 'job.info' + ModuleExploits = 'module.exploits' + ModuleAuxiliary = 'module.auxiliary' + ModulePayloads = 'module.payloads' + ModuleEncoders = 'module.encoders' + ModuleNops = 'module.nops' + ModulePost = 'module.post' + ModuleInfo = 'module.info' + ModuleCompatiblePayloads = 'module.compatible_payloads' + ModuleCompatibleSessions = 'module.compatible_sessions' + ModuleTargetCompatiblePayloads = 'module.target_compatible_payloads' + ModuleOptions = 'module.options' + ModuleExecute = 'module.execute' + ModuleEncodeFormats = 'module.encode_formats' + ModuleEncode = 'module.encode' + PluginLoad = 'plugin.load' + PluginUnload = 'plugin.unload' + PluginLoaded = 'plugin.loaded' + SessionList = 'session.list' + SessionStop = 'session.stop' + SessionShellRead = 'session.shell_read' + SessionShellWrite = 'session.shell_write' + SessionShellUpgrade = 'session.shell_upgrade' + SessionMeterpreterRead = 'session.meterpreter_read' + SessionRingRead = 'session.ring_read' + SessionRingPut = 'session.ring_put' + SessionRingLast = 'session.ring_last' + SessionRingClear = 'session.ring_clear' + SessionMeterpreterWrite = 'session.meterpreter_write' + SessionMeterpreterSessionDetach = 'session.meterpreter_session_detach' + SessionMeterpreterSessionKill = 'session.meterpreter_session_kill' + SessionMeterpreterTabs = 'session.meterpreter_tabs' + SessionMeterpreterRunSingle = 'session.meterpreter_run_single' + SessionMeterpreterScript = 'session.meterpreter_script' + SessionMeterpreterDirectorySeparator = 'session.meterpreter_directory_separator' + SessionCompatibleModules = 'session.compatible_modules' class MsfPlugins(object): - IpsFilter = "ips_filter" - SocketLogger = "socket_logger" - DbTracker = "db_tracker" - Sounds = "sounds" - AutoAddRoute = "auto_add_route" - DbCredCollect = "db_credcollect" + IpsFilter = "ips_filter" + SocketLogger = "socket_logger" + DbTracker = "db_tracker" + Sounds = "sounds" + AutoAddRoute = "auto_add_route" + DbCredCollect = "db_credcollect" class MsfRpcClient(object): - _headers = { - 'Content-Type' : 'binary/message-pack' - } + _headers = { + 'Content-Type' : 'binary/message-pack' + } - def __init__(self, password, **kwargs): - """ - Connects and authenticates to a Metasploit RPC daemon. + def __init__(self, password, **kwargs): + """ + Connects and authenticates to a Metasploit RPC daemon. - Mandatory Arguments: - - password : the password used to authenticate to msfrpcd + Mandatory Arguments: + - password : the password used to authenticate to msfrpcd Optional Keyword Arguments: - username : the username used to authenticate to msfrpcd (default: msf) @@ -194,1142 +197,1120 @@ def __init__(self, password, **kwargs): - ssl : if true uses SSL else regular HTTP (default: SSL enabled) - verify : if true, verify SSL cert when using SSL (default: False) """ - self.uri = kwargs.get('uri', '/api/') - self.port = kwargs.get('port', 55552) - self.server = kwargs.get('server', '127.0.0.1') - self.ssl = kwargs.get('ssl', True) - self.verify_ssl = kwargs.get('verify', False) - self.sessionid = kwargs.get('token') - if self.ssl: - if self.verify_ssl: - self.client = HTTPSConnection(self.server, self.port) - else: - self.client = HTTPSConnection(self.server, self.port, context=ssl._create_unverified_context()) - else: - self.client = HTTPConnection(self.server, self.port) - self.login(kwargs.get('username', 'msf'), password) - - def unpackb_wrapper(self, data): - return self.unpackb_wrapf(data) - - def unpackb_wrapf(self, item): - if type(item) == bytes: - return item.decode('ascii') - if type(item) == list: - nl = [] - for j in item: - nl.append(self.unpackb_wrapf(j)) - return nl - if type(item) == dict: - nd = {} - for j in item: - k = j - if type(k) == bytes: - k = j.decode('ascii') - nd[k] = self.unpackb_wrapf(item[j]) - return nd - return item - - - def call(self, method, *args): - """ - Builds an RPC request and retrieves the result. - - Mandatory Arguments: - - method : the RPC call method name (e.g. db.clients) - - Optional Arguments: - - *args : the RPC method's parameters if necessary - - Returns : RPC call result - """ - l = [method] - l.extend(args) - if method == MsfRpcMethod.AuthLogin: - self.client.request('POST', self.uri, packb(l), self._headers) - r = self.client.getresponse() - if r.status == 200: - return self.unpackb_wrapper(unpackb(r.read())) - raise MsfRpcError('An unknown error has occurred while logging in.') - elif self.authenticated: - l.insert(1, self.sessionid) - self.client.request('POST', self.uri, packb(l), self._headers) - r = self.client.getresponse() - if r.status == 200: - result = self.unpackb_wrapper(unpackb(r.read())) - if 'error' in result: - raise MsfRpcError(result['error_message']) - return result - raise MsfRpcError('An unknown error has occurred while performing the RPC call.') - raise MsfRpcError('You cannot perform this call because you are not authenticated.') - - @property - def core(self): - """ - The msf RPC core manager. - """ - return CoreManager(self) - - @property - def modules(self): - """ - The msf RPC modules RPC manager. - """ - return ModuleManager(self) - - @property - def sessions(self): - """ - The msf RPC sessions (meterpreter & shell) manager. - """ - return SessionManager(self) - - @property - def jobs(self): - """ - The msf RPC jobs manager. - """ - return JobManager(self) - - @property - def consoles(self): - """ - The msf RPC consoles manager - """ - return ConsoleManager(self) - - @property - def authenticated(self): - """ - Whether or not this client is authenticated. - """ - return self.sessionid is not None - - @property - def plugins(self): - """ - The msf RPC plugins manager. - """ - return PluginManager(self) - - @property - def db(self): - """ - The msf RPC database manager. - """ - return DbManager(self) - - @property - def auth(self): - """ - The msf authentication manager. - """ - return AuthManager(self) - - def login(self, username, password): - """ - Authenticates and reauthenticates the user to msfrpcd. - """ - if self.sessionid is None: - r = self.call(MsfRpcMethod.AuthLogin, username, password) - try: - if r['result'] == 'success': - self.sessionid = r['token'] - except KeyError: - raise MsfRpcError('Login failed.') - else: - try: - r = self.call(MsfRpcMethod.DbStatus) - except MsfRpcError: - raise MsfRpcError('Login failed.') - - def logout(self): - """ - Logs the current user out. Note: do not call directly. - """ - self.call(MsfRpcMethod.AuthLogout, self.sessionid) + self.uri = kwargs.get('uri', '/api/') + self.port = kwargs.get('port', 55553) + self.server = kwargs.get('server', '127.0.0.1') + self.ssl = kwargs.get('ssl', True) + self.verify_ssl = kwargs.get('verify', False) + self.sessionid = kwargs.get('token') + if self.ssl: + if self.verify_ssl: + self.client = HTTPSConnection(self.server, self.port) + else: + self.client = HTTPSConnection(self.server, self.port, context=ssl._create_unverified_context()) + else: + self.client = HTTPConnection(self.server, self.port) + self.login(kwargs.get('username', 'msf'), password) + + def call(self, method, *args): + """ + Builds an RPC request and retrieves the result. + + Mandatory Arguments: + - method : the RPC call method name (e.g. db.clients) + + Optional Arguments: + - *args : the RPC method's parameters if necessary + + Returns : RPC call result + """ + l = [ method ] + l.extend(args) + if method == MsfRpcMethod.AuthLogin: + self.client.request('POST', self.uri, packb(l), self._headers) + r = self.client.getresponse() + if r.status == 200: + return unpackb(r.read()) + raise MsfRpcError('An unknown error has occurred while logging in.') + elif self.authenticated: + l.insert(1, self.sessionid) + self.client.request('POST', self.uri, packb(l), self._headers) + r = self.client.getresponse() + if r.status == 200: + result = unpackb(r.read()) + if 'error' in result: + raise MsfRpcError(result['error_message']) + return result + raise MsfRpcError('An unknown error has occurred while performing the RPC call.') + raise MsfRpcError('You cannot perform this call because you are not authenticated.') + + @property + def core(self): + """ + The msf RPC core manager. + """ + return CoreManager(self) + + @property + def modules(self): + """ + The msf RPC modules RPC manager. + """ + return ModuleManager(self) + + @property + def sessions(self): + """ + The msf RPC sessions (meterpreter & shell) manager. + """ + return SessionManager(self) + + @property + def jobs(self): + """ + The msf RPC jobs manager. + """ + return JobManager(self) + + @property + def consoles(self): + """ + The msf RPC consoles manager + """ + return ConsoleManager(self) + + @property + def authenticated(self): + """ + Whether or not this client is authenticated. + """ + return self.sessionid is not None + + @property + def plugins(self): + """ + The msf RPC plugins manager. + """ + return PluginManager(self) + + @property + def db(self): + """ + The msf RPC database manager. + """ + return DbManager(self) + + @property + def auth(self): + """ + The msf authentication manager. + """ + return AuthManager(self) + + def login(self, username, password): + """ + Authenticates and reauthenticates the user to msfrpcd. + """ + if self.sessionid is None: + r = self.call(MsfRpcMethod.AuthLogin, username, password) + try: + if r['result'] == 'success': + self.sessionid = r['token'] + except KeyError: + raise MsfRpcError('Login failed.') + else: + try: + r = self.call(MsfRpcMethod.DbStatus) + except MsfRpcError: + raise MsfRpcError('Login failed.') + + def logout(self): + """ + Logs the current user out. Note: do not call directly. + """ + self.call(MsfRpcMethod.AuthLogout, self.sessionid) class MsfTable(object): - def __init__(self, rpc, wname): - self.rpc = rpc - self.name = wname + def __init__(self, rpc, wname): + self.rpc = rpc + self.name = wname - def dbreport(self, atype, attrs): - attrs.update({ 'workspace' : self.name }) - return self.rpc.call('db.report_%s' % atype, attrs) + def dbreport(self, atype, attrs): + attrs.update({ 'workspace' : self.name }) + return self.rpc.call('db.report_%s' % atype, attrs) - def dbdel(self, atype, attrs): - attrs.update({ 'workspace' : self.name }) - return self.rpc.call('db.del_%s' % atype, attrs) + def dbdel(self, atype, attrs): + attrs.update({ 'workspace' : self.name }) + return self.rpc.call('db.del_%s' % atype, attrs) - def dbget(self, atype, attrs): - attrs.update({ 'workspace' : self.name }) - return self.rpc.call('db.get_%s' % atype, attrs)[atype] + def dbget(self, atype, attrs): + attrs.update({ 'workspace' : self.name }) + return self.rpc.call('db.get_%s' % atype, attrs)[atype] - def records(self, atypes, **kwargs): - kwargs.update({'workspace' : self.name}) - return self.rpc.call('db.%s' % atypes, kwargs)[atypes] + def records(self, atypes, **kwargs): + kwargs.update({'workspace' : self.name}) + return self.rpc.call('db.%s' % atypes, kwargs)[atypes] - @property - def list(self): - raise NotImplementedError + @property + def list(self): + raise NotImplementedError - def report(self, *args, **kwargs): - raise NotImplementedError + def report(self, *args, **kwargs): + raise NotImplementedError - def delete(self, *args, **kwargs): - raise NotImplementedError + def delete(self, *args, **kwargs): + raise NotImplementedError - def find(self, **kwargs): - raise NotImplementedError + def find(self, **kwargs): + raise NotImplementedError - update = report + update = report class NotesTable(MsfTable): - @property - def list(self): - return super(NotesTable, self).records('notes') - - def find(self, **kwargs): - """ - Find notes based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - addresses : a list of addresses to search for. - - names : comma separated string of service names. - - ntype : the note type. - - ports : the port associated with the note. - - proto : the protocol associated with the note. - """ - if 'ports' in kwargs: - kwargs['port'] = True - return super(NotesTable, self).records('notes', **kwargs) - - def report(self, type, data, **kwargs): - """ - Report a Note to the database. Notes can be tied to a Workspace, Host, or Service. - - Mandatory Arguments: - - type : The type of note, e.g. 'smb_peer_os'. - - data : whatever it is you're making a note of. - - Optional Keyword Arguments: - - host : an IP address or a Host object to associate with this Note. - - service : a dict containing 'host', 'port', 'proto' and optionally 'name' keys. - - port : along with 'host' and 'proto', a service to associate with this Note. - - proto : along with 'host' and 'port', a service to associate with this Note. - - update : what to do in case a similar Note exists, see below. - - The 'update' option can have the following values: - - unique : allow only a single Note per host/type pair. - - unique_data : like 'unique', but also compare 'data'. - - insert : always insert a new Note even if one with identical values exists. - - If the provided 'host' is an IP address and does not exist in the database, - it will be created. If 'host' and 'service' are all omitted, the new Note - will be associated with the current 'workspace'. - """ - kwargs.update({ 'data' : data, 'type' : type }) - kwargs.update(kwargs.pop('service', {})) - self.dbreport('note', kwargs) - - def delete(self, **kwargs): - """ - Delete one or more notes based on a search criteria. - - Optional Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - - port : the port associated with a Note. - - proto : the protocol associated with a Note. - - ntype : the note type, e.g. 'smb_peer_os'. - """ - self.dbdel('note', kwargs) - - def get(self, **kwargs): - """ - Get a Note from the database based on the specifications of one or more keyword arguments. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - address : the address associated with a Note, not required if 'host' or 'addr' is specified. - - addr : same as 'address', not required if 'host' or 'address' is specified. - - Optional Keyword Arguments: - - proto : the protocol associated with the Note. - - port : the port associated with the Note. - - ntype : the type of Note. - """ - if not any([i in kwargs for i in ('host', 'address', 'addr')]): - raise TypeError('Expected a host, address, or addr.') - return self.dbget('note', kwargs) - - update = report + @property + def list(self): + return super(NotesTable, self).records('notes') + + def find(self, **kwargs): + """ + Find notes based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - addresses : a list of addresses to search for. + - names : comma separated string of service names. + - ntype : the note type. + - ports : the port associated with the note. + - proto : the protocol associated with the note. + """ + if 'ports' in kwargs: + kwargs['port'] = True + return super(NotesTable, self).records('notes', **kwargs) + + def report(self, type, data, **kwargs): + """ + Report a Note to the database. Notes can be tied to a Workspace, Host, or Service. + + Mandatory Arguments: + - type : The type of note, e.g. 'smb_peer_os'. + - data : whatever it is you're making a note of. + + Optional Keyword Arguments: + - host : an IP address or a Host object to associate with this Note. + - service : a dict containing 'host', 'port', 'proto' and optionally 'name' keys. + - port : along with 'host' and 'proto', a service to associate with this Note. + - proto : along with 'host' and 'port', a service to associate with this Note. + - update : what to do in case a similar Note exists, see below. + + The 'update' option can have the following values: + - unique : allow only a single Note per host/type pair. + - unique_data : like 'unique', but also compare 'data'. + - insert : always insert a new Note even if one with identical values exists. + + If the provided 'host' is an IP address and does not exist in the database, + it will be created. If 'host' and 'service' are all omitted, the new Note + will be associated with the current 'workspace'. + """ + kwargs.update({ 'data' : data, 'type' : type }) + kwargs.update(kwargs.pop('service', {})) + self.dbreport('note', kwargs) + + def delete(self, **kwargs): + """ + Delete one or more notes based on a search criteria. + + Optional Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + - port : the port associated with a Note. + - proto : the protocol associated with a Note. + - ntype : the note type, e.g. 'smb_peer_os'. + """ + self.dbdel('note', kwargs) + + def get(self, **kwargs): + """ + Get a Note from the database based on the specifications of one or more keyword arguments. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - address : the address associated with a Note, not required if 'host' or 'addr' is specified. + - addr : same as 'address', not required if 'host' or 'address' is specified. + + Optional Keyword Arguments: + - proto : the protocol associated with the Note. + - port : the port associated with the Note. + - ntype : the type of Note. + """ + if not any([i in kwargs for i in ('host', 'address', 'addr')]): + raise TypeError('Expected a host, address, or addr.') + return self.dbget('note', kwargs) + + update = report class LootsTable(MsfTable): - @property - def list(self): - return super(LootsTable, self).records('loots') + @property + def list(self): + return super(LootsTable, self).records('loots') - def find(self, **kwargs): - """ - Find loot based on search criteria. + def find(self, **kwargs): + """ + Find loot based on search criteria. - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - """ - return super(LootsTable, self).records('loots', **kwargs) + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + """ + return super(LootsTable, self).records('loots', **kwargs) - def report(self, path, type, **kwargs): - """ - Report Loot to the database + def report(self, path, type, **kwargs): + """ + Report Loot to the database - Mandatory Arguments: - - path : the filesystem path to the Loot - - type : the type of Loot - - ltype : the same as 'type', not required if 'type' is specified. + Mandatory Arguments: + - path : the filesystem path to the Loot + - type : the type of Loot + - ltype : the same as 'type', not required if 'type' is specified. - Optional Keyword Arguments: - - host : an IP address or a Host object to associate with this Note - - ctype : the content type of the loot, e.g. 'text/plain' - - content_type : same as 'ctype'. - - service : a service to associate Loot with. - - name : a name to associate with this Loot. - - info : additional information about this Loot. - - data : the data within the Loot. - """ - kwargs.update({ 'path' : path, 'type' : type }) - self.dbreport('loot', kwargs) + Optional Keyword Arguments: + - host : an IP address or a Host object to associate with this Note + - ctype : the content type of the loot, e.g. 'text/plain' + - content_type : same as 'ctype'. + - service : a service to associate Loot with. + - name : a name to associate with this Loot. + - info : additional information about this Loot. + - data : the data within the Loot. + """ + kwargs.update({ 'path' : path, 'type' : type }) + self.dbreport('loot', kwargs) - update = report + update = report class CredsTable(MsfTable): - @property - def list(self): - return super(CredsTable, self).records('creds') + @property + def list(self): + return super(CredsTable, self).records('creds') + + def find(self, **kwargs): + """ + Find creds based on search criteria. - def find(self, **kwargs): - """ - Find creds based on search criteria. + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + """ + return super(CredsTable, self).records('creds', **kwargs) - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - """ - return super(CredsTable, self).records('creds', **kwargs) + def report(self, host, port, **kwargs): + """ + Store a set of credentials in the database. - def report(self, host, port, **kwargs): - """ - Store a set of credentials in the database. + Mandatory Arguments: + - host : an IP address or Host object reference + - port : a port number - Mandatory Arguments: - - host : an IP address or Host object reference - - port : a port number + Optional Keyword Arguments: + - user : the username. + - password : the password, or path to ssh_key. + - ptype : the type of password (password(ish), hash, or ssh_key). + - proto : a transport name for the port. + - sname : service name. + - active : by default, a cred is active, unless explicitly false. + - proof : data used to prove the account is actually active. + + Sources: Credentials can be sourced from another credential, or from + a vulnerability. For example, if an exploit was used to dump the + smb_hashes, and this credential comes from there, the source_id would + be the Vuln id (as reported by report_vuln) and the type would be "Vuln". + + - source_id : The Vuln or Cred id of the source of this cred. + - source_type : Either Vuln or Cred. + """ + kwargs.update({'host' : host, 'port' : port}) + kwargs['pass'] = kwargs.get('password') + self.dbreport('cred', kwargs) - Optional Keyword Arguments: - - user : the username. - - password : the password, or path to ssh_key. - - ptype : the type of password (password(ish), hash, or ssh_key). - - proto : a transport name for the port. - - sname : service name. - - active : by default, a cred is active, unless explicitly false. - - proof : data used to prove the account is actually active. + update = report - Sources: Credentials can be sourced from another credential, or from - a vulnerability. For example, if an exploit was used to dump the - smb_hashes, and this credential comes from there, the source_id would - be the Vuln id (as reported by report_vuln) and the type would be "Vuln". - - source_id : The Vuln or Cred id of the source of this cred. - - source_type : Either Vuln or Cred. - """ - kwargs.update({'host' : host, 'port' : port}) - kwargs['pass'] = kwargs.get('password') - self.dbreport('cred', kwargs) +class AuthInfoTable(MsfTable): + + def report(self, host, port, **kwargs): + """ + Store a set of credentials in the database. - update = report + Mandatory Arguments: + - host : an IP address or Host object reference + - port : a port number + Optional Keyword Arguments: + - user : the username. + - pass : the password, or path to ssh_key. + - ptype : the type of password (password(ish), hash, or ssh_key). + - proto : a transport name for the port. + - sname : service name. + - active : by default, a cred is active, unless explicitly false. + - proof : data used to prove the account is actually active. + + Sources: Credentials can be sourced from another credential, or from + a vulnerability. For example, if an exploit was used to dump the + smb_hashes, and this credential comes from there, the source_id would + be the Vuln id (as reported by report_vuln) and the type would be "Vuln". + + - source_id : The Vuln or Cred id of the source of this cred. + - source_type : Either Vuln or Cred. + """ + kwargs.update({'host' : host, 'port' : port}) + self.dbreport('auth_info', kwargs) -class AuthInfoTable(MsfTable): + update = report - def report(self, host, port, **kwargs): - """ - Store a set of credentials in the database. - Mandatory Arguments: - - host : an IP address or Host object reference - - port : a port number +class HostsTable(MsfTable): - Optional Keyword Arguments: - - user : the username. - - pass : the password, or path to ssh_key. - - ptype : the type of password (password(ish), hash, or ssh_key). - - proto : a transport name for the port. - - sname : service name. - - active : by default, a cred is active, unless explicitly false. - - proof : data used to prove the account is actually active. + @property + def list(self): + return super(HostsTable, self).records('hosts') - Sources: Credentials can be sourced from another credential, or from - a vulnerability. For example, if an exploit was used to dump the - smb_hashes, and this credential comes from there, the source_id would - be the Vuln id (as reported by report_vuln) and the type would be "Vuln". + def find(self, **kwargs): + """ + Find hosts based on search criteria. - - source_id : The Vuln or Cred id of the source of this cred. - - source_type : Either Vuln or Cred. - """ - kwargs.update({'host' : host, 'port' : port}) - self.dbreport('auth_info', kwargs) + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - only_up : find only hosts that are alive. + - addresses : find hosts based on a list of addresses. + """ + return super(HostsTable, self).records('hosts', **kwargs) - update = report + def report(self, host, **kwargs): + """ + Store a host in the database. + Mandatory Keyword Arguments: + - host : an IP address or Host object reference. -class HostsTable(MsfTable): + Optional Keyword Arguments: + - state : a host state. + - os_name : an operating system. + - os_flavor : something like 'XP or 'Gentoo'. + - os_sp : something like 'SP2'. + - os_lang : something like 'English', 'French', or 'en-US'. + - arch : an architecture. + - mac : the host's MAC address. + - scope : interface identifier for link-local IPv6. + - virtual_host : the name of the VM host software, e.g. 'VMWare', 'QEMU', 'Xen', etc. + """ + kwargs.update({'host' : host}) + self.dbreport('host', kwargs) + + def delete(self, **kwargs): + """ + Deletes a host and associated data matching this address/comm. - @property - def list(self): - return super(HostsTable, self).records('hosts') - - def find(self, **kwargs): - """ - Find hosts based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - only_up : find only hosts that are alive. - - addresses : find hosts based on a list of addresses. - """ - return super(HostsTable, self).records('hosts', **kwargs) - - def report(self, host, **kwargs): - """ - Store a host in the database. - - Mandatory Keyword Arguments: - - host : an IP address or Host object reference. - - Optional Keyword Arguments: - - state : a host state. - - os_name : an operating system. - - os_flavor : something like 'XP or 'Gentoo'. - - os_sp : something like 'SP2'. - - os_lang : something like 'English', 'French', or 'en-US'. - - arch : an architecture. - - mac : the host's MAC address. - - scope : interface identifier for link-local IPv6. - - virtual_host : the name of the VM host software, e.g. 'VMWare', 'QEMU', 'Xen', etc. - """ - kwargs.update({'host' : host}) - self.dbreport('host', kwargs) - - def delete(self, **kwargs): - """ - Deletes a host and associated data matching this address/comm. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): - raise TypeError('Expected host, address, or addresses.') - self.dbdel('host', kwargs) - - def get(self, **kwargs): - """ - Get a host in the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - address : the address associated with a Note, not required if 'host' or 'addr' is specified. - - addr : same as 'address', not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('addr', 'address', 'host')]): - raise TypeError('Expected addr, address, or host.') - return self.dbget('host', kwargs) - - update = report + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): + raise TypeError('Expected host, address, or addresses.') + self.dbdel('host', kwargs) + + def get(self, **kwargs): + """ + Get a host in the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - address : the address associated with a Note, not required if 'host' or 'addr' is specified. + - addr : same as 'address', not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('addr', 'address', 'host')]): + raise TypeError('Expected addr, address, or host.') + return self.dbget('host', kwargs) + + update = report class ServicesTable(MsfTable): - @property - def list(self): - return super(ServicesTable, self).records('services') - - def find(self, **kwargs): - """ - Find hosts based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - only_up : find only hosts that are alive. - - addresses : find hosts based on a list of addresses. - - proto : the protocol of the service. - - ports : a comma separated string of ports. - - names : a comma separated string of service names. - """ - return super(ServicesTable, self).records('services', **kwargs) - - def report(self, host, port, proto, **kwargs): - """ - Record a service in the database. - - Mandatory Arguments: - - host : the host where this service is running. - - port : the port where this service listens. - - proto : the transport layer protocol (e.g. tcp, udp). - - Optional Keyword Arguments: - - name : the application layer protocol (e.g. ssh, mssql, smb) - - sname : an alias for the above - """ - kwargs.update({'host' : host, 'port' : port, 'proto' : proto}) - self.dbreport('service', kwargs) - - def delete(self, **kwargs): - """ - Deletes a port and associated vulns matching this port. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - - or - - - port : used along with 'proto', specifies a service. - - proto : used along with 'port', specifies a service. - """ - if not any([i in kwargs for i in ('host', 'address', 'addresses')]) and \ - not all([i in kwargs for i in ('proto', 'port')]): - raise TypeError('Expected host or port/proto pair.') - self.dbdel('service', kwargs) - - def get(self, **kwargs): - """ - Get a service record from the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - - or - - - port : used along with 'proto', specifies a service. - - proto : used along with 'port', specifies a service. - - Optional Keyword Arguments: - - up : specifies whether or not the service is alive. - - names : a comma separated string of service names. - """ - if not any([i in kwargs for i in ('host', 'addr', 'address')]) and \ - not all([i in kwargs for i in ('proto', 'port')]): - raise TypeError('Expected host or port/proto pair.') - return self.dbget('service', kwargs) - - update = report + @property + def list(self): + return super(ServicesTable, self).records('services') + + def find(self, **kwargs): + """ + Find hosts based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - only_up : find only hosts that are alive. + - addresses : find hosts based on a list of addresses. + - proto : the protocol of the service. + - ports : a comma separated string of ports. + - names : a comma separated string of service names. + """ + return super(ServicesTable, self).records('services', **kwargs) + + def report(self, host, port, proto, **kwargs): + """ + Record a service in the database. + + Mandatory Arguments: + - host : the host where this service is running. + - port : the port where this service listens. + - proto : the transport layer protocol (e.g. tcp, udp). + + Optional Keyword Arguments: + - name : the application layer protocol (e.g. ssh, mssql, smb) + - sname : an alias for the above + """ + kwargs.update({'host' : host, 'port' : port, 'proto' : proto}) + self.dbreport('service', kwargs) + + def delete(self, **kwargs): + """ + Deletes a port and associated vulns matching this port. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + + or + + - port : used along with 'proto', specifies a service. + - proto : used along with 'port', specifies a service. + """ + if not any([i in kwargs for i in ('host', 'address', 'addresses')]) and \ + not all([i in kwargs for i in ('proto', 'port')]): + raise TypeError('Expected host or port/proto pair.') + self.dbdel('service', kwargs) + + def get(self, **kwargs): + """ + Get a service record from the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + + or + + - port : used along with 'proto', specifies a service. + - proto : used along with 'port', specifies a service. + + Optional Keyword Arguments: + - up : specifies whether or not the service is alive. + - names : a comma separated string of service names. + """ + if not any([i in kwargs for i in ('host', 'addr', 'address')]) and \ + not all([i in kwargs for i in ('proto', 'port')]): + raise TypeError('Expected host or port/proto pair.') + return self.dbget('service', kwargs) + + update = report class VulnsTable(MsfTable): - @property - def list(self): - return super(VulnsTable, self).records('vulns') - - def find(self, **kwargs): - """ - Find vulns based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - addresses : find hosts based on a list of addresses. - - proto : the protocol of the service. - - ports : a comma separated string of ports. - - names : a comma separated string of service names. - """ - return super(VulnsTable, self).records('vulns', **kwargs) - - def report(self, host, name, **kwargs): - """ - Record a Vuln in the database. - - Mandatory Arguments: - - host : the host where this vulnerability resides. - - name : the scanner-specific id of the vuln (e.g. NEXPOSE-cifs-acct-password-never-expires). - - Optional Keyword Arguments: - - info : a human readable description of the vuln, free-form text. - - refs : an array of Ref objects or string names of references. - """ - kwargs.update({'host' : host, 'name' : name}) - self.dbreport('vuln', kwargs) - - def delete(self, **kwargs): - """ - Deletes a vuln and associated data matching this address/comm. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): - raise TypeError('Expected host, address, or addresses.') - self.dbdel('vuln', kwargs) - - def get(self, **kwargs): - """ - Get a vuln in the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - address : the address associated with a Note, not required if 'host' or 'addr' is specified. - - addr : same as 'address', not required if 'host' or 'address' is specified. - """ - if not any([ i in kwargs for i in ('addr', 'address', 'host')]): - raise TypeError('Expected addr, address, or host.') - return self.dbreport('vuln', kwargs) - - update = report + @property + def list(self): + return super(VulnsTable, self).records('vulns') + + def find(self, **kwargs): + """ + Find vulns based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - addresses : find hosts based on a list of addresses. + - proto : the protocol of the service. + - ports : a comma separated string of ports. + - names : a comma separated string of service names. + """ + return super(VulnsTable, self).records('vulns', **kwargs) + + def report(self, host, name, **kwargs): + """ + Record a Vuln in the database. + + Mandatory Arguments: + - host : the host where this vulnerability resides. + - name : the scanner-specific id of the vuln (e.g. NEXPOSE-cifs-acct-password-never-expires). + + Optional Keyword Arguments: + - info : a human readable description of the vuln, free-form text. + - refs : an array of Ref objects or string names of references. + """ + kwargs.update({'host' : host, 'name' : name}) + self.dbreport('vuln', kwargs) + + def delete(self, **kwargs): + """ + Deletes a vuln and associated data matching this address/comm. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('host', 'address', 'addresses')]): + raise TypeError('Expected host, address, or addresses.') + self.dbdel('vuln', kwargs) + + def get(self, **kwargs): + """ + Get a vuln in the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - address : the address associated with a Note, not required if 'host' or 'addr' is specified. + - addr : same as 'address', not required if 'host' or 'address' is specified. + """ + if not any([ i in kwargs for i in ('addr', 'address', 'host')]): + raise TypeError('Expected addr, address, or host.') + return self.dbreport('vuln', kwargs) + + update = report class EventsTable(MsfTable): - @property - def list(self): - return super(EventsTable, self).records('events') + @property + def list(self): + return super(EventsTable, self).records('events') - def find(self, **kwargs): - """ - Find events based on search criteria. + def find(self, **kwargs): + """ + Find events based on search criteria. - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - """ - return super(EventsTable, self).records('events', **kwargs) + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + """ + return super(EventsTable, self).records('events', **kwargs) - def report(self, **kwargs): - """ - Record a Vuln in the database. + def report(self, **kwargs): + """ + Record a Vuln in the database. - Mandatory Arguments: - - username : user that invoked the event. - - host : host that invoked the event. - """ - if not any([i in kwargs for i in ('username', 'host')]): - raise TypeError('Expected either username or host') - self.dbreport('vuln', kwargs) + Mandatory Arguments: + - username : user that invoked the event. + - host : host that invoked the event. + """ + if not any([i in kwargs for i in ('username', 'host')]): + raise TypeError('Expected either username or host') + self.dbreport('vuln', kwargs) + + update = report + + +class ClientsTable(MsfTable): + + @property + def list(self): + return super(ClientsTable, self).records('clients') + + def find(self, **kwargs): + """ + Find clients based on search criteria. + + Optional Keyword Arguments: + - limit : the maximum number of results. + - offset : skip n results. + - ua_name : a user-agent string. + - ua_ver : the user-agent version. + - addresses : a list of IP addresses. + """ + return super(ClientsTable, self).records('clients', **kwargs) + + def report(self, ua_string, host, **kwargs): + """ + Report a client running on a host. + + Mandatory Arguments: + - ua_string : the value of the User-Agent header + - host : the host where this client connected from, can be an ip address or a Host object + + Optional Keyword Arguments + - ua_name : one of the user agent name constants + - ua_ver : detected version of the given client + - campaign : an id or Campaign object + + Returns a Client. + """ + kwargs.update({'host' : host, 'ua_string' : ua_string}) + self.dbreport('client', kwargs) + + def delete(self, **kwargs): + """ + Deletes a client and associated data matching this address/comm. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addresses' is specified + - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. + - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. + """ + self.dbdel('client', kwargs) + + def get(self, **kwargs): + """ + Get a client in the database. + + Mandatory Keyword Arguments: + - host : the host associated with a Note, not required if 'address' or 'addr' is specified. + - ua_string : the value of the User-Agent header + """ + if not any([ i in kwargs for i in ('host', 'ua_string')]): + raise TypeError('Expected host or ua_string.') + return self.dbreport('client', kwargs) + + update = report + + +class Workspace(object): + + def __init__(self, rpc, name): + """ + Initializes a workspace object. + + Mandatory Arguments: + - rpc : the msfrpc client object + - name : the name of the workspace + """ + self.rpc = rpc + self.name = name + + @property + def current(self): + """ + The name of the current workspace. + """ + return self.name + + @current.setter + def current(self, name): + self.name = name + + @property + def notes(self): + """ + Returns the notes table for the current workspace. + """ + return NotesTable(self.rpc, self.name) + + @property + def hosts(self): + """ + Returns the hosts table for the current workspace. + """ + return HostsTable(self.rpc, self.name) + + @property + def services(self): + """ + Returns the services table for the current workspace. + """ + return ServicesTable(self.rpc, self.name) + + @property + def vulns(self): + """ + Returns the vulns table for the current workspace. + """ + return VulnsTable(self.rpc, self.name) + + @property + def events(self): + """ + Returns the events table for the current workspace. + """ + return EventsTable(self.rpc, self.name) + + @property + def loots(self): + """ + Returns the loots table for the current workspace. + """ + return LootsTable(self.rpc, self.name) - update = report + @property + def creds(self): + """ + Returns the creds table for the current workspace. + """ + return CredsTable(self.rpc, self.name) + + @property + def clients(self): + """ + Returns the clients table for the current workspace. + """ + return ClientsTable(self.rpc, self.name) + + def delete(self): + """ + Delete the current workspace. + """ + self.rpc.call(MsfRpcMethod.DbDelWorkspace, {'workspace' : self.name}) + + def importdata(self, data): + self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : data}) + + def importfile(self, fname): + r = file(fname, mode='rb') + self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : r.read()}) + r.close() + + +class MsfManager(object): + + def __init__(self, rpc): + """ + Initialize a msf component manager. + + Mandatory Arguments: + - rpc : the msfrpc client object. + """ + self.rpc = rpc -class ClientsTable(MsfTable): +class WorkspaceManager(MsfManager): + + @property + def list(self): + """ + The list of all workspaces in the current msf database. + """ + return self.rpc.call(MsfRpcMethod.DbWorkspaces)['workspaces'] + + def workspace(self, name='default'): + """ + Returns a Workspace object for the given workspace name. + + Optional Arguments: + - name : the name of the workspace + """ + w = self.list + if name not in w: + self.add(name) + return Workspace(self.rpc, name) + + def add(self, name): + """ + Adds a workspace with the given name. + + Mandatory Arguments: + - name : the name of the workspace + """ + self.rpc.call(MsfRpcMethod.DbAddWorkspace, name) + + def get(self, name): + """ + Get a workspace with the given name. + + Mandatory Arguments: + - name : the name of the workspace + """ + return self.rpc.call(MsfRpcMethod.DbGetWorkspace, name)['workspace'] + + def remove(self, name): + """ + Adds a workspace with the given name. + + Mandatory Arguments: + - name : the name of the workspace + """ + self.rpc.call(MsfRpcMethod.DbDelWorkspace, name) + + def set(self, name): + """ + Sets the current workspace. + + Mandatory Arguments: + - name : the name of the workspace + """ + self.rpc.call(MsfRpcMethod.DbSetWorkspace, name) + + @property + def current(self): + """ + The current workspace. + """ + return self.workspace(self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace']) + + +class DbManager(MsfManager): + + def connect(self, username, database='msf', **kwargs): + """ + Connects to a database and creates the msf schema if necessary. + + Mandatory Arguments: + - username : the username for the database connection + + Optional Keyword Arguments: + - host : the IP or hostname of the database server (default: 'localhost') + - driver : the driver to use for the database connection (default: 'postgresql') + - password : the password for the database connection + - database : the database name (default: 'msf') + - port : the port that the server is running on (default: 5432) + """ + runopts = { 'username': username, 'database' : database } + runopts.update(kwargs) + return self.rpc.call(MsfRpcMethod.DbConnect, runopts)['result'] == 'success' + + @property + def driver(self): + """ + The current database driver in use. + """ + return self.rpc.call(MsfRpcMethod.DbDriver, {})['driver'] + + @driver.setter + def driver(self, d): + self.rpc.call(MsfRpcMethod.DbDriver, {'driver' : d}) + + @property + def status(self): + """ + The status of the database connection. + """ + return self.rpc.call(MsfRpcMethod.DbStatus) + + def disconnect(self): + """ + Disconnect from the database. + """ + self.rpc.call(MsfRpcMethod.DbDisconnect) + + @property + def workspaces(self): + """ + A WorkspaceManager object. + """ + return WorkspaceManager(self.rpc) + + @property + def workspace(self): + """ + The name of the current workspace. + """ + return self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace'] + + @workspace.setter + def workspace(self, w): + self.rpc.call(MsfRpcMethod.DbSetWorkspace, w) + + +class AuthManager(MsfManager): + + def login(self, password, **kwargs): + """ + Login to the msfrpc daemon. + + Mandatory Arguments: + - password : the password used to login to msfrpc + + Optional Keyword Arguments: + - username : the username used to authenticate to msfrpcd (default: msf) + - uri : the msfrpcd URI (default: /api/) + - port : the remote msfrpcd port to connect to (default: 55553) + - server : the remote server IP address hosting msfrpcd (default: localhost) + - ssl : if true uses SSL else regular HTTP (default: SSL enabled) + """ + return MsfRpcClient(password, **kwargs) + + def logout(self, sid): + """ + Logs out a user for a given session ID. + + Mandatory Arguments: + - sid : a session ID that is active. + """ + return self.rpc.call(MsfRpcMethod.AuthLogout, sid) + + @property + def tokens(self): + """ + The current list of active session IDs. + """ + return self.rpc.call(MsfRpcMethod.AuthTokenList)['tokens'] + + def add(self, token): + """ + Add a session ID or token. - @property - def list(self): - return super(ClientsTable, self).records('clients') - - def find(self, **kwargs): - """ - Find clients based on search criteria. - - Optional Keyword Arguments: - - limit : the maximum number of results. - - offset : skip n results. - - ua_name : a user-agent string. - - ua_ver : the user-agent version. - - addresses : a list of IP addresses. - """ - return super(ClientsTable, self).records('clients', **kwargs) - - def report(self, ua_string, host, **kwargs): - """ - Report a client running on a host. - - Mandatory Arguments: - - ua_string : the value of the User-Agent header - - host : the host where this client connected from, can be an ip address or a Host object - - Optional Keyword Arguments - - ua_name : one of the user agent name constants - - ua_ver : detected version of the given client - - campaign : an id or Campaign object - - Returns a Client. - """ - kwargs.update({'host' : host, 'ua_string' : ua_string}) - self.dbreport('client', kwargs) - - def delete(self, **kwargs): - """ - Deletes a client and associated data matching this address/comm. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addresses' is specified - - address : the address associated with a Note, not required if 'host' or 'addresses' is specified. - - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified. - """ - self.dbdel('client', kwargs) - - def get(self, **kwargs): - """ - Get a client in the database. - - Mandatory Keyword Arguments: - - host : the host associated with a Note, not required if 'address' or 'addr' is specified. - - ua_string : the value of the User-Agent header - """ - if not any([ i in kwargs for i in ('host', 'ua_string')]): - raise TypeError('Expected host or ua_string.') - return self.dbreport('client', kwargs) - - update = report + Mandatory Argument: + - token : a random string used as a session identifier. + """ + self.rpc.call(MsfRpcMethod.AuthTokenAdd, token) + def remove(self, token): + """ + Remove a session ID or token. -class Workspace(object): + Mandatory Argument: + - token : a session ID or token that is active. + """ + self.rpc.call(MsfRpcMethod.AuthTokenRemove, token) - def __init__(self, rpc, name): - """ - Initializes a workspace object. - - Mandatory Arguments: - - rpc : the msfrpc client object - - name : the name of the workspace - """ - self.rpc = rpc - self.name = name - - @property - def current(self): - """ - The name of the current workspace. - """ - return self.name - - @current.setter - def current(self, name): - self.name = name - - @property - def notes(self): - """ - Returns the notes table for the current workspace. - """ - return NotesTable(self.rpc, self.name) - - @property - def hosts(self): - """ - Returns the hosts table for the current workspace. - """ - return HostsTable(self.rpc, self.name) - - @property - def services(self): - """ - Returns the services table for the current workspace. - """ - return ServicesTable(self.rpc, self.name) - - @property - def vulns(self): - """ - Returns the vulns table for the current workspace. - """ - return VulnsTable(self.rpc, self.name) - - @property - def events(self): - """ - Returns the events table for the current workspace. - """ - return EventsTable(self.rpc, self.name) - - @property - def loots(self): - """ - Returns the loots table for the current workspace. - """ - return LootsTable(self.rpc, self.name) - - @property - def creds(self): - """ - Returns the creds table for the current workspace. - """ - return CredsTable(self.rpc, self.name) - - @property - def clients(self): - """ - Returns the clients table for the current workspace. - """ - return ClientsTable(self.rpc, self.name) - - def delete(self): - """ - Delete the current workspace. - """ - self.rpc.call(MsfRpcMethod.DbDelWorkspace, {'workspace' : self.name}) - - def importdata(self, data): - self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : data}) - - def importfile(self, fname): - r = file(fname, mode='rb') - self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : r.read()}) - r.close() + def generate(self): + """ + Generate a session ID or token. + """ + return self.rpc.call(MsfRpcMethod.AuthTokenGenerate)['token'] -class MsfManager(object): +class PluginManager(MsfManager): - def __init__(self, rpc): - """ - Initialize a msf component manager. + @property + def list(self): + """ + A list of loaded plugins. + """ + return self.rpc.call(MsfRpcMethod.PluginLoaded)['plugins'] - Mandatory Arguments: - - rpc : the msfrpc client object. - """ - self.rpc = rpc + def load(self, plugin): + """ + Load a plugin of a given name. + Mandatory Arguments: + - plugin : a name of a plugin to load. + """ + self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginLoad, plugin) -class WorkspaceManager(MsfManager): + def unload(self, plugin): + """ + Unload a plugin of a given name. - @property - def list(self): - """ - The list of all workspaces in the current msf database. - """ - return self.rpc.call(MsfRpcMethod.DbWorkspaces)['workspaces'] - - def workspace(self, name='default'): - """ - Returns a Workspace object for the given workspace name. - - Optional Arguments: - - name : the name of the workspace - """ - w = self.list - if name not in w: - self.add(name) - return Workspace(self.rpc, name) - - def add(self, name): - """ - Adds a workspace with the given name. - - Mandatory Arguments: - - name : the name of the workspace - """ - self.rpc.call(MsfRpcMethod.DbAddWorkspace, name) - - def get(self, name): - """ - Get a workspace with the given name. - - Mandatory Arguments: - - name : the name of the workspace - """ - return self.rpc.call(MsfRpcMethod.DbGetWorkspace, name)['workspace'] - - def remove(self, name): - """ - Adds a workspace with the given name. - - Mandatory Arguments: - - name : the name of the workspace - """ - self.rpc.call(MsfRpcMethod.DbDelWorkspace, name) - - def set(self, name): - """ - Sets the current workspace. - - Mandatory Arguments: - - name : the name of the workspace - """ - self.rpc.call(MsfRpcMethod.DbSetWorkspace, name) - - @property - def current(self): - """ - The current workspace. - """ - return self.workspace(self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace']) + Mandatory Arguments: + - plugin : a name of a loaded plugin to unload. + """ + self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginUnload, plugin) -class DbManager(MsfManager): +class JobManager(MsfManager): - def connect(self, username, database='msf', **kwargs): - """ - Connects to a database and creates the msf schema if necessary. - - Mandatory Arguments: - - username : the username for the database connection - - Optional Keyword Arguments: - - host : the IP or hostname of the database server (default: 'localhost') - - driver : the driver to use for the database connection (default: 'postgresql') - - password : the password for the database connection - - database : the database name (default: 'msf') - - port : the port that the server is running on (default: 5432) - """ - runopts = { 'username': username, 'database' : database } - runopts.update(kwargs) - return self.rpc.call(MsfRpcMethod.DbConnect, runopts)['result'] == 'success' - - @property - def driver(self): - """ - The current database driver in use. - """ - return self.rpc.call(MsfRpcMethod.DbDriver, {})['driver'] - - @driver.setter - def driver(self, d): - self.rpc.call(MsfRpcMethod.DbDriver, {'driver' : d}) - - @property - def status(self): - """ - The status of the database connection. - """ - return self.rpc.call(MsfRpcMethod.DbStatus) - - def disconnect(self): - """ - Disconnect from the database. - """ - self.rpc.call(MsfRpcMethod.DbDisconnect) - - @property - def workspaces(self): - """ - A WorkspaceManager object. - """ - return WorkspaceManager(self.rpc) - - @property - def workspace(self): - """ - The name of the current workspace. - """ - return self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace'] - - @workspace.setter - def workspace(self, w): - self.rpc.call(MsfRpcMethod.DbSetWorkspace, w) + @property + def list(self): + """ + A list of currently running jobs. + """ + return self.rpc.call(MsfRpcMethod.JobList) + def stop(self, jobid): + """ + Stop a job. -class AuthManager(MsfManager): + Mandatory Argument: + - jobid : the ID of the job. + """ + self.rpc.call(MsfRpcMethod.JobStop, jobid) - def login(self, password, **kwargs): - """ - Login to the msfrpc daemon. - - Mandatory Arguments: - - password : the password used to login to msfrpc - - Optional Keyword Arguments: - - username : the username used to authenticate to msfrpcd (default: msf) - - uri : the msfrpcd URI (default: /api/) - - port : the remote msfrpcd port to connect to (default: 55553) - - server : the remote server IP address hosting msfrpcd (default: localhost) - - ssl : if true uses SSL else regular HTTP (default: SSL enabled) - """ - return MsfRpcClient(password, **kwargs) - - def logout(self, sid): - """ - Logs out a user for a given session ID. - - Mandatory Arguments: - - sid : a session ID that is active. - """ - return self.rpc.call(MsfRpcMethod.AuthLogout, sid) - - @property - def tokens(self): - """ - The current list of active session IDs. - """ - return self.rpc.call(MsfRpcMethod.AuthTokenList)['tokens'] - - def add(self, token): - """ - Add a session ID or token. - - Mandatory Argument: - - token : a random string used as a session identifier. - """ - self.rpc.call(MsfRpcMethod.AuthTokenAdd, token) - - def remove(self, token): - """ - Remove a session ID or token. - - Mandatory Argument: - - token : a session ID or token that is active. - """ - self.rpc.call(MsfRpcMethod.AuthTokenRemove, token) - - def generate(self): - """ - Generate a session ID or token. - """ - return self.rpc.call(MsfRpcMethod.AuthTokenGenerate)['token'] + def info(self, jobid): + """ + Get job information for a particular job. + Mandatory Argument: + - jobid : the ID of the job. + """ + return self.rpc.call(MsfRpcMethod.JobInfo, jobid) -class PluginManager(MsfManager): - @property - def list(self): - """ - A list of loaded plugins. - """ - return self.rpc.call(MsfRpcMethod.PluginLoaded)['plugins'] +class CoreManager(MsfManager): - def load(self, plugin): - """ - Load a plugin of a given name. + @property + def version(self): + """ + The version of msf core. + """ + return self.rpc.call(MsfRpcMethod.CoreVersion) - Mandatory Arguments: - - plugin : a name of a plugin to load. - """ - self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginLoad, plugin) + def stop(self): + """ + Stop the core. + """ + self.rpc.call(MsfRpcMethod.CoreStop) - def unload(self, plugin): - """ - Unload a plugin of a given name. + def setg(self, var, val): + """ + Set a global variable - Mandatory Arguments: - - plugin : a name of a loaded plugin to unload. - """ - self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginUnload, plugin) + Mandatory Arguments: + - var : the variable name + - val : the variable value + """ + self.rpc.call(MsfRpcMethod.CoreSetG, var, val) + def unsetg(self, var): + """ + Unset a global variable -class JobManager(MsfManager): + Mandatory Arguments: + - var : the variable name + """ + self.rpc.call(MsfRpcMethod.CoreUnsetG, var) - @property - def list(self): - """ - A list of currently running jobs. - """ - return self.rpc.call(MsfRpcMethod.JobList) + def save(self): + """ + Save the core state. + """ + self.rpc.call(MsfRpcMethod.CoreSave) - def stop(self, jobid): - """ - Stop a job. + def reload(self): + """ + Reload all modules in the core. + """ + self.rpc.call(MsfRpcMethod.CoreReloadModules) - Mandatory Argument: - - jobid : the ID of the job. - """ - self.rpc.call(MsfRpcMethod.JobStop, jobid) + @property + def stats(self): + """ + Get module statistics from the core. + """ + return self.rpc.call(MsfRpcMethod.CoreModuleStats) - def info(self, jobid): - """ - Get job information for a particular job. + def addmodulepath(self, path): + """ + Add a search path for additional modules. - Mandatory Argument: - - jobid : the ID of the job. - """ - return self.rpc.call(MsfRpcMethod.JobInfo, jobid) + Mandatory Arguments: + - path : the path to search for modules. + """ + return self.rpc.call(MsfRpcMethod.CoreAddModulePath, path) + @property + def threads(self): + """ + The current threads running in the core. + """ + return self.rpc.call(MsfRpcMethod.CoreThreadList) -class CoreManager(MsfManager): + def kill(self, threadid): + """ + Kill a thread running in the core. - @property - def version(self): - """ - The version of msf core. - """ - return self.rpc.call(MsfRpcMethod.CoreVersion) - - def stop(self): - """ - Stop the core. - """ - self.rpc.call(MsfRpcMethod.CoreStop) - - def setg(self, var, val): - """ - Set a global variable - - Mandatory Arguments: - - var : the variable name - - val : the variable value - """ - self.rpc.call(MsfRpcMethod.CoreSetG, var, val) - - def unsetg(self, var): - """ - Unset a global variable - - Mandatory Arguments: - - var : the variable name - """ - self.rpc.call(MsfRpcMethod.CoreUnsetG, var) - - def save(self): - """ - Save the core state. - """ - self.rpc.call(MsfRpcMethod.CoreSave) - - def reload(self): - """ - Reload all modules in the core. - """ - self.rpc.call(MsfRpcMethod.CoreReloadModules) - - @property - def stats(self): - """ - Get module statistics from the core. - """ - return self.rpc.call(MsfRpcMethod.CoreModuleStats) - - def addmodulepath(self, path): - """ - Add a search path for additional modules. - - Mandatory Arguments: - - path : the path to search for modules. - """ - return self.rpc.call(MsfRpcMethod.CoreAddModulePath, path) - - @property - def threads(self): - """ - The current threads running in the core. - """ - return self.rpc.call(MsfRpcMethod.CoreThreadList) - - def kill(self, threadid): - """ - Kill a thread running in the core. - - Mandatory Arguments: - - threadid : the thread ID. - """ - self.rpc.call(MsfRpcMethod.CoreThreadKill, threadid) + Mandatory Arguments: + - threadid : the thread ID. + """ + self.rpc.call(MsfRpcMethod.CoreThreadKill, threadid) class MsfModule(object): @@ -1347,11 +1328,9 @@ def __init__(self, rpc, mtype, mname): self.modulename = mname self.rpc = rpc self._info = rpc.call(MsfRpcMethod.ModuleInfo, mtype, mname) - property_attributes = ["advanced", "evasion", "options", "required", - "runoptions"] + property_attributes = ["advanced", "evasion", "options", "required", "runoptions"] for k in self._info: - if k not in property_attributes: - # don't try to set property attributes + if k not in propery_attributes): setattr(self, k, self._info.get(k)) self._moptions = rpc.call(MsfRpcMethod.ModuleOptions, mtype, mname) self._roptions = [] @@ -1503,493 +1482,492 @@ def execute(self, **kwargs): class ExploitModule(MsfModule): - def __init__(self, rpc, exploit): - """ - Initializes the use of an exploit module. - - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - exploit : the name of the exploit module. - """ - super(ExploitModule, self).__init__(rpc, 'exploit', exploit) - self._target = self._info.get('default_target', 0) - - @property - def payloads(self): - """ - A list of compatible payloads. - """ -# return self.rpc.call(MsfRpcMethod.ModuleCompatiblePayloads, -# self.modulename)['payloads'] - return self.targetpayloads(self.target) - - @property - def target(self): - return self._target - - @target.setter - def target(self, target): - if target not in self.targets: - raise ValueError('Target must be one of %s' % repr(list(self.targets.keys()))) - self._target = target - - def targetpayloads(self, t=0): - """ - Returns a list of compatible payloads for a given target ID. - - Optional Keyword Arguments: - - t : the target ID (default: 0, e.g. 'Automatic') - """ - return self.rpc.call(MsfRpcMethod.ModuleTargetCompatiblePayloads, self.modulename, t)['payloads'] + def __init__(self, rpc, exploit): + """ + Initializes the use of an exploit module. + + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - exploit : the name of the exploit module. + """ + super(ExploitModule, self).__init__(rpc, 'exploit', exploit) + self._target = self._info.get('default_target', 0) + + @property + def payloads(self): + """ + A list of compatible payloads. + """ +# return self.rpc.call(MsfRpcMethod.ModuleCompatiblePayloads, self.modulename)['payloads'] + return self.targetpayloads(self.target) + + @property + def target(self): + return self._target + + @target.setter + def target(self, target): + if target not in self.targets: + raise ValueError('Target must be one of %s' % repr(self.targets.keys())) + self._target = target + + def targetpayloads(self, t=0): + """ + Returns a list of compatible payloads for a given target ID. + + Optional Keyword Arguments: + - t : the target ID (default: 0, e.g. 'Automatic') + """ + return self.rpc.call(MsfRpcMethod.ModuleTargetCompatiblePayloads, self.modulename, t)['payloads'] class PostModule(MsfModule): - def __init__(self, rpc, post): - """ - Initializes the use of a post exploitation module. + def __init__(self, rpc, post): + """ + Initializes the use of a post exploitation module. - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - post : the name of the post exploitation module. - """ - super(PostModule, self).__init__(rpc, 'post', post) + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - post : the name of the post exploitation module. + """ + super(PostModule, self).__init__(rpc, 'post', post) - @property - def sessions(self): - """ - A list of compatible shell/meterpreter sessions. - """ - return self.rpc.compatiblesessions(self.modulename) + @property + def sessions(self): + """ + A list of compatible shell/meterpreter sessions. + """ + return self.rpc.compatiblesessions(self.modulename) class EncoderModule(MsfModule): - def __init__(self, rpc, encoder): - """ - Initializes the use of an encoder module. + def __init__(self, rpc, encoder): + """ + Initializes the use of an encoder module. - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - encoder : the name of the encoder module. - """ - super(EncoderModule, self).__init__(rpc, 'encoder', encoder) + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - encoder : the name of the encoder module. + """ + super(EncoderModule, self).__init__(rpc, 'encoder', encoder) class AuxiliaryModule(MsfModule): - def __init__(self, rpc, auxiliary): - """ - Initializes the use of an auxiliary module. + def __init__(self, rpc, auxiliary): + """ + Initializes the use of an auxiliary module. - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - auxiliary : the name of the auxiliary module. - """ - super(AuxiliaryModule, self).__init__(rpc, 'auxiliary', auxiliary) + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - auxiliary : the name of the auxiliary module. + """ + super(AuxiliaryModule, self).__init__(rpc, 'auxiliary', auxiliary) class PayloadModule(MsfModule): - def __init__(self, rpc, payload): - """ - Initializes the use of a payload module. + def __init__(self, rpc, payload): + """ + Initializes the use of a payload module. - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - payload : the name of the payload module. - """ - super(PayloadModule, self).__init__(rpc, 'payload', payload) + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - payload : the name of the payload module. + """ + super(PayloadModule, self).__init__(rpc, 'payload', payload) class NopModule(MsfModule): - def __init__(self, rpc, nop): - """ - Initializes the use of a nop module. + def __init__(self, rpc, nop): + """ + Initializes the use of a nop module. - Mandatory Arguments: - - rpc : the rpc client used to communicate with msfrpcd - - nop : the name of the nop module. - """ - super(NopModule, self).__init__(rpc, 'nop', nop) + Mandatory Arguments: + - rpc : the rpc client used to communicate with msfrpcd + - nop : the name of the nop module. + """ + super(NopModule, self).__init__(rpc, 'nop', nop) class ModuleManager(MsfManager): - def execute(self, modtype, modname, **kwargs): - """ - Execute the module. - - Mandatory Arguments: - - modtype : the module type (e.g. 'exploit') - - modname : the module name (e.g. 'exploits/windows/http/icecast_header') - - Optional Keyword Arguments: - - **kwargs : the module's run options - """ - return self.rpc.call(MsfRpcMethod.ModuleExecute, modtype, modname, kwargs) - - @property - def exploits(self): - """ - A list of exploit modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleExploits)['modules'] - - @property - def payloads(self): - """ - A list of payload modules. - """ - return self.rpc.call(MsfRpcMethod.ModulePayloads)['modules'] - - @property - def auxiliary(self): - """ - A list of auxiliary modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleAuxiliary)['modules'] - - @property - def post(self): - """ - A list of post modules. - """ - return self.rpc.call(MsfRpcMethod.ModulePost)['modules'] - - @property - def encodeformats(self): - """ - A list of encoding formats. - """ - return self.rpc.call(MsfRpcMethod.ModuleEncodeFormats) - - @property - def encoders(self): - """ - A list of encoder modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleEncoders)['modules'] - - @property - def nops(self): - """ - A list of nop modules. - """ - return self.rpc.call(MsfRpcMethod.ModuleNops)['modules'] - - def use(self, mtype, mname): - """ - Returns a module object. - - Mandatory Arguments: - - mname : the module name (e.g. 'exploits/windows/http/icecast_header') - """ - if mtype == 'exploit': - return ExploitModule(self.rpc, mname) - elif mtype == 'post': - return PostModule(self.rpc, mname) - elif mtype == 'encoder': - return EncoderModule(self.rpc, mname) - elif mtype == 'auxiliary': - return AuxiliaryModule(self.rpc, mname) - elif mtype == 'nop': - return NopModule(self.rpc, mname) - elif mtype == 'payload': - return PayloadModule(self.rpc, mname) - raise MsfRpcError('Unknown module type %s not: exploit, post, encoder, auxiliary, nop, or payload' % mname) + def execute(self, modtype, modname, **kwargs): + """ + Execute the module. + + Mandatory Arguments: + - modtype : the module type (e.g. 'exploit') + - modname : the module name (e.g. 'exploits/windows/http/icecast_header') + + Optional Keyword Arguments: + - **kwargs : the module's run options + """ + return self.rpc.call(MsfRpcMethod.ModuleExecute, modtype, modname, kwargs) + + @property + def exploits(self): + """ + A list of exploit modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleExploits)['modules'] + + @property + def payloads(self): + """ + A list of payload modules. + """ + return self.rpc.call(MsfRpcMethod.ModulePayloads)['modules'] + + @property + def auxiliary(self): + """ + A list of auxiliary modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleAuxiliary)['modules'] + + @property + def post(self): + """ + A list of post modules. + """ + return self.rpc.call(MsfRpcMethod.ModulePost)['modules'] + + @property + def encodeformats(self): + """ + A list of encoding formats. + """ + return self.rpc.call(MsfRpcMethod.ModuleEncodeFormats) + + @property + def encoders(self): + """ + A list of encoder modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleEncoders)['modules'] + + @property + def nops(self): + """ + A list of nop modules. + """ + return self.rpc.call(MsfRpcMethod.ModuleNops)['modules'] + + def use(self, mtype, mname): + """ + Returns a module object. + + Mandatory Arguments: + - mname : the module name (e.g. 'exploits/windows/http/icecast_header') + """ + if mtype == 'exploit': + return ExploitModule(self.rpc, mname) + elif mtype == 'post': + return PostModule(self.rpc, mname) + elif mtype == 'encoder': + return EncoderModule(self.rpc, mname) + elif mtype == 'auxiliary': + return AuxiliaryModule(self.rpc, mname) + elif mtype == 'nop': + return NopModule(self.rpc, mname) + elif mtype == 'payload': + return PayloadModule(self.rpc, mname) + raise MsfRpcError('Unknown module type %s not: exploit, post, encoder, auxiliary, nop, or payload' % mname) class MsfSession(object): - def __init__(self, id, rpc, sd): - """ - Initialize a meterpreter or shell session. - - Mandatory Arguments: - - id : the session identifier. - - rpc : the msfrpc client object. - - sd : the session description - """ - self.id = id - self.rpc = rpc - self.__dict__.update(sd) - - def stop(self): - """ - Stop a meterpreter or shell session. - """ - return self.rpc.call(MsfRpcMethod.SessionStop, self.id) - - @property - def modules(self): - """ - A list of compatible session modules. - """ - return self.rpc.call(MsfRpcMethod.SessionCompatibleModules, self.id)['modules'] - - @property - def ring(self): - return SessionRing(self.rpc, self.id) + def __init__(self, id, rpc, sd): + """ + Initialize a meterpreter or shell session. + + Mandatory Arguments: + - id : the session identifier. + - rpc : the msfrpc client object. + - sd : the session description + """ + self.id = id + self.rpc = rpc + self.__dict__.update(sd) + + def stop(self): + """ + Stop a meterpreter or shell session. + """ + return self.rpc.call(MsfRpcMethod.SessionStop, self.id) + + @property + def modules(self): + """ + A list of compatible session modules. + """ + return self.rpc.call(MsfRpcMethod.SessionCompatibleModules, self.id)['modules'] + + @property + def ring(self): + return SessionRing(self.rpc, self.id) class SessionRing(object): - def __init__(self, rpc, sessionid): - self.rpc = rpc - self.id = sessionid + def __init__(self, rpc, sessionid): + self.rpc = rpc + self.id = sessionid - def read(self, seq=None): - """ - Reads the session ring. + def read(self, seq=None): + """ + Reads the session ring. - Optional Keyword Arguments: - - seq : the sequence ID of the ring (default: 0) - """ - if seq is not None: - return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id, seq) - return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id) + Optional Keyword Arguments: + - seq : the sequence ID of the ring (default: 0) + """ + if seq is not None: + return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id, seq) + return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id) - def put(self, line): - """ - Add a command to the session history. + def put(self, line): + """ + Add a command to the session history. - Mandatory Arguments: - - line : arbitrary data. - """ - self.rpc.call(MsfRpcMethod.SessionRingPut, self.id, line) + Mandatory Arguments: + - line : arbitrary data. + """ + self.rpc.call(MsfRpcMethod.SessionRingPut, self.id, line) - @property - def last(self): - """ - Returns the last sequence ID in the session ring. - """ - return int(self.rpc.call(MsfRpcMethod.SessionRingLast, self.id)['seq']) + @property + def last(self): + """ + Returns the last sequence ID in the session ring. + """ + return int(self.rpc.call(MsfRpcMethod.SessionRingLast, self.id)['seq']) - def clear(self): - """ - Clear the session ring. - """ - return self.rpc.call(MsfRpcMethod.SessionRingClear, self.id) + def clear(self): + """ + Clear the session ring. + """ + return self.rpc.call(MsfRpcMethod.SessionRingClear, self.id) class MeterpreterSession(MsfSession): - def read(self): - """ - Read data from the meterpreter session. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterRead, self.id)['data'] - - def write(self, data): - """ - Write data to the meterpreter session. - - Mandatory Arguments: - - data : arbitrary data or commands - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterWrite, self.id, data) - - def runsingle(self, data): - """ - Run a single meterpreter command - - Mandatory Arguments: - - data : arbitrary data or command - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterRunSingle, self.id, data) - return self.read() - - def runscript(self, path): - """ - Run a meterpreter script - - Mandatory Arguments: - - path : path to a meterpreter script on the msfrpcd host. - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterScript, self.id, path) - return self.read() - - @property - def sep(self): - """ - The operating system path separator. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterDirectorySeparator, self.id)['separator'] - - def detach(self): - """ - Detach the meterpreter session. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionDetach, self.id) - - def kill(self): - """ - Kill the meterpreter session. - """ - self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionKill, self.id) - - def tabs(self, line): - """ - Return a list of commands for a partial command line (tab completion). - - Mandatory Arguments: - - line : a partial command line for completion. - """ - return self.rpc.call(MsfRpcMethod.SessionMeterpreterTabs, self.id, line)['tabs'] + def read(self): + """ + Read data from the meterpreter session. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterRead, self.id)['data'] + + def write(self, data): + """ + Write data to the meterpreter session. + + Mandatory Arguments: + - data : arbitrary data or commands + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterWrite, self.id, data) + + def runsingle(self, data): + """ + Run a single meterpreter command + + Mandatory Arguments: + - data : arbitrary data or command + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterRunSingle, self.id, data) + return self.read() + + def runscript(self, path): + """ + Run a meterpreter script + + Mandatory Arguments: + - path : path to a meterpreter script on the msfrpcd host. + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterScript, self.id, path) + return self.read() + + @property + def sep(self): + """ + The operating system path separator. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterDirectorySeparator, self.id)['separator'] + + def detach(self): + """ + Detach the meterpreter session. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionDetach, self.id) + + def kill(self): + """ + Kill the meterpreter session. + """ + self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionKill, self.id) + + def tabs(self, line): + """ + Return a list of commands for a partial command line (tab completion). + + Mandatory Arguments: + - line : a partial command line for completion. + """ + return self.rpc.call(MsfRpcMethod.SessionMeterpreterTabs, self.id, line)['tabs'] class ShellSession(MsfSession): - def read(self): - """ - Read data from the shell session. - """ - return self.rpc.call(MsfRpcMethod.SessionShellRead, self.id)['data'] + def read(self): + """ + Read data from the shell session. + """ + return self.rpc.call(MsfRpcMethod.SessionShellRead, self.id)['data'] - def write(self, data): - """ - Write data to the shell session. + def write(self, data): + """ + Write data to the shell session. - Mandatory Arguments: - - data : arbitrary data or commands - """ - self.rpc.call(MsfRpcMethod.SessionShellWrite, self.id, data) + Mandatory Arguments: + - data : arbitrary data or commands + """ + self.rpc.call(MsfRpcMethod.SessionShellWrite, self.id, data) - def upgrade(self, lhost, lport): - """ - Upgrade the current shell session. - """ - self.rpc.call(MsfRpcMethod.SessionShellUpgrade, self.id, lhost, lport) - return self.read() + def upgrade(self, lhost, lport): + """ + Upgrade the current shell session. + """ + self.rpc.call(MsfRpcMethod.SessionShellUpgrade, self.id, lhost, lport) + return self.read() class SessionManager(MsfManager): - @property - def list(self): - """ - A list of active sessions. - """ - return self.rpc.call(MsfRpcMethod.SessionList) - - def session(self, id): - """ - Returns a session object for meterpreter or shell sessions. - - Mandatory Arguments: - - id : the session identifier. - """ - s = self.list - if id not in s: - for k in s: - if s[k]['uuid'] == id: - if s[id]['type'] == 'meterpreter': - return MeterpreterSession(id, self.rpc, s) - elif s[id]['type'] == 'shell': - return ShellSession(id, self.rpc, s) - raise KeyError('Session ID (%s) does not exist' % id) - if s[id]['type'] == 'meterpreter': - return MeterpreterSession(id, self.rpc, s) - elif s[id]['type'] == 'shell': - return ShellSession(id, self.rpc, s) - raise NotImplementedError('Could not determine session type: %s' % s[id]['type']) + @property + def list(self): + """ + A list of active sessions. + """ + return self.rpc.call(MsfRpcMethod.SessionList) + + def session(self, id): + """ + Returns a session object for meterpreter or shell sessions. + + Mandatory Arguments: + - id : the session identifier. + """ + s = self.list + if id not in s: + for k in s: + if s[k]['uuid'] == id: + if s[id]['type'] == 'meterpreter': + return MeterpreterSession(id, self.rpc, s) + elif s[id]['type'] == 'shell': + return ShellSession(id, self.rpc, s) + raise KeyError('Session ID (%s) does not exist' % id) + if s[id]['type'] == 'meterpreter': + return MeterpreterSession(id, self.rpc, s) + elif s[id]['type'] == 'shell': + return ShellSession(id, self.rpc, s) + raise NotImplementedError('Could not determine session type: %s' % s[id]['type']) class MsfConsole(object): - def __init__(self, rpc, cid=None): - """ - Initializes an msf console. - - Mandatory Arguments: - - rpc : the msfrpc client object. - - Optional Keyword Arguments: - - cid : the console identifier if it exists already otherwise a new one will be created. - """ - self.rpc = rpc - if cid is None: - r = self.rpc.call(MsfRpcMethod.ConsoleCreate) - if 'id' in r: - self.cid = r['id'] - else: - raise MsfRpcError('Unable to create a new console.') - else: - self.cid = cid - - def read(self): - """ - Read data from the console. - """ - return self.rpc.call(MsfRpcMethod.ConsoleRead, self.cid) - - def write(self, command): - """ - Write data to the console. - """ - if not command.endswith('\n'): - command += '\n' - self.rpc.call(MsfRpcMethod.ConsoleWrite, self.cid, command) - - def sessionkill(self): - """ - Kill all active meterpreter or shell sessions. - """ - self.rpc.call(MsfRpcMethod.ConsoleSessionKill, self.cid) - - def sessiondetach(self): - """ - Detach the current meterpreter or shell session. - """ - self.rpc.call(MsfRpcMethod.ConsoleSessionDetach, self.cid) - - def tabs(self, line): - """ - Tab completion for console commands. - - Mandatory Arguments: - - line : a partial command to be completed. - """ - return self.rpc.call(MsfRpcMethod.ConsoleTabs, self.cid, line)['tabs'] - - def destroy(self): - """ - Destroy the console. - """ - self.rpc.call(MsfRpcMethod.ConsoleDestroy, self.cid) + def __init__(self, rpc, cid=None): + """ + Initializes an msf console. + + Mandatory Arguments: + - rpc : the msfrpc client object. + + Optional Keyword Arguments: + - cid : the console identifier if it exists already otherwise a new one will be created. + """ + self.rpc = rpc + if cid is None: + r = self.rpc.call(MsfRpcMethod.ConsoleCreate) + if 'id' in r: + self.cid = r['id'] + else: + raise MsfRpcError('Unable to create a new console.') + else: + self.cid = cid + + def read(self): + """ + Read data from the console. + """ + return self.rpc.call(MsfRpcMethod.ConsoleRead, self.cid) + + def write(self, command): + """ + Write data to the console. + """ + if not command.endswith('\n'): + command += '\n' + self.rpc.call(MsfRpcMethod.ConsoleWrite, self.cid, command) + + def sessionkill(self): + """ + Kill all active meterpreter or shell sessions. + """ + self.rpc.call(MsfRpcMethod.ConsoleSessionKill, self.cid) + + def sessiondetach(self): + """ + Detach the current meterpreter or shell session. + """ + self.rpc.call(MsfRpcMethod.ConsoleSessionDetach, self.cid) + + def tabs(self, line): + """ + Tab completion for console commands. + + Mandatory Arguments: + - line : a partial command to be completed. + """ + return self.rpc.call(MsfRpcMethod.ConsoleTabs, self.cid, line)['tabs'] + + def destroy(self): + """ + Destroy the console. + """ + self.rpc.call(MsfRpcMethod.ConsoleDestroy, self.cid) class ConsoleManager(MsfManager): - @property - def list(self): - """ - A list of active consoles. - """ - return self.rpc.call(MsfRpcMethod.ConsoleList) - - def console(self, cid=None): - """ - Connect to an active console otherwise create a new console. - - Optional Keyword Arguments: - - cid : the console identifier. - """ - s = self.list - if cid is None: - return MsfConsole(self.rpc) - if cid not in s: - raise KeyError('Console ID (%s) does not exist' % cid) - else: - return MsfConsole(self.rpc, cid=cid) - - def destroy(self, cid): - """ - Destory an active console. - - Mandatory Arguments: - - cid : the console identifier. - """ - self.rpc.call(MsfRpcMethod.ConsoleDestroy, cid) + @property + def list(self): + """ + A list of active consoles. + """ + return self.rpc.call(MsfRpcMethod.ConsoleList)['consoles'] + + def console(self, cid=None): + """ + Connect to an active console otherwise create a new console. + + Optional Keyword Arguments: + - cid : the console identifier. + """ + s = [x['id'] for x in self.list['consoles']] + if cid is None: + return MsfConsole(self.rpc) + if cid not in s: + raise KeyError('Console ID (%s) does not exist' % cid) + else: + return MsfConsole(self.rpc, cid=cid) + + def destroy(self, cid): + """ + Destory an active console. + + Mandatory Arguments: + - cid : the console identifier. + """ + self.rpc.call(MsfRpcMethod.ConsoleDestroy, cid)