Exemple #1
0
    def parse_command(cmd):
        global slow_stop_flag

        if cmd == 's':
            Cracker.print_status()
        elif cmd == 'q':
            Comunicator.printer("Stopping...", reprint=False)
            fast_stop()
        elif cmd == 'f':
            slow_stop_flag = True
            Comunicator.finished = True
            Comunicator.printer(
                "Will finnish current job and stop. Press 'd' to cancel.")
        elif cmd == 'd':
            if Comunicator.finished:
                slow_stop_flag = False
                Comunicator.finished = False
                Comunicator.printer(
                    "Finish command cancelled. Will continue working.")
        elif Comunicator.interactive:
            if cmd == 'p':
                # TODO if finished pause might not work...
                Comunicator.paused = True
                Comunicator.printer("Pause command sent to hashcat")
                # TODO send pause command
            elif cmd == 'r':
                # TODO if process stops resume might not work
                Comunicator.paused = False
                Comunicator.printer("Resume command sent to hashcat")
                # TODO send resume command
            elif cmd == 'c':
                # TODO implement checkpoint command
                pass  # checkpoint
Exemple #2
0
    def process_result():
        # Disable communicator until we start another job
        Comunicator.disable()

        # Check if process exited cleanly
        if Cracker.crt_process is not None:
            Cracker.crt_process.check_clean_exit()
        show_stdout = list(
            filter(
                None,
                SingleProcess(Cracker.attack_command +
                              " --show").split_stdout()))
        password = ""

        # Check if we cracked something!
        if len(show_stdout) != 0:
            for line in show_stdout:
                cracked_obj = Configuration.hashcat_show_regex.match(line)
                die(
                    cracked_obj is None,
                    "REGEX error! could not match the --show line:%s" %
                    show_stdout)
                password = cracked_obj.group(1)

        msg = "[FAIL] Password for '%s' is not contained in rule '%s'" %\
              (Cracker.mac_ssid_job, Cracker.crt_rule["name"])
        if len(password) > 7:
            msg = "[SUCCESS] The password for '%s' is '%s'" % (
                Cracker.mac_ssid_job, password)

        Comunicator.printer(msg)
        Cracker.safe_send_result(password)

        Cracker.clean_variables()
Exemple #3
0
    def print_status():
        def pad(msg):
            width = 13
            return msg.ljust(width, '.') + ": "

        def human_format(num):
            magnitude = 0
            while abs(num) >= 1000:
                magnitude += 1
                num /= 1000.0
            # add more suffixes if you need them
            return '%.1f%sH/s' % (num, ['', 'K', 'M', 'G', 'T', 'P'
                                        ][magnitude])

        def space_format(num):
            return f'{num:,}'

        hashcat_status = Cracker.crt_process.get_dict()
        output = pad("Current rule") + "%s\n" % Cracker.crt_rule["name"]
        eta = hashcat_status["eta"]
        if hashcat_status["eta"] == "":
            eta = "Calculating"
        output += pad("Eta") + "%s\n" % eta

        if hashcat_status["speed"] > 0:
            if len(hashcat_status["devices"]) > 2:
                total_speed = -1
                for idx, speed in enumerate(
                        sorted(hashcat_status["devices"].keys())):
                    if total_speed == -1:
                        total_speed = speed
                        continue
                    output += pad(
                        "Speed #%d" % idx) + "%s\n" % human_format(speed)
                if total_speed != -1:
                    output += pad(
                        "Total Speed") + "%s\n" % human_format(total_speed)
            else:
                output += pad("Total Speed") + "%s\n" % human_format(
                    hashcat_status["speed"])

        if hashcat_status["progress"] > 0:
            progress_len = len(space_format(Cracker.crt_rule["wordsize"]))
            output += pad("Progress") + "%s/%s\n" % (space_format(
                hashcat_status["progress"]).rjust(
                    progress_len,
                    ' '), space_format(Cracker.crt_rule["wordsize"]))

        if output.endswith("\n"):
            output = output[:-1]

        Comunicator.printer(output)
Exemple #4
0
    def resume_work():
        if os.path.exists(Configuration.save_result_filename):
            with open(Configuration.save_result_filename) as fp:
                password = fp.read()

            Cracker.safe_send_result(password)
            return

        while True:
            try:
                Cracker.req.stopwork(suppress_stdout=True)
                break
            except Cracker.req.ServerDown:
                Comunicator.printer(Requester.DownMessage)
                sleep(10)
        return
