Ejemplo n.º 1
0
    def __init__(self, config_path):
        cmd.Cmd.__init__(self)

        self.config_path = config_path

        try:
            self.config = ConfigParser()
            self.config.read(self.config_path)
        except Exception as e:
            print "[-] Error reading cme.conf: {}".format(e)
            sys.exit(1)

        self.workspace_dir = os.path.expanduser('~/.cme/workspaces')
        self.conn = None
        self.p_loader = protocol_loader()
        self.protocols = self.p_loader.get_protocols()

        self.workspace = self.config.get('CME', 'workspace')
        self.do_workspace(self.workspace)

        self.db = self.config.get('CME', 'last_used_db')
        if self.db:
            self.do_proto(self.db)
Ejemplo n.º 2
0
    def __init__(self, config_path):
        cmd.Cmd.__init__(self)

        self.config_path = config_path

        try:
            self.config = ConfigParser()
            self.config.read(self.config_path)
        except Exception as e:
            print "[-] Error reading cme.conf: {}".format(e)
            sys.exit(1)

        self.workspace_dir = os.path.expanduser('~/.cme/workspaces')
        self.conn = None
        self.p_loader = protocol_loader()
        self.protocols = self.p_loader.get_protocols()

        self.workspace = self.config.get('CME', 'workspace')
        self.do_workspace(self.workspace)

        self.db = self.config.get('CME', 'last_used_db')
        if self.db:
            self.do_proto(self.db)
Ejemplo n.º 3
0
def first_run_setup(logger):

    if not os.path.exists(TMP_PATH):
        os.mkdir(TMP_PATH)

    if not os.path.exists(CME_PATH):
        logger.info('First time use detected')
        logger.info('Creating home directory structure')
        os.mkdir(CME_PATH)

    folders = [
        'logs', 'modules', 'protocols', 'workspaces', 'obfuscated_scripts',
        'screenshots'
    ]
    for folder in folders:
        if not os.path.exists(os.path.join(CME_PATH, folder)):
            os.mkdir(os.path.join(CME_PATH, folder))

    if not os.path.exists(os.path.join(WS_PATH, 'default')):
        logger.info('Creating default workspace')
        os.mkdir(os.path.join(WS_PATH, 'default'))

    p_loader = protocol_loader()
    protocols = p_loader.get_protocols()
    for protocol in protocols.keys():
        try:
            protocol_object = p_loader.load_protocol(
                protocols[protocol]['dbpath'])
        except KeyError:
            continue

        proto_db_path = os.path.join(WS_PATH, 'default', protocol + '.db')

        if not os.path.exists(proto_db_path):
            logger.info('Initializing {} protocol database'.format(
                protocol.upper()))
            conn = sqlite3.connect(proto_db_path)
            c = conn.cursor()

            # try to prevent some of the weird sqlite I/O errors
            c.execute('PRAGMA journal_mode = OFF')
            c.execute('PRAGMA foreign_keys = 1')

            getattr(protocol_object, 'database').db_schema(c)

            # commit the changes and close everything off
            conn.commit()
            conn.close()

    if not os.path.exists(CONFIG_PATH):
        logger.info('Copying default configuration file')
        default_path = os.path.join(os.path.dirname(cme.__file__), 'data',
                                    'cme.conf')
        shutil.copy(default_path, CME_PATH)
    else:
        # This is just a quick check to make sure the config file isn't the old 3.x format
        try:
            config = configparser.ConfigParser()
            config.read(CONFIG_PATH)
            config.get('CME', 'workspace')
            config.get('CME', 'pwn3d_label')
            config.get('CME', 'audit_mode')
            config.get('BloodHound', 'bh_enabled')
        except (NoSectionError, NoOptionError):
            logger.info(
                'Old configuration file detected, replacing with new version')
            default_path = os.path.join(os.path.dirname(cme.__file__), 'data',
                                        'cme.conf')
            shutil.copy(default_path, CME_PATH)

    if not os.path.exists(CERT_PATH):
        logger.info('Generating SSL certificate')
        try:
            check_output(['openssl', 'help'], stderr=PIPE)
            if os.name != 'nt':
                os.system(
                    'openssl req -new -x509 -keyout {path} -out {path} -days 365 -nodes -subj "/C=US" > /dev/null 2>&1'
                    .format(path=CERT_PATH))
            else:
                os.system(
                    'openssl req -new -x509 -keyout {path} -out {path} -days 365 -nodes -subj "/C=US"'
                    .format(path=CERT_PATH))
        except OSError as e:
            if e.errno == errno.ENOENT:
                logger.error(
                    'OpenSSL command line utility is not installed, could not generate certificate, using default certificate'
                )
                default_path = os.path.join(os.path.dirname(cme.__file__),
                                            'data', 'default.pem')
                shutil.copy(default_path, CERT_PATH)
            else:
                logger.error(
                    'Error while generating SSL certificate: {}'.format(e))
                sys.exit(1)
