def build_prince_command(self, task, chunk): binary = "../../prince/pp64." if Initialize.get_os() != 1: binary = "./" + binary + "bin" else: binary += "exe" pre_args = " -s " + str(chunk['skip']) + " -l " + str( chunk['length']) + ' ' pre_args += get_wordlist( update_files(task['attackcmd']).replace(task['hashlistAlias'], '')) post_args = " --machine-readable --quiet --status --remove --restore-disable --potfile-disable --session=hashtopolis" post_args += " --status-timer " + str(task['statustimer']) post_args += " --outfile-check-timer=" + str(task['statustimer']) post_args += " --outfile-check-dir=../../hashlist_" + str( task['hashlistId']) post_args += " -o ../../hashlists/" + str( task['hashlistId'] ) + ".out --outfile-format=" + self.get_outfile_format() + " " post_args += " --remove-timer=" + str(task['statustimer']) post_args += " ../../hashlists/" + str(task['hashlistId']) post_args += get_rules_and_hl(update_files(task['attackcmd']), task['hashlistAlias']).replace( task['hashlistAlias'], '') return binary + pre_args + " | " + self.callPath + post_args + task[ 'cmdpars']
def build_preprocessor_command(self, task, chunk, preprocessor): binary = "../../preprocessor/" + str(task['preprocessor']) + "/" + preprocessor['executable'] if Initialize.get_os() != 1: binary = "./" + binary if not os.path.isfile(binary): split = binary.split(".") binary = '.'.join(split[:-1]) + get_bit() + "." + split[-1] # in case the skip or limit command are not available, we try to achieve the same with head/tail (the more chunks are run, the more inefficient it might be) if preprocessor['skipCommand'] is not None and preprocessor['limitCommand'] is not None: pre_args = " " + preprocessor['skipCommand'] + " " + str(chunk['skip']) + " " + preprocessor['limitCommand'] + " " + str(chunk['length']) + ' ' else: pre_args = "" pre_args += ' ' + update_files(task['preprocessorCommand']) # TODO: add support for windows as well (pre-built tools) if preprocessor['skipCommand'] is None or preprocessor['limitCommand'] is None: pre_args += " | head -n " + str(chunk['skip'] + chunk['length']) + " | tail -n " + str(chunk['length']) post_args = " --machine-readable --quiet --status --remove --restore-disable --potfile-disable --session=hashtopolis" post_args += " --status-timer " + str(task['statustimer']) post_args += " --outfile-check-timer=" + str(task['statustimer']) post_args += " --outfile-check-dir=../../hashlist_" + str(task['hashlistId']) post_args += " -o ../../hashlists/" + str(task['hashlistId']) + ".out --outfile-format=" + self.get_outfile_format() + " -p \"" + str(chr(9)) + "\"" post_args += " --remove-timer=" + str(task['statustimer']) post_args += " ../../hashlists/" + str(task['hashlistId']) post_args += update_files(task['attackcmd']).replace(task['hashlistAlias'], '') return binary + pre_args + " | " + self.callPath + post_args + task['cmdpars']
def run_speed_benchmark(self, task): args = " --machine-readable --quiet --progress-only" args += " --restore-disable --potfile-disable --session=hashtopolis -p \"" + str(chr(9)) + "\" " if task['usePrince']: args += get_rules_and_hl(update_files(task['attackcmd']), task['hashlistAlias']).replace(task['hashlistAlias'], "../../hashlists/" + str(task['hashlistId'])) + ' ' args += " example.dict" + ' ' + task['cmdpars'] else: args += update_files(task['attackcmd']).replace(task['hashlistAlias'], "../../hashlists/" + str(task['hashlistId'])) + ' ' + task['cmdpars'] if 'useBrain' in task and task['useBrain']: args += " -S" args += " -o ../../hashlists/" + str(task['hashlistId']) + ".out" full_cmd = self.callPath + args if Initialize.get_os() == 1: full_cmd = full_cmd.replace("/", '\\') try: logging.debug("CALL: " + full_cmd) output = subprocess.check_output(full_cmd, shell=True, cwd=self.cracker_path) except subprocess.CalledProcessError as e: logging.error("Error during speed benchmark, return code: " + str(e.returncode)) send_error("Speed benchmark failed!", self.config.get_value('token'), task['taskId'], None) return 0 output = output.decode(encoding='utf-8').replace("\r\n", "\n").split("\n") benchmark_sum = [0, 0] for line in output: if not line: continue line = line.split(":") if len(line) != 3: continue # we need to do a weighted sum of all the time outputs of the GPUs benchmark_sum[0] += int(line[1]) benchmark_sum[1] += float(line[2])*int(line[1]) return str(benchmark_sum[0]) + ":" + str(float(benchmark_sum[1]) / benchmark_sum[0])
def build_command(self, task, chunk): args = " --machine-readable --quiet --status --restore-disable --session=hashtopolis" args += " --status-timer " + str(task['statustimer']) args += " --outfile-check-timer=" + str(task['statustimer']) args += " --outfile-check-dir=../../hashlist_" + str( task['hashlistId']) args += " -o ../../hashlists/" + str( task['hashlistId'] ) + ".out --outfile-format=" + self.get_outfile_format() + " " args += " -s " + str(chunk['skip']) args += " -l " + str(chunk['length']) if 'useBrain' in task and task[ 'useBrain']: # when using brain we set the according parameters args += " --brain-client --brain-host " + task['brainHost'] args += " --brain-port " + str(task['brainPort']) args += " --brain-password " + task['brainPass'] if 'brainFeatures' in task: args += " --brain-client-features " + str( task['brainFeatures']) else: # remove should only be used if we run without brain args += " --potfile-disable --remove --remove-timer=" + str( task['statustimer']) args += " " + update_files(task['attackcmd']).replace( task['hashlistAlias'], "../../hashlists/" + str(task['hashlistId'])) + " " + task['cmdpars'] if args.find(" -S") != -1: self.uses_slow_hash_flag = True return self.callPath + args
def prince_keyspace(self, task, chunk): binary = "pp64." if Initialize.get_os() != 1: binary = "./" + binary + "bin" else: binary += "exe" full_cmd = binary + " --keyspace " + get_wordlist( update_files(task['attackcmd'], True).replace( task['hashlistAlias'], "")) if Initialize.get_os() == 1: full_cmd = full_cmd.replace("/", '\\') try: logging.debug("CALL: " + full_cmd) output = subprocess.check_output(full_cmd, shell=True, cwd="prince") except subprocess.CalledProcessError: logging.error("Error during PRINCE keyspace measure") send_error("PRINCE keyspace measure failed!", self.config.get_value('token'), task['taskId'], None) sleep(5) return False output = output.decode(encoding='utf-8').replace("\r\n", "\n").split("\n") keyspace = "0" for line in output: if not line: continue keyspace = line # as the keyspace of prince can get very very large, we only save it in case it's small enough to fit in a long, # otherwise we assume that the user will abort the task earlier anyway if int(keyspace ) > 9000000000000000000: # close to max size of a long long int return chunk.send_keyspace(-1, task['taskId']) return chunk.send_keyspace(int(keyspace), task['taskId'])
def run_health_check(self, attack, hashlist_alias): args = " --machine-readable --quiet" args += " --restore-disable --potfile-disable --session=health " args += update_files(attack).replace(hashlist_alias, "../../hashlists/health_check.txt") args += " -o ../../hashlists/health_check.out" full_cmd = self.callPath + args if Initialize.get_os() == 1: full_cmd = full_cmd.replace("/", '\\') logging.debug("CALL: " + full_cmd) proc = subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.cracker_path) output, error = proc.communicate() logging.debug("Started health check attack") # wait until done, on the health check we don't send any update during running. Maybe later we could at least # introduce some heartbeat update to make visible that the agent is still alive. proc.wait() errors = [] states = [] if error: error = escape_ansi(error.replace(b"\r\n", b"\n").decode('utf-8')) error = error.split('\n') for line in error: if not line: continue errors.append(line) if output: output = escape_ansi(output.replace(b"\r\n", b"\n").decode('utf-8')) output = output.split('\n') for line in output: if not line: continue logging.debug(line) status = HashcatStatus(line) if status.is_valid(): states.append(status) return [states, errors]
def preprocessor_keyspace(self, task, chunk): preprocessor = task.get_preprocessor() if preprocessor['keyspaceCommand'] is None: # in case there is no keyspace flag, we just assume the task will be that large to run forever return chunk.send_keyspace(-1, task.get_task()['taskId']) binary = preprocessor['executable'] if Initialize.get_os() != 1: binary = "./" + binary if not os.path.isfile(binary): split = binary.split(".") binary = '.'.join(split[:-1]) + get_bit() + "." + split[-1] full_cmd = binary + " " + preprocessor['keyspaceCommand'] + " " + update_files(task.get_task()['preprocessorCommand']) if Initialize.get_os() == 1: full_cmd = full_cmd.replace("/", '\\') try: logging.debug("CALL: " + full_cmd) output = subprocess.check_output(full_cmd, shell=True, cwd="preprocessor/" + str(task.get_task()['preprocessor'])) except subprocess.CalledProcessError: logging.error("Error during preprocessor keyspace measure") send_error("Preprocessor keyspace measure failed!", self.config.get_value('token'), task.get_task()['taskId'], None) sleep(5) return False output = output.decode(encoding='utf-8').replace("\r\n", "\n").split("\n") keyspace = "0" for line in output: if not line: continue keyspace = line # as the keyspace of preprocessors can get very very large, we only save it in case it's small enough to fit in a long, # otherwise we assume that the user will abort the task earlier anyway if int(keyspace) > 9000000000000000000: # close to max size of a long long int return chunk.send_keyspace(-1, task.get_task()['taskId']) return chunk.send_keyspace(int(keyspace), task.get_task()['taskId'])
def measure_keyspace(self, task, chunk): if 'usePrince' in task.get_task() and task.get_task()['usePrince']: return self.prince_keyspace(task.get_task(), chunk) elif 'usePreprocessor' in task.get_task() and task.get_task()['usePreprocessor']: return self.preprocessor_keyspace(task, chunk) task = task.get_task() # TODO: refactor this to be better code full_cmd = self.callPath + " --keyspace --quiet " + update_files(task['attackcmd']).replace(task['hashlistAlias'] + " ", "") + ' ' + task['cmdpars'] if 'useBrain' in task and task['useBrain']: full_cmd += " -S" if Initialize.get_os() == 1: full_cmd = full_cmd.replace("/", '\\') try: logging.debug("CALL: " + full_cmd) output = subprocess.check_output(full_cmd, shell=True, cwd=self.cracker_path) except subprocess.CalledProcessError as e: logging.error("Error during keyspace measure: " + str(e)) send_error("Keyspace measure failed!", self.config.get_value('token'), task['taskId'], None) sleep(5) return False output = output.decode(encoding='utf-8').replace("\r\n", "\n").split("\n") keyspace = "0" for line in output: if not line: continue keyspace = line return chunk.send_keyspace(int(keyspace), task['taskId'])
def run_speed_benchmark(self, task): args = " --machine-readable --quiet --progress-only" args += " --restore-disable --potfile-disable --session=hashtopolis " args += update_files(task['attackcmd']).replace(task['hashlistAlias'], "../../hashlists/" + str(task['hashlistId'])) args += " -o ../../hashlists/" + str(task['hashlistId']) + ".out" full_cmd = self.callPath + args if Initialize.get_os() == 1: full_cmd = full_cmd.replace("/", '\\') try: logging.debug("CALL: " + full_cmd) output = subprocess.check_output(full_cmd, shell=True, cwd=self.cracker_path) except subprocess.CalledProcessError as e: logging.error("Error during keyspace measure, return code: " + str(e.returncode)) send_error("Keyspace measure failed!", self.config.get_value('token'), task['taskId']) return 0 output = output.decode(encoding='utf-8').replace("\r\n", "\n").split("\n") sum = [0, 0] for line in output: if len(line) == 0: continue line = line.split(":") if len(line) != 3: continue sum[0] += int(line[1]) sum[1] += float(line[2]) return str(sum[0]) + ":" + str(sum[1])
def measure_keyspace(self, task, chunk): if 'usePrince' in task.get_task() and task.get_task()['usePrince']: return self.prince_keyspace(task.get_task(), chunk) elif 'usePreprocessor' in task.get_task() and task.get_task()['usePreprocessor']: return self.preprocessor_keyspace(task, chunk) task = task.get_task() # TODO: refactor this to be better code full_cmd = self.callPath + " --keyspace --quiet " + update_files(task['attackcmd']).replace(task['hashlistAlias'] + " ", "") + ' ' + task['cmdpars'] if 'useBrain' in task and task['useBrain']: full_cmd += " -S" if Initialize.get_os() == 1: full_cmd = full_cmd.replace("/", '\\') output = b'' try: logging.debug("CALL: " + full_cmd) output = subprocess.check_output(full_cmd, shell=True, cwd=self.cracker_path, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: logging.error("Error during keyspace measure: " + str(e) + " Output: " + output.decode(encoding='utf-8')) send_error("Keyspace measure failed!", self.config.get_value('token'), task['taskId'], None) sleep(5) return False output = output.decode(encoding='utf-8').replace("\r\n", "\n").split("\n") ks = 0 # try to parse each line as a keyspace result integer (normally only one line should be in output, but some warnings might show up) for line in output: if not line: continue try: ks = int(line) except ValueError: pass return chunk.send_keyspace(ks, task['taskId'])
def run_benchmark(self, task): if task['benchType'] == 'speed': # do a speed benchmark return self.run_speed_benchmark(task) args = " --machine-readable --quiet --runtime=" + str(task['bench']) args += " --restore-disable --potfile-disable --session=hashtopolis -p \"" + str( chr(9)) + "\" " args += update_files(task['attackcmd']).replace( task['hashlistAlias'], "../../hashlists/" + str(task['hashlistId'])) + ' ' + task['cmdpars'] args += " -o ../../hashlists/" + str(task['hashlistId']) + ".out" full_cmd = self.callPath + args if Initialize.get_os() == 1: full_cmd = full_cmd.replace("/", '\\') logging.debug("CALL: " + full_cmd) proc = subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.cracker_path) output, error = proc.communicate() logging.debug("started benchmark") proc.wait() # wait until done if error: error = escape_ansi(error.replace(b"\r\n", b"\n").decode('utf-8')) # parse errors and send it to server error = error.split('\n') for line in error: if not line: continue query = copy_and_set_token(dict_clientError, self.config.get_value('token')) query['taskId'] = task['taskId'] query['message'] = line req = JsonRequest(query) req.execute() # return 0 it might not be ideal to return here. In case of errors still try to read the benchmark. if output: output = output.replace(b"\r\n", b"\n").decode('utf-8') output = output.split('\n') last_valid_status = None for line in output: if not line: continue logging.debug("HCSTAT: " + line.strip()) status = HashcatStatus(line) if status.is_valid(): last_valid_status = status if last_valid_status is None: return 0 # we just calculate how far in the task the agent went during the benchmark time return (last_valid_status.get_progress() - last_valid_status.get_rejected()) / float( last_valid_status.get_progress_total()) return 0
def build_pipe_command(self, task, chunk): # call the command with piping pre_args = " --stdout -s " + str(chunk['skip']) + " -l " + str(chunk['length']) + ' ' pre_args += update_files(task['attackcmd']).replace(task['hashlistAlias'], '') post_args = " --machine-readable --quiet --status --remove --restore-disable --potfile-disable --session=hashtopolis" post_args += " --status-timer " + str(task['statustimer']) post_args += " --outfile-check-timer=" + str(task['statustimer']) post_args += " --outfile-check-dir=../../hashlist_" + str(task['hashlistId']) post_args += " -o ../../hashlists/" + str(task['hashlistId']) + ".out --outfile-format=" + self.get_outfile_format() + " -p \"" + str(chr(9)) + "\"" post_args += " --remove-timer=" + str(task['statustimer']) post_args += " ../../hashlists/" + str(task['hashlistId']) return self.callPath + pre_args + " | " + self.callPath + post_args + task['cmdpars']
def measure_keyspace(self, task, chunk): full_cmd = self.callPath + " --keyspace --quiet " + update_files(task['attackcmd']).replace(task['hashlistAlias'] + " ", "") if Initialize.get_os() == 1: full_cmd = full_cmd.replace("/", '\\') try: output = subprocess.check_output(full_cmd, shell=True, cwd=self.cracker_path) except subprocess.CalledProcessError: logging.error("Error during keyspace measure") send_error("Keyspace measure failed!", self.config.get_value('token'), task['taskId']) return output = output.decode(encoding='utf-8').replace("\r\n", "\n").split("\n") keyspace = "0" for line in output: if len(line) == 0: continue keyspace = line chunk.send_keyspace(int(keyspace), task['taskId'])
def run_chunk(self, task, chunk): args = " --machine-readable --quiet --status --remove --restore-disable --potfile-disable --session=hashtopolis" args += " --status-timer " + str(task['statustimer']) args += " --outfile-check-timer=" + str(task['statustimer']) args += " --outfile-check-dir=../hashlist_" + str(task['hashlistId']) args += " -o ../../hashlists/" + str(task['hashlistId']) + ".out" args += " --remove-timer=" + str(task['statustimer']) args += " -s " + str(chunk['skip']) args += " -l " + str(chunk['length']) args += " " + update_files(task['attackcmd']).replace(task['hashlistAlias'], "../../hashlists/" + str(task['hashlistId'])) full_cmd = self.callPath + args if Initialize.get_os() == 1: full_cmd = full_cmd.replace("/", '\\') # clear old found file if os.path.exists("hashlists/" + str(task['hashlistId']) + ".out"): os.remove("hashlists/" + str(task['hashlistId']) + ".out") # create zap folder if not os.path.exists("hashlist_" + str(task['hashlistId'])): os.mkdir("hashlist_" + str(task['hashlistId'])) logging.debug("CALL: " + full_cmd) if Initialize.get_os() != 1: proc = subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.cracker_path, preexec_fn=os.setsid) else: proc = subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.cracker_path) logging.debug("started cracking") out_thread = Thread(target=self.stream_watcher, name='stdout-watcher', args=('OUT', proc.stdout)) err_thread = Thread(target=self.stream_watcher, name='stderr-watcher', args=('ERR', proc.stderr)) crk_thread = Thread(target=self.output_watcher, name='crack-watcher', args=("hashlists/" + str(task['hashlistId']) + ".out", proc)) out_thread.start() err_thread.start() crk_thread.start() self.first_status = False self.last_update = time.time() main_thread = Thread(target=self.run_loop, name='run_loop', args=(proc, chunk, task)) main_thread.start() # wait for all threads to finish proc.wait() crk_thread.join() out_thread.join() err_thread.join() main_thread.join() logging.info("finished chunk")