From c4bda6068c139fbcfdc67e9c753e507ce9b02e1c Mon Sep 17 00:00:00 2001 From: Lucien A Date: Thu, 15 Jun 2023 22:03:32 +0200 Subject: [PATCH] complete module arguments --- core/module.py | 90 ++++++++++++++++++++++--------------- core/sessions.py | 32 ++++++++----- core/terminal.py | 35 ++++++++++----- modules/audit/filesystem.py | 10 ++--- 4 files changed, 104 insertions(+), 63 deletions(-) diff --git a/core/module.py b/core/module.py index b9ce2b79..d2c4beef 100644 --- a/core/module.py +++ b/core/module.py @@ -11,18 +11,16 @@ """ -from core.vectorlist import VectorList -from core.vectors import ModuleExec -from core.weexceptions import DevException, ArgparseError -from core.loggers import log +import shlex + +import utils from core import argparsers from core import messages -from mako.template import Template from core import modules -import shlex -import utils -import ast -import os +from core.loggers import log +from core.vectorlist import VectorList +from core.weexceptions import DevException, ArgparseError + class Status: """Represent the module statuses. @@ -43,6 +41,7 @@ class Status: class Module: aliases = [] + arguments = [] def __init__(self, session, name, folder): """Module object constructor. @@ -73,9 +72,53 @@ def __init__(self, session, name, folder): # Arguments dictionary is initially empty self.args = {} - self.init() + self._register_arguments(self.arguments) + + def complete(self, text) -> []: + names = [] + + for a in self.arguments: + name = a.get('name') + if isinstance(name, list): + name = name[0] + name = name.strip('-') + if name.startswith(text): + names.append(f'{name} ') + + return names + + def register_arguments(self, arguments): + self.arguments = arguments + + def _register_arguments(self, arguments): + """Register the module arguments. + + Register arguments to be added to the argparse parser. + + Args: + arguments (list of dict): List of dictionaries in the form + `[{ 'name' : 'arg1', 'opt' : '', .. }, {'name' : 'arg2', 'opt' : '', .. }]` + to be passed to the `ArgumentParser.add_argument()` method. + """ + + try: + for arg_opts in arguments: + + # Handle if the argument registration is done before + # The vector registration. This should at least warn + if arg_opts.get('choices') == []: + log.warn(messages.module.error_choices_s_s_empty % (self.name, + arg_name)) + + self.argparser.add_argument( + arg_opts['name'], + **dict((k, v) for k, v in arg_opts.items() if k != 'name') + ) + except Exception as e: + raise DevException(messages.module.error_setting_arguments_s % (e)) + def run_cmdline(self, line, cmd = ''): """Execute the module from command line. @@ -306,33 +349,6 @@ def register_info(self, info): if not self.argparser.description: raise DevException(messages.module.error_module_missing_description) - def register_arguments(self, arguments = []): - """Register the module arguments. - - Register arguments to be added to the argparse parser. - - Args: - arguments (list of dict): List of dictionaries in the form - `[{ 'name' : 'arg1', 'opt' : '', .. }, {'name' : 'arg2', 'opt' : '', .. }]` - to be passed to the `ArgumentParser.add_argument()` method. - """ - - try: - for arg_opts in arguments: - - # Handle if the argument registration is done before - # The vector registration. This should at least warn - if arg_opts.get('choices') == []: - log.warn(messages.module.error_choices_s_s_empty % (self.name, - arg_name)) - - self.argparser.add_argument( - arg_opts['name'], - **dict((k, v) for k, v in arg_opts.items() if k != 'name') - ) - except Exception as e: - raise DevException(messages.module.error_setting_arguments_s % (e)) - def register_vectors(self, vectors): """Register the module vectors. diff --git a/core/sessions.py b/core/sessions.py index 0de9d950..65279851 100644 --- a/core/sessions.py +++ b/core/sessions.py @@ -1,17 +1,19 @@ -from core import messages -from core.weexceptions import FatalException +import ast +import atexit +import glob +import logging +import os +import pprint +import urllib.parse + +import yaml from mako import template + +from core import messages from core.config import sessions_path, sessions_ext from core.loggers import log, dlog, stream_handler from core.module import Status -import os -import yaml -import glob -import logging -import urllib.parse -import atexit -import ast -import pprint +from core.weexceptions import FatalException arg_blacklist = ( 'default_shell', @@ -48,12 +50,20 @@ def get_stored_args(self, term = ''): path = ("%s.%s" % (mod_name, argument)) if not term or path.startswith(term): args.append((path, arg_value)) - # If is not a module, just print if matches with print_filters + # If is not a module, just print if not in blacklist elif mod_name not in arg_blacklist and mod_name.startswith(term): args.append((mod_name, mod_value)) return args + def complete(self, text): + names = [] + for name, val in self.items(): + if not isinstance(val, dict) and name not in arg_blacklist and name.startswith(text): + names.append(name) + + return names + def get_connection_info(self): return template.Template(messages.sessions.connection_info).render( url = self['url'], diff --git a/core/terminal.py b/core/terminal.py index 292519e4..2f982f27 100644 --- a/core/terminal.py +++ b/core/terminal.py @@ -1,11 +1,12 @@ -from core.weexceptions import FatalException, ChannelException -from core.loggers import log, dlog +from mako import template + +import utils +from core import config from core import messages from core import modules -from core import config +from core.loggers import log, dlog from core.module import Status -import utils -from mako import template +from core.weexceptions import ChannelException try: import gnureadline as readline @@ -13,11 +14,9 @@ import readline import cmd -import glob -import os import shlex import atexit -import sys + class CmdModules(cmd.Cmd): @@ -285,10 +284,26 @@ def do_show(self, line, cmd): """Command "show" which prints session variables""" self.session.print_to_user(line) - + + def completenames_and_args(self, text): + names = [] + + mod_text, arg_text = text.split('.') if '.' in text else (text, '',) + + for n in self.completenames(mod_text): + if n.startswith(mod_text): + if n in modules.loaded: + mod = modules.loaded[n] + if mod_text == n: + names.extend([f'{n}.{o}' for o in mod.complete(arg_text)]) + elif len(mod.arguments): + names.append(f'{n}.') + return names + def complete_set(self, text, line, begidx, endidx): if line.count(' ') < 2: - return [a[0] for a in self.session.get_stored_args(text)] + res = self.session.complete(text) + self.completenames_and_args(text) + return res def do_set(self, line, cmd): """Command "set" to set session variables.""" diff --git a/modules/audit/filesystem.py b/modules/audit/filesystem.py index c6fa19b1..25ca5810 100644 --- a/modules/audit/filesystem.py +++ b/modules/audit/filesystem.py @@ -1,13 +1,13 @@ -from core.vectors import PhpCode, ShellCmd, ModuleExec, Os -from core.module import Module from core.loggers import log -from core import modules -import utils +from core.module import Module +from core.vectors import ModuleExec -class Filesystem(Module): +class Filesystem(Module): """Audit the file system for weak permissions.""" + check_functions = [] + def init(self): self.register_info(