def statsgen(*, wordlist: str, output: str = None, min_length:int = None, max_length: int = None, simple_masks: List[str] = None, charsets: List[str] = None, quiet: bool = True, hiderare: int = 0): #import pdb; pdb.set_trace() try: permission = [os.R_OK] Path.access(permission, wordlist) statsgen = StatsGen(wordlist = wordlist, output = output, minlength = min_length, maxlength = max_length, simplemasks = simple_masks, charsets = charsets, quiet = quiet, hiderare = hiderare) if not quiet: print(Pack.STATSGEN_BANNER) print(f"[*] Analyzing passwords in {wordlist}") statsgen.generate_stats() statsgen.print_stats() except Exception as error: print_failure(error)
def search_hashes(self, hashes_file: str, *, timeout: int, greppable: bool = False): """ search each hash in hashes_file in all the availables online cracking APIs """ #import pdb; pdb.set_trace() try: if self.enable: permission = [os.R_OK] Path.access(permission, hashes_file) sth_cmd = f"{self.main_exec} --no-banner --accessible" if isinstance(timeout, int) and timeout > 0: sth_cmd += f"--timeout {timeout}" sth_cmd += f" --file {hashes_file}" print_status( f"Searching hashes in {hashes_file} file in availables online cracking APIs" ) Bash.exec(sth_cmd) else: print_failure("Auxliary plugin {self.main_name} is disable") except Exception as error: print_failure(error)
def main(): try: parser = amadb_parser() args = parser.parse_args() workspace = args.workspace credentials_file = Path(args.creds_file) cracker = args.cracker if args.insert_hashes and cracker in [John.MAINNAME, Hashcat.MAINNAME]: hashes_file = Path(args.insert_hashes) if cracker == John.MAINNAME: John.insert_hashes_to_db(hashes_file, workspace, credentials_file) elif cracker == Hashcat.MAINNAME: Hashcat.insert_hashes_to_db(hashes_file, workspace, credentials_file) elif args.insert_hashes and cracker not in [ John.MAINNAME, Hashcat.MAINNAME ]: raise Exception(f"Cracker {args.cracker} doesn't crack hashes") if args.insert_services: print_status("Please, implement me") #services_file = Path(args.insert_hashes) except Exception as error: print_failure(error)
def hash_status(query_hash: str, potfile: str = None): """ Check the status (broken by Hashcat or not) of query hash Return: if query_hash is in potfile then [HASHTYPE, HASH, PASSWORD] list is returned otherwise None is returned """ #import pdb;pdb.set_trace() if potfile is None: HOME = Path.home() potfile = Path.joinpath(HOME, ".hashcat/hashcat.potfile") try: permission = [os.R_OK] Path.access(permission, potfile) cracked_pattern = re.compile(rf"({query_hash}):(\W*|\w*|.*)", re.DOTALL) with open(potfile, 'r') as hashcat_potfile: while cracked_hash := hashcat_potfile.readline().rstrip(): if cracked_hashpot := cracked_pattern.fullmatch( cracked_hash): hashpot = cracked_hashpot.groups() return CrackedHash(cracked_hash=hashpot[0], password=hashpot[1], cracker=Hashcat)
def do_read(self, args): """ Read a backup file and set options of a module """ #import pdb; pdb.set_trace() try: selectedModule = self._cmd.selectedModule if not selectedModule: raise Exception("No module selected") backup_file = Path(args.backup) permission = [os.R_OK] Path.access(permission, backup_file) print_status( f"Reading {ColorStr(backup_file).StyleBRIGHT} backup file and setting {ColorStr(selectedModule.MNAME).StyleBRIGHT} options" ) with open(backup_file, 'r') as backup: while setv_cmd := backup.readline(): setv_cmd = setv_cmd.rstrip() split_setv_cmd = setv_cmd.split(' ') if len( split_setv_cmd ) == 4: # this options is of a pre/post attack module setv, helper, option, value = split_setv_cmd if helper in ["-pre", "--preattack"]: if isinstance(selectedModule, Attack): selectedModule.setv(option, value, pre_attack=True) else: print_failure( f"Unable to run {setv_cmd} command. Auxiliary modules have not PreAttack modules" ) elif helper in ["-post", "--postattack"]: if isinstance(selectedModule, Attack): selectedModule.setv(option, value, post_attack=True) else: print_failure( f"Unable to run {setv_cmd} command. Auxiliary modules have not PostAttack modules" ) else: print_failure("Unknown helper module") elif len(split_setv_cmd ) == 3: # this options is of the main module setv, option, value = split_setv_cmd selectedModule.setv(option, value) else: print_failure(f"Invalid command : {setv_cmd}") except Exception as error: print_failure(error)
def maskgen(*, statsgen_output: str, output: str, min_length: int = None, max_length: int = None, target_time: int = None, min_time:int = None, max_time:int = None, min_complexity: int = None, max_complexity: int = None, min_occurrence: int = None, max_occurrence: int = None, sorting:str = "optindex", check_masks: List[str] = None, check_masks_file: str = None, show_masks: bool = False, quiet: bool = True): #import pdb; pdb.set_trace() try: permission = [os.R_OK] Path.access(permission, statsgen_output) if not quiet: print(Pack.MASKGEN_BANNER) print(f"[*] Analyzing masks in {statsgen_output}") pps = 1000000000 maskgen = MaskGen( target_time = target_time, output_file = output, minlength = min_length, maxlength = max_length, mintime = min_time, maxtime = max_time, mincomplexity = min_complexity, maxcomplexity = max_complexity, minoccurrence = min_occurrence, maxoccurrence = max_occurrence, showmasks = show_masks ) print("[*] Using {:,d} keys/sec for calculations.".format(pps)) # Load masks maskgen.loadmasks(statsgen_output) # Matching masks from the command-line if check_masks: print(f"[*] Checking coverage of the these masks [{', '.join(check_masks)}]") maskgen.getmaskscoverage(check_masks) # Matching masks from a file elif check_masks_file: checkmasksfile = open(check_masks_file, 'r') print("[*] Checking coverage of masks in [%s]" % check_masks_file) maskgen.getmaskscoverage(checkmasksfile) else:# Printing masks in a file print("[*] Sorting masks by their [%s]." % sorting) maskgen.generate_masks(sorting) except Exception as error: print_failure(error)
def wholegen(*, wordlist: str, output: str, charsets: List[str] = None, minlength: int = None, maxlength: int = None, mindigit:int = None, maxdigit:int = None, minupper:int = None, maxupper:int = None, minlower:int = None, maxlower:int = None, minspecial:int = None, maxspecial:int = None, mincomplexity:int = None, maxcomplexity:int = None, minoccurrence:int = None, maxoccurrence:int = None, mintime:int = None, maxtime:int = None, target_time:int = None, hiderare: int = 0, showmasks:bool = False, quiet: bool = False, sorting = "optindex"): #import pdb; pdb.set_trace() try: permission = [os.R_OK] Path.access(permission, wordlist) print(f"[*] Analyzing passwords in {wordlist}") whole = WholeGen( wordlist = wordlist, output = output, charsets = charsets, minlength = minlength, maxlength = maxlength, mindigit = mindigit, maxdigit = maxdigit, minupper = minupper, maxupper = maxupper, minlower = minlower, maxlower = maxlower, minspecial = minspecial, maxspecial = maxspecial, mincomplexity = mincomplexity, maxcomplexity = maxcomplexity, minoccurrence = minoccurrence, maxoccurrence = maxoccurrence, mintime = mintime, maxtime = maxtime, target_time = target_time, hiderare = hiderare, showmasks = showmasks, quiet = quiet) whole.full_analysis(sorting) except Exception as error: print_failure(error)
def get_ama_configurations(ama_config:Path): configurations = None with open(ama_config) as config: configurations = json.load(config) if db_credentials := configurations["db_credentials_file"]: configurations["db_credentials_file"] = Path(db_credentials)
def dbCreds(dbconfig: Path): #import pdb; pdb.set_trace() db_credentials = None try: dbconfig_file = dbconfig.expanduser() permission = [os.R_OK] Path.access(permission, dbconfig_file) db_credentials = None with open(dbconfig_file, 'r') as credentials_json: db_credentials = json.load(credentials_json) return db_credentials except Exception as error: print_failure(error)
def array_masks(self, masks_file:Path, ARRAY:int): """ distribute masks_file into ARRAY masks file e.g. if weak.hcmasks has 215 masks and ARRAY=4, then array_masks split weak.hcmasks in weak0.hcmasks, weak1.hcmasks, weak2.hcmasks and weak3.hcmasks where weak0-2.hcmasks have 215/4 ~ 53 masks and weak3.hcmasks (the rest of masks) """ #import pdb; pdb.set_trace() base_path = masks_file.parent name_masks_file = masks_file.name suffix = masks_file.suffix only_name_masks_file = name_masks_file[:-len(suffix)] nmasks = line_counter(masks_file) with open(masks_file, 'r') as masks: for a in range(ARRAY): INIT = ceil(nmasks/ARRAY)*a if a == (ARRAY - 1): END = nmasks else: END = ceil(nmasks/ARRAY)*(a+1) name_split_masks_file = only_name_masks_file + str(a) + suffix split_masks_file = Path.joinpath(base_path, name_split_masks_file) with open(split_masks_file, 'w') as split_masks: k = INIT mask = masks.readline() while mask and k < END: split_masks.write(mask) k += 1 if k < END: mask = masks.readline()
def init_ama_config(): #import pdb;pdb.set_trace() ama_config_file = Path.joinpath(AMA_HOME, 'config/ama.json') database_credentials = Path.joinpath(AMA_HOME, 'db/database.json') configurations = { 'db_credentials_file': str(database_credentials), 'slurm_conf_file': None, 'john': None, 'hashcat': None } with open(ama_config_file, 'w') as config: json.dump(configurations, config, indent=4) print_successful( f"Configuration file has been created: {ColorStr(ama_config_file).StyleBRIGHT}" )
def find_slurm_config(): """ Parse slurm.conf file to get the configurations (IP4s of nodes, partitions, nodes resources) force[bool] :force parsing even when slurm_conf file wasn't supplied, searching 'slurm.conf' file in POSSIBLE_SLURM_PATH """ POSSIBLE_SLURM_PATH = [Path('/etc/slurm-llnl'), Path('/etc/slurm')] slurm_conf = 'slurm.conf' for slurm_path in POSSIBLE_SLURM_PATH: if slurm_path.exists(): for base, dirs, files in os.walk(slurm_path): if slurm_conf in files: return os.path.join(base, slurm_conf) return None
def attack(self, *, local=False, pre_attack_output: Any = None, db_status: bool = False, workspace: str = None, db_credential_file: Path = None, cracker_main_exec: Path = None, slurm_conf=None): """ Masks attack using John the Ripper Args: local (bool): try to perform the attack locally """ #import pdb; pdb.set_trace() try: self.no_empty_required_options(local) if slurm_conf: self.slurm.config = slurm_conf if cracker_main_exec: jtr = John(john_exec=cracker_main_exec) else: jtr = John() hash_types = self.options['hash_type'].value.split(',') hashes_file = Path(self.options['hashes_file'].value) masks_file = Path(self.options['masks_file'].value) jtr.masks_attack(hash_types=hash_types, hashes_file=hashes_file, masks_file=masks_file, slurm=self.slurm, local=local, db_status=db_status, workspace=workspace, db_credential_file=db_credential_file) except Exception as error: print_failure(error)
def __init__( self, name, base_path, inside_dirs=[], # list of inside directories (strings) inside_files=[], # list of inside files (string) filesStructs=[] ): # list of inside files structs (instances of FilesStruct) self.base_path = Path(base_path) self.path = Path.joinpath(self.base_path, name) #list of FilesStruct instances self.inside_dirs = [ Path.joinpath(self.path, inside_dir) for inside_dir in inside_dirs ] #list of Path instances self.inside_files = [ Path.joinpath(self.path, inside_file) for inside_file in inside_files ] self.filesStructs = filesStructs
def hashes_file_status(query_hashes_file: Path, potfile=None): """ Check the status (broken by John or not) of hashes in query_hashes_file and return the cracked and uncracked hashes """ #import pdb; pdb.set_trace() hashes_status = {'cracked': [], "uncracked": []} if potfile is None: HOME = Path.home() potfile = Path.joinpath(HOME, ".hashcat/hashcat.potfile") try: permission = [os.R_OK] Path.access(permission, potfile, query_hashes_file) with open(query_hashes_file, 'r') as hashes_file: while query_hash := hashes_file.readline().rstrip(): if cracker_hash := Hashcat.hash_status(query_hash): hashes_status['cracked'].append( cracker_hash.get_loot()) else: #crackedHash is uncracked
def improve_wordlist(self, *, wordlist: str, quiet=False): """ Cupp - improve a wordlist """ #import pdb; pdb.set_trace() if self.enable: CONFIG = self.CONFIG try: permission = [os.R_OK] Path.access(permission, wordlist) if not quiet: cupp.print_cow() improved_wordlist = cupp.improve_dictionary(wordlist) return improved_wordlist except Exception as error: print_failure(error) else: print_failure("Auxiliary application {self.main_name} is disable") return None
def init_db_connection(self): db_conn = None #import pdb; pdb.set_trace() try: db_credentials = Path(self.config.get("db_credentials_file")) dbCredentials = Connection.dbCreds(db_credentials) db_conn = psycopg2.connect(**dbCredentials) del dbCredentials except Exception as error: print_failure(error) #print_failure("Error while connecting to database") finally: return db_conn
class Ama(Cmd): """ CLI App to interact with ama-framework """ # CORE_CATEGORY = Category.CORE # MODULE_CATEGORY = Category.MODULE # DB_CATEGORY = Category.DB # SLURM_CATEGORY = Category.SLURM AMA_HOME = AMA_HOME def __init__(self, ama_config:Path = Path.joinpath(AMA_HOME, 'config/ama.json')): super().__init__(use_ipython=True) self.debug = True self.intro = Banner.random() self.prompt = "ama > " self.continuation_prompt = "> " self.default_category = Category.CORE self.config = Ama.get_ama_configurations(ama_config) self.db_conn = self.init_db_connection() self.workspace = "default" # selected workspace # ama configuration (slurm.conf path, dbcreds path, john and hashcat executable path) self.modules = amaModules # format {NAME: MODULE_CLASS, ....} self.selectedModule = None # selected module with 'use' command (Instance of the module) self.filteredModules = [] # filtered modules(format: [(#, MODULE_CLASS), ...]) self.gvalues = {} # global values(format {OPTION_NAME: OPTION_VALUE, ...}) self.slurm_config = self.init_slurm_config() #import pdb; pdb.set_trace() @staticmethod def get_ama_configurations(ama_config:Path): configurations = None with open(ama_config) as config: configurations = json.load(config) if db_credentials := configurations["db_credentials_file"]: configurations["db_credentials_file"] = Path(db_credentials) if slurm_conf_file := configurations["slurm_conf_file"]: configurations["slurm_conf_file"] = Path(slurm_conf_file)
def __init__(self, ama_config:Path = Path.joinpath(AMA_HOME, 'config/ama.json')): super().__init__(use_ipython=True) self.debug = True self.intro = Banner.random() self.prompt = "ama > " self.continuation_prompt = "> " self.default_category = Category.CORE self.config = Ama.get_ama_configurations(ama_config) self.db_conn = self.init_db_connection() self.workspace = "default" # selected workspace # ama configuration (slurm.conf path, dbcreds path, john and hashcat executable path) self.modules = amaModules # format {NAME: MODULE_CLASS, ....} self.selectedModule = None # selected module with 'use' command (Instance of the module) self.filteredModules = [] # filtered modules(format: [(#, MODULE_CLASS), ...]) self.gvalues = {} # global values(format {OPTION_NAME: OPTION_VALUE, ...}) self.slurm_config = self.init_slurm_config()
def wordlist_attack(self, *, user=None, users_file=None, passwd=None, passwd_file=None, users_passwd_file=None, port=None, ip4=True, output=None, output_format=None, verbose=True, stopInSuccess=False, stopInSuccessPerTarget=True, targets_file=None, target=None, service=None, slurm=None): """ Perform a wordlist attack against services using hydra submiting parallel task in a cluster using slurm. Args: user (str): None, users_file (str): None, passwd_file (str): None, users_passwd_file (str): None, port (str): None, ip4 (str): True, output=None, output_format=None, verbose=True, stopInSucess=False, stopInSucessPerTarget=True, targets_file=None, target=None, service=None slurm = None """ #import pdb; pdb.set_trace() if self.enable: try: # validation of data Args.not_none(service) Args.some_not_none(user, users_file) Args.some_not_none(passwd, passwd_file, users_passwd_file) Args.some_not_none(target, targets_file) permission = [os.R_OK] Hydra.checkService(service) #cmd2.Cmd.poutput(f"Attacking {service} service of {target} target with {wordlist} wordlist.") #print_failure(f"Attacking {service} service of {target} target with {wordlist} wordlist.") attack_cmd = f"{self.main_exec}" # user and password flags if users_passwd_file: Path.access(permission, users_passwd_file) attack_cmd += f" -C {users_passwd_file}" else: # user if user: attack_cmd += f" -l {user}" else: # use userFile as users file Path.access(permission, users_file) attack_cmd += f" -L {users_file}" # passwords if passwd: attack_cmd += f" -p {passwd}" else: # passwd_file is not None Path.access(permission, passwd_file) attack_cmd += f" -P {passwd_file}" # port if port: attack_cmd += f" -s {port}" # output if output: attack_cmd += f" -o {output}" # ip version if ip4: attack_cmd += " -4" else: # ipv6 attack_cmd += " -6" # verbose if verbose: attack_cmd += " -V" # exit if success if stopInSuccessPerTarget: attack_cmd += " -f" if stopInSuccess: attack_cmd += " -F" # target if targets_file: Path.access(permission, targets_file) attack_cmd += f" -M {targets_file}" else: # simple target attack_cmd += f" {target}" # service attack_cmd += f" {service}" if slurm.partition: parallel_job_type = slurm.parallel_job_parser() if not parallel_job_type in ["OMP"]: raise InvalidParallelJob(parallel_job_type) parallel_work = [attack_cmd] batch_script_name = slurm.gen_batch_script(parallel_work) Bash.exec(f"sbatch {batch_script_name}") else: Bash.exec(attack_cmd) except Exception as error: #cmd2.Cmd.pexcept(error) print_failure(error) else: #cmd2.Cmd.pwarning(f"Cracker {self.main_name} is disable") print_failure(f"Cracker {self.main_name} is disable")
def spider(self, url: str, *, depth: int = 2, min_length: int = 3, offsite: bool = False, exclude: str = None, allowed: str = None, write: str = None, lowercase: bool = False, with_numbers: bool = False, convert_umlauts: bool = True, meta: bool = False, meta_file: str = None, email: bool = False, email_file: str = None, count: bool = False, verbose: bool = True, debug: bool = False): #import pdb; pdb.set_trace() try: permission = [os.R_OK] cewl_cmd = f"{self.main_exec} --depth {depth} --min_word_length {min_length}" if offsite: cewl_cmd += " --offsite" if exclude: Path.access(permission, exclude) cewl_cmd += f" --exclude {exclude}" if allowed: cewl_cmd += f" --allowed {allowed}" if write: cewl_cmd += f" --write {write}" if lowercase: cewl_cmd += " --lowercase" if with_numbers: cewl_cmd += " --with_numbers" if convert_umlauts: cewl_cmd += " --convert-umlauts" if meta: if meta_file: Path.access(permission, meta_file) cewl_cmd += f" --meta --meta_file {meta_file}" else: raise Exception( "meta option enable, but meta_file not supplied") if email: if email_file: Path.access(permission, email_file) cewl_cmd += f" --email --email_file {email_file}" else: raise Exception( "email option enable, but email_file not supplied") if count: cewl_cmd += " --count" if verbose: cewl_cmd += " --verbose" if debug: cewl_cmd += " --debug" cewl_cmd += f" {url}" print_status(f"Running: {cewl_cmd}") Bash.exec(cewl_cmd) except Exception as error: print_failure(error)
def hybrid_attack(self, *, hash_types: List[str], hashes_file: str, inverse: bool = False, wordlists: List[str], masks: List[str] = None, masks_file: Path = None, sleep: int = 1, slurm: Slurm, local: bool = False, db_status: bool = False, workspace: str = None, db_credential_file: Path = None): """ hybrid attack using hashcat submiting parallel tasks in a cluster with Slurm Args: hash_type (str): Hashcat's hash type hashes_file (str): Hash file to attack inverse (bool): If inverse is false the attack combine WORDLISTS + MASKS, otherwise it combine MASKS + WORDLISTS wordlists (List[str]): wordlists to attack masks (List[str]): masks to attack masks_file (str): masks file to attack slurm (Slurm): Instance of Slurm class """ #import pdb; pdb.set_trace() if self.enable: try: if not inverse: attack_mode = 6 else: attack_mode = 7 permission = [os.R_OK] Path.access(permission, hashes_file, *wordlists) Hashcat.check_hash_type(hash_types) if masks and masks_file: raise Exception("Only supplied masks or a masks file") elif masks: valid_masks = [] for mask in masks: if Mask.is_mask(mask): valid_masks.append(mask) if not valid_masks: raise Exception("No valid masks supplied") masks = valid_masks else: # masks_file supplied Path.access(permission, masks_file) masks = [] with open(masks_file, 'r') as _masks_file: while mask := _masks_file.readline().rstrip(): if Mask.is_mask(mask): masks.append(mask) if not inverse: print_status( f"Attacking hashes in {ColorStr(hashes_file).StyleBRIGHT} file in hibrid mode {ColorStr('WORDLISTS + MASKS').StyleBRIGHT} " ) else: print_status( f"Attacking hashes in {ColorStr(hashes_file).StyleBRIGHT} file in hibrid mode {ColorStr('MASKS + WORDLISTS').StyleBRIGHT}" ) print_status(f"Wordlists: {ColorStr(wordlists).StyleBRIGHT}") if masks and masks_file is None: print_status(f"Masks: {ColorStr(masks).StyleBRIGHT}") else: print_status( f"Masks file: {ColorStr(masks_file).StyleBRIGHT}") hash_types_names = [ Hashcat.HASHES[hash_type]['Name'] for hash_type in hash_types ] print_status( f"Possible hashes identities: {ColorStr(hash_types_names).StyleBRIGHT}" ) #import pdb; pdb.set_trace() if (not local) and slurm and slurm.partition: parallel_job_type = slurm.parallel_job_parser() if not parallel_job_type in ["GPU"]: raise InvalidParallelJob(parallel_job_type) parallel_work = [] for hash_type in hash_types: for wordlist in wordlists: for mask in masks: if not inverse: attack_cmd = ( f"{self.main_exec}" f" -a {attack_mode}" f" -m {hash_type}" f" {hashes_file} {wordlist} {mask}") else: attack_cmd = ( f"{self.main_exec}" f" -a {attack_mode}" f" -m {hash_type}" f" {hashes_file} {mask} {wordlist}") header_attack = f"echo -e '\\n\\n[*] Running: {attack_cmd}'" if db_status and workspace and db_credential_file: insert_cracked_hashes = ( f"amadb -c {db_credential_file} -w {workspace}" f" --cracker {Hashcat.MAINNAME} -j {hashes_file}" ) parallel_work.append( (header_attack, attack_cmd, insert_cracked_hashes)) else: parallel_work.append( (header_attack, attack_cmd)) slurm_script_name = slurm.gen_batch_script(parallel_work) #import pdb; pdb.set_trace() Bash.exec(f"sbatch {slurm_script_name}") else: #import pdb; pdb.set_trace() all_cracked = False for hash_type in hash_types: for wordlist in wordlists: for mask in masks: all_cracked = Hashcat.are_all_hashes_cracked( hashes_file) if not all_cracked: # some hash isn't cracked yet if not inverse: attack_cmd = ( f"{self.main_exec}" f" -a {attack_mode}" f" -m {hash_type}" f" {hashes_file} {wordlist} {mask}" ) else: attack_cmd = ( f"{self.main_exec}" f" -a {attack_mode}" f" -m {hash_type}" f" {hashes_file} {mask} {wordlist}" ) print() print_status( f"Running: {ColorStr(attack_cmd).StyleBRIGHT}" ) Bash.exec(attack_cmd) if sleep > 0: print_status( f"{ColorStr('Sleeping ...').StyleBRIGHT}" ) time.sleep(sleep) else: print_successful( f"Hashes in {ColorStr(hashes_file).StyleBRIGHT} were cracked" ) break if all_cracked: break if all_cracked: break #import pdb; pdb.set_trace() if db_status and workspace and db_credential_file: Hashcat.insert_hashes_to_db(hashes_file, workspace, db_credential_file) except Exception as error: print_failure(error)
#import pdb;pdb.set_trace() if not self.path.exists(): self.path.mkdir() for directory in self.inside_dirs: if not directory.exists(): directory.mkdir() for inside_file in self.inside_files: if not inside_file.exists(): inside_file.touch() for filesStruct in self.filesStructs: filesStruct.create() USER_HOME = Path.home() AMA_HOME = Path.joinpath(USER_HOME, '.ama') def create_ama_home(base_path: Path = USER_HOME): """ create ama-framework home file structure """ #import pdb;pdb.set_trace() ama_home = FilesStruct('.ama', base_path=base_path) BASE_PATH = ama_home.path ama_db = FilesStruct('db', base_path=BASE_PATH, inside_files=['database.json'])
def brute_force_attack(self, *, hash_types: str, hashes_file: str, mask: str, sleep: int = 1, slurm: Slurm, local: bool = False, db_status: bool = False, workspace: str = None, db_credential_file: Path = None): """ Brute force attack using hashcat submiting parallel tasks in a cluster with Slurm Args: hash_type (str): Hashcat's hash type hashes_file (str): Hash file to attack mask (str): mask to attack slurm (Slurm): Instance of Slurm class """ #import pdb; pdb.set_trace() if self.enable: try: attack_mode = 3 permission = [os.R_OK] Mask.is_valid_mask(mask) Path.access(permission, hashes_file) Hashcat.check_hash_type(hash_types) print_status( f"Attacking hashes in {ColorStr(hashes_file).StyleBRIGHT} file with {ColorStr(mask).StyleBRIGHT} mask" ) hash_types_names = [ Hashcat.HASHES[hash_type]['Name'] for hash_type in hash_types ] print_status( f"Possible hashes identities: {ColorStr(hash_types_names).StyleBRIGHT}" ) if (not local) and slurm and slurm.partition: parallel_job_type = slurm.parallel_job_parser() if not parallel_job_type in ["GPU"]: raise InvalidParallelJob(parallel_job_type) parallel_work = [] for hash_type in hash_types: attack_cmd = (f"srun {self.main_exec}" f" -a {attack_mode}" f" -m {hash_type}" f" {hashes_file} {mask}") header_attack = f"echo -e '\\n\\n[*] Running: {attack_cmd}'" if db_status and workspace and db_credential_file: insert_cracked_hashes = ( f"amadb -c {db_credential_file} -w {workspace}" f" --cracker {Hashcat.MAINNAME} -j {hashes_file}" ) parallel_work.append((header_attack, attack_cmd, insert_cracked_hashes)) else: parallel_work.append((header_attack, attack_cmd)) slurm_script_name = slurm.gen_batch_script(parallel_work) #import pdb;pdb.set_trace() Bash.exec(f"sbatch {slurm_script_name}") else: #import pdb;pdb.set_trace() for hash_type in hash_types: are_all_hashes_cracked = Hashcat.are_all_hashes_cracked( hashes_file) if not are_all_hashes_cracked: # some hash isn't cracked yet attack_cmd = (f"{self.main_exec}" f" -a {attack_mode}" f" -m {hash_type}" f" {hashes_file} {mask}") print() print_status( f"Running: {ColorStr(attack_cmd).StyleBRIGHT}") Bash.exec(attack_cmd) if sleep > 0: print_status( f"{ColorStr('Sleeping ...').StyleBRIGHT}") time.sleep(sleep) else: print_successful( f"Hashes in {ColorStr(hashes_file).StyleBRIGHT} were cracked" ) break #import pdb;pdb.set_trace() if db_status and workspace and db_credential_file: Hashcat.insert_hashes_to_db(hashes_file, workspace, db_credential_file) except Exception as error: print_failure(error) else: print_failure( f"Cracker {ColorStr(self.main_name).StyleBRIGHT} is disable")
def attack(self, *, local:bool = False, force:bool = False, pre_attack_output: Any = None, db_status:bool = False, workspace:str = None, db_credential_file: Path = None, cracker_main_exec:Path = None): """ Hybrid Attack using hashcat cracker """ #import pdb; pdb.set_trace() try: if not force: self.no_empty_required_options(local) if cracker_main_exec: hc = Hashcat(hashcat_exec=cracker_main_exec) else: hc = Hashcat() hash_type = None if isinstance(self.options['hash_type'].value, int): hash_types = [self.options['hash_type'].value] elif isinstance(self.options['hash_type'].value, str): hash_types = [int(hash_type) for hash_type in self.options['hash_type'].value.split(',')] else: raise TypeError(f"Invalid type hash_type: {type(hash_type)}") wordlists = [wordlist.strip() for wordlist in self.options['wordlists'].value.split(',')] masks = self.options['masks'].value if os.path.isfile(masks) and os.access(masks, os.R_OK): #a masks file was supplied masks_file = Path(masks) hc.hybrid_attack( hash_types = hash_types, hashes_file = self.options['hashes_file'].value, inverse = self.options['inverse'].value, wordlists = wordlists, masks_file = masks_file, sleep = self.options['sleep'].value, slurm = self.slurm, local = local, db_status= db_status, workspace= workspace, db_credential_file=db_credential_file) else: masks = [mask.strip() for mask in masks.split(',')] hc.hybrid_attack( hash_types = hash_types, hashes_file = self.options['hashes_file'].value, inverse = self.options['inverse'].value, wordlists = wordlists, masks = masks, sleep = self.options['sleep'].value, slurm = self.slurm, local = local, db_status= db_status, workspace= workspace, db_credential_file=db_credential_file) except Exception as error: print_failure(error)
def initDB(dbName="ama", roleName="attacker"): """ Database initialization (creation of database, role, and initialization of default workspace) """ try: #cmd2.Cmd.poutput(f"Creating {roleName} role") print_status(f"Creating role: {ColorStr(roleName).StyleBRIGHT}") password = getpass( prompt= f"Password for {ColorStr(roleName).StyleBRIGHT} role (empty for random generation): " ) if not password: passwd = PasswordGenerator() passwd.minlen = 16 passwd.maxlen = 16 passwd.minnumbers = 2 passwd.minschars = 3 passwd.minuchars = 2 password = passwd.generate() Bash.exec( f"psql -U postgres -c \"CREATE ROLE {roleName} WITH LOGIN CREATEDB PASSWORD '{password}'\"", quiet=True) Bash.exec( f"psql -U postgres -c \"CREATE DATABASE {roleName} OWNER {roleName}\"", quiet=True) #cmd2.Cmd.poutput(f"Role {roleName} has been created") print_successful( f"Role {ColorStr(roleName).StyleBRIGHT} has been created") #cmd2.Cmd.poutput(f"Creating {dbName} database") print_status(f"Creating {ColorStr(dbName).StyleBRIGHT} database") Bash.exec( f"psql -U {roleName} -c \"CREATE DATABASE {dbName} OWNER {roleName}\"", quiet=True) #cmd2.Cmd.poutput("Database {dbName} has been created") # creation workspaces table dbCredential = { 'host': 'localhost', 'database': dbName, 'user': roleName, 'password': password } workspace = "default" tablesCreation = (""" CREATE TABLE IF NOT EXISTS workspaces ( name VARCHAR (100) UNIQUE NOT NULL ) """, f""" CREATE TABLE IF NOT EXISTS hashes_{workspace} ( hash VARCHAR (128) UNIQUE NOT NULL, type VARCHAR (20), cracker VARCHAR (20) NOT NULL, password VARCHAR (32) NOT NULL ) """, f""" CREATE TABLE IF NOT EXISTS services_{workspace} ( service VARCHAR (20) NOT NULL, target VARCHAR (15) NOT NULL, service_user VARCHAR (20) NOT NULL, password VARCHAR (32) NOT NULL ) """) valueInsert = (""" INSERT INTO workspaces (name) VALUES (%s); """) conn = None conn = psycopg2.connect(**dbCredential) cur = conn.cursor() # workspace table creation and # hashes and services tables creation for "default" workspace for cmdTable in tablesCreation: cur.execute(cmdTable) conn.commit() # default workspace insertion cur.execute(valueInsert, (workspace, )) conn.commit() cur.close() print_successful( f"Database {ColorStr(dbName).StyleBRIGHT} has been created") #import pdb; pdb.set_trace() # writing credential to AMA_HOME/db/database.json file database_json_file = Path.joinpath(AMA_HOME, 'db/database.json') with open(database_json_file, 'w') as db_credentials: json.dump(dbCredential, db_credentials, indent=4) print_successful( f"Database credential file has been created: {ColorStr(database_json_file).StyleBRIGHT}" ) del dbCredential except (Exception, psycopg2.DatabaseError) as error: print_failure(error)
def masks_attack(self, *, hash_types: List[int], hashes_file: str, masks_file: str, masks_attack_script: str, sleep: int = 1, slurm: Slurm, local: bool = False, db_status: bool = False, workspace: str = None, db_credential_file: Path = None): """ Masks attack using hashcat submitting parallel tasks in a cluster with Slurm Args: hash_type (str): Jonh's hash type hashes_file (str): Hash file to attack masks_file (str): Masks file to attack slurm (Slurm): Instance of Slurm class """ #import pdb; pdb.set_trace() if self.enable: try: attack_mode = 3 permission = [os.R_OK] Path.access(permission, hashes_file, masks_file) Hashcat.check_hash_type(hash_types) print_status( f"Attacking hashes in {ColorStr(hashes_file).StyleBRIGHT} file with {ColorStr(masks_file).StyleBRIGHT} masks file." ) hash_types_names = [ Hashcat.HASHES[hash_type]['Name'] for hash_type in hash_types ] print_status( f"Possible hashes identities: {ColorStr(hash_types_names).StyleBRIGHT}" ) if (not local) and slurm and slurm.partition: Hashcat.gen_masks_attack( hash_types=hash_types, hashes_file=hashes_file, masks_file=masks_file, masks_attack_script=masks_attack_script, slurm=slurm, db_status=db_status, workspace=workspace, db_credential_file=db_credential_file) parallel_work = [(f"python3 {masks_attack_script}", )] slurm_script_name = slurm.gen_batch_script(parallel_work) #import pdb; pdb.set_trace() Bash.exec(f"sbatch {slurm_script_name}") else: #import pdb; pdb.set_trace() all_cracked = False for hash_type in hash_types: with open(masks_file, 'r') as masks: while mask := masks.readline().rstrip(): if not Mask.is_mask(mask): print_failure("Invalid mask: {mask}") break all_cracked = Hashcat.are_all_hashes_cracked( hashes_file) if not all_cracked: attack_cmd = (f"{self.main_exec}" f" -a {attack_mode}" f" -m {hash_type}" f" {hashes_file} {mask}") print() print_status( f"Running: {ColorStr(attack_cmd).StyleBRIGHT}" ) Bash.exec(attack_cmd) if sleep > 0: print_status( f"{ColorStr('Sleeping ...').StyleBRIGHT}" ) time.sleep(sleep) else: break #all hashes were cracked so stop attack if all_cracked := Hashcat.are_all_hashes_cracked( hashes_file): print_successful( f"Hashes in {ColorStr(hashes_file).StyleBRIGHT} were cracked" ) break #import pdb; pdb.set_trace() if db_status and workspace and db_credential_file: Hashcat.insert_hashes_to_db(hashes_file, workspace, db_credential_file)