Esempio n. 1
0
def _set_plugins():
    # TODO
    # load plugin scripts .pyc file support
    if conf.plugins:
        founds = []
        cache_plugins = copy.deepcopy(conf.plugins)

        for found in glob.glob(
                os.path.join(paths.POCSUITE_PLUGINS_PATH, "*.py*")):
            dirname, filename = os.path.split(found)
            plugin_name = os.path.splitext(filename)[0]
            if found.endswith(('__init__.py', '__init__.pyc')):
                continue
            if plugin_name not in conf.plugins:
                continue
            cache_plugins.remove(plugin_name)
            founds.append(found)
        if len(cache_plugins) > 0:
            for file in cache_plugins:
                if os.path.exists(file):
                    founds.append(file)

        for file in founds:
            debug_msg = "loading plugin script '{0}'".format(file)
            logger.debug(debug_msg)
            load_file_to_module(file)
Esempio n. 2
0
def _set_conf_attributes():
    """
    This function set some needed attributes into the configuration
    singleton.
    """

    debug_msg = "initializing the configuration"
    logger.debug(debug_msg)

    conf.url = None
    conf.url_file = None
    conf.mode = 'verify'
    conf.poc = None
    conf.cookie = None
    conf.host = None
    conf.referer = None
    conf.agent = None
    conf.headers = None
    conf.random_agent = None
    conf.proxy = None
    conf.proxy_cred = None
    conf.proxies = {}
    conf.timeout = 30
    conf.retry = 0
    conf.delay = 0
    conf.http_headers = {}
    conf.login_user = None
    conf.login_pass = None
    conf.shodan_token = None
    conf.censys_uid = None
    conf.censys_secret = None
    conf.dork = None
    conf.dork_zoomeye = None
    conf.dork_shodan = None
    conf.dork_censys = None
    conf.max_page = 1
    conf.search_type = 'host'
    conf.comparison = False
    conf.vul_keyword = None
    conf.ssvid = None
    conf.plugins = []
    conf.threads = 1
    conf.batch = False
    conf.check_requires = False
    conf.quiet = False
    conf.update_all = False
    conf.verbose = 1

    conf.ipv6 = False
    conf.multiple_targets = False
    conf.pocs_path = None
    conf.output_path = None
    conf.plugin_name = None
    conf.plugin_code = None
    conf.connect_back_host = None
    conf.connect_back_port = DEFAULT_LISTENER_PORT
    conf.console_mode = False
    conf.show_version = False
    conf.api = False  # api for zipoc
    conf.ppt = False
Esempio n. 3
0
def update():
    if not conf.update_all:
        return
    success = False
    if not os.path.exists(os.path.join(paths.POCSUITE_ROOT_PATH, "../",
                                       ".git")):
        warn_msg = "not a git repository. It is recommended to clone the 'knownsec/pocsuite3' repository "
        warn_msg += "from GitHub (e.g. 'git clone --depth 1 {} pocsuite3')".format(
            GIT_REPOSITORY)
        logger.warn(warn_msg)
        if VERSION == get_latest_revision():
            logger.info("already at the latest revision '{}'".format(
                get_revision_number()))
            return
    else:
        info_msg = "updating pocsuite3 to the latest development revision from the "
        info_msg += "GitHub repository"
        logger.info(info_msg)
        debug_msg = "pocsuite3 will try to update itself using 'git' command"
        logger.debug(debug_msg)
        data_to_stdout("\r[{0}] [INFO] update in progress ".format(
            time.strftime("%X")))
        cwd_path = os.path.join(paths.POCSUITE_ROOT_PATH, "../")
        try:
            process = subprocess.Popen(
                "git checkout . && git pull %s HEAD" % GIT_REPOSITORY,
                shell=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                cwd=cwd_path.encode(sys.getfilesystemencoding()
                                    or UNICODE_ENCODING))
            poll_process(process, True)
            stdout, stderr = process.communicate()
            success = not process.returncode
        except (IOError, OSError) as ex:
            success = False
            stderr = str(ex)
        if success:
            logger.info("{0} the latest revision '{1}'".format(
                "already at" if b"Already" in stdout else "updated to",
                get_revision_number()))
        else:
            if "Not a git repository" in stderr:
                err_msg = "not a valid git repository. Please checkout the 'knownsec/pocsuite3' repository "
                err_msg += "from GitHub (e.g. 'git clone --depth 1 %s pocsuite3')" % GIT_REPOSITORY
                logger.error(err_msg)
            else:
                logger.error("update could not be completed ('%s')" %
                             re.sub(r"\W+", " ", stderr).strip())
    if not success:
        if IS_WIN:
            info_msg = "for Windows platform it's recommended "
            info_msg += "to use a GitHub for Windows client for updating "
            info_msg += "purposes (http://windows.github.com/) or just "
            info_msg += "download the latest snapshot from "
            info_msg += "https://github.com/knownsec/pocsuite3/downloads"
        else:
            info_msg = "for Linux platform it's recommended "
            info_msg += "to install a standard 'git' package (e.g.: 'sudo apt-get install git')"
        logger.info(info_msg)
