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)
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)
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)
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
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
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()
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))
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()
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()
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