Exemple #5
0
    def do_work():
        # Something just finished!
        if Cracker.crt_process is not None and Cracker.crt_process.isdead():
            Cracker.process_result()

        # Process is still running - update eta
        if Cracker.crt_process is not None:
            Cracker.update_eta()
            return

        if slow_stop_flag:
            Comunicator.info_logger(
                "Slow shutdown signal received - shutting down!")
            sys.exit(0)

        # Before getting more work make sure we are up to date
        Cracker.complete_missing()

        # Test capabilities once
        if not Cracker.capabilities_tested:
            Configuration.test_capabilities()
            Cracker.capabilities_tested = True

        # Nothing is running - getting more work
        try:
            work = Cracker.req.getwork()
        except Cracker.req.ServerDown:
            Comunicator.printer(Comunicator.printer(Requester.DownMessage))
            return

        die(work is True, "A server side error occured while getting work!")

        # No work to be done right now
        if work is None:
            Comunicator.printer(
                "No work to be done, checking in 10 seconds again.")
            return

        # Redundant check
        if work is False:
            Comunicator.warning_logger("Capabilities out of date!")
            return

        # Make status seem a bit more responsive
        Cracker.old_eta = "Cracking process starting"

        Cracker.start_cracking(work)
Exemple #6
0
    def run():
        Configuration.initialize()
        Cracker.crt_workload = 4  # TODO get value from parameters, adjust from keyboard

        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)

        Cracker.req = Requester(Configuration.apikey,
                                Comunicator.error_printer)

        Cracker.resume_work()

        Comunicator.initialize()

        Comunicator.printer("Cracker initialized", reprint=False)

        # Disable terminal echo
        os.system("stty -echo")

        try:
            last_time = None
            while True:
                now_time = datetime.now()
                if last_time is None or (now_time -
                                         last_time).total_seconds() > 10:
                    last_time = now_time
                    Cracker.crack_existing_handshakes()

                cmd = Comunicator.get_command()
                if cmd is not None:
                    Cracker.parse_command(cmd)
                sleep(0.1)
        except Exception as e:
            Configuration.dual_print(
                Configuration.logger.critical,
                "Caught unexpected exception: '%s'" % (traceback.format_exc()))
            Cracker.clean_variables()
            die(True, e)
        finally:
            # Reenable terminal echo
            os.system("stty echo")
            pass
Exemple #7
0
    def run():
        Comunicator.initialize()

        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)

        Configuration.initialize()
        Cracker.crt_workload = Configuration.hashcat_workload  # TODO maybe adjust from keyboard

        Cracker.req = Requester(Configuration.apikey, Comunicator.error_logger)

        Cracker.resume_work()

        Comunicator.printer("Cracker initialized", reprint=False)

        try:
            # Disable terminal echo
            os.system("stty -echo")

            last_time = None
            while True:
                now_time = datetime.now()
                if last_time is None or (now_time -
                                         last_time).total_seconds() > 10:
                    last_time = now_time
                    Cracker.do_work()

                cmd = Comunicator.get_command()
                if cmd is not None:
                    Cracker.parse_command(cmd)
                sleep(0.1)
        except Exception as e:
            Cracker.clean_variables()
            Comunicator.fatal_debug_printer(
                "Caught unexpected exception: '%s' '%s'" %
                (e, traceback.format_exc()))
        finally:
            # Reenable terminal echo
            os.system("stty echo")
            pass