Ejemplo n.º 4
0
def gen_cli_args():

    VERSION = '5.0.1dev'
    CODENAME = 'P3l1as'

    p_loader = protocol_loader()
    protocols = p_loader.get_protocols()

    parser = argparse.ArgumentParser(
        description="""
      ______ .______           ___        ______  __  ___ .___  ___.      ___      .______    _______ ___   ___  _______   ______
     /      ||   _  \         /   \      /      ||  |/  / |   \/   |     /   \     |   _  \  |   ____|\  \ /  / |   ____| /      |
    |  ,----'|  |_)  |       /  ^  \    |  ,----'|  '  /  |  \  /  |    /  ^  \    |  |_)  | |  |__    \  V  /  |  |__   |  ,----'
    |  |     |      /       /  /_\  \   |  |     |    <   |  |\/|  |   /  /_\  \   |   ___/  |   __|    >   <   |   __|  |  |
    |  `----.|  |\  \----. /  _____  \  |  `----.|  .  \  |  |  |  |  /  _____  \  |  |      |  |____  /  .  \  |  |____ |  `----.
     \______|| _| `._____|/__/     \__\  \______||__|\__\ |__|  |__| /__/     \__\ | _|      |_______|/__/ \__\ |_______| \______|

                                         A swiss army knife for pentesting networks
                                    Forged by @byt3bl33d3r using the powah of dank memes

                                                      {}: {}
                                                     {}: {}
""".format(highlight('Version', 'red'), highlight(VERSION),
           highlight('Codename', 'red'), highlight(CODENAME)),
        formatter_class=RawTextHelpFormatter,
        #version='{} - {}'.format(VERSION, CODENAME),
        epilog="Ya feelin' a bit buggy all of a sudden?")

    parser.add_argument(
        "-t",
        type=int,
        dest="threads",
        default=100,
        help="set how many concurrent threads to use (default: 100)")
    parser.add_argument(
        "--timeout",
        default=None,
        type=int,
        help='max timeout in seconds of each thread (default: None)')
    parser.add_argument(
        "--jitter",
        metavar='INTERVAL',
        type=str,
        help='sets a random delay between each connection (default: None)')
    parser.add_argument("--darrell",
                        action='store_true',
                        help='give Darrell a hand')
    parser.add_argument("--verbose",
                        action='store_true',
                        help="enable verbose output")

    subparsers = parser.add_subparsers(title='protocols',
                                       dest='protocol',
                                       description='available protocols')

    std_parser = argparse.ArgumentParser(add_help=False)
    std_parser.add_argument(
        "target",
        nargs='*',
        type=str,
        help=
        "the target IP(s), range(s), CIDR(s), hostname(s), FQDN(s), file(s) containing a list of targets, NMap XML or .Nessus file(s)"
    )
    std_parser.add_argument(
        '-id',
        metavar="CRED_ID",
        nargs='+',
        default=[],
        type=str,
        dest='cred_id',
        help='database credential ID(s) to use for authentication')
    std_parser.add_argument("-u",
                            metavar="USERNAME",
                            dest='username',
                            nargs='+',
                            default=[],
                            help="username(s) or file(s) containing usernames")
    std_parser.add_argument("-p",
                            metavar="PASSWORD",
                            dest='password',
                            nargs='+',
                            default=[],
                            help="password(s) or file(s) containing passwords")
    fail_group = std_parser.add_mutually_exclusive_group()
    fail_group.add_argument("--gfail-limit",
                            metavar='LIMIT',
                            type=int,
                            help='max number of global failed login attempts')
    fail_group.add_argument(
        "--ufail-limit",
        metavar='LIMIT',
        type=int,
        help='max number of failed login attempts per username')
    fail_group.add_argument(
        "--fail-limit",
        metavar='LIMIT',
        type=int,
        help='max number of failed login attempts per host')

    module_parser = argparse.ArgumentParser(add_help=False)
    mgroup = module_parser.add_mutually_exclusive_group()
    mgroup.add_argument("-M",
                        "--module",
                        metavar='MODULE',
                        help='module to use')
    #mgroup.add_argument('-MC','--module-chain', metavar='CHAIN_COMMAND', help='Payload module chain command string to run')
    module_parser.add_argument('-o',
                               metavar='MODULE_OPTION',
                               nargs='+',
                               default=[],
                               dest='module_options',
                               help='module options')
    module_parser.add_argument('-L',
                               '--list-modules',
                               action='store_true',
                               help='list available modules')
    module_parser.add_argument('--options',
                               dest='show_module_options',
                               action='store_true',
                               help='display module options')
    module_parser.add_argument("--server",
                               choices={'http', 'https'},
                               default='https',
                               help='use the selected server (default: https)')
    module_parser.add_argument(
        "--server-host",
        type=str,
        default='0.0.0.0',
        metavar='HOST',
        help='IP to bind the server to (default: 0.0.0.0)')
    module_parser.add_argument("--server-port",
                               metavar='PORT',
                               type=int,
                               help='start the server on the specified port')

    for protocol in protocols.keys():
        protocol_object = p_loader.load_protocol(protocols[protocol]['path'])
        subparsers = getattr(protocol_object,
                             protocol).proto_args(subparsers, std_parser,
                                                  module_parser)

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    args = parser.parse_args()

    return args
