示例#1
0
文件: Commands.py 项目: lkheh/EaST
class Commands:
    def __init__(self, server):
        self.commands = {"exploit": self.start_module,
                         "message": self.register_module_message,
                         "status": self.module_status,
                         "kill_process": self.kill_process,
                         "options": self.get_module_options,
                         "get_args_for_module": self.get_module_args,
                         "restore_tabs": self.restore_tabs,
                         "get_all_server_data": self.get_all_server_data,
                         "listener_message": self.on_listener_message,
                         "listener_get_options": self.get_listener_options,
                         "gui_command_to_listener": self.gui_command_to_listener,
                         "get_source": self.get_source,
                         "save_source": self.save_source
                         }
        self.server = server
        self.using_module = ""
        self.available_modules = self.get_all_modules_paths()
        self.modules_handler = ModulesHandler(server)
        self.listener_handler = ListenerHandler(server)
        self.logger = logging.getLogger()
        self.options_parser = OptionsParser()
        self.port_scanner = PortScannerMT.Scanner(4000, 5000)

    def get_all_modules_paths(self):
        """Get common modules and modules from packs if available"""
        exploits = Modules.get_modules_names_dict(EXPLOITS_PATH)
        if not os.path.exists(PACKS_PATH):
            os.makedirs(PACKS_PATH)
        files = os.listdir(PACKS_PATH)
        packs = []
        for f in files:
            path_to_pack = os.path.join(PACKS_PATH, f)
            if os.path.isdir(path_to_pack):
                pack_dirs = [fname.lower() for fname in os.listdir(path_to_pack)]
                if "exploits" in pack_dirs:
                    full_path_to_pack_exploits = os.path.join(path_to_pack, "exploits")
                    exploits.update(Modules.get_modules_names_dict(full_path_to_pack_exploits))
        return exploits

    def execute(self, message, request):
        """
        Execution of command from websocket-client
        @param (JSON)message:  Object, containing keys "command" and "args"
        @param request: Websocket client request. Used to send response from server to this client
        """
        if message == "":
            return
        data = parse_json(message)
        if not data or type(data) is not dict or "command" not in data.keys() or "args" not in data.keys():
            resp = dict(command="message", args="This is not command")
            request.send_message(json.dumps(resp))
            return
        command = data["command"]
        args = data["args"]
        if command in self.commands.keys():
            self.commands[command](args, request)

    def start_module(self, args, request):
        """Run a module
        @param (dict)args: key 'module_name' => (string) Name of module
                           key 'listener' => (bool) Use listener
                           key 'listener_options' => (dict) Listener options
        """
        if args["module_name"] not in self.available_modules.keys():
            return
        module_name = self.available_modules[args["module_name"]]
        use_listener = args["use_listener"]
        options = args["options"]
        new_module_name = self.modules_handler.make_unique_name(args["module_name"])
        if use_listener:
            free_socket_data = self.port_scanner.scan(search_for='closed', first_match=True, nthreads=10)
            if free_socket_data:
                listener_options = dict(PORT=free_socket_data[0][1])
                print listener_options

            listener_process = subprocess.Popen([sys.executable, LISTENER], shell=False, env=os.environ.copy())
            self.listener_handler.addListener(new_module_name, listener_process, listener_options)
            self.server.add_process(listener_process)
        process = subprocess.Popen([sys.executable, module_name], shell=False, env=os.environ.copy())
        options = self.options_parser.parse_data(options)
        self.modules_handler.register_process(new_module_name, process, options)
        self.server.add_process(process)

        # We need to register first log message of module
        log_args = {"pid": process.pid,
                    "module_name": new_module_name,
                    "message": "Module %s has been started" % new_module_name,
                    "listener": use_listener,
                    "state": None
                    }
        self.register_module_message(log_args, request)

        # Send command to GUI to start logging
        self.send_all(log_args, request, "start_log")

    def get_all_server_data(self, args, request):
        """
        Send server data to gui(version, available modules)
        """
        data = []
        for name in self.available_modules.keys():
            data.append([self.available_modules[name], name])
        available_modules = self.modules_handler.get_modules_info(data)
        
        # Get framework version
        module = self.modules_handler.import_from_uri("start.py")
        version = "?"
        if module and hasattr(module, "VERSION"):
            version = module.VERSION
        args = dict(modules=available_modules, version=version)
        resp = dict(command="set_all_data", args=args)
        request.send_message(json.dumps(resp))        

    def restore_tabs(self, args, request):
        """ Send data of working modules to restore tabs in gui
        """
        log = self.modules_handler.get_full_log()
        listeners_messages = self.listener_handler.getListenersMessages()
        for module_name in log.keys():
            if module_name in listeners_messages.keys():
                log[module_name]["listener"]=listeners_messages[module_name]
        resp = dict(command="restore_tabs", args=log)
        request.send_message(json.dumps(resp))

    def module_status(self, args, request):
        """Get last log message of module
        :param args: (dict):
                    key "module_name":(string) Name of module;
                    key "pid": (int) PID of this module
        """
        modules = self.modules_handler.get_full_log()
        listeners_messages = self.listener_handler.getListenersMessages()
        for module_name in modules.keys():
            if module_name in listeners_messages.keys():
                modules[module_name]["listener"] = listeners_messages[module_name]
        resp = dict(command="status", args=modules)
        request.send_message(json.dumps(resp))
        return

    def kill_process(self, args, request):
        """Kills running process
                :param args: (dict):
                key "module_name":(string) Name of module;
                key "pid": (int) PID of this module
        """
        module_name = args["module_name"]
        if module_name not in self.modules_handler.processes.keys():
            return
        remove = "remove" in args
        self.modules_handler.kill_process(module_name, remove)
        self.listener_handler.killListener(module_name)

    def register_module_message(self, args, request):
        """Add log message from module
        @param (dict)args: (string)'message'=>Message from module;
                           (bool)'state'=>State of module(success, fail or nothing);
                           (int)'pid'=>Process ID of module
                           (bool)'inline'=>Write on last line if True
                           (bool)'replace'=>Replace last line if True
        """
        inline = args.get("inline", False)
        replace = args.get("replace", False)
        if "message" in args.keys() and "state" in args.keys() and "pid" in args.keys():
            self.modules_handler.add(args["pid"], args["message"], args["state"], inline, replace)

    def get_module_options(self, args, request):
        """Send options of module to gui
        @param (dict)args: (string)'module_name'=>Name of module
        """
        if args["module_name"] in self.available_modules.keys():
            opts = self.modules_handler.get_available_options_for_module(self.available_modules[args["module_name"]])
        opts = self.options_parser.prepare_options(opts)
        json_resp = []
        for key in opts.keys():
            json_resp.append(dict(option=key, value=opts[key]))
        self.send_all(json_resp, request, "options")



    def get_module_args(self, args, request):
        """
        Send modules options to running module
        """
        resp = self.modules_handler.get_module_options(args["pid"])
        module_name = self.modules_handler.get_module_name_by_pid(args["pid"])
        listener_options = self.listener_handler.getListenerOptionsByName(module_name)
        resp["listener"] = listener_options
        request.send_message(json.dumps(resp))

    def on_listener_message(self, args, request):
        """
        Add message from listener to gui or get last command from gui to listener
        """
        pid = args['pid']
        message = args['message']
        action = args['action']
        state = args['state']
        if action == 'get':
            message = self.listener_handler.getMessageFromGui(pid)
            request.send_message(json.dumps(dict(message=message)))
            return
        if action == 'add':
            self.listener_handler.addMessageToGui(pid, message)
        if state is not None:
            self.listener_handler.setShellConnected(pid, state)

    def get_listener_options(self, args, request):
        """
        Send options sets by gui to listener
        """
        pid = args['pid']
        options = self.listener_handler.getListenerOptions(pid)
        request.send_message(json.dumps(options))

    def gui_command_to_listener(self, args, request):
        """
        Add gui command to listener to queue
        """
        module_name = args['module_name']
        message = args['message']
        self.listener_handler.addMessageFromGui(module_name, message)

    def get_source(self, args, request):
        """
        Get source code of module
        """
        module_name = args['module_name']
        with open(self.available_modules[args['module_name']]) as file:
            lines = file.read().splitlines()
            source = "\n".join(lines)
        resp = dict(command="get_source", args=dict(message=source, module_name=module_name))
        request.send_message(json.dumps(resp))

    def save_source(self, args, request):
        """
        Save edited source code of module
        """
        code = args['message'].encode('utf-8')
        f = open(self.available_modules[args['module_name']],'w')
        f.write(code)
        f.close()

    def send_all(self, message, request=None, command=""):		
        self.logger.debug(message)
        if request:
            resp = {}
            if command:
                resp["command"] = command
            else:
                resp["command"] = "message"
            resp["args"] = message
            request.send_message(json.dumps(resp))