Esempio n. 4
0
    def get_links(self, url, url_ext=()):
        # TODO:
        # set base url from base tag or current url
        self.base_url = url
        url_part = urlparse(url)
        self.origin = (url_part.scheme, url_part.netloc)
        self.urls = {
            'url': set(),
            'js': set(),
            'img': set()
        }
        if isinstance(url_ext, str):
            url_ext = set(url_ext)

        self.url_ext = url_ext

        debug_msg = "crawler visiting: {0}".format(url)
        logger.debug(debug_msg)

        resp = requests.get(url)
        content_type = resp.headers.get('content-type', '')
        if 'text/html' in content_type:
            html = resp.text
            self.feed(html)

        return self.urls
Esempio n. 5
0
def _set_network_proxy():
    if conf.proxy:
        debug_msg = "setting the HTTP/SOCKS proxy for all network requests"
        logger.debug(debug_msg)

        try:
            _ = urlsplit(conf.proxy)
        except Exception as ex:
            err_msg = "invalid proxy address '{0}' ('{1}')".format(
                conf.proxy, str(ex))
            raise PocsuiteSyntaxException(err_msg)

        hostname_port = _.netloc.split(":")
        scheme = _.scheme.upper()
        hostname = hostname_port[0]
        port = None
        username = None
        password = None

        if len(hostname_port) == 2:
            try:
                port = int(hostname_port[1])
            except Exception:
                pass

        if not all((scheme, hasattr(PROXY_TYPE, scheme), hostname, port)):
            err_msg = "proxy value must be in format '({0})://address:port'".format(
                "|".join(_[0].lower()
                         for _ in get_public_type_members(PROXY_TYPE)))
            raise PocsuiteSyntaxException(err_msg)

        if conf.proxy_cred:
            _ = re.search(r"\A(.*?):(.*?)\Z", conf.proxy_cred)
            if not _:
                err_msg = "proxy authentication credentials "
                err_msg += "value must be in format username:password"
                raise PocsuiteSyntaxException(err_msg)
            else:
                username = _.group(1)
                password = _.group(2)

        if scheme in (PROXY_TYPE.SOCKS4, PROXY_TYPE.SOCKS5):
            socks.set_default_proxy(
                socks.PROXY_TYPE_SOCKS5
                if scheme == PROXY_TYPE.SOCKS5 else socks.PROXY_TYPE_SOCKS4,
                hostname,
                port,
                username=username,
                password=password)
            socket.socket = socks.socksocket
        else:
            if conf.proxy_cred:
                proxy_string = "{0}@".format(conf.proxy_cred)
            else:
                proxy_string = ""

            proxy_string = "{0}{1}:{2}".format(proxy_string, hostname, port)
            conf.proxies = {"http": proxy_string, "https": proxy_string}
Esempio n. 6
0
def config_file_parser(configFile):
    """
    Parse configuration file and save settings into the configuration
    advanced dictionary.
    """

    # global config

    debugMsg = "parsing configuration file"
    logger.debug(debugMsg)

    if not os.path.isfile(configFile):
        raise PocsuiteFilePathException(
            "file '{}' don't exist".format(configFile))

    config = ConfigParser()
    config.read(configFile)

    if not config.has_section("Target"):
        errMsg = "missing a mandatory section 'Target' in the configuration file"
        raise PocsuiteMissingMandatoryOptionException(errMsg)

    sections = config.sections()
    for section in sections:
        options = config.options(section)
        if options:
            for option in options:
                datatype = "string"
                try:
                    datatype = optDict[section][option]
                except KeyError:
                    pass

                try:
                    if datatype == OPTION_TYPE.BOOLEAN:
                        value = config.getboolean(
                            section, option) if config.get(section,
                                                           option) else False
                    elif datatype == OPTION_TYPE.INTEGER:
                        value = config.getint(section, option) if config.get(
                            section, option) else 0
                    elif datatype == OPTION_TYPE.FLOAT:
                        value = config.getfloat(section, option) if config.get(
                            section, option) else 0.0
                    else:
                        value = config.get(section, option)
                except ValueError as ex:
                    errMsg = "error occurred while processing the option "
                    errMsg += "'%s' in provided configuration file ('%s')" % (
                        option, ex)
                    raise PocsuiteValueException(errMsg)

                if value:
                    conf[option] = value