Ejemplo n.º 5
0
def gen_cli_args():

    VERSION = '5.2.3'
    CODENAME = "The Dark Knight"

    p_loader = protocol_loader()
    protocols = p_loader.get_protocols()

    parser = argparse.ArgumentParser(description=f"""
      ______ .______           ___        ______  __  ___ .___  ___.      ___      .______    _______ ___   ___  _______   ______
     /      ||   _  \         /   \      /      ||  |/  / |   \/   |     /   \     |   _  \  |   ____|\  \ /  / |   ____| /      |
    |  ,----'|  |_)  |       /  ^  \    |  ,----'|  '  /  |  \  /  |    /  ^  \    |  |_)  | |  |__    \  V  /  |  |__   |  ,----'
    |  |     |      /       /  /_\  \   |  |     |    <   |  |\/|  |   /  /_\  \   |   ___/  |   __|    >   <   |   __|  |  |
    |  `----.|  |\  \----. /  _____  \  |  `----.|  .  \  |  |  |  |  /  _____  \  |  |      |  |____  /  .  \  |  |____ |  `----.
     \______|| _| `._____|/__/     \__\  \______||__|\__\ |__|  |__| /__/     \__\ | _|      |_______|/__/ \__\ |_______| \______|

                                                A swiss army knife for pentesting networks
                                    Forged by @byt3bl33d3r and @mpgn_x64 using the powah of dank memes

                                           {colored("Exclusive release for Porchetta Industries users", "magenta")}
                                                       {colored("https://porchetta.industries/", "magenta")}

                                                   {highlight('Version', 'red')} : {highlight(VERSION)}
                                                   {highlight('Codename', 'red')}: {highlight(CODENAME)}
""",
                                     formatter_class=RawTextHelpFormatter)

    parser.add_argument(
        "-t",
        type=int,
        dest="threads",
        default=100,
        help="set how many concurrent threads to use (default: 100)")
    parser.add_argument(
        "--timeout",
        default=None,
        type=int,
        help='max timeout in seconds of each thread (default: None)')
    parser.add_argument(
        "--jitter",
        metavar='INTERVAL',
        type=str,
        help='sets a random delay between each connection (default: None)')
    parser.add_argument("--darrell",
                        action='store_true',
                        help='give Darrell a hand')
    parser.add_argument("--verbose",
                        action='store_true',
                        help="enable verbose output")

    subparsers = parser.add_subparsers(title='protocols',
                                       dest='protocol',
                                       description='available protocols')

    std_parser = argparse.ArgumentParser(add_help=False)
    std_parser.add_argument(
        "target",
        nargs='*',
        type=str,
        help=
        "the target IP(s), range(s), CIDR(s), hostname(s), FQDN(s), file(s) containing a list of targets, NMap XML or .Nessus file(s)"
    )
    std_parser.add_argument(
        '-id',
        metavar="CRED_ID",
        nargs='+',
        default=[],
        type=str,
        dest='cred_id',
        help='database credential ID(s) to use for authentication')
    std_parser.add_argument("-u",
                            metavar="USERNAME",
                            dest='username',
                            nargs='+',
                            default=[],
                            help="username(s) or file(s) containing usernames")
    std_parser.add_argument("-p",
                            metavar="PASSWORD",
                            dest='password',
                            nargs='+',
                            default=[],
                            help="password(s) or file(s) containing passwords")
    std_parser.add_argument(
        "-k",
        "--kerberos",
        action='store_true',
        help="Use Kerberos authentication from ccache file (KRB5CCNAME)")
    std_parser.add_argument("--export",
                            metavar="EXPORT",
                            nargs='+',
                            help="Export result into a file, probably buggy")
    std_parser.add_argument(
        "--aesKey",
        metavar="AESKEY",
        nargs='+',
        help="AES key to use for Kerberos Authentication (128 or 256 bits)")
    std_parser.add_argument(
        "--kdcHost",
        metavar="KDCHOST",
        help=
        "FQDN of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter"
    )

    fail_group = std_parser.add_mutually_exclusive_group()
    fail_group.add_argument("--gfail-limit",
                            metavar='LIMIT',
                            type=int,
                            help='max number of global failed login attempts')
    fail_group.add_argument(
        "--ufail-limit",
        metavar='LIMIT',
        type=int,
        help='max number of failed login attempts per username')
    fail_group.add_argument(
        "--fail-limit",
        metavar='LIMIT',
        type=int,
        help='max number of failed login attempts per host')

    module_parser = argparse.ArgumentParser(add_help=False)
    mgroup = module_parser.add_mutually_exclusive_group()
    mgroup.add_argument("-M",
                        "--module",
                        metavar='MODULE',
                        help='module to use')
    #mgroup.add_argument('-MC','--module-chain', metavar='CHAIN_COMMAND', help='Payload module chain command string to run')
    module_parser.add_argument('-o',
                               metavar='MODULE_OPTION',
                               nargs='+',
                               default=[],
                               dest='module_options',
                               help='module options')
    module_parser.add_argument('-L',
                               '--list-modules',
                               action='store_true',
                               help='list available modules')
    module_parser.add_argument('--options',
                               dest='show_module_options',
                               action='store_true',
                               help='display module options')
    module_parser.add_argument("--server",
                               choices={'http', 'https'},
                               default='https',
                               help='use the selected server (default: https)')
    module_parser.add_argument(
        "--server-host",
        type=str,
        default='0.0.0.0',
        metavar='HOST',
        help='IP to bind the server to (default: 0.0.0.0)')
    module_parser.add_argument("--server-port",
                               metavar='PORT',
                               type=int,
                               help='start the server on the specified port')
    module_parser.add_argument(
        "--connectback-host",
        type=str,
        metavar='CHOST',
        help=
        'IP for the remote system to connect back to (default: same as server-host)'
    )

    for protocol in protocols.keys():
        protocol_object = p_loader.load_protocol(protocols[protocol]['path'])
        subparsers = getattr(protocol_object,
                             protocol).proto_args(subparsers, std_parser,
                                                  module_parser)

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    args = parser.parse_args()

    return args