示例#2
0
class Commands:
    def __init__(self, server):
        self.commands = {"exploit": self.start_module,
                         "message": self.register_module_message,
                         "on_modules_log": self.get_modules_log,
                         "kill_process": self.kill_process,
                         "options": self.get_module_options,
                         "get_args_for_module": self.get_module_args,
                         "get_all_server_data": self.get_all_server_data,
                         "listener_message": self.on_listener_message,
                         "listener_get_options": self.get_listener_options,
                         "gui_command_to_listener": self.gui_command_to_listener,
                         "get_source": self.get_source,
                         "save_source": self.save_source,
                         "generate_report": self.generate_report
                         }
        self.server = server
        self.using_module = ""
        self.available_modules = self.get_all_modules_paths()
        self.modules_handler = ModulesHandler(server)
        self.listener_handler = ListenerHandler(server)
        self.logger = logging.getLogger()
        self.options_parser = OptionsParser()
        self.port_scanner = PortScannerMT.Scanner(4000, 5000)
        self.report_generator = ReportGenerator()

    def get_all_modules_paths(self):
        """Get common modules and modules from packs if available"""
        exploits = Modules.get_modules_names_dict(EXPLOITS_PATH)
        if not os.path.exists(PACKS_PATH):
            os.makedirs(PACKS_PATH)
        files = os.listdir(PACKS_PATH)
        for f in files:
            path_to_pack = os.path.join(PACKS_PATH, f)
            if os.path.isdir(path_to_pack):
                pack_dirs = [fname.lower() for fname in os.listdir(path_to_pack)]
                if "exploits" in pack_dirs:
                    full_path_to_pack_exploits = os.path.join(path_to_pack, "exploits")
                    exploits.update(Modules.get_modules_names_dict(full_path_to_pack_exploits))
        return exploits

    def execute(self, message, client):
        """
        Execution of command from websocket-client
        @param message:(Dict)  Object, containing keys "command" and "args"
        @param client:(WebSocketHandler) Websocket client handler. Used to send response from server to this client
        """
        if not message or type(message) is not dict or "command" not in message.keys() or "args" not in message.keys():
            resp = dict(command="message", args="This is not command")
            client.send_message(json.dumps(resp))
            return
        command = message["command"]
        args = message["args"]
        if command in self.commands.keys():
            self.commands[command](args, client)

    def start_module(self, args, client):
        """Run a module
        @param (dict)args: key 'module_name' => (string) Name of module
                           key 'listener' => (bool) Use listener
                           key 'listener_options' => (dict) Listener options
        """
        if args["module_name"] not in self.available_modules.keys():
            return
        module_name = self.available_modules[args["module_name"]]
        use_listener = args["use_listener"]
        options = args["options"]
        new_module_name = self.modules_handler.make_unique_name(args["module_name"])

        # After getting unique module name send it to gui
        data = dict(command="start_module",
                    args=dict(module_name=new_module_name, listener=use_listener))
        client.send_message(json.dumps(data))

        if use_listener:
            exclude_ports = self.listener_handler.get_busy_ports_list()
            free_socket_data = self.port_scanner.scan(search_for='closed', first_match=True, nthreads=10, exclude=exclude_ports)
            if free_socket_data:
                listener_options = dict(PORT=free_socket_data[0][1])
            listener_process = subprocess.Popen([sys.executable, LISTENER], shell=False, env=os.environ.copy())
            self.listener_handler.addListener(new_module_name, listener_process, listener_options)
            self.server.add_process(listener_process)
        process = subprocess.Popen([sys.executable, module_name], shell=False, env=os.environ.copy())
        options = self.options_parser.parse_data(options)
        self.modules_handler.register_process(new_module_name, args["module_name"], process, options)
        self.server.add_process(process)

        # We need to register first log message of module
        log_args = {"pid": process.pid,
                    "module_name": new_module_name,
                    "message": "Module %s has been started" % new_module_name,
                    "listener": use_listener,
                    "state": None
                    }
        self.register_module_message(log_args, client)

    def get_all_server_data(self, args, client):
        """
        Send server data to gui(version, available modules)
        """
        data = []
        for name in self.available_modules.keys():
            data.append([self.available_modules[name], name])
        available_modules = self.modules_handler.get_modules_info(data)

        # Get framework version
        module = self.modules_handler.import_from_uri("start.py")
        version = "?"
        if module and hasattr(module, "VERSION"):
            version = module.VERSION
        args = dict(modules=available_modules, version=version)
        resp = dict(command="set_all_data", args=args)
        client.send_message(json.dumps(resp))

    def get_modules_log(self, args, client):
        """Get last log message of module
        :param args: (dict):
                    key "module_name":(string) Name of module;
                    key "pid": (int) PID of this module
        """
        modules = self.modules_handler.get_full_log()
        listeners_messages = self.listener_handler.getListenersMessages()
        for module_name in modules.keys():
            if module_name in listeners_messages.keys():
                modules[module_name]["listener"] = listeners_messages[module_name]
        resp = dict(command="on_modules_log", args=modules)
        client.send_message(json.dumps(resp))

    def kill_process(self, args, request):
        """Kills running process
                :param args: (dict):
                key "module_name":(string) Name of module;
                key "pid": (int) PID of this module
        """
        module_name = args["module_name"]
        if module_name not in self.modules_handler.processes.keys():
            return
        remove = "remove" in args
        self.modules_handler.kill_process(module_name, remove)
        self.listener_handler.killListener(module_name)

    def register_module_message(self, args, client):
        """Add log message from module
        @param (dict)args: (string)'message'=>Message from module;
                           (bool)'state'=>State of module(success, fail or nothing);
                           (int)'pid'=>Process ID of module
                           (bool)'inline'=>Write on last line if True
                           (bool)'replace'=>Replace last line if True
        """
        inline = args.get("inline", False)
        replace = args.get("replace", False)
        if "message" in args.keys() and "state" in args.keys() and "pid" in args.keys():
            module = self.modules_handler.add(args["pid"], args["message"], args["state"], inline, replace)
            message = {"command": "on_module_message",
                       "args": {
                           "module_name": module.module_name,
                           "message": module.log[-1].formatted(),
                           "state": args["state"]
                       }}
            if args["state"] is not None:
                self.generate_report(args["pid"])

            self.send_message_to_ui(json.dumps(message))
        client.send_message(json.dumps({"message": "ok"}))

    def get_module_options(self, args, client):
        """Send options of module to gui
        @param (dict)args: (string)'module_name'=>Name of module
        """
        if args["module_name"] in self.available_modules.keys():
            opts = self.modules_handler.get_available_options_for_module(self.available_modules[args["module_name"]])
        opts = self.options_parser.prepare_options(opts)
        json_resp = []
        for key in opts.keys():
            json_resp.append(dict(option=key, value=opts[key]))
        client.send_message(json.dumps(dict(command="options", args=json_resp)))

    def get_module_args(self, args, client):
        """
        Send modules options to running module
        """
        resp = self.modules_handler.get_module_options(args["pid"])
        module_name = self.modules_handler.get_module_name_by_pid(args["pid"])
        listener_options = self.listener_handler.getListenerOptionsByName(module_name)
        resp["listener"] = listener_options
        client.send_message(json.dumps(resp))

    def gui_command_to_listener(self, args, client):
        """
        Add gui command to listener to queue
        """
        module_name = args['module_name']
        message = args['message']
        self.listener_handler.addMessage(module_name, ">> "+message)
        pid = self.listener_handler.getPidByModuleName(module_name)
        self.send_message_to_client_by_name(pid.__str__(), json.dumps(args))

    def on_listener_message(self, args, client):
        """
        Add message from listener to gui or get last command from gui to listener
        """
        pid = args['pid']
        message = args['message']
        state = args['state']

        module_name = self.listener_handler.getModuleNameByPid(pid)
        self.listener_handler.addMessage(module_name, message)
        data = dict(command="on_listener_message", args=dict(module_name=module_name, state=state, message=message))
        self.send_message_to_ui(json.dumps(data))
        if state is not None:
            self.listener_handler.setShellConnected(pid, state)

    def get_listener_options(self, args, client):
        """
        Send options sets by gui to listener
        """
        pid = args['pid']
        options = self.listener_handler.getListenerOptions(pid)
        client.send_message(json.dumps(options))

    def get_source(self, args, client):
        """
        Get source code of module
        """
        module_name = args['module_name']
        with open(self.available_modules[args['module_name']]) as file:
            lines = file.read().splitlines()
            source = "\n".join(lines)
        resp = dict(command="get_source", args=dict(message=source, module_name=module_name))
        client.send_message(json.dumps(resp))

    def save_source(self, args, client):
        """
        Save edited source code of module
        """
        host, port = client.socket.getsockname()
        if "localhost" not in host and "127.0.0.1" not in host:
            message = "Only localhost user can save sources"
            resp = dict(command="show_message_box", args=dict(message=message))
            client.send_message(json.dumps(resp))
            return
        code = args['message'].encode('utf-8')
        f = open(self.available_modules[args['module_name']],'w')
        f.write(code)
        f.close()

    def generate_report(self, pid):
        module_name = self.modules_handler.get_module_name_by_pid(pid)
        if not module_name:
            return
        module_inst = self.modules_handler.get_module_inst_by_name(module_name)
        listener_inst = self.listener_handler.get_listener_inst_by_name(module_name)
        info = self.modules_handler.get_module_info((self.available_modules[module_inst.original_name], module_name))
        module_vars = {
            "LOG": module_inst.log,
            "RESULT": module_inst.state,
            "OPTIONS": module_inst.options
        }
        listener_vars = {
            "IS_SHELL_CONNECTED": 0,
            "LISTENER_OPTIONS": 0,
            "LISTENER_LOG": 0
        }
        if listener_inst:
            listener_vars = {
                "IS_SHELL_CONNECTED": listener_inst.isShellConnected,
                "LISTENER_OPTIONS": listener_inst.options,
                "LISTENER_LOG": listener_inst.getMessagesFormatted()
            }
        module_vars.update(info)
        module_vars.update(listener_vars)
        module_vars["CVE"] = module_vars["CVE Name"]
        self.report_generator.append_module(module_vars)

    def send_message_to_ui(self, message):
        self.server.send_message_to_all_uis(message)

    def send_message_to_client_by_name(self, client_name, message):
        self.server.send_message_to_client(client_name, message)