Esempio n. 7
0
def _set_plugins():
    # TODO
    # load plugin scripts .pyc file support
    if conf.plugins:
        for found in glob.glob(os.path.join(paths.POCSUITE_PLUGINS_PATH, "*.py*")):
            dirname, filename = os.path.split(found)
            plugin_name = os.path.splitext(filename)[0]
            if found.endswith(('__init__.py', '__init__.pyc')):
                continue
            if plugin_name not in conf.plugins:
                continue

            debug_msg = "loading plugin script '{0}'".format(found)
            logger.debug(debug_msg)
            load_file_to_module(found)
Esempio n. 8
0
    def execute(self, target, headers=None, params=None, mode='verify', verbose=True):
        self.target = target
        self.url = parse_target_url(target) if self.current_protocol == POC_CATEGORY.PROTOCOL.HTTP else self.build_url()
        self.headers = headers
        self.params = str_to_dict(params) if params else {}
        self.mode = mode
        self.verbose = verbose
        self.expt = (0, 'None')
        # TODO
        output = None

        try:
            output = self._execute()

        except NotImplementedError as e:
            self.expt = (ERROR_TYPE_ID.NOTIMPLEMENTEDERROR, e)
            logger.log(CUSTOM_LOGGING.ERROR, 'POC: {0} not defined "{1}" mode'.format(self.name, self.mode))
            output = Output(self)

        except ConnectTimeout as e:
            self.expt = (ERROR_TYPE_ID.CONNECTTIMEOUT, e)
            while conf.retry > 0:
                logger.debug('POC: {0} timeout, start it over.'.format(self.name))
                try:
                    output = self._execute()
                    break
                except ConnectTimeout:
                    logger.debug('POC: {0} time-out retry failed!'.format(self.name))
                conf.retry -= 1
            else:
                msg = "connect target '{0}' failed!".format(target)
                logger.error(msg)
                output = Output(self)

        except HTTPError as e:
            self.expt = (ERROR_TYPE_ID.HTTPERROR, e)
            logger.warn('POC: {0} HTTPError occurs, start it over.'.format(self.name))
            output = Output(self)

        except ConnectionError as e:
            self.expt = (ERROR_TYPE_ID.CONNECTIONERROR, e)
            msg = "connect target '{0}' failed!".format(target)
            logger.error(msg)
            output = Output(self)

        except TooManyRedirects as e:
            self.expt = (ERROR_TYPE_ID.TOOMANYREDIRECTS, e)
            logger.debug(str(e))
            output = Output(self)

        except Exception as e:
            self.expt = (ERROR_TYPE_ID.OTHER, e)
            logger.debug(str(e))
            output = Output(self)

        return output
Esempio n. 9
0
def _set_kb_attributes(flush_all=True):
    """
    This function set some needed attributes into the knowledge base
    singleton.
    """

    debug_msg = "initializing the knowledge base"
    logger.debug(debug_msg)

    kb.abs_file_paths = set()
    kb.os = None
    kb.os_version = None
    kb.arch = None
    kb.dbms = None
    kb.auth_header = None
    kb.counters = {}
    kb.multi_thread_mode = False
    kb.thread_continue = True
    kb.thread_exception = False
    kb.word_lists = None
    kb.single_log_flags = set()

    kb.cache = AttribDict()
    kb.cache.addrinfo = {}
    kb.cache.content = {}
    kb.cache.regex = {}

    kb.data = AttribDict()
    kb.data.local_ips = []
    kb.data.connect_back_ip = None
    kb.data.connect_back_port = DEFAULT_LISTENER_PORT
    kb.data.clients = []
    kb.targets = OrderedSet()
    kb.plugins = AttribDict()
    kb.plugins.targets = AttribDict()
    kb.plugins.pocs = AttribDict()
    kb.plugins.results = AttribDict()
    kb.results = []
    kb.current_poc = None
    kb.registered_pocs = AttribDict()
    kb.task_queue = Queue()
    kb.cmd_line = DIY_OPTIONS or []

    kb.comparison = None