Ejemplo n.º 6
0
def main():
    first_run_setup(logger)

    args = gen_cli_args()

    if args.darrell:
        links = open(
            os.path.join(os.path.dirname(cme.__file__), 'data',
                         'videos_for_darrell.harambe')).read().splitlines()
        try:
            webbrowser.open(random.choice(links))
        except:
            sys.exit(1)

    cme_path = os.path.expanduser('~/.cme')

    config = configparser.ConfigParser()
    config.read(os.path.join(cme_path, 'cme.conf'))

    module = None
    module_server = None
    targets = []
    jitter = None
    server_port_dict = {'http': 80, 'https': 443, 'smb': 445}
    current_workspace = config.get('CME', 'workspace')

    if args.verbose:
        setup_debug_logger()

    logging.debug('Passed args:\n' + pformat(vars(args)))

    if args.jitter:
        if '-' in args.jitter:
            start, end = args.jitter.split('-')
            jitter = (int(start), int(end))
        else:
            jitter = (0, int(args.jitter))

    if hasattr(args, 'cred_id') and args.cred_id:
        for cred_id in args.cred_id:
            if '-' in str(cred_id):
                start_id, end_id = cred_id.split('-')
                try:
                    for n in range(int(start_id), int(end_id) + 1):
                        args.cred_id.append(n)
                    args.cred_id.remove(cred_id)
                except Exception as e:
                    logger.error(
                        'Error parsing database credential id: {}'.format(e))
                    sys.exit(1)

    if hasattr(args, 'target') and args.target:
        for target in args.target:
            if os.path.exists(target):
                target_file_type = identify_target_file(target)
                if target_file_type == 'nmap':
                    targets.extend(parse_nmap_xml(target, args.protocol))
                elif target_file_type == 'nessus':
                    targets.extend(parse_nessus_file(target, args.protocol))
                else:
                    with open(target, 'r') as target_file:
                        for target_entry in target_file:
                            targets.extend(parse_targets(target_entry.strip()))
            else:
                targets.extend(parse_targets(target))

    # The following is a quick hack for the powershell obfuscation functionality, I know this is yucky
    if hasattr(args, 'clear_obfscripts') and args.clear_obfscripts:
        shutil.rmtree(os.path.expanduser('~/.cme/obfuscated_scripts/'))
        os.mkdir(os.path.expanduser('~/.cme/obfuscated_scripts/'))
        logger.success('Cleared cached obfuscated PowerShell scripts')

    if hasattr(args, 'obfs') and args.obfs:
        powershell.obfuscate_ps_scripts = True

    p_loader = protocol_loader()
    protocol_path = p_loader.get_protocols()[args.protocol]['path']
    protocol_db_path = p_loader.get_protocols()[args.protocol]['dbpath']

    protocol_object = getattr(p_loader.load_protocol(protocol_path),
                              args.protocol)
    protocol_db_object = getattr(p_loader.load_protocol(protocol_db_path),
                                 'database')

    db_path = os.path.join(cme_path, 'workspaces', current_workspace,
                           args.protocol + '.db')
    # set the database connection to autocommit w/ isolation level
    db_connection = sqlite3.connect(db_path, check_same_thread=False)
    db_connection.text_factory = str
    db_connection.isolation_level = None
    db = protocol_db_object(db_connection)

    setattr(protocol_object, 'config', config)

    if hasattr(args, 'module'):

        loader = module_loader(args, db, logger)

        if args.list_modules:
            modules = loader.get_modules()

            for name, props in sorted(modules.items()):
                logger.info('{:<25} {}'.format(name, props['description']))
            sys.exit(0)

        elif args.module and args.show_module_options:

            modules = loader.get_modules()
            for name, props in modules.items():
                if args.module.lower() == name.lower():
                    logger.info('{} module options:\n{}'.format(
                        name, props['options']))
            sys.exit(0)

        elif args.module:
            modules = loader.get_modules()
            for name, props in modules.items():
                if args.module.lower() == name.lower():
                    module = loader.init_module(props['path'])
                    setattr(protocol_object, 'module', module)
                    break

            if not module:
                logger.error('Module not found')
                exit(1)

            if getattr(module, 'opsec_safe') is False:
                ans = input(
                    highlight(
                        '[!] Module is not opsec safe, are you sure you want to run this? [Y/n] ',
                        'red'))
                if ans.lower() not in ['y', 'yes', '']:
                    sys.exit(1)

            if getattr(module, 'multiple_hosts') is False and len(targets) > 1:
                ans = input(
                    highlight(
                        "[!] Running this module on multiple hosts doesn't really make any sense, are you sure you want to continue? [Y/n] ",
                        'red'))
                if ans.lower() not in ['y', 'yes', '']:
                    sys.exit(1)

            if hasattr(module, 'on_request') or hasattr(
                    module, 'has_response'):

                if hasattr(module, 'required_server'):
                    args.server = getattr(module, 'required_server')

                if not args.server_port:
                    args.server_port = server_port_dict[args.server]

                context = Context(db, logger, args)
                module_server = CMEServer(module, context, logger,
                                          args.server_host, args.server_port,
                                          args.server)
                module_server.start()
                setattr(protocol_object, 'server', module_server.server)

    try:
        asyncio.run(
            start_threadpool(protocol_object, args, db, targets, jitter))
    except KeyboardInterrupt:
        logging.debug("Got keyboard interrupt")
    finally:
        if module_server:
            module_server.shutdown()
