feat(modules): allow multiple modules to be ran
parent
2c762989eb
commit
e7fcea0851
|
@ -63,7 +63,7 @@ def gen_cli_args():
|
||||||
|
|
||||||
module_parser = argparse.ArgumentParser(add_help=False)
|
module_parser = argparse.ArgumentParser(add_help=False)
|
||||||
mgroup = module_parser.add_mutually_exclusive_group()
|
mgroup = module_parser.add_mutually_exclusive_group()
|
||||||
mgroup.add_argument("-M", "--module", metavar='MODULE', help='module to use')
|
mgroup.add_argument("-M", "--module", action='append', metavar='MODULE', help='module to use')
|
||||||
#mgroup.add_argument('-MC','--module-chain', metavar='CHAIN_COMMAND', help='Payload module chain command string to run')
|
#mgroup.add_argument('-MC','--module-chain', metavar='CHAIN_COMMAND', help='Payload module chain command string to run')
|
||||||
module_parser.add_argument('-o', metavar='MODULE_OPTION', nargs='+', default=[], dest='module_options', help='module options')
|
module_parser.add_argument('-o', metavar='MODULE_OPTION', nargs='+', default=[], dest='module_options', help='module options')
|
||||||
module_parser.add_argument('-L', '--list-modules', action='store_true', help='list available modules')
|
module_parser.add_argument('-L', '--list-modules', action='store_true', help='list available modules')
|
||||||
|
|
|
@ -119,28 +119,30 @@ class connection(object):
|
||||||
r = getattr(self, k)()
|
r = getattr(self, k)()
|
||||||
|
|
||||||
def call_modules(self):
|
def call_modules(self):
|
||||||
module_logger = CMEAdapter(extra={
|
for module in self.module:
|
||||||
'module': self.module.name.upper(),
|
logging.debug(f"Loading module {module}")
|
||||||
'host': self.host,
|
module_logger = CMEAdapter(extra={
|
||||||
'port': self.args.port,
|
'module': module.name.upper(),
|
||||||
'hostname': self.hostname
|
'host': self.host,
|
||||||
})
|
'port': self.args.port,
|
||||||
|
'hostname': self.hostname
|
||||||
|
})
|
||||||
|
|
||||||
context = Context(self.db, module_logger, self.args)
|
context = Context(self.db, module_logger, self.args)
|
||||||
context.localip = self.local_ip
|
context.localip = self.local_ip
|
||||||
|
|
||||||
if hasattr(self.module, 'on_request') or hasattr(self.module, 'has_response'):
|
if hasattr(module, 'on_request') or hasattr(module, 'has_response'):
|
||||||
self.server.connection = self
|
self.server.connection = self
|
||||||
self.server.context.localip = self.local_ip
|
self.server.context.localip = self.local_ip
|
||||||
|
|
||||||
if hasattr(self.module, 'on_login'):
|
if hasattr(module, 'on_login'):
|
||||||
self.module.on_login(context, self)
|
module.on_login(context, self)
|
||||||
|
|
||||||
if self.admin_privs and hasattr(self.module, 'on_admin_login'):
|
if self.admin_privs and hasattr(module, 'on_admin_login'):
|
||||||
self.module.on_admin_login(context, self)
|
module.on_admin_login(context, self)
|
||||||
|
|
||||||
if (not hasattr(self.module, 'on_request') and not hasattr(self.module, 'has_response')) and hasattr(self.module, 'on_shutdown'):
|
if (not hasattr(module, 'on_request') and not hasattr(module, 'has_response')) and hasattr(module,'on_shutdown'):
|
||||||
self.module.on_shutdown(context, self)
|
module.on_shutdown(context, self)
|
||||||
|
|
||||||
def inc_failed_login(self, username):
|
def inc_failed_login(self, username):
|
||||||
global global_failed_logins
|
global global_failed_logins
|
||||||
|
|
|
@ -241,55 +241,61 @@ def main():
|
||||||
|
|
||||||
if hasattr(args, 'module'):
|
if hasattr(args, 'module'):
|
||||||
loader = module_loader(args, db, logger)
|
loader = module_loader(args, db, logger)
|
||||||
if args.list_modules:
|
modules = loader.get_modules()
|
||||||
modules = loader.get_modules()
|
|
||||||
|
|
||||||
|
if args.list_modules:
|
||||||
for name, props in sorted(modules.items()):
|
for name, props in sorted(modules.items()):
|
||||||
logger.info('{:<25} {}'.format(name, props['description']))
|
logger.info('{:<25} {}'.format(name, props['description']))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
elif args.module and args.show_module_options:
|
elif args.module and args.show_module_options:
|
||||||
|
|
||||||
modules = loader.get_modules()
|
|
||||||
for name, props in modules.items():
|
for name, props in modules.items():
|
||||||
if args.module.lower() == name.lower():
|
if args.module.lower() == name.lower():
|
||||||
logger.info('{} module options:\n{}'.format(name, props['options']))
|
logger.info('{} module options:\n{}'.format(name, props['options']))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
elif args.module:
|
elif args.module:
|
||||||
modules = loader.get_modules()
|
logging.debug(f"Modules to be Loaded: {args.module}, {type(args.module)}")
|
||||||
for name, props in modules.items():
|
for m in args.module:
|
||||||
if args.module.lower() == name.lower():
|
if m not in modules:
|
||||||
module = loader.init_module(props['path'])
|
logger.error(f"Module not found: {m}")
|
||||||
setattr(protocol_object, 'module', module)
|
exit(1)
|
||||||
break
|
|
||||||
|
|
||||||
if not module:
|
logging.debug(f"Loading module {m} at path {modules[m]['path']}")
|
||||||
logger.error('Module not found')
|
module = loader.init_module(modules[m]['path'])
|
||||||
exit(1)
|
|
||||||
|
|
||||||
if getattr(module, 'opsec_safe') is False:
|
if not module.opsec_safe:
|
||||||
ans = input(highlight('[!] Module is not opsec safe, are you sure you want to run this? [Y/n] ', 'red'))
|
ans = input(
|
||||||
if ans.lower() not in ['y', 'yes', '']:
|
highlight('[!] Module is not opsec safe, are you sure you want to run this? [Y/n] ', 'red'))
|
||||||
sys.exit(1)
|
if ans.lower() not in ['y', 'yes', '']:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
if getattr(module, 'multiple_hosts') is False and len(targets) > 1:
|
if not module.multiple_hosts and len(targets) > 1:
|
||||||
ans = input(highlight("[!] Running this module on multiple hosts doesn't really make any sense, are you sure you want to continue? [Y/n] ", 'red'))
|
ans = input(highlight("[!] Running this module on multiple hosts doesn't really make any sense, are you sure you want to continue? [Y/n] ", 'red'))
|
||||||
if ans.lower() not in ['y', 'yes', '']:
|
if ans.lower() not in ['y', 'yes', '']:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if hasattr(module, 'on_request') or hasattr(module, 'has_response'):
|
if hasattr(module, 'on_request') or hasattr(module, 'has_response'):
|
||||||
|
if hasattr(module, 'required_server'):
|
||||||
|
args.server = module.required_server
|
||||||
|
|
||||||
if hasattr(module, 'required_server'):
|
if not args.server_port:
|
||||||
args.server = getattr(module, 'required_server')
|
args.server_port = server_port_dict[args.server]
|
||||||
|
|
||||||
if not args.server_port:
|
# loading a module server multiple times will obviously fail
|
||||||
args.server_port = server_port_dict[args.server]
|
try:
|
||||||
|
context = Context(db, logger, args)
|
||||||
|
module_server = CMEServer(module, context, logger, args.server_host, args.server_port, args.server)
|
||||||
|
module_server.start()
|
||||||
|
protocol_object.server = module_server.server
|
||||||
|
except Exception as e:
|
||||||
|
logging.debug(f"Error loading module server for {module}: {e}")
|
||||||
|
|
||||||
context = Context(db, logger, args)
|
logging.debug(f"proto_object: {protocol_object}, type: {type(protocol_object)}")
|
||||||
module_server = CMEServer(module, context, logger, args.server_host, args.server_port, args.server)
|
logging.debug(f"proto object dir: {dir(protocol_object)}")
|
||||||
module_server.start()
|
# get currently set modules, otherwise default to empty list
|
||||||
setattr(protocol_object, 'server', module_server.server)
|
current_modules = getattr(protocol_object, 'module', [])
|
||||||
|
current_modules.append(module)
|
||||||
|
setattr(protocol_object, 'module', current_modules)
|
||||||
|
logging.debug(f"proto object module after adding: {protocol_object.module}")
|
||||||
|
|
||||||
if hasattr(args, 'ntds') and args.ntds and not args.userntds:
|
if hasattr(args, 'ntds') and args.ntds and not args.userntds:
|
||||||
ans = input(highlight('[!] Dumping the ntds can crash the DC on Windows Server 2019. Use the option --user <user> to dump a specific user safely [Y/n] ', 'red'))
|
ans = input(highlight('[!] Dumping the ntds can crash the DC on Windows Server 2019. Use the option --user <user> to dump a specific user safely [Y/n] ', 'red'))
|
||||||
|
|
Loading…
Reference in New Issue