Esempio n. 10
0
    def create_shellcode(self,
                         _shellcode_type='reverse',
                         command='calc.exe',
                         message='',
                         encode=None,
                         make_exe=0,
                         debug=0,
                         filename="",
                         dll_inj_funcs=[],
                         shell_args={},
                         use_precompiled=True):
        """
        Function for create shellcode.
        :param _shellcode_type: (string) Can be "reverse" or "bind".
        :param command: (string) Command for Windows command-shellcode.
        :param message: (string) Message for "message" for message-shellcode.
        :param encode: (string) Encoder type. Can be "xor", "alphanum", "rot_13", "fnstenv" or "jumpcall". If empty shellcode will not be encoded.
        :param make_exe: (bool) or (int) If True(or 1) exe file will be generated from shellcode.
        :param debug: (bool) or (int) If True(or 1) shellcode will be printed to stdout.
        :param filename: (string) Used for assign special name to executable or dll shellcode.
        :param dll_inj_funcs: (list of strings) Functions names for dll hijacking. If not empty dll with shellcode will be generated.
        :param cloud_generate (bool) Used for generate shellcode on cloud server.
        :return: (string) Generated shellcode.
        """
        generator = ShellGenerator(self.OS_TARGET, self.OS_TARGET_ARCH)
        shellcode, self.binary_path = generator.get_shellcode(
            _shellcode_type,
            connectback_ip=self.CONNECTBACK_IP,
            connectback_port=self.CONNECTBACK_PORT,
            make_exe=make_exe,
            debug=debug,
            filename=filename,
            dll_inj_funcs=dll_inj_funcs,
            shell_args=shell_args,
            use_precompiled=use_precompiled)
        if encode:
            if debug:
                logger.debug("[] Encode shellcode is on and started")
            e = CodeEncoders(self.OS_SYSTEM, self.OS_TARGET,
                             self.OS_TARGET_ARCH, self.BADCHARS)
            e_shellcode = e.encode_shellcode(shellcode, encode, debug)

            if debug:
                logger.debug("Length of encoded shellcode: %d" %
                             len(e_shellcode))
                logger.debug("[] Encode shellcode finished")
            if e_shellcode:
                shellcode = e_shellcode
        else:
            if debug:
                logger.debug("[] Encode shellcode is off")
        return shellcode
Esempio n. 11
0
def start():
	tasks_count = kb.task_queue.qsize()
	info_msg = "pocsusite got a total of {0} tasks".format(tasks_count)
	logger.info(info_msg)
	logger.debug("pocsuite will open {} threads".format(conf.threads))
	
	try:
		run_threads(conf.threads, task_run)
	finally:
		task_done()
	
	if conf.mode == "shell" and not conf.api:
		info_msg = "connect back ip: {0}    port: {1}".format(conf.connect_back_host, conf.connect_back_port)
		logger.info(info_msg)
		info_msg = "waiting for shell connect to pocsuite"
		logger.info(info_msg)
		if conf.console_mode:
			handle_listener_connection_for_console()
		else:
			handle_listener_connection()