Ejemplo n.º 7
0
def first_run_setup(logger):

    if not os.path.exists(TMP_PATH):
        os.mkdir(TMP_PATH)

    if not os.path.exists(CME_PATH):
        logger.info('First time use detected')
        logger.info('Creating home directory structure')
        os.mkdir(CME_PATH)

    folders = ['logs', 'modules', 'protocols', 'workspaces', 'obfuscated_scripts']
    for folder in folders:
        if not os.path.exists(os.path.join(CME_PATH, folder)):
            os.mkdir(os.path.join(CME_PATH,folder))

    if not os.path.exists(os.path.join(WS_PATH, 'default')):
        logger.info('Creating default workspace')
        os.mkdir(os.path.join(WS_PATH, 'default'))

    p_loader =  protocol_loader()
    protocols = p_loader.get_protocols()
    for protocol in protocols.keys():
        try:
            protocol_object = p_loader.load_protocol(protocols[protocol]['dbpath'])
        except KeyError:
            continue

        proto_db_path = os.path.join(WS_PATH, 'default', protocol + '.db')

        if not os.path.exists(proto_db_path):
            logger.info('Initializing {} protocol database'.format(protocol.upper()))
            conn = sqlite3.connect(proto_db_path)
            c = conn.cursor()

            # try to prevent some of the weird sqlite I/O errors
            c.execute('PRAGMA journal_mode = OFF')
            c.execute('PRAGMA foreign_keys = 1')

            getattr(protocol_object, 'database').db_schema(c)

            # commit the changes and close everything off
            conn.commit()
            conn.close()

    if not os.path.exists(CONFIG_PATH):
        logger.info('Copying default configuration file')
        default_path = os.path.join(os.path.dirname(cme.__file__), 'data', 'cme.conf')
        shutil.copy(default_path, CME_PATH)
    else:
        # This is just a quick check to make sure the config file isn't the old 3.x format
        try:
            config = ConfigParser()
            config.read(CONFIG_PATH)
            current_workspace = config.get('CME', 'workspace')
        except NoSectionError:
            logger.info('v3.x configuration file detected, replacing with new version')
            default_path = os.path.join(os.path.dirname(cme.__file__), 'data', 'cme.conf')
            shutil.copy(default_path, CME_PATH)

    if not os.path.exists(CERT_PATH):
        logger.info('Generating SSL certificate')
        try:
            out = check_output(['openssl', 'help'], stderr=PIPE)
        except OSError as e:
            if e.errno == os.errno.ENOENT:
                logger.error('OpenSSL command line utility is not installed, could not generate certificate')
                exit(1)
            else:
                logger.error('Error while generating SSL certificate: {}'.format(e))
                exit(1)

        os.system('openssl req -new -x509 -keyout {path} -out {path} -days 365 -nodes -subj "/C=US" > /dev/null 2>&1'.format(path=CERT_PATH))