示例#3
0
class Commands(API):
    def __init__(self, server):
        API.__init__(self)
        self.commands = self.get_api_functions()
        self.server = server
        self.available_modules = self.get_all_modules_paths()
        self.modules_handler = ModulesHandler(self)
        self.logger = logging.getLogger()
        self.options_parser = OptionsParser()
        self.port_scanner = PortScannerMT.Scanner(4000, 5000)
        self.report_generator = ReportGenerator()
        self.service_messages_handler = ServiceMessagesHandler()

    def get_api_functions(self):
        """
        Find all api_wrapped methods in class Commands
        Returns (dict): method name => method
        """
        api_methods = {
            k: v
            for k, v in vars(self.__class__).items()
            if inspect.isfunction(v) and v.__name__ == 'api_wrapped'
        }
        return api_methods

    def get_all_modules_paths(self):
        """Get common modules and modules from packs if available"""
        exploits = Modules.get_modules_names_dict(EXPLOITS_PATH)
        if not os.path.exists(PACKS_PATH):
            os.makedirs(PACKS_PATH)
        files = os.listdir(PACKS_PATH)
        for f in files:
            path_to_pack = os.path.join(PACKS_PATH, f)
            if os.path.isdir(path_to_pack):
                pack_dirs = [
                    fname.lower() for fname in os.listdir(path_to_pack)
                ]
                if "exploits" in pack_dirs:
                    full_path_to_pack_exploits = os.path.join(
                        path_to_pack, 'exploits')
                    exploits.update(
                        Modules.get_modules_names_dict(
                            full_path_to_pack_exploits))
        return exploits

    def _get_wrapped_function_required_args(self, func):
        if not hasattr(func, '__wrapped__'):
            return None
        args_spec = inspect.getargspec(func.__wrapped__)
        # Now slice 2 first arguments(self, client) and kw_args
        required_args = args_spec.args[2:-len(args_spec.defaults or [])]
        return args_spec.args, required_args

    def execute(self, message, client):
        """
        Execution of command from websocket-client
        @param message:(Dict)  Object, containing keys "command" and "args"
        @param client:(WebSocketHandler) Websocket client handler. Used to send response from server to this client
        """
        if not message or type(
                message
        ) is not dict or "command" not in message or "args" not in message:
            self.send_error(client, 'Error while handling request')
            return
        command = message["command"]
        args = message["args"]
        uuid = message.get('uuid')
        args = args if args else {}
        if command not in self.commands:
            self.send_error(client, 'Wrong command')
            return
        func = self.commands[command]
        func_args, func_req_args = self._get_wrapped_function_required_args(
            func)

        # find missing or excess args
        func_args_set = set(func_args)
        func_req_args_set = set(func_req_args)
        input_args_set = set(args)
        intersection = func_req_args_set.intersection(input_args_set)
        # missing
        if len(intersection) != len(func_req_args_set):
            diff = func_req_args_set.difference(input_args_set)
            msg = 'Following required parameters are missing: %s' % ', '.join(
                diff)
            print(command, 'Error: %s' % msg)
            self.send_error(client, msg)
            return
        diff = input_args_set.difference(func_args_set)
        if diff:
            msg = 'Following parameters are excess: %s' % ', '.join(diff)
            print(command, 'Error: %s' % msg)
            self.send_error(client, msg)
            return
        # if no errors call func
        resp = func(self, client, **args)
        if uuid:
            client.send_message(
                dict(command='on_callback', args=resp, uuid=uuid))

    @API.callable
    def start_module(self,
                     client,
                     module_name,
                     use_listener,
                     use_custom_port=False,
                     custom_port=0,
                     listener_type=1,
                     options={}):
        """
        Runs a module
        Args:
            module_name: (string) Name of module
            use_listener: (bool) If True - enable listener for module
            use_custom_port: (bool) Use custom listener port
            custom_port: (int) Custom listener port
            listener_type: (int) 1 - reverse, 2 - bind
            options: (dict) Option of module set up in GUI
        Returns:
            (dict):
                'module_name': (string) Unique name of running module
                'listener': (bool) Is listener enabled
        """
        if module_name not in self.available_modules:
            print('There is no module with name %s' % module_name)
            return
        module_path = self.available_modules[module_name]
        new_module_name = self.modules_handler.make_unique_name(module_name)
        options = self.options_parser.parse_data(options)
        running_module = self.modules_handler.register_process(
            new_module_name, module_name, options)
        if use_listener and listener_type == 1:
            exclude_ports = self.modules_handler.get_busy_ports_list()
            if use_custom_port and custom_port:
                if custom_port in exclude_ports or self.port_scanner.check_port_state(
                        custom_port):
                    message = 'Lister port %d is busy. Try another port for listener' % custom_port
                    return self.make_error(message)
                listener_options = dict(PORT=custom_port)
            else:
                free_socket_data = self.port_scanner.scan(
                    search_for='closed',
                    first_match=True,
                    nthreads=10,
                    exclude=exclude_ports)
                listener_options = dict(PORT=free_socket_data[0][1])
            running_module.listener_options = listener_options
            listener_process = subprocess.Popen(
                [sys.executable, LISTENER_PATH, new_module_name],
                shell=False,
                env=os.environ.copy())
            self.modules_handler.add_listener_pid(new_module_name,
                                                  listener_process.pid)
        process = subprocess.Popen(
            [sys.executable, module_path, new_module_name],
            shell=False,
            env=os.environ.copy())
        self.modules_handler.add_module_pid(new_module_name, process.pid)
        return dict(module_name=new_module_name, listener=use_listener)

    @API.callable
    def install_via_pip(self, client, library_name):
        """
        Install python module via pip
        Args:
            library_name: Name of module to install
        """
        import subprocess
        try:
            proc = subprocess.Popen(['pip', 'install', library_name])
        except Exception as e:
            print e
            return self.make_error('Can\'t install module %s' % library_name)
        else:
            proc.communicate()
            if proc.returncode == 0:
                self.service_messages_handler.remove_import_error(library_name)
                return dict(module_to_import=library_name)
            return self.make_error('Can\'t install module %s' % library_name)

    @API.callable
    def get_all_server_data(self, client):
        """
        Returns dict of modules, version, service messages
        """
        data = []
        self.service_messages_handler.reset()
        for name in self.available_modules:
            data.append([self.available_modules[name], name])
        available_modules = self.modules_handler.get_modules_info(data)
        service_messages = self.service_messages_handler.get_grouped()
        # Get framework version
        module = self.modules_handler.import_from_uri("start.py", False)
        version = "?"
        if module and hasattr(module, "VERSION"):
            version = module.VERSION
        return dict(modules=available_modules,
                    version=version,
                    serviceMessages=service_messages)

    @API.callable
    def get_modules_log(self, client):
        """
        Get all modules and listeners log
        """
        modules = self.modules_handler.get_full_log()
        return modules

    @API.callable
    def kill_process(self, client, module_name):
        """
        Kills running processes of module and listener if exists
        Args:
            module_name: (string) Name of module
        """
        if module_name not in self.modules_handler.running_modules:
            return
        self.modules_handler.kill_process(module_name)

    @API.callable
    def register_module_message(self,
                                client,
                                message,
                                state,
                                module_name,
                                type='text',
                                inline=False,
                                replace=False):
        """
        Add log message from module
        Args:
            message: (string) Message from module
            state: (bool or None) State of module(success, fail or nothing)
            module_name: (string) Name og running module
            type: (string) text or image
            inline: (bool) Write on last line if True
            replace: (bool) Replace last line if True
        """
        module = self.modules_handler.add_message(module_name, message, state,
                                                  inline, replace, type)
        message = {
            "command": "on_module_message",
            "args": {
                "module_name": module.module_name,
                "message": module.log[-1].formatted(),
                "state": state
            }
        }
        # TODO REPORTS
        # if state is not None:
        #     self.generate_report(pid)
        self.send_message_to_ui(message)
        return dict(message="ok")

    @API.callable
    def get_module_options(self, client, module_name):
        """
        Send options of module to gui
        Args:
            module_name: real module name without '.py' extension
        Returns:
            (list) List of options from module's dict OPTIONS
        """
        if module_name in self.available_modules:
            opts = self.modules_handler.get_available_options_for_module(
                self.available_modules[module_name])
        opts = self.options_parser.prepare_options(opts)
        json_resp = []
        for key in opts:
            json_resp.append(dict(option=key, value=opts[key]))
        return json_resp

    @API.callable
    def get_module_args(self, client, module_name):
        """
        Get module options changed by GUI
        Args:
            module_name: (string) Name of running module
        Returns:
            (dict) Dict of options
        """
        resp = self.modules_handler.get_changed_options(module_name)
        return resp

    @API.callable
    def gui_command_to_listener(self, client, module_name, message):
        """
        Sends command from GUI to listener
        Args:
            module_name: (string) Name of running module
            message: (string) Message for listener from gui(os command)
        """
        self.modules_handler.add_listener_message(module_name, ">> " + message)
        args = dict(module_name=module_name, message=message)
        self.send_message_to_listener(module_name, args)

    @API.callable
    def on_listener_message(self, client, module_name, message, state):
        """
        Add message from listener to gui or get last command from gui to listener
        Args:
            module_name: (string) Name of running module
            message: (string) Message from listener
            state: (int)  0 - shell is not connected
                          1 - shell connected
                          2 - shell disconnected
        """
        self.modules_handler.add_listener_message(module_name, message, state)
        data = dict(command="on_listener_message",
                    args=dict(module_name=module_name,
                              state=state,
                              message=message))
        self.send_message_to_ui(data)

    @API.callable
    def get_listener_options(self, client, module_name):
        """
        Get listener options by listener PID or module PID
        Args:
            module_name: (string) Name of running module
        """
        if not module_name:
            return self.make_error('PIDs are not specified')
        options = self.modules_handler.get_module_inst_by_name(
            module_name).listener_options
        return options

    @API.callable
    def add_listener_options(self, client, module_name, options):
        """
        Adds/Changes options of listener
        Args:
            module_name: (string) Name of running module
            options: (dict) listener options
        """
        module = self.modules_handler.get_module_inst_by_name(module_name)
        module.listener_options = options
        return {"re"}

    @API.callable
    def add_listener_pid(self, client, module_name, pid):
        """
        Adds listener PID to running module instance
        Args:
            module_name: (string) Name of running module
            pid: (int) Listener PID
        """
        self.modules_handler.add_listener_pid(module_name, pid)

    @API.callable
    def get_source(self, client, module_name):
        """
        Get source code of module
        Args:
            module_name: (string) real module name, without '.py' extension
        """
        with open(self.available_modules[module_name]) as f:
            lines = f.read().splitlines()
            source = "\n".join(lines)
        return dict(message=source, module_name=module_name)

    @API.callable
    def save_source(self, client, module_name, message):
        """
        Save edited source code of module
        Args:
            module_name: (string) real module name, without '.py' extension
            message: (string) Edited source code of module
        """
        host, port = client.socket.getsockname()
        if "localhost" not in host and "127.0.0.1" not in host:
            message = "Only localhost user can save sources"
            self.send_error(client, message)
            return
        code = message.encode('utf-8')
        with open(self.available_modules[module_name], 'wb') as f:
            f.write(code)
        self.send_info(client, 'Module %s successfully changed' % module_name)

    @API.callable
    def is_listener_connected(self, client, module_name):
        """
        Get info about state of listener
        Args:
            module_name: (string) Name of running module
        """
        state = None
        module = self.modules_handler.get_module_inst_by_name(module_name)
        if module:
            state = module.is_shell_connected
            if state == 0:
                state = False
            elif state == 1:
                state = True
        resp = dict(state=state)
        return resp

    def make_error(self, error_msg):
        return dict(error=True, message=error_msg)

    def send_error(self, client, error_msg):
        client.send_message(
            dict(command='on_error', args=dict(message=error_msg)))

    def send_info(self, client, info_msg):
        client.send_message(
            dict(command='on_info', args=dict(message=info_msg)))

    def generate_report(self, module_name):
        module_inst = self.modules_handler.get_module_inst_by_name(module_name)
        info = self.modules_handler.get_module_info(
            (self.available_modules[module_inst.original_name], module_name))
        module_vars = {
            "LOG": module_inst.log,
            "RESULT": module_inst.state,
            "OPTIONS": module_inst.options
        }
        listener_vars = {
            "IS_SHELL_CONNECTED": module_inst.is_shell_connected,
            "LISTENER_OPTIONS": module_inst.listener_options,
            "LISTENER_LOG": '\n'.join(module_inst.listener_messages)
        }
        module_vars.update(info)
        module_vars.update(listener_vars)
        module_vars["CVE"] = module_vars["CVE Name"]
        self.report_generator.append_module(module_vars)

    def send_message_to_ui(self, message):
        self.server.send_message_to_all_uis(message)

    def send_message_to_listener(self, module_name, message):
        self.server.send_message_to_listener(module_name, message)