Esempio n. 12
0
 def get_shellcode(self,
                   shellcode_type,
                   connectback_ip="127.0.0.1",
                   connectback_port=5555,
                   make_exe=0,
                   debug=0,
                   filename="",
                   dll_inj_funcs=None,
                   shell_args=None,
                   use_precompiled=True):
     if shell_args is None:
         shell_args = {}
     if dll_inj_funcs is None:
         dll_inj_funcs = []
     self.check_settings(connectback_ip, connectback_port)
     filepath = ''
     if self.use_precompiled:
         logger.info(
             'Some utils needed for shellcode compilation are not found. Only precompiled shellcodes can be used.'
         )
     self.use_precompiled = use_precompiled or self.use_precompiled
     ext = '.bin' if self.use_precompiled else '.asm'
     if shellcode_type == SHELLCODE_CONNECTION.BIND:
         path = self._make_path('bind_tcp' + ext)
         if self.use_precompiled:
             values = dict(BIND_PORT=port_to_hex(connectback_port))
         else:
             values = dict(BIND_PORT=port_to_dd(connectback_port))
     elif shellcode_type == SHELLCODE_CONNECTION.REVERSE:
         path = self._make_path('reverse_tcp' + ext)
         if self.use_precompiled:
             values = dict(CONNECTBACK_IP=ip_to_hex(connectback_ip),
                           CONNECTBACK_PORT=port_to_hex(connectback_port))
         else:
             values = dict(CONNECTBACK_IP=ip_to_dd(connectback_ip),
                           CONNECTBACK_PORT=port_to_dd(connectback_port))
     # handle custom shellcode
     else:
         path = os.path.join(self.shellcodes_root, shellcode_type + ext)
         values = shell_args
     shell = self.read_and_replace(path, values, use_precompiled)
     if not self.use_precompiled:
         shell, filepath = create_shellcode(shell,
                                            self.OS_TARGET,
                                            self.OS_TARGET_ARCH,
                                            make_exe,
                                            debug=debug,
                                            filename=filename,
                                            dll_inj_funcs=dll_inj_funcs)
     if debug:
         logger.debug('Shellcode generated with length=%s' % len(shell))
         logger.debug(b''.join(b'\\x%02x' % x for x in shell))
     if (make_exe or dll_inj_funcs) and self.use_precompiled:
         exe_gen = ShellcodeToExe(shell,
                                  self.OS_TARGET,
                                  self.OS_TARGET_ARCH,
                                  filename=filename,
                                  dll_inj_funcs=dll_inj_funcs)
         if make_exe:
             filepath = exe_gen.create_executable()
             if debug:
                 logger.debug('Executable trojan is generated: %s' %
                              filepath)
         if dll_inj_funcs:
             filepath = exe_gen.create_executable()
             if debug:
                 logger.debug('DLL is generated: %s' % filepath + '.dll')
     return shell, filepath
Esempio n. 13
0
    import readline as _readline
except ImportError:
    try:
        from pyreadline import *
        import pyreadline as _readline
    except ImportError:
        # raise PocsuiteSystemException("Import pyreadline faild,try pip3 install pyreadline")
        pass

if IS_WIN and _readline:
    try:
        _outputfile = _readline.GetOutputFile()
    except AttributeError:
        debugMsg = "Failed GetOutputFile when using platform's "
        debugMsg += "readline library"
        logger.debug(debugMsg)

        _readline = None

# Test to see if libedit is being used instead of GNU readline.
# Thanks to Boyd Waters for this patch.
uses_libedit = False

if PLATFORM == 'mac' and _readline:
    import commands

    (status, result) = commands.getstatusoutput("otool -L %s | grep libedit" %
                                                _readline.__file__)

    if status == 0 and len(result) > 0:
        # We are bound to libedit - new in Leopard