Ejemplo n.º 8
0
def main():

    setup_logger()
    logger = CMEAdapter()
    first_run_setup(logger)

    args = gen_cli_args()

    if args.darrell:
        links = open(os.path.join(os.path.dirname(cme.__file__), 'data', 'videos_for_darrell.harambe')).read().splitlines()
        try:
            webbrowser.open(random.choice(links))
        except:
            sys.exit(1)

    cme_path = os.path.expanduser('~/.cme')

    config = ConfigParser()
    config.read(os.path.join(cme_path, 'cme.conf'))

    module  = None
    module_server = None
    targets = []
    jitter = None
    server_port_dict = {'http': 80, 'https': 443, 'smb': 445}
    current_workspace = config.get('CME', 'workspace')

    if args.verbose:
        setup_debug_logger()

    logging.debug('Passed args:\n' + pformat(vars(args)))

    if args.jitter:
        if '-' in args.jitter:
            start, end = args.jitter.split('-')
            jitter = (int(start), int(end))
        else:
            jitter = (0, int(args.jitter))

    if hasattr(args, 'username') and args.username:
        for user in args.username:
            if os.path.exists(user):
                args.username.remove(user)
                args.username.append(open(user, 'r'))

    if hasattr(args, 'password') and args.password:
        for passw in args.password:
            if os.path.exists(passw):
                args.password.remove(passw)
                args.password.append(open(passw, 'r'))

    elif hasattr(args, 'hash') and args.hash:
        for ntlm_hash in args.hash:
            if os.path.exists(ntlm_hash):
                args.hash.remove(ntlm_hash)
                args.hash.append(open(ntlm_hash, 'r'))

    if hasattr(args, 'cred_id') and args.cred_id:
        for cred_id in args.cred_id:
            if '-' in str(cred_id):
                start_id, end_id = cred_id.split('-')
                try:
                    for n in range(int(start_id), int(end_id) + 1):
                        args.cred_id.append(n)
                    args.cred_id.remove(cred_id)
                except Exception as e:
                    logger.error('Error parsing database credential id: {}'.format(e))
                    sys.exit(1)

    if hasattr(args, 'target') and args.target:
        for target in args.target:
            if os.path.exists(target):
                with open(target, 'r') as target_file:
                    for target_entry in target_file:
                        targets.extend(parse_targets(target_entry))
            else:
                targets.extend(parse_targets(target))

    # The following is a quick hack for the powershell obfuscation functionality, I know this is yucky
    if hasattr(args, 'clear_obfscripts') and args.clear_obfscripts:
        shutil.rmtree(os.path.expanduser('~/.cme/obfuscated_scripts/'))
        os.mkdir(os.path.expanduser('~/.cme/obfuscated_scripts/'))
        logger.success('Cleared cached obfuscated PowerShell scripts')

    if hasattr(args, 'obfs') and args.obfs:
        powershell.obfuscate_ps_scripts = True

    p_loader = protocol_loader()
    protocol_path = p_loader.get_protocols()[args.protocol]['path']
    protocol_db_path = p_loader.get_protocols()[args.protocol]['dbpath']

    protocol_object = getattr(p_loader.load_protocol(protocol_path), args.protocol)
    protocol_db_object = getattr(p_loader.load_protocol(protocol_db_path), 'database')

    db_path = os.path.join(cme_path, 'workspaces', current_workspace, args.protocol + '.db')
    # set the database connection to autocommit w/ isolation level
    db_connection = sqlite3.connect(db_path, check_same_thread=False)
    db_connection.text_factory = str
    db_connection.isolation_level = None
    db = protocol_db_object(db_connection)

    if hasattr(args, 'module'):

        loader = module_loader(args, db, logger)

        if args.list_modules:
            modules = loader.get_modules()

            for name, props in sorted(modules.items()):
                logger.info('{:<25} {}'.format(name, props['description']))
            sys.exit(0)

        elif args.module and args.show_module_options:

            modules = loader.get_modules()
            for name, props in modules.items():
                if args.module.lower() == name.lower():
                    logger.info('{} module options:\n{}'.format(name, props['options']))
            sys.exit(0)

        elif args.module:
            modules = loader.get_modules()
            for name, props in modules.items():
                if args.module.lower() == name.lower():
                    module = loader.init_module(props['path'])
                    setattr(protocol_object, 'module', module)
                    break

            if not module:
                logger.error('Module not found')
                exit(1)

            if getattr(module, 'opsec_safe') is False:
                ans = raw_input(highlight('[!] Module is not opsec safe, are you sure you want to run this? [Y/n] ', 'red'))
                if ans.lower() not in ['y', 'yes', '']:
                    sys.exit(1)

            if getattr(module, 'multiple_hosts') is False and len(targets) > 1:
                ans = raw_input(highlight("[!] Running this module on multiple hosts doesn't really make any sense, are you sure you want to continue? [Y/n] ", 'red'))
                if ans.lower() not in ['y', 'yes', '']:
                    sys.exit(1)

            if hasattr(module, 'on_request') or hasattr(module, 'has_response'):

                if hasattr(module, 'required_server'):
                    args.server = getattr(module, 'required_server')

                if not args.server_port:
                    args.server_port = server_port_dict[args.server]

                context = Context(db, logger, args)
                module_server = CMEServer(module, context, logger, args.server_host, args.server_port, args.server)
                module_server.start()
                setattr(protocol_object, 'server', module_server.server)

    try:
        '''
            Open all the greenlet (as supposed to redlet??) threads
            Whoever came up with that name has a fetish for traffic lights
        '''
        pool = Pool(args.threads)
        jobs = []
        for target in targets:
            jobs.append(pool.spawn(protocol_object, args, db, str(target)))

            if jitter:
                value = random.choice(range(jitter[0], jitter[1]))
                logging.debug("Doin' the Jitterbug for {} seconds".format(value))
                sleep(value)

        for job in jobs:
            job.join(timeout=args.timeout)
    except KeyboardInterrupt:
        pass

    if module_server: module_server.shutdown()