Exemple #8
0
    def load_config():
        """
            Loads api key from file defined in variable Configuration.apikey_path.
            Ignores lines prefixed by '#', any leading ' ' and trailing '\n'
            The key is stored in Configuration.apikey
        :return:
            None
        """
        error_string = ""
        try:
            with open(Configuration.config_file) as file:
                config = json.load(file)

                def load_key(lkey):
                    try:
                        return config[lkey], ""
                    except KeyError:
                        return None, "Missing vital information '%s' from config file\n" % lkey

                Configuration.apikey, err = load_key("apikey")
                error_string += err
                Configuration.john_path, err = load_key("john_path")
                error_string += err
                Configuration.remote_server, err = load_key("server_location")
                error_string += err
                Configuration.hashcat_workload, err = load_key(
                    "hashcat_workload")
                error_string += err
        except json.decoder.JSONDecodeError as e:
            Comunicator.fatal_regular_message(
                "Configuration file '%s' is not a valid json with error '%s'. Fix"
                "file or completely remove to restore to default state." %
                (Configuration.config_file, e))
        except FileNotFoundError:
            with open(Configuration.config_file, "w") as fd:
                json.dump(Configuration.empty_config, fd)
            Comunicator.fatal_regular_message(
                "Configuration file '%s' did not exist. Empty file was generated, please"
                "fill in data for the cracker to properly work." %
                Configuration.config_file)
        if len(error_string) > 0:
            if error_string.endswith("\n"):
                error_string = error_string[:-1]
            Comunicator.fatal_regular_message(error_string)

        # Check remote server location
        if Configuration.remote_server is None or len(
                Configuration.remote_server) < 1:
            Comunicator.fatal_regular_message(
                "Invalid or missing remote server location. Please write server location"
                "in configuration file Ex. "
                "'\"server_location\": \"http://127.0.0.1:9645/\"'")
        if not (Configuration.remote_server.startswith("https://")
                or Configuration.remote_server.startswith("http://")):
            Comunicator.fatal_regular_message(
                "Server location should start with either 'https://' or 'http://'"
            )

        if not Configuration.remote_server.endswith("/"):
            Configuration.remote_server += "/"
        Configuration.remote_server += "api/v1/"

        Comunicator.printer("Using remote server '%s'" %
                            Configuration.remote_server)

        # Check hashcat workload
        if type(Configuration.hashcat_workload) is not int:
            Comunicator.fatal_regular_message(
                "Key 'hashcat_workload' from configuration file '%s' has invalid type %s"
                " instead of int" % (Configuration.config_file,
                                     type(Configuration.hashcat_workload)))
        if Configuration.hashcat_workload < 1 or Configuration.hashcat_workload > 4:
            Comunicator.dual_printer(
                Comunicator.logger.warn,
                "Hashcat workload should be 1-4. Value found is %d."
                "Using default 4")
            Configuration.hashcat_workload = 4

        # Check API key
        if Configuration.apikey is None or len(Configuration.apikey) < 10:
            Comunicator.fatal_regular_message(
                "Invalid or missing api key in config file '%s'. Please generate key "
                "and write it on the configuration file." %
                Configuration.config_file)

        # Check john path
        if len(Configuration.john_path) == 0:
            Configuration.john_path = None
        elif not os.path.exists(Configuration.john_path):
            Comunicator.fatal_regular_message(
                "Supplied path for john the ripper '%s' is not valid" %
                Configuration.john_path)
Exemple #9
0
    def gather_capabilities():
        """
            Returns a dictionary of the client capabilities.
            The list has two types of items:
                1) Installed programs in the form of 'program': True
                2) Files in the form of 'filename': sha1hash(file)
            The hashes are used server side to check if the files changed in any way

            This function also calls Configuration.check_file() to check if files changed
            in any way
            :return:
                Dictionary as described above
        """
        sha1_file_changed = False

        # Check if local john configuration exists
        if os.path.isfile("john-local.conf") and Configuration.check_file(
                "john-local.conf", "john-local.conf"):
            sha1_file_changed = True

        for directory in Configuration.capab_dirs:
            if not os.path.isdir(directory):
                continue

            all_files = os.listdir(directory)

            for file in all_files:
                path = os.path.join(directory, file)
                if os.path.isfile(path) and not file.startswith("."):
                    if Configuration.check_file(path, file):
                        sha1_file_changed = True

        if sha1_file_changed:
            try:
                with open(Configuration.sha1s_filename, "w+") as fd:
                    json.dump(Configuration.old_sha1s, fd, indent=4)
            except Exception as e:
                Comunicator.fatal_debug_printer(
                    "Error trying to dump data in %s: %s" %
                    (Configuration.sha1s_filename, e))

        one_program = False
        for program in Configuration.programs:
            # John path needs to be hardcoded it seems
            # Only the key is relevant for hashcat/john - we mark them with True
            if program == "john":
                if Configuration.john_path is not None:
                    if not os.path.exists(Configuration.john_path):
                        Comunicator.fatal_debug_printer(
                            "Supplied john path '%s' is invalid. Check config file!"
                            % Configuration.john_path)
                    Configuration.capabilities[program] = True
                    one_program = True
                else:
                    Comunicator.printer(
                        "John the ripper not installed, some rules will not run until it is installed and "
                        "path supplied in config file '%s'" %
                        Configuration.config_file)
                continue

            if which(program) is not None:
                Configuration.capabilities[program] = True
                one_program = True
            else:
                Comunicator.printer(
                    "'%s' not installed, some rules will not run until it is installed"
                    % program)

        if not one_program:
            Comunicator.fatal_regular_message(
                "None of the cracking programs are installed, cracking not possible!"
            )