Esempio n. 14
0
def cmd_line_parser(argv=None):
    """
    This function parses the command line parameters and arguments
    """

    if not argv:
        argv = sys.argv

    _ = os.path.basename(argv[0])
    usage = "pocsuite [options]"
    parser = OptionParser(usage=usage)
    try:
        parser.add_option("--version",
                          dest="show_version",
                          action="store_true",
                          help="Show program's version number and exit")

        parser.add_option("--update",
                          dest="update_all",
                          action="store_true",
                          help="Update Pocsuite")

        parser.add_option("-v",
                          dest="verbose",
                          type="int",
                          default=1,
                          help="Verbosity level: 0-6 (default 1)")

        # Target options
        target = OptionGroup(
            parser, "Target", "At least one of these "
            "options has to be provided to define the target(s)")
        target.add_option(
            "-u",
            "--url",
            dest="url",
            help="Target URL (e.g. \"http://www.site.com/vuln.php?id=1\")")

        target.add_option("-f",
                          "--file",
                          dest="url_file",
                          help="Scan multiple targets given in a textual file")
        target.add_option(
            "-r",
            dest="poc",
            help="Load POC file from local or remote from seebug website")
        # Mode options
        mode = OptionGroup(parser, "Mode", "Pocsuite running mode options")

        mode.add_option("--verify",
                        dest="mode",
                        default='verify',
                        action="store_const",
                        const='verify',
                        help="Run poc with verify mode")

        mode.add_option("--attack",
                        dest="mode",
                        action="store_const",
                        const='attack',
                        help="Run poc with attack mode")
        mode.add_option("--shell",
                        dest="mode",
                        action="store_const",
                        const='shell',
                        help="Run poc with shell mode")
        # Requests options
        request = OptionGroup(parser, "Request", "Network request options")
        request.add_option("--cookie",
                           dest="cookie",
                           help="HTTP Cookie header value")
        request.add_option("--host",
                           dest="host",
                           help="HTTP Host header value")
        request.add_option("--referer",
                           dest="referer",
                           help="HTTP Referer header value")
        request.add_option("--user-agent",
                           dest="agent",
                           help="HTTP User-Agent header value")
        request.add_option(
            "--random-agent",
            dest="random_agent",
            action="store_true",
            default=False,
            help="Use randomly selected HTTP User-Agent header value")
        request.add_option("--proxy",
                           dest="proxy",
                           help="Use a proxy to connect to the target URL")
        request.add_option(
            "--proxy-cred",
            dest="proxy_cred",
            help="Proxy authentication credentials (name:password)")
        request.add_option(
            "--timeout",
            dest="timeout",
            help="Seconds to wait before timeout connection (default 30)")
        request.add_option("--retry",
                           dest="retry",
                           default=False,
                           help="Time out retrials times.")
        request.add_option("--delay",
                           dest="delay",
                           help="Delay between two request of one thread")
        request.add_option(
            "--headers",
            dest="headers",
            help="Extra headers (e.g. \"key1: value1\\nkey2: value2\")")
        # Account options
        account = OptionGroup(parser, "Account", "Telnet404 account options")
        account.add_option("--login-user",
                           dest="login_user",
                           help="Telnet404 login user")
        account.add_option("--login-pass",
                           dest="login_pass",
                           help="Telnet404 login password")
        # Modules options
        modules = OptionGroup(parser, "Modules",
                              "Modules(Seebug Zoomeye CEye Listener) options")
        modules.add_option("--dork",
                           dest="dork",
                           action="store",
                           default=None,
                           help="Zoomeye dork used for search.")
        modules.add_option(
            "--max-page",
            dest="max_page",
            type=int,
            default=1,
            help="Max page used in ZoomEye API(10 targets/Page).")
        modules.add_option("--search-type",
                           dest="search_type",
                           action="store",
                           default='host',
                           help="search type used in ZoomEye API, web or host")
        modules.add_option("--vul-keyword",
                           dest="vul_keyword",
                           action="store",
                           default=None,
                           help="Seebug keyword used for search.")
        modules.add_option("--ssv-id",
                           dest="ssvid",
                           action="store",
                           default=None,
                           help="Seebug SSVID number for target PoC.")
        modules.add_option(
            "--lhost",
            dest="connect_back_host",
            action="store",
            default=None,
            help="Connect back host for target PoC in shell mode")
        modules.add_option(
            "--lport",
            dest="connect_back_port",
            action="store",
            default=None,
            help="Connect back port for target PoC in shell mode")

        # Optimization options
        optimization = OptionGroup(parser, "Optimization",
                                   "Optimization options")
        optimization.add_option("--plugins",
                                dest="plugins",
                                action="store",
                                default=None,
                                help="Load plugins to execute")
        optimization.add_option("--pocs-path",
                                dest="pocs_path",
                                action="store",
                                default=None,
                                help="User defined poc scripts path")
        optimization.add_option(
            "--threads",
            dest="threads",
            type=int,
            default=1,
            help="Max number of concurrent network requests (default 1)")
        optimization.add_option(
            "--batch",
            dest="batch",
            help="Automatically choose defaut choice without asking.")
        optimization.add_option("--requires",
                                dest="check_requires",
                                action="store_true",
                                default=False,
                                help="Check install_requires")
        optimization.add_option(
            "--quiet",
            dest="quiet",
            action="store_true",
            default=False,
            help="Activate quiet mode, working without logger.")

        # Diy options
        diy_options = OptionGroup(parser, "Poc options",
                                  "definition options for PoC")

        for line in argv:
            if line.startswith("--"):
                if line[2:] not in CMD_PARSE_WHITELIST:
                    diy_options.add_option(line)

        parser.add_option_group(target)
        parser.add_option_group(mode)
        parser.add_option_group(request)
        parser.add_option_group(account)
        parser.add_option_group(modules)
        parser.add_option_group(optimization)
        parser.add_option_group(diy_options)

        (args, _) = parser.parse_args(argv)
        if not any((args.url, args.url_file, args.update_all, args.plugins,
                    args.dork)):
            err_msg = "missing a mandatory option (-u, --url-file, --update). "
            err_msg += "Use -h for basic and -hh for advanced help\n"
            parser.error(err_msg)

        return args

    except (OptionError, TypeError) as e:
        parser.error(e)

    except SystemExit:
        # Protection against Windows dummy double clicking
        if IS_WIN:
            data_to_stdout("\nPress Enter to continue...")
            input()
        raise

    debug_msg = "parsing command line"
    logger.debug(debug_msg)