Ejemplo n.º 9
0
def main():

    setup_logger()
    logger = CMEAdapter()
    first_run_setup(logger)

    args = gen_cli_args()

    if args.darrell:
        links = open(
            os.path.join(os.path.dirname(cme.__file__), 'data',
                         'videos_for_darrell.harambe')).read().splitlines()
        try:
            webbrowser.open(random.choice(links))
        except:
            sys.exit(1)

    cme_path = os.path.expanduser('~/.cme')

    config = ConfigParser()
    config.read(os.path.join(cme_path, 'cme.conf'))

    module = None
    module_server = None
    targets = []
    jitter = None
    server_port_dict = {'http': 80, 'https': 443, 'smb': 445}
    current_workspace = config.get('CME', 'workspace')

    if args.verbose:
        setup_debug_logger()

    logging.debug('Passed args:\n' + pformat(vars(args)))

    if args.jitter:
        if '-' in args.jitter:
            start, end = args.jitter.split('-')
            jitter = (int(start), int(end))
        else:
            jitter = (0, int(args.jitter))

    if hasattr(args, 'username') and args.username:
        for user in args.username:
            if os.path.exists(user):
                args.username.remove(user)
                args.username.append(open(user, 'r'))

    if hasattr(args, 'password') and args.password:
        for passw in args.password:
            if os.path.exists(passw):
                args.password.remove(passw)
                args.password.append(open(passw, 'r'))

    elif hasattr(args, 'hash') and args.hash:
        for ntlm_hash in args.hash:
            if os.path.exists(ntlm_hash):
                args.hash.remove(ntlm_hash)
                args.hash.append(open(ntlm_hash, 'r'))

    if hasattr(args, 'cred_id') and args.cred_id:
        for cred_id in args.cred_id:
            if '-' in str(cred_id):
                start_id, end_id = cred_id.split('-')
                try:
                    for n in range(int(start_id), int(end_id) + 1):
                        args.cred_id.append(n)
                    args.cred_id.remove(cred_id)
                except Exception as e:
                    logger.error(
                        'Error parsing database credential id: {}'.format(e))
                    sys.exit(1)

    if hasattr(args, 'target') and args.target:
        for target in args.target:
            if os.path.exists(target):
                with open(target, 'r') as target_file:
                    for target_entry in target_file:
                        targets.extend(parse_targets(target_entry))
            else:
                targets.extend(parse_targets(target))

    p_loader = protocol_loader()
    protocol_path = p_loader.get_protocols()[args.protocol]['path']
    protocol_db_path = p_loader.get_protocols()[args.protocol]['dbpath']

    protocol_object = getattr(p_loader.load_protocol(protocol_path),
                              args.protocol)
    protocol_db_object = getattr(p_loader.load_protocol(protocol_db_path),
                                 'database')

    db_path = os.path.join(cme_path, 'workspaces', current_workspace,
                           args.protocol + '.db')
    # set the database connection to autocommit w/ isolation level
    db_connection = sqlite3.connect(db_path, check_same_thread=False)
    db_connection.text_factory = str
    db_connection.isolation_level = None
    db = protocol_db_object(db_connection)

    if hasattr(args, 'module'):

        loader = module_loader(args, db, logger)

        if args.list_modules:
            modules = loader.get_modules()

            for m in modules:
                logger.info('{:<25} {}'.format(m, modules[m]['description']))
            sys.exit(0)

        elif args.module and args.show_module_options:

            modules = loader.get_modules()
            for m in modules.keys():
                if args.module.lower() == m.lower():
                    logger.info('{} module options:\n{}'.format(
                        m, modules[m]['options']))
            sys.exit(0)

        elif args.module:
            modules = loader.get_modules()
            for m in modules.keys():
                if args.module.lower() == m.lower():
                    module = loader.init_module(modules[m]['path'])
                    setattr(protocol_object, 'module', module)
                    break

            if not module:
                logger.error('Module not found')
                exit(1)

            if getattr(module, 'opsec_safe') is False:
                ans = raw_input(
                    highlight(
                        '[!] Module is not opsec safe, are you sure you want to run this? [Y/n]',
                        'red'))
                if ans.lower() not in ['y', 'yes', '']:
                    sys.exit(1)

            if getattr(module, 'multiple_hosts') is False and len(targets) > 1:
                ans = raw_input(
                    highlight(
                        "[!] Running this module on multiple hosts doesn't really make any sense, are you sure you want to continue? [Y/n]",
                        'red'))
                if ans.lower() not in ['y', 'yes', '']:
                    sys.exit(1)

            if hasattr(module, 'on_request') or hasattr(
                    module, 'has_response'):

                if hasattr(module, 'required_server'):
                    args.server = getattr(module, 'required_server')

                if not args.server_port:
                    args.server_port = server_port_dict[args.server]

                context = Context(db, logger, args)
                module_server = CMEServer(module, context, logger,
                                          args.server_host, args.server_port,
                                          args.server)
                module_server.start()
                setattr(protocol_object, 'server', module_server.server)

    try:
        '''
            Open all the greenlet (as supposed to redlet??) threads
            Whoever came up with that name has a fetish for traffic lights
        '''
        pool = Pool(args.threads)
        jobs = []
        for target in targets:
            jobs.append(pool.spawn(protocol_object, args, db, str(target)))

            if jitter:
                value = random.choice(range(jitter[0], jitter[1]))
                logging.debug(
                    "Doin' the Jitterbug for {} seconds".format(value))
                sleep(value)

        for job in jobs:
            job.join(timeout=args.timeout)
    except KeyboardInterrupt:
        pass

    if module_server: module_server.shutdown()
