def benchmark(self, slurm=None): """ Run john benchmark """ #import pdb; pdb.set_trace() if self.enable: #cmd2.Cmd.poutput(f"Performing John Benchmark.") #print_status(f"Performing John Benchmark.") if slurm and slurm.partition: parallel_job_type = slurm.parallel_job_parser() if not parallel_job_type in ["MPI", "OMP"]: raise InvalidParallelJob(parallel_job_type) attack_cmd = f"{self.main_exec} --test" if parallel_job_type == "MPI": attack_cmd = f"srun --mpi={slurm.pmix} " + attack_cmd elif parallel_job_type == "OMP": attack_cmd = f"srun " + attack_cmd header_attack = f"echo -e \"\\n\\n[*] Running: {attack_cmd}\"" parallel_work = [(header_attack, attack_cmd)] batch_script_name = slurm.gen_batch_script(parallel_work) Bash.exec(f"sbatch {batch_script_name}") else: attack_cmd = f"{self.main_exec} --test" print_status("Running: {ColorStr(attack_cmd).StyleBRIGHT}") Bash.exec(attack_cmd) else: print_failure(f"Cracker {ColorStr(self.main_name).StyleBRIGHT} is disable")
def benchmark(self, slurm, local: bool = False): """ Hashcat benchmark """ #import pdb; pdb.set_trace() if self.enable: 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) #core, extra = slurm.parameters() attack_cmd = f"srun {self.main_exec} -b" header_attack = f"echo -e '\\n\\n[*] Running: {attack_cmd}'" parallel_work = [(header_attack, attack_cmd)] batch_script_name = slurm.gen_batch_script(parallel_work) Bash.exec(f"sbatch {batch_script_name}") else: attack_cmd = f"{self.main_exec} -b" print_status(f"Running: {ColorStr(attack_cmd).StyleBRIGHT}") Bash.exec(attack_cmd) else: print_failure( f"Cracker {ColorStr(self.main_name).StyleBRIGHT} is disable")
def hybridAttack(self, *, hashType, hashesFile, wordlist, masksFile, slurm=None, inverse=False): """ hybrid attack Combine wordlist + masks file (by default, when inverse=False) in other file and perform a wordlist attack with that file, if inverse=True combine masks file + wordlist """ print_status(f"Attacking {hashType} hashes in {hashFile} file with an hybrid MFW attack.") hybridWordlist = "hybrid.txt" if Mask.isMask(masksFile): # masksFile is a simple mask wordlist = wordlist[0] mask = masksFile with open(hybridWordlist, 'w') as outputFile: Combinator.genHybridWM(wordlist, mask , outputFile, inverse=False) print_successful(f"Combinated wordlist and mask was generated: {hybridWordlist}") else: wordlist = wordlist[0] Combinator.hybridWMF(wordlist = wordlist, masksFile = masksFile, output = hybridWordlist) JTRAttacks.wordlist(hashType = hashType, hashFile = hashFile, wordlist = hybridWordlist, hpc = hpc)
def search_hash(self, query_hash: str, *, timeout: int, greppable: bool = False): """ search an hash in all the availables online cracking APIs """ #import pdb; pdb.set_trace() if self.enable: sth_cmd = f"{self.main_exec} --no-banner --accessible" if isinstance(timeout, int) and timeout > 0: sth_cmd += f"--timeout {timeout}" sth_cmd += f" --text {query_hash}" print_status( f"Searching {query_hash} hash in availables online cracking APIs" ) Bash.exec(sth_cmd) else: print_failure("Auxliary plugin {self.main_name} is disable")
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 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 do_unsetg(self, args): """ Unset global value of an option """ selectedModule = self._cmd.selectedModule if selectedModule: option = args.option.lower() if selectedModule.isOption(option): if selectedModule.isModuleOption(option): selectedModule.options[option].value = None else: #is a valid slurm option selectedModule.slurm.options[option].value = None setattr(selectedModule.slurm, option, None) #delete option:value from global values if option in self._cmd.gvalues: del self._cmd.gvalues[option] else: print_status( "{option.upper()} value is not a global value") else: print_failure( f"No {option.upper()} option in {selectedModule.mname} module" ) else: print_failure("No module selected")
def incremental_attack(self, *, hash_types: List[int], hashes_file: str, incremental_attack_script: str, charset: str = '?a', min_length: int = 0, max_length: int = 0, masks_file: str = "incremental_masks.txt", sleep: int = 1, slurm: Slurm, local: bool = False, db_status: bool = False, workspace: str = None, db_credential_file: Path = None): """ Incremental 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 min_length (int): minimum length of mask ('?a'*min_length) max_length (int): maximum length of mask ('?a'*max_length) masks_file (str): file name to save masks used by incremental attack (default: incremental_masks.txt) slurm (Slurm): Instance of Slurm class """ #import pdb; pdb.set_trace() print_status( f"Generating incremental masks file: {ColorStr(masks_file).StyleBRIGHT}" ) masks = None if Mask.is_valid_charset(charset): masks = [ charset * length for length in range(min_length, max_length + 1) ] else: masks = [ '?a' * length for length in range(min_length, max_length + 1) ] with open(masks_file, 'w') as incremental_masks: for mask in masks: incremental_masks.write(f"{mask}\n") print_successful( f"Incremental masks file {ColorStr(masks_file).StyleBRIGHT} has been generated" ) self.masks_attack(hash_types=hash_types, hashes_file=hashes_file, masks_file=masks_file, masks_attack_script=incremental_attack_script, slurm=slurm, sleep=sleep, local=local, db_status=db_status, workspace=workspace, db_credential_file=db_credential_file)
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 insert_hashes_to_db(hashes_file: Path, workspace: str, creds_file: Path, *, pretty:bool = False): cur = db_conn = None try: #import pdb;pdb.set_trace() hashes_status = John.hashes_file_status(hashes_file) cracked_hashes = hashes_status['cracked'] db_credentials = Connection.dbCreds(creds_file) db_conn = psycopg2.connect(**db_credentials) cur = db_conn.cursor() cur.execute(f"SELECT hash from hashes_{workspace}") cracked_hashes_db = cur.fetchall() new_cracked_hashes = [] #only non-repeated cracked hashes for cracked_hash in cracked_hashes: # cracked_hash = (hash, type, cracked, password) repeated = False for cracked_hash_db in cracked_hashes_db: # cracked_hash_db = (cracked_hash) if cracked_hash[0] == cracked_hash_db[0]: repeated = True break if not repeated: new_cracked_hashes.append(cracked_hash) if new_cracked_hashes: insert_cracked_hash = ( f""" INSERT INTO hashes_{workspace} (hash, type, cracker, password) VALUES (%s, %s, %s, %s) """ ) cur.executemany(insert_cracked_hash, new_cracked_hashes) if pretty: print_status(f"Cracked hashes were saved to {ColorStr(workspace).StyleBRIGHT} workspace database") else: print(f"\n[*] Cracked hashes were saved to {workspace} workspace database") else: if pretty: print_status(f"No new cracked hashes to save to {ColorStr(workspace).StyleBRIGHT} workspace database") else: print(f"\n[*] No new cracked hashes to save to {workspace} workspace database") db_conn.commit() cur.close() except Exception as error: print_failure(error) finally: if cur is not None: cur.close() if db_conn is not None: db_conn.close()
def deleteall(*, database="ama", user="******", host='localhost'): """ Delete all workspaces from workspaces table """ #import pdb; pdb.set_trace() delete = Answer.shortAnwser("Do you want to delete all your workspaces(y/n)? ") if delete: password = getpass(prompt=f"Password of {user} role: ") dbCredential = {'host': host, 'database': database, 'user': user, 'password': password} conn = None cur = None try: conn = psycopg2.connect(**dbCredential) cur = conn.cursor() cur.execute("SELECT name FROM workspaces") conn.commit() workspaces = cur.fetchall() workspace_tables = ["hashes", "services"] for workspace, *_ in workspaces: for table in workspace_tables: cur.execute(f"DROP TABLE IF EXISTS {table}_{workspace}") #delete workspace name from workspaces table deleteWorkspace = ( f""" DELETE FROM workspaces WHERE name = '{workspace}' """ ) cur.execute(deleteWorkspace, (workspace, )) conn.commit() print_status(f"Workspaces were deleted") defaultWorkspace = "default" Workspace.init(defaultWorkspace, **dbCredential) except (Exception, psycopg2.DatabaseError) as error: #cmd2.Cmd.pexcept(error) print_failure(error) finally: if cur is not None: cur.close() if conn is not None: conn.close() else: #cmd2.Cmd.poutput("Be carefully you could lose all your data.") print_status("Be carefully you could lose all your data.")
def rename(oldWorkspace, newWorkspace, *, database="ama", user="******", host='localhost'): """ Rename a workspace """ #import pdb; pdb.set_trace() password = getpass(prompt=f"Password of {user} role: ") dbCredential = {'host': host, 'database': database, 'user': user, 'password': password} if Workspace.existWorkspace(oldWorkspace, **dbCredential): conn = None cur = None try: conn = psycopg2.connect(**dbCredential) cur = conn.cursor() renameWorkspace = \ f""" UPDATE workspaces SET name = '{newWorkspace}' WHERE name = '{oldWorkspace}' """ cur.execute(renameWorkspace, (newWorkspace, oldWorkspace, )) conn.commit() renameWorkspaceTables = ( f""" ALTER TABLE hashes_{oldWorkspace} RENAME TO hashes_{newWorkspace} """, f""" ALTER TABLE services_{oldWorkspace} RENAME TO services_{newWorkspace} """ ) for renameTable in renameWorkspaceTables: cur.execute(renameTable, (newWorkspace, oldWorkspace, )) conn.commit() cur.close() #cmd2.Cmd.poutput(f"Workspace {oldWorkspace} rename to {newWorkspace}") print_status(f"Workspace {oldWorkspace} rename to {newWorkspace}") except (Exception, psycopg2.DatabaseError) as error: #cmd2.Cmd.pexcept(error) print_failure(error) finally: if cur is not None: cur.close() if conn is not None: conn.close() else: #cmd2.Cmd.pwarning(f"Workspace {oldWorkspace} doesn't exist") print_failure(f"Workspace {oldWorkspace} doesn't exist")
def do_db_disconnect(self, args): """ Disconnect database """ try: self._cmd.db_conn.close() self._cmd.db_conn = None db_creds = Connection.dbCreds( self._cmd.config['db_credentials_file']) dbName = db_creds['database'] print_status( f"Database {ColorStr(dbName).StyleBRIGHT} disconnected") del db_creds except (Exception, psycopg2.DatabaseError) as error: print_failure(error)
def switch(self, workspace=None): """ Switch between workspaces """ #import pdb; pdb.set_trace() if workspace: try: if self.exist(workspace): self._cmd.workspace = workspace else: raise WorkspaceExistsError(workspace) print_status(f"Current workspace: {ColorStr(workspace).StyleBRIGHT}") except (Exception, psycopg2.DatabaseError) as error: print_failure(error) else: print_failure("No workspace selected")
def do_run(self, args): """ Run the selected auxiliary module """ #import pdb; pdb.set_trace() selectedModule = self._cmd.selectedModule if selectedModule: if isinstance(selectedModule, Auxiliary): print_status( f"Running {ColorStr(selectedModule.MNAME).StyleBRIGHT} module" ) selectedModule.run() else: # selectedModule is an instance of Attack print_failure( f"No run method for {ColorStr(selectedModule.MNAME).StyleBRIGHT} module" ) else: print_failure("No module selected")
def do_attack(self, args): """ Perform an attack with the selected module """ if selectedModule := self._cmd.selectedModule: if isinstance(selectedModule, Attack): pre_attack_output = None if pre_attack := selectedModule.selected_pre_attack: print_status( f"Running {ColorStr(pre_attack.mname).StyleBRIGHT} preattack module" ) pre_attack_output = pre_attack.run(quiet=args.quiet) print_status( f"Running {ColorStr(selectedModule.mname).StyleBRIGHT} attack module" ) db_status = True if self._cmd.db_conn else False if selectedModule.CRACKER == John.MAINNAME: cracker_main_exec = self._cmd.config['john'] elif selectedModule.CRACKER == Hashcat.MAINNAME: cracker_main_exec = self._cmd.config['hashcat'] else: cracker_main_exec = None #import pdb;pdb.set_trace() attack_output = selectedModule.attack( local=args.local, #force = args.force, pre_attack_output=pre_attack_output, db_status=db_status, workspace=self._cmd.workspace, db_credential_file=self._cmd.config['db_credentials_file'], cracker_main_exec=cracker_main_exec, slurm_conf=self._cmd.slurm_config) if post_attack := selectedModule.selected_post_attack: print_status( f"Running {ColorStr(post_attack.mname).StyleBRIGHT} posattack module" ) post_attack.run(quiet=args.quiet, attack_output=attack_output)
def wordlist_attack(self , *, hash_types: List[str] = None , hashes_file: Path, wordlists: List[Path], rules:str = None, rules_file:Path = None, slurm: Slurm, local:bool = False, db_status:bool = False, workspace:str = None, db_credential_file: Path = None): """ Wordlist attack using john submiting parallel tasks in a cluster with Slurm Args: hash_type (str): Jonh's hash type hashes_file (str): Hash file to attack wordlist (str): wordlist to attack slurm (Slurm): Instance of Slurm class """ #import pdb; pdb.set_trace() if self.enable: try: permission = [os.R_OK] Path.access(permission, hashes_file, *wordlists) if hash_types: John.check_hash_type(hash_types) if rules and rules_file: Path.access(permission, rules_file) print_status(f"Attacking hashes in {ColorStr(hashes_file).StyleBRIGHT} file in wordlist mode") print_status(f"Wordlists: {ColorStr(wordlists).StyleBRIGHT}") print_status(f"Possible hashes identities: {ColorStr(hash_types).StyleBRIGHT}") if (not local) and slurm and slurm.partition: #import pdb; pdb.set_trace() self.check_slurm_partition(slurm.partition, slurm.config['partitions']) parallel_job_type = slurm.parallel_job_parser() if not parallel_job_type in ["MPI", "OMP"]: raise InvalidParallelJob(parallel_job_type) hash_types_len = len(hash_types) wordlists_len = len(wordlists) array_tasks = slurm.sbatch['array'].value #import pdb;pdb.set_trace() if array_tasks is None: array_tasks = 1 #debugged - date Apr 9 if wordlists_len > 1: # hash_types_len >= 1 if array_tasks > 1: if array_tasks > wordlists_len: print_failure(f"These is more array jobs that work to process (ARRAY={array_tasks}, WLS={wordlists_len})") print_status(f"Adjusting {ColorStr('ARRAY').StyleBRIGHT} to {wordlists_len} (1 job per wordlist)") array_tasks = wordlists_len slurm.set_option('array', array_tasks) for array_task_id in range(array_tasks): init = floor(wordlists_len/array_tasks)*array_task_id if array_task_id == (array_tasks - 1): end = wordlists_len else: end = floor(wordlists_len/array_tasks)*(array_task_id+1) print_status(f"(array id {array_task_id}) Processing: wordlists={ColorStr(wordlists[init:end]).StyleBRIGHT}, hash_types={ColorStr('ALL').StyleBRIGHT}") WLS = self.pylist2bash(wordlists) HID = self.pylist2bash(hash_types) ARRAY = slurm.sbatch['array'].value #array enumeration: 0-(ARRAY-1) LEN_WLS = "${#WLS[@]}" INIT = "$((LEN_WLS/ARRAY * SLURM_ARRAY_TASK_ID))" END = "$((LEN_WLS/ARRAY * (SLURM_ARRAY_TASK_ID+1)))" variable_definition_block = ( f"WLS={WLS}", f"HID={HID}", f"LEN_WLS={LEN_WLS}", f"ARRAY={ARRAY}", f"INIT={INIT}", "\nif [[ $SLURM_ARRAY_TASK_ID -eq $((ARRAY -1)) ]]; then", "\t" + "END=$LEN_WLS", "else", "\t" + f"END={END}", "fi", ) else: WLS = self.pylist2bash(wordlists) HID = self.pylist2bash(hash_types) INIT = 0 END = wordlists_len variable_definition_block = ( f"WLS={WLS}", f"HID={HID}", f"INIT={INIT}", f"END={END}", ) attack_cmd = f"{self.main_exec}" attack_cmd += " --format=${identity}" attack_cmd += " -w ${wl}" if parallel_job_type == "MPI": attack_cmd = f"srun --mpi={slurm.pmix} " + attack_cmd elif parallel_job_type == "OMP": attack_cmd = f"srun " + attack_cmd if rules and rules_file: attack_cmd += f" --rules={rules} {rules_file}" attack_cmd += f" {hashes_file}" header_attack = f"echo -e \"\\n\\n[*] Running: {attack_cmd}\"" insert_cracked_hashes = '' if db_status and workspace and db_credential_file: insert_cracked_hashes = ( f"amadb -c {db_credential_file} -w {workspace}" f" --cracker {John.MAINNAME} -j {hashes_file}" ) cracking_block = ( "for wl in ${WLS[@]:INIT:END-INIT}; do", "\tfor identity in ${HID[@]}; do", "\t\t" + header_attack, "\t\t" + attack_cmd, "\t\t" + insert_cracked_hashes, "\t\t" + "all_cracked=false", "\t\t" + "if $all_cracked; then break; fi", "\tdone", "done" ) parallel_work = (variable_definition_block, cracking_block) slurm_script_name = slurm.gen_batch_script(parallel_work) #import pdb;pdb.set_trace() Bash.exec(f"sbatch {slurm_script_name}") #debugged - date apr 9 2021 elif hash_types_len > 1 and wordlists_len == 1: #import pdb;pdb.set_trace() if array_tasks > 1: if array_tasks > hash_types_len: print_failure(f"These is more array jobs that work to process (ARRAY={array_tasks}, HID={hash_types_len})") print_status(f"Adjusting {ColorStr('ARRAY').StyleBRIGHT} to {hash_type_len} (1 job per hash type)") array_tasks = hash_types_len slurm.set_option('array', array_tasks) for array_task_id in range(array_tasks): init = floor(hash_types_len/array_tasks)*array_task_id if array_task_id == (array_tasks - 1): end = hash_types_len else: end = floor(hash_types_len/array_tasks)*(array_task_id+1) print_status(f"(array id {array_task_id}) Processing: hash-types={ColorStr(hash_types[init:end]).StyleBRIGHT}, wordlists={ColorStr('ALL').StyleBRIGHT}") HID = self.pylist2bash(hash_types) ARRAY = slurm.sbatch['array'].value #array enumeration: 0-(ARRAY-1) LEN_HID = "${#HID[@]}" INIT = "$((LEN_HID/ARRAY * SLURM_ARRAY_TASK_ID))" END = "$((LEN_HID/ARRAY * (SLURM_ARRAY_TASK_ID+1)))" variable_definition_block = ( f"HID={HID}", f"LEN_HID={LEN_HID}", f"ARRAY={ARRAY}", f"INIT={INIT}", "\nif [[ $SLURM_ARRAY_TASK_ID -eq $((ARRAY -1)) ]]; then", "\t" + "END=$LEN_HID", "else", "\t" + f"END={END}", "fi", ) else: HID = self.pylist2bash(hash_types) INIT = 0 END = hash_types_len variable_definition_block = ( f"HID={HID}", f"INIT={INIT}", f"END={END}", ) wordlist = wordlists[0] attack_cmd = f"{self.main_exec} --wordlist={wordlist}" attack_cmd += " --format=${identity}" if parallel_job_type == "MPI": attack_cmd = f"srun --mpi={slurm.pmix} " + attack_cmd elif parallel_job_type == "OMP": attack_cmd = f"srun " + attack_cmd if rules and rules_file: attack_cmd += f" --rules={rules} {rules_file}" attack_cmd += f" {hashes_file}" header_attack = f"echo -e \"\\n\\n[*] Running: {attack_cmd}\"" insert_cracked_hashes = '' if db_status and workspace and db_credential_file: insert_cracked_hashes = ( f"amadb -c {db_credential_file} -w {workspace}" f" --cracker {John.MAINNAME} -j {hashes_file}" ) cracking_block = ( "for identity in ${HID[@]:INIT:END-INIT}; do", "\t" + header_attack, "\t" + attack_cmd, "\t" + insert_cracked_hashes, "\t" + "all_cracked=false", "\t" + "if $all_cracked; then break; fi", "done" ) parallel_work = (variable_definition_block, cracking_block) slurm_script_name = slurm.gen_batch_script(parallel_work) #import pdb;pdb.set_trace() Bash.exec(f"sbatch {slurm_script_name}") # replaced by case: hash_types_len >= 1 and wordlists_len > 1 #debugged - date apr 9 2021 # elif hash_types_len == 1 and wordlists_len > 1: # #import pdb;pdb.set_trace() # if array_tasks > 1: # if array_tasks > wordlists_len: # print_failure(f"These is more array jobs that work to process (ARRAY={array_tasks}, WLS={wordlists_len})") # print_status(f"Adjusting {ColorStr('ARRAY').StyleBRIGHT} to {wordlists_len} (1 job per wordlist)") # array_tasks = wordlists_len # slurm.set_option('array', array_tasks) # for array_task_id in range(array_tasks): # init = floor(wordlists_len/array_tasks)*array_task_id # if array_task_id == (array_tasks - 1): # end = wordlists_len # else: # end = floor(wordlists_len/array_tasks)*(array_task_id+1) # print_status(f"(array id {array_task_id}) Processing: wordlists={ColorStr(wordlists[init:end]).StyleBRIGHT}, hash types={ColorStr('ALL').StyleBRIGHT}") # WLS = self.pylist2bash(wordlists) # ARRAY = slurm.sbatch['array'].value #array enumeration: 0-(ARRAY-1) # LEN_WLS = "${#WLS[@]}" # INIT = "$((LEN_WLS/ARRAY * SLURM_ARRAY_TASK_ID))" # END = "$((LEN_WLS/ARRAY * (SLURM_ARRAY_TASK_ID+1)))" # variable_definition_block = ( # f"WLS={WLS}", # f"LEN_WLS={LEN_WLS}", # f"ARRAY={ARRAY}", # f"INIT={INIT}", # "\nif [[ $SLURM_ARRAY_TASK_ID -eq $((ARRAY -1)) ]]; then", # "\t" + "END=$LEN_WLS", # "else", # "\t" + f"END={END}", # "fi", # ) # else: # WLS = self.pylist2bash(wordlists) # INIT = 0 # END = wordlists_len # variable_definition_block = ( # f"WLS={WLS}", # f"INIT={INIT}", # f"END={END}" # ) # hash_type = hash_types[0] # attack_cmd = f"{self.main_exec} --format={hash_type}" # attack_cmd += " -w ${wl}" # if parallel_job_type == "MPI": # attack_cmd = f"srun --mpi={slurm.pmix} " + attack_cmd # elif parallel_job_type == "OMP": # attack_cmd = f"srun " + attack_cmd # if rules and rules_file: # attack_cmd += f" --rules={rules} {rules_file}" # attack_cmd += f" {hashes_file}" # header_attack = f"echo -e \"\\n\\n[*] Running: {attack_cmd}\"" # insert_cracked_hashes = '' # if db_status and workspace and db_credential_file: # insert_cracked_hashes = ( # f"amadb -c {db_credential_file} -w {workspace}" # f" --cracker {John.MAINNAME} -j {hashes_file}" # ) # cracking_block = ( # "for wl in ${WLS[@]:INIT:END-INIT}; do", # "\t" + header_attack, # "\t" + attack_cmd, # "\t" + insert_cracked_hashes, # "\t" + "all_cracked=false", # "\t" + "if $all_cracked; then break; fi", # "done" # ) # parallel_work = (variable_definition_block, # cracking_block) # slurm_script_name = slurm.gen_batch_script(parallel_work) # #import pdb;pdb.set_trace() # Bash.exec(f"sbatch {slurm_script_name}") # debugged - date apr 9 2021 else: # hash_types_len == 1 and wordlists_len == 1: if array_tasks > 1: print_failure("There is not much work for performing an array attack") slurm.set_option('array', None) if slurm.sbatch['output'] == "slurm-%A_%a.out": # default output name for array jobs slurm.set_option('output', 'slurm-%j.out') #import pdb;pdb.set_trace() hash_type = hash_types[0] wordlist = wordlists[0] attack_cmd = ( f"{self.main_exec}" f" --wordlist={wordlist}" f" --format={hash_type}" ) if parallel_job_type == "MPI": attack_cmd = f"srun --mpi={slurm.pmix} " + attack_cmd elif parallel_job_type == "OMP": attack_cmd = f"srun " + attack_cmd if rules and rules_file: attack_cmd += f" --rules={rules} {rules_file}" attack_cmd += f" {hashes_file}" header_attack = f"echo -e \"\\n\\n[*] Running: {attack_cmd}\"" insert_cracked_hashes = '' if db_status and workspace and db_credential_file: insert_cracked_hashes = ( f"amadb -c {db_credential_file} -w {workspace}" f" --cracker {John.MAINNAME} -j {hashes_file}" ) cracking_block = (header_attack, attack_cmd, insert_cracked_hashes) parallel_work = [cracking_block] slurm_script_name = slurm.gen_batch_script(parallel_work) import pdb;pdb.set_trace() Bash.exec(f"sbatch {slurm_script_name}") else: for hash_type in hash_types: are_all_hashes_cracked = John.are_all_hashes_cracked(hashes_file) if not are_all_hashes_cracked: # some hash isn't cracked yet attack_cmd = f"{self.main_exec} --wordlist={wordlist}" if hash_type: attack_cmd += f" --format={hash_type}" if rules and rules_file: attack_cmd += f" --rules={rules} {rules_file}" attack_cmd += f" {hashes_file}" print() print_status(f"Running: {ColorStr(attack_cmd).StyleBRIGHT}") Bash.exec(attack_cmd) else: print_successful(f"Hashes in {ColorStr(hashes_file).StyleBRIGHT} were cracked") break if db_status and workspace and db_credential_file: John.insert_hashes_to_db(hashes_file, workspace, db_credential_file, pretty=True) except Exception as error: #cmd2.Cmd.pexcept(error) print_failure(error) else: print_failure(f"Cracker {ColorStr(self.main_name).StyleBRIGHT} is disable")
def masks_attack(self, *, hash_types: List[str] = None, hashes_file: Path, masks_file: Path, slurm: Slurm, local: bool = False, db_status:bool = False, workspace:str = None, db_credential_file: Path = None): """ Masks attack using john submiting parallel tasks in a cluster with Slurm Args: hash_type (str): John's hash type hashes_file (str): Hash file to attack masks_file (str): Masks file mask_attack_script (str): Name for generated mask attack script slurm (Slurm): Instance of Slurm class """ #import pdb; pdb.set_trace() if self.enable: try: permission = [os.R_OK] Path.access(permission, hashes_file, masks_file) if hash_types: John.check_hash_type(hash_types) print_status(f"Attacking hashes in {ColorStr(hashes_file).StyleBRIGHT} file with {ColorStr(masks_file).StyleBRIGHT} masks file") print_status(f"Possible hashes identities: {ColorStr(hash_types).StyleBRIGHT}") if (not local) and slurm and slurm.partition: self.check_slurm_partition(slurm.partition, slurm.config['partitions']) parallel_job_type = slurm.parallel_job_parser() if not parallel_job_type in ["MPI", "OMP"]: raise InvalidParallelJob(parallel_job_type) array_tasks = slurm.sbatch['array'].value if array_tasks is None: array_tasks = 1 base_path = masks_file.parent name_masks_file = masks_file.name suffix = masks_file.suffix if array_tasks > 1: self.array_masks(masks_file, array_tasks) only_name_masks_file = name_masks_file[:-len(suffix)] for a in range(array_tasks): name_split_masks_file = only_name_masks_file + str(a) + suffix split_masks_file = Path.joinpath(base_path, name_split_masks_file) print_status(f"(array id {a}) Processing: masks file = {split_masks_file}") MASKS_FILE = only_name_masks_file + "${SLURM_ARRAY_TASK_ID}" + suffix else: MASKS_FILE = masks_file.name MASKS_FILE = Path.joinpath(base_path, MASKS_FILE) HASHES_FILE = hashes_file HID = self.pylist2bash(hash_types) #ARRAY = slurm.sbatch['array'].value variable_definition_block = ( f"HASHES_FILE={HASHES_FILE}", f"MASKS_FILE={MASKS_FILE}", f"HID={HID}", #f"ARRAY=" ) attack_cmd = f"{self.main_exec}" attack_cmd += " --mask=${mask}" attack_cmd += " --format=${hid}" if parallel_job_type == "MPI": attack_cmd = f"srun --mpi={slurm.pmix} " + attack_cmd elif parallel_job_type == "OMP": attack_cmd = f"srun " + attack_cmd attack_cmd += " ${HASHES_FILE}" header_attack = f"echo -e \"\\n\\n[*] Running: {attack_cmd}\"" insert_cracked_hashes = '' if db_status and workspace and db_credential_file: insert_cracked_hashes = ( f"amadb -c {db_credential_file} -w {workspace}" f" --cracker {John.MAINNAME} -j {hashes_file}" ) cracking_block = ( "while read mask", "do", "\tfor hid in ${HID[@]}; do", "\t\t" + header_attack, "\t\t" + attack_cmd, "\t\t" + insert_cracked_hashes, "\t\t" + "all_cracked=false", "\t\t" + "if $all_cracked; then break; fi", "\tdone", "done < ${MASKS_FILE}" ) parallel_work = (variable_definition_block, cracking_block) slurm_script_name = slurm.gen_batch_script(parallel_work) import pdb; pdb.set_trace() Bash.exec(f"sbatch {slurm_script_name}") else: all_cracked = False for hash_type in hash_types: with open(masks_file, 'r') as masks: while mask := masks.readline().rstrip(): all_cracked = John.are_all_hashes_cracked(hashes_file) if not all_cracked: attack_cmd = f"{self.main_exec} --mask={mask}" if hash_type: attack_cmd += f" --format={hash_type}" attack_cmd += f" {hashes_file}" print() print_status(f"Running: {ColorStr(attack_cmd).StyleBRIGHT}") Bash.exec(attack_cmd) else: break if all_cracked := John.are_all_hashes_cracked(hashes_file): print_successful(f"Hashes in {ColorStr(hashes_file).StyleBRIGHT} were cracked") break if db_status and workspace and db_credential_file: John.insert_hashes_to_db(hashes_file, workspace, db_credential_file, pretty=True)
def delete(workspace=None, selectedWorkspace=None, *, database="ama", user="******", host='localhost'): """ Delete a workspace and return the name of workspace in use """ #import pdb; pdb.set_trace() password = getpass(prompt=f"Password of {user} role: ") dbCredential = {'host': host, 'database': database, 'user': user, 'password': password} if Workspace.existWorkspace(workspace, **dbCredential): conn = None cur = None try: if workspace == selectedWorkspace: # workspace is in current use forceDelete = Answer.shortAnwser(f"Workspace {workspace} is in current use. Do you want to delete it(y/n)? ") # y: True and n: False if not forceDelete: print_status("Be carefully you can lose your data") return selectedWorkspace conn = psycopg2.connect(**dbCredential) cur = conn.cursor() workspace_tables = ["hashes", "services"] for table in workspace_tables: cur.execute(f"DROP TABLE IF EXISTS {table}_{workspace}") #delete workspace name from workspaces table deleteWorkspace = ( f""" DELETE FROM workspaces WHERE name = '{workspace}' """ ) cur.execute(deleteWorkspace, (workspace, )) conn.commit() #cmd2.Cmd.poutput(f"Workspace {workspace} was deleted") print_status(f"Workspace {workspace} was deleted") defaultWorkspace = "default" if workspace == selectedWorkspace: print_status(f"Current workspace: {defaultWorkspace}") if workspace == defaultWorkspace: Workspace.init(workspace, **dbCredential) return workspace else: if not Workspace.existWorkspace(defaultWorkspace, **dbCredential): Workspace.init(defaultWorkspace, **dbCredential) return defaultWorkspace except (Exception, psycopg2.DatabaseError) as error: #cmd2.Cmd.pexcept(error) print_failure(error) finally: if cur is not None: cur.close() if conn is not None: conn.close() else: #cmd2.Cmd.pwarning(f"Workspace {workspace} doesn't exist") print_failure(f"Workspace {workspace} doesn't exist")
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 do_bkp(self, args): """ Save all the commands used to set options of a module """ #import pdb; pdb.set_trace() output = None try: if selectedModule := self._cmd.selectedModule: if args.required and args.only_module: print_status( f"Performing backup of {ColorStr(selectedModule.mname).StyleBRIGHT} require module options" ) elif (not args.required) and args.only_module: print_status( f"Performing backup of {ColorStr(selectedModule.mname).StyleBRIGHT} module options" ) elif args.required and args.only_slurm: if isinstance(selectedModule, Auxiliary): raise Exception( "Auxiliary modules have not slurm options") else: # selectedModule is an Attack print_status( f"Performing backup of {ColorStr(selectedModule.mname).StyleBRIGHT} required slurm options" ) elif (not args.required) and args.only_slurm: if isinstance(selectedModule, Auxiliary): raise Exception( "Auxiliary modules have not slurm options") else: print_status( f"Performing backup of {ColorStr(selectedModule.mname).StyleBRIGHT} slurm options" ) elif args.required and not (args.only_module or args.only_slurm): print_status( f"Performing backup of {ColorStr(selectedModule.mname).StyleBRIGHT} required options" ) elif not (args.required or args.only_module or args.only_slurm): print_status( f"Performing backup of {ColorStr(selectedModule.mname).StyleBRIGHT} options" ) if args.output: output = open(args.output, 'w') else: output = sys.stdout no_empty_options = selectedModule.get_no_empty_options( args.required) only_module = args.only_module only_slurm = args.only_slurm for name, value in no_empty_options.items(): if (selectedModule.isModuleOption(name) and only_module) or \ (selectedModule.isSlurmOption(name) and only_slurm) or \ (not only_module and not only_slurm): bkp_cmd = f"setv {name.upper()} {value}" output.write(f"{bkp_cmd}\n") if isinstance(selectedModule, Attack): if pre_attack_module := selectedModule.selected_pre_attack: no_empty_pre_attack_options = pre_attack_module.get_no_empty_options( ) for name, value in no_empty_pre_attack_options.items(): if (selectedModule.isModuleOption(name) and only_module) or \ (selectedModule.isSlurmOption(name) and only_slurm) or \ (not only_module and not only_slurm): bkp_cmd = f"setv -pre {name.upper()} {value}" output.write(f"{bkp_cmd}\n") if post_attack_module := selectedModule.selected_post_attack: no_empty_post_attack_options = post_attack_module.get_no_empty_options( ) for name, value in no_empty_post_attack_options.items( ): if (selectedModule.isModuleOption(name) and only_module) or \ (selectedModule.isSlurmOption(name) and only_slurm) or \ (not only_module and not only_slurm): bkp_cmd = f"setv -post {name.upper()} {value}" output.write(f"{bkp_cmd}\n")
def run(self, quiet: bool = False, attack_output: Any = None): """ Execution of auxiliary/hashes/hashes_status ama module """ #import pdb; pdb.set_trace() global_hashes_status = {'cracked': [], 'uncracked': []} try: cracker_name = self.options['cracker'].value if cracker_name is not None: if cracker_name not in [John.MAINNAME, Hashcat.MAINNAME]: raise Exception("Selected invalid cracker: {cracker_name}") elif cracker_name == John.MAINNAME: crackers = [John] else: #cracker_name == Hashcat.MAINNAME crackers = [Hashcat] else: crackers = get_availables_hashes_crackers() hashes_file = self.options['hashes_file'].value potfile = self.options['potfile'].value for cracker in crackers: hashes_status = cracker.hashes_file_status( hashes_file, potfile) for cracked_hash in hashes_status['cracked']: if cracked_hash not in global_hashes_status['cracked']: global_hashes_status['cracked'].append(cracked_hash) for uncracked_hash in hashes_status['uncracked']: if uncracked_hash not in global_hashes_status['uncracked']: global_hashes_status['uncracked'].append( uncracked_hash) if uncracked_hashes := self.options.get( 'uncracked_hashes', Argument.get_empty()).value: with open(uncracked_hashes, 'w') as uncracked_hashes_file: #hashes_status['uncracked'] struct is [[UNCRACKED_HASH], [OTHER_UNCRACKED_HASH], ...] for [uhash] in global_hashes_status['uncracked']: uncracked_hashes_file.write(f"{uhash}\n") print_status( f"Uncracked hashes have written to {uncracked_hashes} file" ) # print status of hashes in hashesFile if not quiet: status_hashes_table = (f""" Cracked Hashes: {tabulate(global_hashes_status["cracked"],headers = ["Hash", "Type", "Password", "Cracker"])} Uncracked Hashes: {tabulate(global_hashes_status["uncracked"],headers = ["Hash"])} """) print(status_hashes_table) return hashes_status
def incremental_attack(self, *, hash_types: List[str] = None, hashes_file: str, slurm: Slurm , local:bool = False, db_status:bool = False, workspace:str = None, db_credential_file: Path = None): """ Incemental attack using john submiting parallel tasks in a cluster with Slurm Args: hash_type (str): John's hash type hashes_file (str): Hash file to attack slurm (Slurm): Instance of Slurm class """ #import pdb; pdb.set_trace() if self.enable: try: permission = [os.R_OK] Path.access(permission, hashes_file) if hash_types: John.check_hash_type(hash_types) print_status(f"Attacking hashes in {ColorStr(hashes_file).StyleBRIGHT} file in incremental mode") print_status(f"Possible hashes identities: {ColorStr(hash_types).StyleBRIGHT}") if (not local) and slurm and slurm.partition: parallel_job_type = slurm.parallel_job_parser() if not parallel_job_type in ["MPI", "OMP"]: raise InvalidParallelJob(parallel_job_type) parallel_work = [] for hash_type in hash_types: attack_cmd = f"{self.main_exec} --incremental" if parallel_job_type == "MPI": attack_cmd = f"srun --mpi={slurm.pmix} " + attack_cmd elif parallel_job_type == "OMP": attack_cmd = f"srun " + attack_cmd if hash_type: attack_cmd += f" --format={hash_type}" attack_cmd += f" {hashes_file}" 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 {John.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) Bash.exec(f"sbatch {slurm_script_name}") else: #import pdb;pdb.set_trace() for hash_type in hash_types: attack_cmd = f"{self.main_exec} --incremental" if hash_type: attack_cmd += f" --format={hash_type}" attack_cmd += f" {hashes_file}" if are_all_hashes_cracked := John.are_all_hashes_cracked(hashes_file): print_successful(f"Hashes in {ColorStr(hashes_file).StyleBRIGHT} were cracked") break else: # some hash isn't cracked yet print() print_status(f"Running: {ColorStr(attack_cmd).StyleBRIGHT}") Bash.exec(attack_cmd) if db_status and workspace and db_credential_file: John.insert_hashes_to_db(hashes_file, workspace, db_credential_file, pretty=True) except Exception as error: #cmd2.Cmd.pexcept(error) print_failure(error) else: print_failure(f"Cracker {ColorStr(self.main_name).StyleBRIGHT} is disable")
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)
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)
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 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")