· 5 years ago · Mar 06, 2020, 04:30 PM
1#!/usr/bin/env python
2
3from httplib import HTTPConnection, HTTPSConnection
4from numbers import Number
5
6from msgpack import packb, unpackb
7
8__author__ = 'Nadeem Douba'
9__copyright__ = 'Copyright 2012, PyMetasploit Project'
10__credits__ = []
11
12__license__ = 'GPL'
13__version__ = '0.4'
14__maintainer__ = 'Nadeem Douba'
15__email__ = 'ndouba@gmail.com'
16__status__ = 'Development'
17
18__all__ = [
19 'MsfRpcError',
20 'MsfRpcMethod',
21 'MsfPlugins',
22 'MsfRpcClient',
23 'MsfTable',
24 'NotesTable',
25 'LootsTable',
26 'CredsTable',
27 'AuthInfoTable',
28 'HostsTable',
29 'ServicesTable',
30 'VulnsTable',
31 'EventsTable',
32 'ClientsTable',
33 'Workspace',
34 'MsfManager',
35 'WorkspaceManager',
36 'DbManager',
37 'AuthManager',
38 'PluginManager',
39 'JobManager',
40 'CoreManager',
41 'MsfModule',
42 'ExploitModule',
43 'PostModule',
44 'EncoderModule',
45 'AuxiliaryModule',
46 'PayloadModule',
47 'NopModule',
48 'ModuleManager',
49 'MsfSession',
50 'MeterpreterSession',
51 'ShellSession',
52 'SessionManager',
53 'MsfConsole',
54 'ConsoleManager',
55 'ReportFilter',
56 'ReportFilterQuery'
57]
58
59
60class MsfRpcError(Exception):
61 pass
62
63
64class MsfRpcMethod(object):
65 AuthLogin = 'auth.login'
66 AuthLogout = 'auth.logout'
67 AuthTokenList = 'auth.token_list'
68 AuthTokenAdd = 'auth.token_add'
69 AuthTokenGenerate = 'auth.token_generate'
70 AuthTokenRemove = 'auth.token_remove'
71 ConsoleCreate = 'console.create'
72 ConsoleList = 'console.list'
73 ConsoleDestroy = 'console.destroy'
74 ConsoleRead = 'console.read'
75 ConsoleWrite = 'console.write'
76 ConsoleTabs = 'console.tabs'
77 ConsoleSessionKill = 'console.session_kill'
78 ConsoleSessionDetach = 'console.session_detach'
79 CoreVersion = 'core.version'
80 CoreStop = 'core.stop'
81 CoreSetG = 'core.setg'
82 CoreUnsetG = 'core.unsetg'
83 CoreSave = 'core.save'
84 CoreReloadModules = 'core.reload_modules'
85 CoreModuleStats = 'core.module_stats'
86 CoreAddModulePath = 'core.add_module_path'
87 CoreThreadList = 'core.thread_list'
88 CoreThreadKill = 'core.thread_kill'
89 DbHosts = 'db.hosts'
90 DbServices = 'db.services'
91 DbVulns = 'db.vulns'
92 DbWorkspaces = 'db.workspaces'
93 DbCurrentWorkspace = 'db.current_workspace'
94 DbGetWorkspace = 'db.get_workspace'
95 DbSetWorkspace = 'db.set_workspace'
96 DbDelWorkspace = 'db.del_workspace'
97 DbAddWorkspace = 'db.add_workspace'
98 DbGetHost = 'db.get_host'
99 DbReportHost = 'db.report_host'
100 DbReportService = 'db.report_service'
101 DbGetService = 'db.get_service'
102 DbGetNote = 'db.get_note'
103 DbGetClient = 'db.get_client'
104 DbReportClient = 'db.report_client'
105 DbReportNote = 'db.report_note'
106 DbNotes = 'db.notes'
107 DbReportAuthInfo = 'db.report_auth_info'
108 DbGetAuthInfo = 'db.get_auth_info'
109 DbGetRef = 'db.get_ref'
110 DbDelVuln = 'db.del_vuln'
111 DbDelNote = 'db.del_note'
112 DbDelService = 'db.del_service'
113 DbDelHost = 'db.del_host'
114 DbReportVuln = 'db.report_vuln'
115 DbEvents = 'db.events'
116 DbReportEvent = 'db.report_event'
117 DbReportLoot = 'db.report_loot'
118 DbLoots = 'db.loots'
119 DbReportCred = 'db.report_cred'
120 DbCreds = 'db.creds'
121 DbImportData = 'db.import_data'
122 DbGetVuln = 'db.get_vuln'
123 DbClients = 'db.clients'
124 DbDelClient = 'db.del_client'
125 DbDriver = 'db.driver'
126 DbConnect = 'db.connect'
127 DbStatus = 'db.status'
128 DbDisconnect = 'db.disconnect'
129 JobList = 'job.list'
130 JobStop = 'job.stop'
131 JobInfo = 'job.info'
132 ModuleExploits = 'module.exploits'
133 ModuleAuxiliary = 'module.auxiliary'
134 ModulePayloads = 'module.payloads'
135 ModuleEncoders = 'module.encoders'
136 ModuleNops = 'module.nops'
137 ModulePost = 'module.post'
138 ModuleInfo = 'module.info'
139 ModuleCompatiblePayloads = 'module.compatible_payloads'
140 ModuleCompatibleSessions = 'module.compatible_sessions'
141 ModuleTargetCompatiblePayloads = 'module.target_compatible_payloads'
142 ModuleOptions = 'module.options'
143 ModuleExecute = 'module.execute'
144 ModuleEncodeFormats = 'module.encode_formats'
145 ModuleEncode = 'module.encode'
146 PluginLoad = 'plugin.load'
147 PluginUnload = 'plugin.unload'
148 PluginLoaded = 'plugin.loaded'
149 SessionList = 'session.list'
150 SessionStop = 'session.stop'
151 SessionShellRead = 'session.shell_read'
152 SessionShellWrite = 'session.shell_write'
153 SessionShellUpgrade = 'session.shell_upgrade'
154 SessionMeterpreterRead = 'session.meterpreter_read'
155 SessionRingRead = 'session.ring_read'
156 SessionRingPut = 'session.ring_put'
157 SessionRingLast = 'session.ring_last'
158 SessionRingClear = 'session.ring_clear'
159 SessionMeterpreterWrite = 'session.meterpreter_write'
160 SessionMeterpreterSessionDetach = 'session.meterpreter_session_detach'
161 SessionMeterpreterSessionKill = 'session.meterpreter_session_kill'
162 SessionMeterpreterTabs = 'session.meterpreter_tabs'
163 SessionMeterpreterRunSingle = 'session.meterpreter_run_single'
164 SessionMeterpreterScript = 'session.meterpreter_script'
165 SessionMeterpreterDirectorySeparator = 'session.meterpreter_directory_separator'
166 SessionCompatibleModules = 'session.compatible_modules'
167
168
169class MsfPlugins(object):
170 IpsFilter = "ips_filter"
171 SocketLogger = "socket_logger"
172 DbTracker = "db_tracker"
173 Sounds = "sounds"
174 AutoAddRoute = "auto_add_route"
175 DbCredCollect = "db_credcollect"
176
177
178class MsfRpcClient(object):
179
180 _headers = {
181 'Content-Type' : 'binary/message-pack'
182 }
183
184 def __init__(self, password, **kwargs):
185 """
186 Connects and authenticates to a Metasploit RPC daemon.
187
188 Mandatory Arguments:
189 - password : the password used to authenticate to msfrpcd
190
191 Optional Keyword Arguments:
192 - username : the username used to authenticate to msfrpcd (default: msf)
193 - uri : the msfrpcd URI (default: /api/)
194 - port : the remote msfrpcd port to connect to (default: 55553)
195 - server : the remote server IP address hosting msfrpcd (default: localhost)
196 - ssl : if true uses SSL else regular HTTP (default: SSL enabled)
197 """
198 self.uri = kwargs.get('uri', '/api/')
199 self.port = kwargs.get('port', 55553)
200 self.server = kwargs.get('server', '127.0.0.1')
201 self.ssl = kwargs.get('ssl', True)
202 self.sessionid = kwargs.get('token')
203 if self.ssl:
204 self.client = HTTPSConnection(self.server, self.port)
205 else:
206 self.client = HTTPConnection(self.server, self.port)
207 self.login(kwargs.get('username', 'msf'), password)
208
209 def call(self, method, *args):
210 """
211 Builds an RPC request and retrieves the result.
212
213 Mandatory Arguments:
214 - method : the RPC call method name (e.g. db.clients)
215
216 Optional Arguments:
217 - *args : the RPC method's parameters if necessary
218
219 Returns : RPC call result
220 """
221 l = [ method ]
222 l.extend(args)
223 if method == MsfRpcMethod.AuthLogin:
224 self.client.request('POST', self.uri, packb(l), self._headers)
225 r = self.client.getresponse()
226 if r.status == 200:
227 return unpackb(r.read())
228 raise MsfRpcError('An unknown error has occurred while logging in.')
229 elif self.authenticated:
230 l.insert(1, self.sessionid)
231 self.client.request('POST', self.uri, packb(l), self._headers)
232 r = self.client.getresponse()
233 if r.status == 200:
234 result = unpackb(r.read())
235 if 'error' in result:
236 raise MsfRpcError(result['error_message'])
237 return result
238 raise MsfRpcError('An unknown error has occurred while performing the RPC call.')
239 raise MsfRpcError('You cannot perform this call because you are not authenticated.')
240
241 @property
242 def core(self):
243 """
244 The msf RPC core manager.
245 """
246 return CoreManager(self)
247
248 @property
249 def modules(self):
250 """
251 The msf RPC modules RPC manager.
252 """
253 return ModuleManager(self)
254
255 @property
256 def sessions(self):
257 """
258 The msf RPC sessions (meterpreter & shell) manager.
259 """
260 return SessionManager(self)
261
262 @property
263 def jobs(self):
264 """
265 The msf RPC jobs manager.
266 """
267 return JobManager(self)
268
269 @property
270 def consoles(self):
271 """
272 The msf RPC consoles manager
273 """
274 return ConsoleManager(self)
275
276 @property
277 def authenticated(self):
278 """
279 Whether or not this client is authenticated.
280 """
281 return self.sessionid is not None
282
283 @property
284 def plugins(self):
285 """
286 The msf RPC plugins manager.
287 """
288 return PluginManager(self)
289
290 @property
291 def db(self):
292 """
293 The msf RPC database manager.
294 """
295 return DbManager(self)
296
297 @property
298 def auth(self):
299 """
300 The msf authentication manager.
301 """
302 return AuthManager(self)
303
304 def login(self, username, password):
305 """
306 Authenticates and reauthenticates the user to msfrpcd.
307 """
308 if self.sessionid is None:
309 r = self.call(MsfRpcMethod.AuthLogin, username, password)
310 try:
311 if r['result'] == 'success':
312 self.sessionid = r['token']
313 except KeyError:
314 raise MsfRpcError('Login failed.')
315 else:
316 try:
317 r = self.call(MsfRpcMethod.DbStatus)
318 except MsfRpcError:
319 raise MsfRpcError('Login failed.')
320
321 def logout(self):
322 """
323 Logs the current user out. Note: do not call directly.
324 """
325 self.call(MsfRpcMethod.AuthLogout, self.sessionid)
326
327
328class MsfTable(object):
329
330 def __init__(self, rpc, wname):
331 self.rpc = rpc
332 self.name = wname
333
334 def dbreport(self, atype, attrs):
335 attrs.update({ 'workspace' : self.name })
336 return self.rpc.call('db.report_%s' % atype, attrs)
337
338 def dbdel(self, atype, attrs):
339 attrs.update({ 'workspace' : self.name })
340 return self.rpc.call('db.del_%s' % atype, attrs)
341
342 def dbget(self, atype, attrs):
343 attrs.update({ 'workspace' : self.name })
344 return self.rpc.call('db.get_%s' % atype, attrs)[atype]
345
346 def records(self, atypes, **kwargs):
347 kwargs.update({'workspace' : self.name})
348 return self.rpc.call('db.%s' % atypes, kwargs)[atypes]
349
350 @property
351 def list(self):
352 raise NotImplementedError
353
354 def report(self, *args, **kwargs):
355 raise NotImplementedError
356
357 def delete(self, *args, **kwargs):
358 raise NotImplementedError
359
360 def find(self, **kwargs):
361 raise NotImplementedError
362
363 update = report
364
365
366class NotesTable(MsfTable):
367
368 @property
369 def list(self):
370 return super(NotesTable, self).records('notes')
371
372 def find(self, **kwargs):
373 """
374 Find notes based on search criteria.
375
376 Optional Keyword Arguments:
377 - limit : the maximum number of results.
378 - offset : skip n results.
379 - addresses : a list of addresses to search for.
380 - names : comma separated string of service names.
381 - ntype : the note type.
382 - ports : the port associated with the note.
383 - proto : the protocol associated with the note.
384 """
385 if 'ports' in kwargs:
386 kwargs['port'] = True
387 return super(NotesTable, self).records('notes', **kwargs)
388
389 def report(self, type, data, **kwargs):
390 """
391 Report a Note to the database. Notes can be tied to a Workspace, Host, or Service.
392
393 Mandatory Arguments:
394 - type : The type of note, e.g. 'smb_peer_os'.
395 - data : whatever it is you're making a note of.
396
397 Optional Keyword Arguments:
398 - host : an IP address or a Host object to associate with this Note.
399 - service : a dict containing 'host', 'port', 'proto' and optionally 'name' keys.
400 - port : along with 'host' and 'proto', a service to associate with this Note.
401 - proto : along with 'host' and 'port', a service to associate with this Note.
402 - update : what to do in case a similar Note exists, see below.
403
404 The 'update' option can have the following values:
405 - unique : allow only a single Note per host/type pair.
406 - unique_data : like 'unique', but also compare 'data'.
407 - insert : always insert a new Note even if one with identical values exists.
408
409 If the provided 'host' is an IP address and does not exist in the database,
410 it will be created. If 'host' and 'service' are all omitted, the new Note
411 will be associated with the current 'workspace'.
412 """
413 kwargs.update({ 'data' : data, 'type' : type })
414 kwargs.update(kwargs.pop('service', {}))
415 self.dbreport('note', kwargs)
416
417 def delete(self, **kwargs):
418 """
419 Delete one or more notes based on a search criteria.
420
421 Optional Keyword Arguments:
422 - host : the host associated with a Note, not required if 'address' or 'addresses' is specified
423 - address : the address associated with a Note, not required if 'host' or 'addresses' is specified.
424 - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified.
425 - port : the port associated with a Note.
426 - proto : the protocol associated with a Note.
427 - ntype : the note type, e.g. 'smb_peer_os'.
428 """
429 self.dbdel('note', kwargs)
430
431 def get(self, **kwargs):
432 """
433 Get a Note from the database based on the specifications of one or more keyword arguments.
434
435 Mandatory Keyword Arguments:
436 - host : the host associated with a Note, not required if 'address' or 'addr' is specified.
437 - address : the address associated with a Note, not required if 'host' or 'addr' is specified.
438 - addr : same as 'address', not required if 'host' or 'address' is specified.
439
440 Optional Keyword Arguments:
441 - proto : the protocol associated with the Note.
442 - port : the port associated with the Note.
443 - ntype : the type of Note.
444 """
445 if not any([i in kwargs for i in ('host', 'address', 'addr')]):
446 raise TypeError('Expected a host, address, or addr.')
447 return self.dbget('note', kwargs)
448
449 update = report
450
451
452class LootsTable(MsfTable):
453
454 @property
455 def list(self):
456 return super(LootsTable, self).records('loots')
457
458 def find(self, **kwargs):
459 """
460 Find loot based on search criteria.
461
462 Optional Keyword Arguments:
463 - limit : the maximum number of results.
464 - offset : skip n results.
465 """
466 return super(LootsTable, self).records('loots', **kwargs)
467
468 def report(self, path, type, **kwargs):
469 """
470 Report Loot to the database
471
472 Mandatory Arguments:
473 - path : the filesystem path to the Loot
474 - type : the type of Loot
475 - ltype : the same as 'type', not required if 'type' is specified.
476
477 Optional Keyword Arguments:
478 - host : an IP address or a Host object to associate with this Note
479 - ctype : the content type of the loot, e.g. 'text/plain'
480 - content_type : same as 'ctype'.
481 - service : a service to associate Loot with.
482 - name : a name to associate with this Loot.
483 - info : additional information about this Loot.
484 - data : the data within the Loot.
485 """
486 kwargs.update({ 'path' : path, 'type' : type })
487 self.dbreport('loot', kwargs)
488
489 update = report
490
491
492class CredsTable(MsfTable):
493
494 @property
495 def list(self):
496 return super(CredsTable, self).records('creds')
497
498 def find(self, **kwargs):
499 """
500 Find creds based on search criteria.
501
502 Optional Keyword Arguments:
503 - limit : the maximum number of results.
504 - offset : skip n results.
505 """
506 return super(CredsTable, self).records('creds', **kwargs)
507
508 def report(self, host, port, **kwargs):
509 """
510 Store a set of credentials in the database.
511
512 Mandatory Arguments:
513 - host : an IP address or Host object reference
514 - port : a port number
515
516 Optional Keyword Arguments:
517 - user : the username.
518 - password : the password, or path to ssh_key.
519 - ptype : the type of password (password(ish), hash, or ssh_key).
520 - proto : a transport name for the port.
521 - sname : service name.
522 - active : by default, a cred is active, unless explicitly false.
523 - proof : data used to prove the account is actually active.
524
525 Sources: Credentials can be sourced from another credential, or from
526 a vulnerability. For example, if an exploit was used to dump the
527 smb_hashes, and this credential comes from there, the source_id would
528 be the Vuln id (as reported by report_vuln) and the type would be "Vuln".
529
530 - source_id : The Vuln or Cred id of the source of this cred.
531 - source_type : Either Vuln or Cred.
532 """
533 kwargs.update({'host' : host, 'port' : port})
534 kwargs['pass'] = kwargs.get('password')
535 self.dbreport('cred', kwargs)
536
537 update = report
538
539
540class AuthInfoTable(MsfTable):
541
542 def report(self, host, port, **kwargs):
543 """
544 Store a set of credentials in the database.
545
546 Mandatory Arguments:
547 - host : an IP address or Host object reference
548 - port : a port number
549
550 Optional Keyword Arguments:
551 - user : the username.
552 - pass : the password, or path to ssh_key.
553 - ptype : the type of password (password(ish), hash, or ssh_key).
554 - proto : a transport name for the port.
555 - sname : service name.
556 - active : by default, a cred is active, unless explicitly false.
557 - proof : data used to prove the account is actually active.
558
559 Sources: Credentials can be sourced from another credential, or from
560 a vulnerability. For example, if an exploit was used to dump the
561 smb_hashes, and this credential comes from there, the source_id would
562 be the Vuln id (as reported by report_vuln) and the type would be "Vuln".
563
564 - source_id : The Vuln or Cred id of the source of this cred.
565 - source_type : Either Vuln or Cred.
566 """
567 kwargs.update({'host' : host, 'port' : port})
568 self.dbreport('auth_info', kwargs)
569
570 update = report
571
572
573class HostsTable(MsfTable):
574
575 @property
576 def list(self):
577 return super(HostsTable, self).records('hosts')
578
579 def find(self, **kwargs):
580 """
581 Find hosts based on search criteria.
582
583 Optional Keyword Arguments:
584 - limit : the maximum number of results.
585 - offset : skip n results.
586 - only_up : find only hosts that are alive.
587 - addresses : find hosts based on a list of addresses.
588 """
589 return super(HostsTable, self).records('hosts', **kwargs)
590
591 def report(self, host, **kwargs):
592 """
593 Store a host in the database.
594
595 Mandatory Keyword Arguments:
596 - host : an IP address or Host object reference.
597
598 Optional Keyword Arguments:
599 - state : a host state.
600 - os_name : an operating system.
601 - os_flavor : something like 'XP or 'Gentoo'.
602 - os_sp : something like 'SP2'.
603 - os_lang : something like 'English', 'French', or 'en-US'.
604 - arch : an architecture.
605 - mac : the host's MAC address.
606 - scope : interface identifier for link-local IPv6.
607 - virtual_host : the name of the VM host software, e.g. 'VMWare', 'QEMU', 'Xen', etc.
608 """
609 kwargs.update({'host' : host})
610 self.dbreport('host', kwargs)
611
612 def delete(self, **kwargs):
613 """
614 Deletes a host and associated data matching this address/comm.
615
616 Mandatory Keyword Arguments:
617 - host : the host associated with a Note, not required if 'address' or 'addresses' is specified
618 - address : the address associated with a Note, not required if 'host' or 'addresses' is specified.
619 - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified.
620 """
621 if not any([ i in kwargs for i in ('host', 'address', 'addresses')]):
622 raise TypeError('Expected host, address, or addresses.')
623 self.dbdel('host', kwargs)
624
625 def get(self, **kwargs):
626 """
627 Get a host in the database.
628
629 Mandatory Keyword Arguments:
630 - host : the host associated with a Note, not required if 'address' or 'addr' is specified.
631 - address : the address associated with a Note, not required if 'host' or 'addr' is specified.
632 - addr : same as 'address', not required if 'host' or 'address' is specified.
633 """
634 if not any([ i in kwargs for i in ('addr', 'address', 'host')]):
635 raise TypeError('Expected addr, address, or host.')
636 return self.dbget('host', kwargs)
637
638 update = report
639
640
641class ServicesTable(MsfTable):
642
643 @property
644 def list(self):
645 return super(ServicesTable, self).records('services')
646
647 def find(self, **kwargs):
648 """
649 Find hosts based on search criteria.
650
651 Optional Keyword Arguments:
652 - limit : the maximum number of results.
653 - offset : skip n results.
654 - only_up : find only hosts that are alive.
655 - addresses : find hosts based on a list of addresses.
656 - proto : the protocol of the service.
657 - ports : a comma separated string of ports.
658 - names : a comma separated string of service names.
659 """
660 return super(ServicesTable, self).records('services', **kwargs)
661
662 def report(self, host, port, proto, **kwargs):
663 """
664 Record a service in the database.
665
666 Mandatory Arguments:
667 - host : the host where this service is running.
668 - port : the port where this service listens.
669 - proto : the transport layer protocol (e.g. tcp, udp).
670
671 Optional Keyword Arguments:
672 - name : the application layer protocol (e.g. ssh, mssql, smb)
673 - sname : an alias for the above
674 """
675 kwargs.update({'host' : host, 'port' : port, 'proto' : proto})
676 self.dbreport('service', kwargs)
677
678 def delete(self, **kwargs):
679 """
680 Deletes a port and associated vulns matching this port.
681
682 Mandatory Keyword Arguments:
683 - host : the host associated with a Note, not required if 'address' or 'addresses' is specified
684 - address : the address associated with a Note, not required if 'host' or 'addresses' is specified.
685 - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified.
686
687 or
688
689 - port : used along with 'proto', specifies a service.
690 - proto : used along with 'port', specifies a service.
691 """
692 if not any([i in kwargs for i in ('host', 'address', 'addresses')]) and \
693 not all([i in kwargs for i in ('proto', 'port')]):
694 raise TypeError('Expected host or port/proto pair.')
695 self.dbdel('service', kwargs)
696
697 def get(self, **kwargs):
698 """
699 Get a service record from the database.
700
701 Mandatory Keyword Arguments:
702 - host : the host associated with a Note, not required if 'address' or 'addresses' is specified
703 - address : the address associated with a Note, not required if 'host' or 'addresses' is specified.
704 - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified.
705
706 or
707
708 - port : used along with 'proto', specifies a service.
709 - proto : used along with 'port', specifies a service.
710
711 Optional Keyword Arguments:
712 - up : specifies whether or not the service is alive.
713 - names : a comma separated string of service names.
714 """
715 if not any([i in kwargs for i in ('host', 'addr', 'address')]) and \
716 not all([i in kwargs for i in ('proto', 'port')]):
717 raise TypeError('Expected host or port/proto pair.')
718 return self.dbget('service', kwargs)
719
720 update = report
721
722
723class VulnsTable(MsfTable):
724
725 @property
726 def list(self):
727 return super(VulnsTable, self).records('vulns')
728
729 def find(self, **kwargs):
730 """
731 Find vulns based on search criteria.
732
733 Optional Keyword Arguments:
734 - limit : the maximum number of results.
735 - offset : skip n results.
736 - addresses : find hosts based on a list of addresses.
737 - proto : the protocol of the service.
738 - ports : a comma separated string of ports.
739 - names : a comma separated string of service names.
740 """
741 return super(VulnsTable, self).records('vulns', **kwargs)
742
743 def report(self, host, name, **kwargs):
744 """
745 Record a Vuln in the database.
746
747 Mandatory Arguments:
748 - host : the host where this vulnerability resides.
749 - name : the scanner-specific id of the vuln (e.g. NEXPOSE-cifs-acct-password-never-expires).
750
751 Optional Keyword Arguments:
752 - info : a human readable description of the vuln, free-form text.
753 - refs : an array of Ref objects or string names of references.
754 """
755 kwargs.update({'host' : host, 'name' : name})
756 self.dbreport('vuln', kwargs)
757
758 def delete(self, **kwargs):
759 """
760 Deletes a vuln and associated data matching this address/comm.
761
762 Mandatory Keyword Arguments:
763 - host : the host associated with a Note, not required if 'address' or 'addresses' is specified
764 - address : the address associated with a Note, not required if 'host' or 'addresses' is specified.
765 - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified.
766 """
767 if not any([ i in kwargs for i in ('host', 'address', 'addresses')]):
768 raise TypeError('Expected host, address, or addresses.')
769 self.dbdel('vuln', kwargs)
770
771 def get(self, **kwargs):
772 """
773 Get a vuln in the database.
774
775 Mandatory Keyword Arguments:
776 - host : the host associated with a Note, not required if 'address' or 'addr' is specified.
777 - address : the address associated with a Note, not required if 'host' or 'addr' is specified.
778 - addr : same as 'address', not required if 'host' or 'address' is specified.
779 """
780 if not any([ i in kwargs for i in ('addr', 'address', 'host')]):
781 raise TypeError('Expected addr, address, or host.')
782 return self.dbreport('vuln', kwargs)
783
784 update = report
785
786
787class EventsTable(MsfTable):
788
789 @property
790 def list(self):
791 return super(EventsTable, self).records('events')
792
793 def find(self, **kwargs):
794 """
795 Find events based on search criteria.
796
797 Optional Keyword Arguments:
798 - limit : the maximum number of results.
799 - offset : skip n results.
800 """
801 return super(EventsTable, self).records('events', **kwargs)
802
803 def report(self, **kwargs):
804 """
805 Record a Vuln in the database.
806
807 Mandatory Arguments:
808 - username : user that invoked the event.
809 - host : host that invoked the event.
810 """
811 if not any([i in kwargs for i in ('username', 'host')]):
812 raise TypeError('Expected either username or host')
813 self.dbreport('vuln', kwargs)
814
815 update = report
816
817
818class ClientsTable(MsfTable):
819
820 @property
821 def list(self):
822 return super(ClientsTable, self).records('clients')
823
824 def find(self, **kwargs):
825 """
826 Find clients based on search criteria.
827
828 Optional Keyword Arguments:
829 - limit : the maximum number of results.
830 - offset : skip n results.
831 - ua_name : a user-agent string.
832 - ua_ver : the user-agent version.
833 - addresses : a list of IP addresses.
834 """
835 return super(ClientsTable, self).records('clients', **kwargs)
836
837 def report(self, ua_string, host, **kwargs):
838 """
839 Report a client running on a host.
840
841 Mandatory Arguments:
842 - ua_string : the value of the User-Agent header
843 - host : the host where this client connected from, can be an ip address or a Host object
844
845 Optional Keyword Arguments
846 - ua_name : one of the user agent name constants
847 - ua_ver : detected version of the given client
848 - campaign : an id or Campaign object
849
850 Returns a Client.
851 """
852 kwargs.update({'host' : host, 'ua_string' : ua_string})
853 self.dbreport('client', kwargs)
854
855 def delete(self, **kwargs):
856 """
857 Deletes a client and associated data matching this address/comm.
858
859 Mandatory Keyword Arguments:
860 - host : the host associated with a Note, not required if 'address' or 'addresses' is specified
861 - address : the address associated with a Note, not required if 'host' or 'addresses' is specified.
862 - addresses : a list of addresses associated with Notes, not required if 'host' or 'address' is specified.
863 """
864 self.dbdel('client', kwargs)
865
866 def get(self, **kwargs):
867 """
868 Get a client in the database.
869
870 Mandatory Keyword Arguments:
871 - host : the host associated with a Note, not required if 'address' or 'addr' is specified.
872 - ua_string : the value of the User-Agent header
873 """
874 if not any([ i in kwargs for i in ('host', 'ua_string')]):
875 raise TypeError('Expected host or ua_string.')
876 return self.dbreport('client', kwargs)
877
878 update = report
879
880
881class Workspace(object):
882
883 def __init__(self, rpc, name):
884 """
885 Initializes a workspace object.
886
887 Mandatory Arguments:
888 - rpc : the msfrpc client object
889 - name : the name of the workspace
890 """
891 self.rpc = rpc
892 self.name = name
893
894 @property
895 def current(self):
896 """
897 The name of the current workspace.
898 """
899 return self.name
900
901 @current.setter
902 def current(self, name):
903 self.name = name
904
905 @property
906 def notes(self):
907 """
908 Returns the notes table for the current workspace.
909 """
910 return NotesTable(self.rpc, self.name)
911
912 @property
913 def hosts(self):
914 """
915 Returns the hosts table for the current workspace.
916 """
917 return HostsTable(self.rpc, self.name)
918
919 @property
920 def services(self):
921 """
922 Returns the services table for the current workspace.
923 """
924 return ServicesTable(self.rpc, self.name)
925
926 @property
927 def vulns(self):
928 """
929 Returns the vulns table for the current workspace.
930 """
931 return VulnsTable(self.rpc, self.name)
932
933 @property
934 def events(self):
935 """
936 Returns the events table for the current workspace.
937 """
938 return EventsTable(self.rpc, self.name)
939
940 @property
941 def loots(self):
942 """
943 Returns the loots table for the current workspace.
944 """
945 return LootsTable(self.rpc, self.name)
946
947 @property
948 def creds(self):
949 """
950 Returns the creds table for the current workspace.
951 """
952 return CredsTable(self.rpc, self.name)
953
954 @property
955 def clients(self):
956 """
957 Returns the clients table for the current workspace.
958 """
959 return ClientsTable(self.rpc, self.name)
960
961 def delete(self):
962 """
963 Delete the current workspace.
964 """
965 self.rpc.call(MsfRpcMethod.DbDelWorkspace, {'workspace' : self.name})
966
967 def importdata(self, data):
968 self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : data})
969
970 def importfile(self, fname):
971 r = file(fname, mode='rb')
972 self.rpc.call(MsfRpcMethod.DbImportData, {'workspace' : self.name, 'data' : r.read()})
973 r.close()
974
975
976class MsfManager(object):
977
978 def __init__(self, rpc):
979 """
980 Initialize a msf component manager.
981
982 Mandatory Arguments:
983 - rpc : the msfrpc client object.
984 """
985 self.rpc = rpc
986
987
988class WorkspaceManager(MsfManager):
989
990 @property
991 def list(self):
992 """
993 The list of all workspaces in the current msf database.
994 """
995 return self.rpc.call(MsfRpcMethod.DbWorkspaces)['workspaces']
996
997 def workspace(self, name='default'):
998 """
999 Returns a Workspace object for the given workspace name.
1000
1001 Optional Arguments:
1002 - name : the name of the workspace
1003 """
1004 w = self.list
1005 if name not in w:
1006 self.add(name)
1007 return Workspace(self.rpc, name)
1008
1009 def add(self, name):
1010 """
1011 Adds a workspace with the given name.
1012
1013 Mandatory Arguments:
1014 - name : the name of the workspace
1015 """
1016 self.rpc.call(MsfRpcMethod.DbAddWorkspace, name)
1017
1018 def get(self, name):
1019 """
1020 Get a workspace with the given name.
1021
1022 Mandatory Arguments:
1023 - name : the name of the workspace
1024 """
1025 return self.rpc.call(MsfRpcMethod.DbGetWorkspace, name)['workspace']
1026
1027 def remove(self, name):
1028 """
1029 Adds a workspace with the given name.
1030
1031 Mandatory Arguments:
1032 - name : the name of the workspace
1033 """
1034 self.rpc.call(MsfRpcMethod.DbDelWorkspace, name)
1035
1036 def set(self, name):
1037 """
1038 Sets the current workspace.
1039
1040 Mandatory Arguments:
1041 - name : the name of the workspace
1042 """
1043 self.rpc.call(MsfRpcMethod.DbSetWorkspace, name)
1044
1045 @property
1046 def current(self):
1047 """
1048 The current workspace.
1049 """
1050 return self.workspace(self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace'])
1051
1052
1053class DbManager(MsfManager):
1054
1055 def connect(self, username, database='msf', **kwargs):
1056 """
1057 Connects to a database and creates the msf schema if necessary.
1058
1059 Mandatory Arguments:
1060 - username : the username for the database connection
1061
1062 Optional Keyword Arguments:
1063 - host : the IP or hostname of the database server (default: 'localhost')
1064 - driver : the driver to use for the database connection (default: 'postgresql')
1065 - password : the password for the database connection
1066 - database : the database name (default: 'msf')
1067 - port : the port that the server is running on (default: 5432)
1068 """
1069 runopts = { 'username': username, 'database' : database }
1070 runopts.update(kwargs)
1071 return self.rpc.call(MsfRpcMethod.DbConnect, runopts)['result'] == 'success'
1072
1073 @property
1074 def driver(self):
1075 """
1076 The current database driver in use.
1077 """
1078 return self.rpc.call(MsfRpcMethod.DbDriver, {})['driver']
1079
1080 @driver.setter
1081 def driver(self, d):
1082 self.rpc.call(MsfRpcMethod.DbDriver, {'driver' : d})
1083
1084 @property
1085 def status(self):
1086 """
1087 The status of the database connection.
1088 """
1089 return self.rpc.call(MsfRpcMethod.DbStatus)
1090
1091 def disconnect(self):
1092 """
1093 Disconnect from the database.
1094 """
1095 self.rpc.call(MsfRpcMethod.DbDisconnect)
1096
1097 @property
1098 def workspaces(self):
1099 """
1100 A WorkspaceManager object.
1101 """
1102 return WorkspaceManager(self.rpc)
1103
1104 @property
1105 def workspace(self):
1106 """
1107 The name of the current workspace.
1108 """
1109 return self.rpc.call(MsfRpcMethod.DbCurrentWorkspace)['workspace']
1110
1111 @workspace.setter
1112 def workspace(self, w):
1113 self.rpc.call(MsfRpcMethod.DbSetWorkspace, w)
1114
1115
1116class AuthManager(MsfManager):
1117
1118 def login(self, password, **kwargs):
1119 """
1120 Login to the msfrpc daemon.
1121
1122 Mandatory Arguments:
1123 - password : the password used to login to msfrpc
1124
1125 Optional Keyword Arguments:
1126 - username : the username used to authenticate to msfrpcd (default: msf)
1127 - uri : the msfrpcd URI (default: /api/)
1128 - port : the remote msfrpcd port to connect to (default: 55553)
1129 - server : the remote server IP address hosting msfrpcd (default: localhost)
1130 - ssl : if true uses SSL else regular HTTP (default: SSL enabled)
1131 """
1132 return MsfRpcClient(password, **kwargs)
1133
1134 def logout(self, sid):
1135 """
1136 Logs out a user for a given session ID.
1137
1138 Mandatory Arguments:
1139 - sid : a session ID that is active.
1140 """
1141 return self.rpc.call(MsfRpcMethod.AuthLogout, sid)
1142
1143 @property
1144 def tokens(self):
1145 """
1146 The current list of active session IDs.
1147 """
1148 return self.rpc.call(MsfRpcMethod.AuthTokenList)['tokens']
1149
1150 def add(self, token):
1151 """
1152 Add a session ID or token.
1153
1154 Mandatory Argument:
1155 - token : a random string used as a session identifier.
1156 """
1157 self.rpc.call(MsfRpcMethod.AuthTokenAdd, token)
1158
1159 def remove(self, token):
1160 """
1161 Remove a session ID or token.
1162
1163 Mandatory Argument:
1164 - token : a session ID or token that is active.
1165 """
1166 self.rpc.call(MsfRpcMethod.AuthTokenRemove, token)
1167
1168 def generate(self):
1169 """
1170 Generate a session ID or token.
1171 """
1172 return self.rpc.call(MsfRpcMethod.AuthTokenGenerate)['token']
1173
1174
1175class PluginManager(MsfManager):
1176
1177 @property
1178 def list(self):
1179 """
1180 A list of loaded plugins.
1181 """
1182 return self.rpc.call(MsfRpcMethod.PluginLoaded)['plugins']
1183
1184 def load(self, plugin):
1185 """
1186 Load a plugin of a given name.
1187
1188 Mandatory Arguments:
1189 - plugin : a name of a plugin to load.
1190 """
1191 self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginLoad, plugin)
1192
1193 def unload(self, plugin):
1194 """
1195 Unload a plugin of a given name.
1196
1197 Mandatory Arguments:
1198 - plugin : a name of a loaded plugin to unload.
1199 """
1200 self.rpc.call(MsfRpcMethod, MsfRpcMethod.PluginUnload, plugin)
1201
1202
1203class JobManager(MsfManager):
1204
1205 @property
1206 def list(self):
1207 """
1208 A list of currently running jobs.
1209 """
1210 return self.rpc.call(MsfRpcMethod.JobList)
1211
1212 def stop(self, jobid):
1213 """
1214 Stop a job.
1215
1216 Mandatory Argument:
1217 - jobid : the ID of the job.
1218 """
1219 self.rpc.call(MsfRpcMethod.JobStop, jobid)
1220
1221 def info(self, jobid):
1222 """
1223 Get job information for a particular job.
1224
1225 Mandatory Argument:
1226 - jobid : the ID of the job.
1227 """
1228 return self.rpc.call(MsfRpcMethod.JobInfo, jobid)
1229
1230
1231class CoreManager(MsfManager):
1232
1233 @property
1234 def version(self):
1235 """
1236 The version of msf core.
1237 """
1238 return self.rpc.call(MsfRpcMethod.CoreVersion)
1239
1240 def stop(self):
1241 """
1242 Stop the core.
1243 """
1244 self.rpc.call(MsfRpcMethod.CoreStop)
1245
1246 def setg(self, var, val):
1247 """
1248 Set a global variable
1249
1250 Mandatory Arguments:
1251 - var : the variable name
1252 - val : the variable value
1253 """
1254 self.rpc.call(MsfRpcMethod.CoreSetG, var, val)
1255
1256 def unsetg(self, var):
1257 """
1258 Unset a global variable
1259
1260 Mandatory Arguments:
1261 - var : the variable name
1262 """
1263 self.rpc.call(MsfRpcMethod.CoreUnsetG, var)
1264
1265 def save(self):
1266 """
1267 Save the core state.
1268 """
1269 self.rpc.call(MsfRpcMethod.CoreSave)
1270
1271 def reload(self):
1272 """
1273 Reload all modules in the core.
1274 """
1275 self.rpc.call(MsfRpcMethod.CoreReloadModules)
1276
1277 @property
1278 def stats(self):
1279 """
1280 Get module statistics from the core.
1281 """
1282 return self.rpc.call(MsfRpcMethod.CoreModuleStats)
1283
1284 def addmodulepath(self, path):
1285 """
1286 Add a search path for additional modules.
1287
1288 Mandatory Arguments:
1289 - path : the path to search for modules.
1290 """
1291 return self.rpc.call(MsfRpcMethod.CoreAddModulePath, path)
1292
1293 @property
1294 def threads(self):
1295 """
1296 The current threads running in the core.
1297 """
1298 return self.rpc.call(MsfRpcMethod.CoreThreadList)
1299
1300 def kill(self, threadid):
1301 """
1302 Kill a thread running in the core.
1303
1304 Mandatory Arguments:
1305 - threadid : the thread ID.
1306 """
1307 self.rpc.call(MsfRpcMethod.CoreThreadKill, threadid)
1308
1309
1310class MsfModule(object):
1311
1312 def __init__(self, rpc, mtype, mname):
1313 """
1314 Initializes an msf module object.
1315
1316 Mandatory Arguments:
1317 - rpc : the msfrpc client object.
1318 - mtype : the module type (e.g. 'exploit')
1319 - mname : the module name (e.g. 'exploits/windows/http/icecast_header')
1320 """
1321 self.moduletype = mtype
1322 self.modulename = mname
1323 self.rpc = rpc
1324 self._info = rpc.call(MsfRpcMethod.ModuleInfo, mtype, mname)
1325 property_attributes = ["MsfModuleDefaultProperty_options", "advanced", "evasion", "required", "runoptions"]
1326 for k in self._info:
1327 if k not in property_attributes: # don't try to set property attributes
1328 setattr(self, k, self._info.get(k))
1329 else:
1330 raise KeyError("Invalid option '%s'." % k)
1331 self._moptions = rpc.call(MsfRpcMethod.ModuleOptions, mtype, mname)
1332 self._roptions = []
1333 self._aoptions = []
1334 self._eoptions = []
1335 self._runopts = {}
1336 for o in self._moptions:
1337 if self._moptions[o]['required']:
1338 self._roptions.append(o)
1339 if self._moptions[o]['advanced']:
1340 self._aoptions.append(o)
1341 if self._moptions[o]['evasion']:
1342 self._eoptions.append(o)
1343 if 'default' in self._moptions[o]:
1344 self._runopts[o] = self._moptions[o]['default']
1345
1346 @property
1347 def MsfModuleDefaultProperty_options(self):
1348 """
1349 All the module options.
1350 """
1351 return self._moptions.keys()
1352
1353 @property
1354 def required(self):
1355 """
1356 The required module options.
1357 """
1358 return self._roptions
1359
1360 @property
1361 def evasion(self):
1362 """
1363 Module options that are used for evasion.
1364 """
1365 return self._eoptions
1366
1367 @property
1368 def advanced(self):
1369 """
1370 Advanced module options.
1371 """
1372 return self._aoptions
1373
1374 @property
1375 def runoptions(self):
1376 """
1377 The running (currently set) options for a module. This will raise an error
1378 if some of the required options are missing.
1379 """
1380 outstanding = set(self.required).difference(self._runopts.keys())
1381 if outstanding:
1382 raise TypeError('Module missing required parameter: %s' % ', '.join(outstanding))
1383 return self._runopts
1384
1385 def optioninfo(self, option):
1386 """
1387 Get information about the module option
1388
1389 Mandatory Argument:
1390 - option : the option name.
1391 """
1392 return self._moptions[option]
1393
1394 def __getitem__(self, item):
1395 """
1396 Get the current option value.
1397
1398 Mandatory Arguments:
1399 - item : the option name.
1400 """
1401 if item not in self._moptions:
1402 raise KeyError("Invalid option '%s'." % item)
1403 return self._runopts.get(item)
1404
1405 def __setitem__(self, key, value):
1406 """
1407 Set the current option value.
1408
1409 Mandatory Arguments:
1410 - key : the option name.
1411 - value : the option value.
1412 """
1413 if key not in self.MsfModuleDefaultProperty_options:
1414 raise KeyError("Invalid option '%s'." % key)
1415 elif 'enums' in self._moptions[key] and value not in self._moptions[key]['enums']:
1416 raise ValueError("Value ('%s') is not one of %s" % (value, repr(self._moptions[key]['enums'])))
1417 elif self._moptions[key]['type'] == 'bool' and not isinstance(value, bool):
1418 raise TypeError("Value must be a boolean not '%s'" % type(value).__name__)
1419 elif self._moptions[key]['type'] in ['integer', 'float'] and not isinstance(value, Number):
1420 raise TypeError("Value must be an integer not '%s'" % type(value).__name__)
1421 self._runopts[key] = value
1422
1423 def __delitem__(self, key):
1424 del self._runopts[key]
1425
1426 def __contains__(self, item):
1427 return item in self._runopts
1428
1429 def update(self, d):
1430 """
1431 Update a set of options.
1432
1433 Mandatory Arguments:
1434 - d : a dictionary of options
1435 """
1436 for k in d:
1437 self[k] = d[k]
1438
1439 def execute(self, **kwargs):
1440 """
1441 Executes the module with its run options as parameters.
1442
1443 Optional Keyword Arguments:
1444 - payload : the payload of an exploit module (this is mandatory if the module is an exploit).
1445 - **kwargs : can contain any module options.
1446 """
1447 runopts = self.runoptions.copy()
1448 if isinstance(self, ExploitModule):
1449 payload = kwargs.get('payload')
1450 runopts['TARGET'] = self.target
1451 if 'DisablePayloadHandler' in runopts and runopts['DisablePayloadHandler']:
1452 pass
1453 elif payload is None:
1454 runopts['DisablePayloadHandler'] = True
1455 else:
1456 if isinstance(payload, PayloadModule):
1457 if payload.modulename not in self.payloads:
1458 raise ValueError(
1459 'Invalid payload (%s) for given target (%d).' % (payload.modulename, self.target)
1460 )
1461 runopts['PAYLOAD'] = payload.modulename
1462 for k, v in payload.runoptions.iteritems():
1463 if v is None or (isinstance(v, basestring) and not v):
1464 continue
1465 if k not in runopts or runopts[k] is None or \
1466 (isinstance(runopts[k], basestring) and not runopts[k]):
1467 runopts[k] = v
1468# runopts.update(payload.runoptions)
1469 elif isinstance(payload, basestring):
1470 if payload not in self.payloads:
1471 raise ValueError('Invalid payload (%s) for given target (%d).' % (payload, self.target))
1472 runopts['PAYLOAD'] = payload
1473 else:
1474 raise TypeError("Expected type str or PayloadModule not '%s'" % type(kwargs['payload']).__name__)
1475
1476 return self.rpc.call(MsfRpcMethod.ModuleExecute, self.moduletype, self.modulename, runopts)
1477
1478
1479class ExploitModule(MsfModule):
1480
1481 def __init__(self, rpc, exploit):
1482 """
1483 Initializes the use of an exploit module.
1484
1485 Mandatory Arguments:
1486 - rpc : the rpc client used to communicate with msfrpcd
1487 - exploit : the name of the exploit module.
1488 """
1489 super(ExploitModule, self).__init__(rpc, 'exploit', exploit)
1490 self._target = self._info.get('default_target', 0)
1491
1492 @property
1493 def payloads(self):
1494 """
1495 A list of compatible payloads.
1496 """
1497# return self.rpc.call(MsfRpcMethod.ModuleCompatiblePayloads, self.modulename)['payloads']
1498 return self.targetpayloads(self.target)
1499
1500 @property
1501 def target(self):
1502 return self._target
1503
1504 @target.setter
1505 def target(self, target):
1506 if target not in self.targets:
1507 raise ValueError('Target must be one of %s' % repr(self.targets.keys()))
1508 self._target = target
1509
1510 def targetpayloads(self, t=0):
1511 """
1512 Returns a list of compatible payloads for a given target ID.
1513
1514 Optional Keyword Arguments:
1515 - t : the target ID (default: 0, e.g. 'Automatic')
1516 """
1517 return self.rpc.call(MsfRpcMethod.ModuleTargetCompatiblePayloads, self.modulename, t)['payloads']
1518
1519
1520class PostModule(MsfModule):
1521
1522 def __init__(self, rpc, post):
1523 """
1524 Initializes the use of a post exploitation module.
1525
1526 Mandatory Arguments:
1527 - rpc : the rpc client used to communicate with msfrpcd
1528 - post : the name of the post exploitation module.
1529 """
1530 super(PostModule, self).__init__(rpc, 'post', post)
1531
1532 @property
1533 def sessions(self):
1534 """
1535 A list of compatible shell/meterpreter sessions.
1536 """
1537 return self.rpc.compatiblesessions(self.modulename)
1538
1539
1540class EncoderModule(MsfModule):
1541
1542 def __init__(self, rpc, encoder):
1543 """
1544 Initializes the use of an encoder module.
1545
1546 Mandatory Arguments:
1547 - rpc : the rpc client used to communicate with msfrpcd
1548 - encoder : the name of the encoder module.
1549 """
1550 super(EncoderModule, self).__init__(rpc, 'encoder', encoder)
1551
1552
1553class AuxiliaryModule(MsfModule):
1554
1555 def __init__(self, rpc, auxiliary):
1556 """
1557 Initializes the use of an auxiliary module.
1558
1559 Mandatory Arguments:
1560 - rpc : the rpc client used to communicate with msfrpcd
1561 - auxiliary : the name of the auxiliary module.
1562 """
1563 super(AuxiliaryModule, self).__init__(rpc, 'auxiliary', auxiliary)
1564
1565
1566class PayloadModule(MsfModule):
1567
1568 def __init__(self, rpc, payload):
1569 """
1570 Initializes the use of a payload module.
1571
1572 Mandatory Arguments:
1573 - rpc : the rpc client used to communicate with msfrpcd
1574 - payload : the name of the payload module.
1575 """
1576 super(PayloadModule, self).__init__(rpc, 'payload', payload)
1577
1578
1579class NopModule(MsfModule):
1580
1581 def __init__(self, rpc, nop):
1582 """
1583 Initializes the use of a nop module.
1584
1585 Mandatory Arguments:
1586 - rpc : the rpc client used to communicate with msfrpcd
1587 - nop : the name of the nop module.
1588 """
1589 super(NopModule, self).__init__(rpc, 'nop', nop)
1590
1591
1592class ModuleManager(MsfManager):
1593
1594 def execute(self, modtype, modname, **kwargs):
1595 """
1596 Execute the module.
1597
1598 Mandatory Arguments:
1599 - modtype : the module type (e.g. 'exploit')
1600 - modname : the module name (e.g. 'exploits/windows/http/icecast_header')
1601
1602 Optional Keyword Arguments:
1603 - **kwargs : the module's run options
1604 """
1605 return self.rpc.call(MsfRpcMethod.ModuleExecute, modtype, modname, kwargs)
1606
1607 @property
1608 def exploits(self):
1609 """
1610 A list of exploit modules.
1611 """
1612 return self.rpc.call(MsfRpcMethod.ModuleExploits)['modules']
1613
1614 @property
1615 def payloads(self):
1616 """
1617 A list of payload modules.
1618 """
1619 return self.rpc.call(MsfRpcMethod.ModulePayloads)['modules']
1620
1621 @property
1622 def auxiliary(self):
1623 """
1624 A list of auxiliary modules.
1625 """
1626 return self.rpc.call(MsfRpcMethod.ModuleAuxiliary)['modules']
1627
1628 @property
1629 def post(self):
1630 """
1631 A list of post modules.
1632 """
1633 return self.rpc.call(MsfRpcMethod.ModulePost)['modules']
1634
1635 @property
1636 def encodeformats(self):
1637 """
1638 A list of encoding formats.
1639 """
1640 return self.rpc.call(MsfRpcMethod.ModuleEncodeFormats)
1641
1642 @property
1643 def encoders(self):
1644 """
1645 A list of encoder modules.
1646 """
1647 return self.rpc.call(MsfRpcMethod.ModuleEncoders)['modules']
1648
1649 @property
1650 def nops(self):
1651 """
1652 A list of nop modules.
1653 """
1654 return self.rpc.call(MsfRpcMethod.ModuleNops)['modules']
1655
1656 def use(self, mtype, mname):
1657 """
1658 Returns a module object.
1659
1660 Mandatory Arguments:
1661 - mname : the module name (e.g. 'exploits/windows/http/icecast_header')
1662 """
1663 if mtype == 'exploit':
1664 return ExploitModule(self.rpc, mname)
1665 elif mtype == 'post':
1666 return PostModule(self.rpc, mname)
1667 elif mtype == 'encoder':
1668 return EncoderModule(self.rpc, mname)
1669 elif mtype == 'auxiliary':
1670 return AuxiliaryModule(self.rpc, mname)
1671 elif mtype == 'nop':
1672 return NopModule(self.rpc, mname)
1673 elif mtype == 'payload':
1674 return PayloadModule(self.rpc, mname)
1675 raise MsfRpcError('Unknown module type %s not: exploit, post, encoder, auxiliary, nop, or payload' % mname)
1676
1677
1678class MsfSession(object):
1679
1680 def __init__(self, id, rpc, sd):
1681 """
1682 Initialize a meterpreter or shell session.
1683
1684 Mandatory Arguments:
1685 - id : the session identifier.
1686 - rpc : the msfrpc client object.
1687 - sd : the session description
1688 """
1689 self.id = id
1690 self.rpc = rpc
1691 self.__dict__.update(sd)
1692
1693 def stop(self):
1694 """
1695 Stop a meterpreter or shell session.
1696 """
1697 return self.rpc.call(MsfRpcMethod.SessionStop, self.id)
1698
1699 @property
1700 def modules(self):
1701 """
1702 A list of compatible session modules.
1703 """
1704 return self.rpc.call(MsfRpcMethod.SessionCompatibleModules, self.id)['modules']
1705
1706 @property
1707 def ring(self):
1708 return SessionRing(self.rpc, self.id)
1709
1710
1711class SessionRing(object):
1712
1713 def __init__(self, rpc, sessionid):
1714 self.rpc = rpc
1715 self.id = sessionid
1716
1717 def read(self, seq=None):
1718 """
1719 Reads the session ring.
1720
1721 Optional Keyword Arguments:
1722 - seq : the sequence ID of the ring (default: 0)
1723 """
1724 if seq is not None:
1725 return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id, seq)
1726 return self.rpc.call(MsfRpcMethod.SessionRingRead, self.id)
1727
1728 def put(self, line):
1729 """
1730 Add a command to the session history.
1731
1732 Mandatory Arguments:
1733 - line : arbitrary data.
1734 """
1735 self.rpc.call(MsfRpcMethod.SessionRingPut, self.id, line)
1736
1737 @property
1738 def last(self):
1739 """
1740 Returns the last sequence ID in the session ring.
1741 """
1742 return int(self.rpc.call(MsfRpcMethod.SessionRingLast, self.id)['seq'])
1743
1744 def clear(self):
1745 """
1746 Clear the session ring.
1747 """
1748 return self.rpc.call(MsfRpcMethod.SessionRingClear, self.id)
1749
1750
1751class MeterpreterSession(MsfSession):
1752
1753 def read(self):
1754 """
1755 Read data from the meterpreter session.
1756 """
1757 return self.rpc.call(MsfRpcMethod.SessionMeterpreterRead, self.id)['data']
1758
1759 def write(self, data):
1760 """
1761 Write data to the meterpreter session.
1762
1763 Mandatory Arguments:
1764 - data : arbitrary data or commands
1765 """
1766 self.rpc.call(MsfRpcMethod.SessionMeterpreterWrite, self.id, data)
1767
1768 def runsingle(self, data):
1769 """
1770 Run a single meterpreter command
1771
1772 Mandatory Arguments:
1773 - data : arbitrary data or command
1774 """
1775 self.rpc.call(MsfRpcMethod.SessionMeterpreterRunSingle, self.id, data)
1776 return self.read()
1777
1778 def runscript(self, path):
1779 """
1780 Run a meterpreter script
1781
1782 Mandatory Arguments:
1783 - path : path to a meterpreter script on the msfrpcd host.
1784 """
1785 self.rpc.call(MsfRpcMethod.SessionMeterpreterScript, self.id, path)
1786 return self.read()
1787
1788 @property
1789 def sep(self):
1790 """
1791 The operating system path separator.
1792 """
1793 return self.rpc.call(MsfRpcMethod.SessionMeterpreterDirectorySeparator, self.id)['separator']
1794
1795 def detach(self):
1796 """
1797 Detach the meterpreter session.
1798 """
1799 return self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionDetach, self.id)
1800
1801 def kill(self):
1802 """
1803 Kill the meterpreter session.
1804 """
1805 self.rpc.call(MsfRpcMethod.SessionMeterpreterSessionKill, self.id)
1806
1807 def tabs(self, line):
1808 """
1809 Return a list of commands for a partial command line (tab completion).
1810
1811 Mandatory Arguments:
1812 - line : a partial command line for completion.
1813 """
1814 return self.rpc.call(MsfRpcMethod.SessionMeterpreterTabs, self.id, line)['tabs']
1815
1816
1817class ShellSession(MsfSession):
1818
1819 def read(self):
1820 """
1821 Read data from the shell session.
1822 """
1823 return self.rpc.call(MsfRpcMethod.SessionShellRead, self.id)['data']
1824
1825 def write(self, data):
1826 """
1827 Write data to the shell session.
1828
1829 Mandatory Arguments:
1830 - data : arbitrary data or commands
1831 """
1832 self.rpc.call(MsfRpcMethod.SessionShellWrite, self.id, data)
1833
1834 def upgrade(self, lhost, lport):
1835 """
1836 Upgrade the current shell session.
1837 """
1838 self.rpc.call(MsfRpcMethod.SessionShellUpgrade, self.id, lhost, lport)
1839 return self.read()
1840
1841
1842class SessionManager(MsfManager):
1843
1844 @property
1845 def list(self):
1846 """
1847 A list of active sessions.
1848 """
1849 return self.rpc.call(MsfRpcMethod.SessionList)
1850
1851 def session(self, id):
1852 """
1853 Returns a session object for meterpreter or shell sessions.
1854
1855 Mandatory Arguments:
1856 - id : the session identifier.
1857 """
1858 s = self.list
1859 if id not in s:
1860 for k in s:
1861 if s[k]['uuid'] == id:
1862 if s[id]['type'] == 'meterpreter':
1863 return MeterpreterSession(id, self.rpc, s)
1864 elif s[id]['type'] == 'shell':
1865 return ShellSession(id, self.rpc, s)
1866 raise KeyError('Session ID (%s) does not exist' % id)
1867 if s[id]['type'] == 'meterpreter':
1868 return MeterpreterSession(id, self.rpc, s)
1869 elif s[id]['type'] == 'shell':
1870 return ShellSession(id, self.rpc, s)
1871 raise NotImplementedError('Could not determine session type: %s' % s[id]['type'])
1872
1873
1874class MsfConsole(object):
1875
1876 def __init__(self, rpc, cid=None):
1877 """
1878 Initializes an msf console.
1879
1880 Mandatory Arguments:
1881 - rpc : the msfrpc client object.
1882
1883 Optional Keyword Arguments:
1884 - cid : the console identifier if it exists already otherwise a new one will be created.
1885 """
1886 self.rpc = rpc
1887 if cid is None:
1888 r = self.rpc.call(MsfRpcMethod.ConsoleCreate)
1889 if 'id' in r:
1890 self.cid = r['id']
1891 else:
1892 raise MsfRpcError('Unable to create a new console.')
1893 else:
1894 self.cid = cid
1895
1896 def read(self):
1897 """
1898 Read data from the console.
1899 """
1900 return self.rpc.call(MsfRpcMethod.ConsoleRead, self.cid)
1901
1902 def write(self, command):
1903 """
1904 Write data to the console.
1905 """
1906 if not command.endswith('\n'):
1907 command += '\n'
1908 self.rpc.call(MsfRpcMethod.ConsoleWrite, self.cid, command)
1909
1910 def sessionkill(self):
1911 """
1912 Kill all active meterpreter or shell sessions.
1913 """
1914 self.rpc.call(MsfRpcMethod.ConsoleSessionKill, self.cid)
1915
1916 def sessiondetach(self):
1917 """
1918 Detach the current meterpreter or shell session.
1919 """
1920 self.rpc.call(MsfRpcMethod.ConsoleSessionDetach, self.cid)
1921
1922 def tabs(self, line):
1923 """
1924 Tab completion for console commands.
1925
1926 Mandatory Arguments:
1927 - line : a partial command to be completed.
1928 """
1929 return self.rpc.call(MsfRpcMethod.ConsoleTabs, self.cid, line)['tabs']
1930
1931 def destroy(self):
1932 """
1933 Destroy the console.
1934 """
1935 self.rpc.call(MsfRpcMethod.ConsoleDestroy, self.cid)
1936
1937
1938class ConsoleManager(MsfManager):
1939
1940 @property
1941 def list(self):
1942 """
1943 A list of active consoles.
1944 """
1945 return self.rpc.call(MsfRpcMethod.ConsoleList)
1946
1947 def console(self, cid=None):
1948 """
1949 Connect to an active console otherwise create a new console.
1950
1951 Optional Keyword Arguments:
1952 - cid : the console identifier.
1953 """
1954 s = self.list
1955 if cid is None:
1956 return MsfConsole(self.rpc)
1957 if cid not in s:
1958 raise KeyError('Console ID (%s) does not exist' % cid)
1959 else:
1960 return MsfConsole(self.rpc, cid=cid)
1961
1962 def destroy(self, cid):
1963 """
1964 Destory an active console.
1965
1966 Mandatory Arguments:
1967 - cid : the console identifier.
1968 """
1969 self.rpc.call(MsfRpcMethod.ConsoleDestroy, cid)