Ejemplo n.º 10
0
def gen_cli_args():

    VERSION  = '4.0.1dev'
    CODENAME = 'Bug Pr0n'

    p_loader =  protocol_loader()
    protocols = p_loader.get_protocols()

    parser = argparse.ArgumentParser(description="""
      ______ .______           ___        ______  __  ___ .___  ___.      ___      .______    _______ ___   ___  _______   ______
     /      ||   _  \         /   \      /      ||  |/  / |   \/   |     /   \     |   _  \  |   ____|\  \ /  / |   ____| /      |
    |  ,----'|  |_)  |       /  ^  \    |  ,----'|  '  /  |  \  /  |    /  ^  \    |  |_)  | |  |__    \  V  /  |  |__   |  ,----'
    |  |     |      /       /  /_\  \   |  |     |    <   |  |\/|  |   /  /_\  \   |   ___/  |   __|    >   <   |   __|  |  |
    |  `----.|  |\  \----. /  _____  \  |  `----.|  .  \  |  |  |  |  /  _____  \  |  |      |  |____  /  .  \  |  |____ |  `----.
     \______|| _| `._____|/__/     \__\  \______||__|\__\ |__|  |__| /__/     \__\ | _|      |_______|/__/ \__\ |_______| \______|

                                         A swiss army knife for pentesting networks
                                    Forged by @byt3bl33d3r using the powah of dank memes

                                                      {}: {}
                                                     {}: {}
""".format(highlight('Version', 'red'),
           highlight(VERSION),
           highlight('Codename', 'red'),
           highlight(CODENAME)),

                                    formatter_class=RawTextHelpFormatter,
                                    version='{} - {}'.format(VERSION, CODENAME),
                                    epilog="Ya feelin' a bit buggy all of a sudden?")

    parser.add_argument("-t", type=int, dest="threads", default=100, help="set how many concurrent threads to use (default: 100)")
    parser.add_argument("--timeout", default=None, type=int, help='max timeout in seconds of each thread (default: None)')
    parser.add_argument("--jitter", metavar='INTERVAL', type=str, help='sets a random delay between each connection (default: None)')
    parser.add_argument("--darrell", action='store_true', help='give Darrell a hand')
    parser.add_argument("--verbose", action='store_true', help="enable verbose output")

    subparsers = parser.add_subparsers(title='protocols', dest='protocol', description='available protocols')

    std_parser = argparse.ArgumentParser(add_help=False)
    std_parser.add_argument("target", nargs='*', type=str, help="the target IP(s), range(s), CIDR(s), hostname(s), FQDN(s), file(s) containing a list of targets, NMap XML or .Nessus file(s)")
    std_parser.add_argument('-id', metavar="CRED_ID", nargs='+', default=[], type=str, dest='cred_id', help='database credential ID(s) to use for authentication')
    std_parser.add_argument("-u", metavar="USERNAME", dest='username', nargs='+', default=[], help="username(s) or file(s) containing usernames")
    std_parser.add_argument("-p", metavar="PASSWORD", dest='password', nargs='+', default=[], help="password(s) or file(s) containing passwords")
    fail_group = std_parser.add_mutually_exclusive_group()
    fail_group.add_argument("--gfail-limit", metavar='LIMIT', type=int, help='max number of global failed login attempts')
    fail_group.add_argument("--ufail-limit", metavar='LIMIT', type=int, help='max number of failed login attempts per username')
    fail_group.add_argument("--fail-limit", metavar='LIMIT', type=int, help='max number of failed login attempts per host')

    module_parser = argparse.ArgumentParser(add_help=False)
    mgroup = module_parser.add_mutually_exclusive_group()
    mgroup.add_argument("-M", "--module", metavar='MODULE', help='module to use')
    #mgroup.add_argument('-MC','--module-chain', metavar='CHAIN_COMMAND', help='Payload module chain command string to run')
    module_parser.add_argument('-o', metavar='MODULE_OPTION', nargs='+', default=[], dest='module_options', help='module options')
    module_parser.add_argument('-L', '--list-modules', action='store_true', help='list available modules')
    module_parser.add_argument('--options', dest='show_module_options', action='store_true', help='display module options')
    module_parser.add_argument("--server", choices={'http', 'https'}, default='https', help='use the selected server (default: https)')
    module_parser.add_argument("--server-host", type=str, default='0.0.0.0', metavar='HOST', help='IP to bind the server to (default: 0.0.0.0)')
    module_parser.add_argument("--server-port", metavar='PORT', type=int, help='start the server on the specified port')

    for protocol in protocols.keys():
        protocol_object = p_loader.load_protocol(protocols[protocol]['path'])
        subparsers = getattr(protocol_object, protocol).proto_args(subparsers, std_parser, module_parser)

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    args = parser.parse_args()

    return args