示例#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
示例#2
0
    def stopwork(self, suppress_stdout=False):
        """
            Stop current job
            :return:
                True - An error occurred
                None - Current job stopped
            :raises Requester.ServerDown: The server could not be reached
        """
        url = Configuration.remote_server + "stopwork"
        Comunicator.info_logger("Stopping work from '%s'" % url)

        response = None
        try:
            response = requests.post(url,
                                     data={"apikey": self.apikey},
                                     timeout=10)
        except requests.exceptions.ConnectionError:
            raise Requester.ServerDown
        except requests.exceptions.Timeout:
            Configuration.log_fatal("Backend is unresponsive")
        if response.status_code == 502:
            raise Requester.ServerDown

        _, err = Requester._decode_json(response)
        if err != "":
            msg = "Error stopping work '%s'" % err
            if suppress_stdout:
                Comunicator.error_logger(msg)
            else:
                self.err_printer(msg)
            return True

        return None
示例#3
0
    def getmissing(self):
        """
            Get missing capabilities
            :return:
                True - An error occurred
                [{capability}] - List of capabilities
            :raises Requester.ServerDown: The server could not be reached
        """
        url = Configuration.remote_server + "getmissing"
        Comunicator.info_logger("Getting missing capabilites at '%s'" % url)

        response = None
        try:
            response = requests.post(url,
                                     json={
                                         "apikey": self.apikey,
                                         "capabilities":
                                         Configuration.capabilities
                                     },
                                     timeout=10)
        except requests.exceptions.ConnectionError:
            raise Requester.ServerDown
        except requests.exceptions.Timeout:
            Comunicator.fatal_regular_message("Backend is unresponsive")
        if response.status_code == 502:
            raise Requester.ServerDown

        data, err = Requester._decode_json(response)
        if err != "":
            self.err_printer(
                "Error while retrieving missing capabilites '%s'" % err)
            return True

        return data
示例#4
0
    def process_result():
        # Disable communicator until we start another job
        Comunicator.disable()

        # Check if process exited cleanly
        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)

        Cracker.safe_send_result(password)

        Cracker.clean_variables()
示例#5
0
    def _force_cleanup(self):
        try:
            if self.fst_proc and self.fst_proc.poll() is None:
                self.interrupt(self.fst_proc, self.fst_cmd)

            if self.snd_proc and self.snd_proc.poll() is None:
                self.interrupt(self.snd_proc, self.snd_cmd)

            # Close both processes writing pipe if they are still open
            self.fst_err_w = DoubleProcess._close_helper(
                self.fst_err_w)[0]  # Stops fst_err_reader_thread
            self.snd_err_w = DoubleProcess._close_helper(
                self.snd_err_w)[0]  # Stops snd_err_reader_thread
            self.snd_out_w = DoubleProcess._close_helper(
                self.snd_out_w)[0]  # Stops snd_out_reader_thread

            # Close interprocess pipe if it not killed yet
            self.comm_r = DoubleProcess._close_helper(self.comm_r)[0]
            self.comm_w = DoubleProcess._close_helper(self.comm_w)[0]

            # Join threads if they are still running. Stopping the threads also closes the respective pipes
            self.fst_err_reader_thread = DoubleProcess._join_helper(
                self.fst_err_reader_thread)[0]
            self.snd_err_reader_thread = DoubleProcess._join_helper(
                self.snd_err_reader_thread)[0]
            self.snd_out_reader_thread = DoubleProcess._join_helper(
                self.snd_out_reader_thread)[0]

            # The reading ends of the pipes were closed by the threads
            self.snd_err_r = self.snd_out_r = self.fst_err_r = None

        except AttributeError as e:
            Comunicator.error_logger("Attribute error raised %s" % e)
            pass
示例#6
0
    def checkfile(self, filename):
        """
            Check if a capability can be downloaded
            :return:
                True - An error occurred
                None - The file can be downloaded
            :raises Requester.ServerDown: The server could not be reached
         """
        url = Configuration.remote_server + "checkfile"
        Comunicator.info_logger("Checking if file '%s' exists at '%s'" %
                                (filename, url))

        response = None
        try:
            response = requests.post(url,
                                     data={
                                         "apikey": self.apikey,
                                         "file": filename
                                     },
                                     timeout=10)
        except requests.exceptions.ConnectionError:
            raise Requester.ServerDown
        except requests.exceptions.Timeout:
            Comunicator.fatal_regular_message("Backend is unresponsive")
        if response.status_code == 502:
            raise Requester.ServerDown

        _, err = Requester._decode_json(response)
        if err != "":
            self.err_printer("Error downloading '%s': '%s'" % (filename, err))
            return True

        return None
示例#7
0
    def getfile(self, filename, path):
        """
            Download capability file
            :param filename: Filename of the capability to download
            :param path: Local relative path where to save the downloaded file
            :return:
                None - File downloaded
            :raises Requester.ServerDown: The server could not be reached
        """

        url = Configuration.remote_server + "getfile"
        Comunicator.info_logger("Getting file '%s' from '%s'" %
                                (filename, url))

        try:
            with requests.post(url,
                               data={
                                   "apikey": self.apikey,
                                   "file": filename
                               },
                               stream=True,
                               timeout=10) as req:
                req.raise_for_status()
                with open(path, "wb+") as fd:
                    for chunk in req.iter_content(chunk_size=8192):
                        if chunk:
                            fd.write(chunk)
        except requests.exceptions.ConnectionError:
            raise Requester.ServerDown
        except requests.exceptions.Timeout:
            Comunicator.fatal_regular_message("Backend is unresponsive")

        return None
示例#8
0
    def _force_cleanup(self):
        try:
            if self.proc and self.proc.poll() is None:
                self.interrupt(self.proc, self.cmd)

            # Stop ___hashcat_writer_thread as soon as possible (takes a bit because of the sleep(1))
            self.stop_in_thread = True

            # Close both processes writing pipe if they are still open
            self.err_w = SingleProcess._close_helper(
                self.err_w)[0]  # Stops err_reader_thread
            self.out_w = SingleProcess._close_helper(
                self.out_w)[0]  # Stops out_reader_thread

            # Join threads if they are still running. Stopping the threads also closes the respective pipes
            self.in_writer_thread = SingleProcess._join_helper(
                self.in_writer_thread)[0]
            self.err_reader_thread = SingleProcess._join_helper(
                self.err_reader_thread)[0]
            self.out_reader_thread = SingleProcess._join_helper(
                self.out_reader_thread)[0]

            # The reading/writing ends of the pipes were closed by the threads
            self.err_r = self.out_r = self.in_w = None

            # Close the reading end of the stdin pipe
            self.in_r = SingleProcess._close_helper(self.in_r)[0]

        except AttributeError as e:
            Comunicator.error_logger("Attribute error raised %s" % e)
            pass
示例#9
0
    def sendeta(self, eta):
        """
            Send eta for current
            :return:
                True - An error occurred
                None - Eta successfully sent
            :raises Requester.ServerDown: The server could not be reached
         """
        url = Configuration.remote_server + "sendeta"
        Comunicator.info_logger("Sending eta to '%s': '%s'" % (url, eta))

        response = None
        try:
            response = requests.post(url,
                                     data={
                                         "apikey": self.apikey,
                                         "eta": eta
                                     },
                                     timeout=10)
        except requests.exceptions.ConnectionError:
            raise Requester.ServerDown
        except requests.exceptions.Timeout:
            Comunicator.fatal_regular_message("Backend is unresponsive")
        if response.status_code == 502:
            raise Requester.ServerDown

        _, err = Requester._decode_json(response)
        if err != "":
            self.err_printer("Error sending eta '%s'" % err)
            return True

        return None
示例#10
0
    def interrupt(process, cmd, wait_time=2.0):
        try:
            pid = process.pid
            if type(cmd) is list:
                cmd = ' '.join(cmd)

            Comunicator.info_logger('sending interrupt to PID %d (%s)' %
                                    (pid, cmd))

            if wait_time == 0.0:
                os.kill(pid, signal.SIGTERM)
                process.terminate()
                return

            os.kill(pid, signal.SIGINT)

            start_time = time.time()  # Time since Interrupt was sent
            while process.poll() is None:
                # Process is still running
                time.sleep(0.1)
                if time.time() - start_time > wait_time:
                    # We waited too long for process to die, terminate it.
                    Comunicator.info_logger(
                        'Waited > %0.2f seconds for process to die, killing it'
                        % wait_time)
                    os.kill(pid, signal.SIGTERM)
                    process.terminate()
                    break

        except OSError as e:
            if 'No such process' in str(e):
                return
            raise e  # process cannot be killed
示例#11
0
    def update_eta():
        new_eta_dict = Cracker.crt_process.get_dict()

        if Cracker.eta_dict is None:
            is_changed = True
        else:
            is_changed = False
            for key, value in new_eta_dict.items():
                if value != Cracker.eta_dict[key]:
                    is_changed = True
                    break

        # If no changes were made no updates are necessary
        if not is_changed:
            return

        Cracker.eta_dict = new_eta_dict
        # TODO This message is wrongly displayed right around when a hashcat process stops
        eta = "Error calculating ETA"

        # TODO maksfile eta is not properly calculated because hashcat outputs eta for current queue
        # TODO each mask has it's own queue
        # TODO implement rule 5 with hashcat only
        if Cracker.crt_rule["type"] == "filemask_hashcat" or Cracker.crt_rule[
                "wordsize"] <= 0:
            eta = "No ETA available"
        elif Cracker.eta_dict["progress"] == -1 and Cracker.eta_dict[
                "eta"] == "":
            eta = "Cracking process starting"
        elif Cracker.eta_dict["eta"] != "" and Cracker.eta_dict[
                "eta"] != "(0 secs)":
            eta = Cracker.eta_dict["eta"]
        elif Cracker.eta_dict["speed"] != -1 and Cracker.eta_dict[
                "progress"] != -1:
            # For rules generated at runtime with variable base dictionary length we cannot calculate ETA
            speed = Cracker.eta_dict["speed"]
            if speed != 0:
                if Cracker.crt_rule["wordsize"] < Cracker.eta_dict["progress"]:
                    Comunicator.error_logger(
                        "Dict size (%d) seems less than current attacked (%d)"
                        % (Cracker.crt_rule["wordsize"],
                           Cracker.eta_dict["progress"]))

                eta_seconds = (Cracker.crt_rule["wordsize"] -
                               Cracker.eta_dict["progress"]) / speed
                eta = Cracker.seconds_to_time(eta_seconds)
            else:
                eta = "Generating dict..."

        # Check if the eta already has the desired value in order to avoid an update
        # Usually happens when 'Cracker.crt_rule["wordsize"] <= 0'
        if Cracker.old_eta == eta:
            return

        Cracker.old_eta = eta

        try:
            Cracker.req.sendeta(eta)
        except Cracker.req.ServerDown:
            pass
示例#12
0
def die(condition, message):
    if condition:
        msg = "File '%s', line %s, in %s: '%s'" % \
                 (inspect.getmodule(inspect.stack()[1][0]).__file__, inspect.currentframe().f_back.f_lineno,
                  inspect.stack()[1][3], message)
        Comunicator.dual_printer(Comunicator.logger.critical, msg)
        sys.exit(-1)
示例#13
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()
示例#14
0
    def safe_send_result(password):
        written_flag = False
        while True:
            try:
                res = Cracker.req.sendresult(password)
                die(
                    res is True,
                    "Sending result '%s' for job '%s' produced an error" %
                    (password, Cracker.mac_ssid_job))

                if os.path.exists(Configuration.save_result_filename):
                    os.remove(Configuration.save_result_filename)

                if res is False:
                    Comunicator.warning_logger(
                        "Server cancelled last job. Requesting stopwork.")
                    Cracker.req.stopwork()

                break
            except Cracker.req.ServerDown:
                if not written_flag:
                    msg = "Trying to send result '%s' for last job but the server is unreachable" % password
                    Comunicator.dual_printer(Comunicator.logger.warning, msg)
                    written_flag = True
                    with open(Configuration.save_result_filename, "w") as fp:
                        fp.write(password)
                sleep(10)
示例#15
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)
示例#16
0
文件: config.py 项目: vladtp/psknow
 def test_capabilities():
     """
         Test cracking capabilities and run dummy programs to check for errors
         Removes capabilities from 'capabilities' if the test fails
     :return:
         None
     """
     if "john" in Configuration.capabilities:
         res = Configuration.test_john()
         if res is not True:
             del Configuration.capabilities["john"]
             Comunicator.dual_printer(
                 Comunicator.logger.warn,
                 "John is currently not available:\n%s" % res)
示例#17
0
    def _reap(self, now=False):
        if self.reaped:
            return True

        if now and self.proc.poll() is None:
            # Wait for the first process to stop executing
            self.proc.wait()

        if self.proc.poll() is not None:
            # Stop ___hashcat_writer_thread as soon as possible (takes a bit because of the sleep(1))
            self.stop_in_thread = True  # This stops the ___hashcat_writer_thread

            # The process stopped executing, close it's write pipes
            self.err_w = SingleProcess._close_helper(
                self.err_w)[0]  # Stops err_reader_thread
            self.out_w = SingleProcess._close_helper(
                self.out_w)[0]  # Stops out_reader_thread

            # After we closed the writing end of the pipe _all_reader_thread should stop
            self.err_reader_thread = SingleProcess._join_helper(
                self.err_reader_thread)[0]
            self.out_reader_thread = SingleProcess._join_helper(
                self.out_reader_thread)[0]

            # This process might take a bit to shutdown because it has a sleep(1)
            # Mark stop_in_thread as true ASAP in order to give the thread time to stop
            self.in_writer_thread = SingleProcess._join_helper(
                self.in_writer_thread)[0]

            # Convert error from list to string
            self.err = "".join(self.err)

            # Mark the second process as completely stopped
            self.reaped = True

            if self.critical and self.proc.poll() != 0:
                # Second process could be hashcat which sometimes returns 1 but no error
                if SingleProcess.command_is_hashcat(
                        self.cmd) and self.proc.poll() != 1:
                    Comunicator.debug_logger(
                        "Process %s exited with status %d. Stderr:\n%s" %
                        (self.cmd, self.proc.poll(), self.err))
                    self._force_cleanup()
                    Comunicator.fatal_debug_printer(
                        "Fatal error encountered in critical single process. See logs."
                    )

            return True
        return False
示例#18
0
    def _reap_snd(self, now=False):
        if self.snd_reaped:
            return True

        if now and self.snd_proc.poll() is None:
            self.snd_proc.wait()
            # self.snd_out, _ = self.snd_proc.get_output()

        if self.snd_proc.poll() is not None:
            # Process stopped so close the writing end of the pipes
            self.snd_err_w.close()
            self.snd_err_w = None

            self.snd_out_w.close()
            self.snd_out_w = None

            # Cleanup the reading pipe
            self.comm_r.close()
            self.comm_r = None

            # After we closed the writing end of the pipe _all_reader_thread should stop
            self.snd_err_reader_thread.join()
            self.snd_err_reader_thread = None

            self.snd_out_reader_thread.join()
            self.snd_out_reader_thread = None

            # Convert error from list to string
            self.snd_err = "".join(self.snd_err)

            # Mark the second process as completely stopped
            self.snd_reaped = True

            if self.critical and self.snd_proc.poll() != 0:
                # Second process could be hashcat which sometimes returns 1 but no error
                if DoubleProcess.command_is_hashcat(
                        self.snd_cmd) and self.snd_proc.poll() != 1:
                    Comunicator.debug_logger(
                        "Second process %s exited with status %d. Stderr:\n%s"
                        % (self.snd_cmd, self.snd_proc.poll(), self.snd_err))
                    self._force_cleanup()
                    Comunicator.fatal_debug_printer(
                        "Fatal error encountered in critical second process. See logs."
                    )

            return True

        return False
示例#19
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
示例#20
0
def fast_stop():
    if Cracker.crt_process is not None:
        Comunicator.info_logger("Killing running process %s" % Cracker.crt_process.get_command())
        # Kill currently running process
        Cracker.crt_process.terminate()

    # Clean current varibles so all tempfiles are deleted
    Cracker.clean_variables()

    try:
        if Cracker.req is not None:
            Cracker.req.stopwork()
    except Cracker.req.ServerDown:
        pass
    Comunicator.stop()

    sys.exit(0)
示例#21
0
    def start_cracking(work):
        Cracker.mac_ssid_job = "%s-%s" % (work["handshake"]["mac"],
                                          work["handshake"]["ssid"])
        msg = "Running '%s' with rule '%s'" % (Cracker.mac_ssid_job,
                                               work["rule"]["name"])
        Comunicator.enable(interactive=False)
        Comunicator.dual_printer(msg, Configuration.logger.info)

        _, Cracker.path_temp_file = mkstemp(prefix="psknow_crack")

        if work["handshake"]["file_type"] == "16800":
            with open(Cracker.path_temp_file, "w") as fd:
                fd.write(work["handshake"]["data"])
        else:
            with open(Cracker.path_temp_file, "wb") as fd:
                fd.write(b64decode(work["handshake"]["data"].encode("utf8")))

        # Memorize attack type - we need it to decode the output
        attack_type = work["handshake"]["handshake_type"]
        Cracker.crt_rule = work["rule"]

        attacked_file = Cracker.path_temp_file

        # Get commands needed to run hashcat
        generator_command, Cracker.attack_command, Cracker.scrambler =\
            Cracker.get_attack_command(Cracker.crt_rule, attack_type, attacked_file, work["handshake"]["ssid"])

        Configuration.logger.info(
            "Trying rule %s on '%s-%s'" %
            (Cracker.crt_rule["name"], work["handshake"]["mac"],
             work["handshake"]["ssid"]))

        if Cracker.is_potfile_duplicated(Cracker.attack_command):
            msg = "Duplication for %s happened. It is already present in potfile!" % Cracker.mac_ssid_job
            Configuration.dual_print(Configuration.logger.critical, msg)
            fast_stop()

        if generator_command == "":
            Cracker.crt_process = SingleProcess(Cracker.attack_command)
        else:
            Cracker.crt_process = DoubleProcess(generator_command,
                                                Cracker.attack_command)
示例#22
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)
示例#23
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
示例#24
0
class SwitcherCom(object):

    cmd_off = 'OFF'
    cmd_on = 'ON'
    cmd_status = 'STATUS'
    cmd_reload = 'RELOAD'
    cmd_gpio_pin = 'GPIO{0:02d}'

    state_on = 'ON'
    state_off = 'OFF'
    state_unknow = None

    resp_error = 'ERROR'
    resp_timeout = 'TIMEOUT'
    resp_ok = 'OK'
    resp_reloading = 'RELOADING'
    reps_configured = 'CONFIGURED'

    def __init__(self, log):
        self._log = log
        self.comm = Comunicator(
            Comunicator.MODE_CLIENT, SWITCHER_PIPE_IN, SWITCHER_PIPE_OUT, log
        )

    def send_command(self, command):

        response = None

        if self.comm.send_message(os.getpid(), command, timeout=15):
            self._log.info("Inviato comando %s", command)
            response = self.comm.read_message()
        else:
            return self.resp_error

        return response[1]

    def is_response_ok(self, response):
        return response[0:2] == self.resp_ok

    def get_response_msg(self, response):
        return response[3:].strip()
示例#25
0
    def getwork(self):
        """
            Send a request for work to the server
            :return:
                None - Nothing can be down with capabilities
                False - A sha1 has does not match, capabilities need updating
                True - An error occurred
                {data} - Work data requested
            :raises Requester.ServerDown: The server could not be reached
        """
        url = Configuration.remote_server + "getwork"
        Comunicator.info_logger("Requesting work from '%s'" % url)

        response = None
        try:
            response = requests.post(url,
                                     json={
                                         "apikey": self.apikey,
                                         "capabilities":
                                         Configuration.capabilities
                                     },
                                     timeout=10)
        except requests.exceptions.ConnectionError:
            raise Requester.ServerDown
        except requests.exceptions.Timeout:
            Comunicator.fatal_regular_message("Backend is unresponsive")
        if response.status_code == 502:
            raise Requester.ServerDown

        data, err = Requester._decode_json(response)
        if err != "":
            if err == Configuration.cap_updated:
                return False

            if err == Configuration.no_work_message:
                return None

            self.err_printer("Error retrieving data from server '%s'" % err)
            return True

        return data
示例#26
0
    def complete_missing():
        gather_flag = False
        try:
            missings = Cracker.req.getmissing()
        except Cracker.req.ServerDown:
            return

        die(missings is True, "Server side error occurred.")

        if missings is None:
            return

        for missing in missings:
            if missing["type"] == "program":
                Comunicator.info_logger("Please install program '%s'" %
                                        missing["name"])
            elif missing["type"] in [
                    "dict", "maskfile", "generator", "john-local.conf"
            ]:
                Comunicator.dual_printer(
                    Comunicator.logger.info,
                    "Downloading '%s'..." % missing["path"])
                gather_flag = True

                if "/" in missing["path"]:
                    directory, filename = missing["path"].rsplit('/', 1)

                    # Create directory if they do not exist
                    os.makedirs(directory, exist_ok=True)
                else:
                    filename = missing["path"]

                try:
                    if Cracker.req.checkfile(filename) is None and \
                            Cracker.req.getfile(filename, missing["path"]) is None:
                        Comunicator.dual_printer(
                            Comunicator.logger.info,
                            "Downloaded '%s'" % missing["path"])
                        if missing["type"] == "generator":
                            os.chmod(
                                missing["path"],
                                stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
                except Cracker.req.ServerDown:
                    return
            else:
                Comunicator.warning_logger("Unknown missing type '%s'" %
                                           missing)

        if gather_flag:
            Configuration.gather_capabilities()
示例#27
0
    def _reap_fst(self, now=False):
        if self.fst_reaped:
            return True

        if now and self.fst_proc.poll() is None:
            # Wait for the first process to stop executing
            self.fst_proc.wait()

        if self.fst_proc.poll() is not None:
            # The first process stopped executing, close it's write pipes
            self.fst_err_w.close()
            self.fst_err_w = None

            self.comm_w.close()
            self.comm_w = None

            # After we closed the writing end of the err pipe _all_reader_thread should stop
            self.fst_err_reader_thread.join()
            self.fst_err_reader_thread = None

            # Convert error from list to string
            self.fst_err = "".join(self.fst_err)

            # Mark the first process as completely stopped
            self.fst_reaped = True

            # TODO this can be generic. If this becomes static the poll needs to be checked against None
            if self.critical and self.fst_proc.poll() != 0:
                Comunicator.error_logger(
                    "First process %s exited with status %d. Stderr:\n%s" %
                    (self.fst_cmd, self.fst_proc.poll(), self.fst_err))
                self._force_cleanup()
                Comunicator.fatal_debug_printer(
                    "Fatal error encountered in critical first process. See logs."
                )

            return True
        return False
示例#28
0
    def pausework(self):
        """
             Pause current job
             :return:
                True - An error occurred
                None - Current job paused
             :raises Requester.ServerDown: The server could not be reached
         """
        url = Configuration.remote_server + "pausework"
        Comunicator.info_logger("Pausing work from '%s'" % url)
        try:
            response = requests.post(url, data={"apikey": self.apikey})
        except requests.exceptions.ConnectionError:
            raise Requester.ServerDown
        if response.status_code == 502:
            raise Requester.ServerDown

        _, err = Requester._decode_json(response)
        if err != "":
            self.err_printer("Error pausing work '%s'" % err)
            return True

        return None
示例#29
0
文件: config.py 项目: vladtp/psknow
    def load_sha1s():
        """
            To reduce startup time sha1's are stored in the file Configuration.sha1s_filename
            and only recalculated if the file has changed after the hash was calculated.
            This function loads the sha1 hashes along with the time when the hash was calculated into
            the variable Configuration.old_sha1s
        :return:
            None
        """
        Configuration.old_sha1s = {}
        if not os.path.exists(Configuration.sha1s_filename):
            with open(Configuration.sha1s_filename, "w+") as _:
                return

        try:
            with open(Configuration.sha1s_filename) as fd:
                Configuration.old_sha1s = json.load(fd)
        except json.decoder.JSONDecodeError:
            return
        except Exception as e:
            Comunicator.fatal_debug_printer(
                "Error trying to load %s data: %s" %
                (Configuration.sha1s_filename, e))
示例#30
0
    def sendresult(self, password):
        """
            Send results for current job
            :param password: password for the current job, can be ""
            :return:
                False - The job expired
                True - An error occurred
                None - Current job stopped
            :raises Requester.ServerDown: The server could not be reached
        """
        url = Configuration.remote_server + "sendresult"
        Comunicator.info_logger("Sending result at '%s'" % url)

        response = None
        try:
            response = requests.post(url,
                                     data={
                                         "apikey": self.apikey,
                                         "password": password
                                     },
                                     timeout=10)
        except requests.exceptions.ConnectionError:
            raise Requester.ServerDown
        except requests.exceptions.Timeout:
            Comunicator.fatal_regular_message("Backend is unresponsive")
        if response.status_code == 502:
            raise Requester.ServerDown

        _, err = Requester._decode_json(response)
        if err != "":
            if err == Configuration.no_job_message:
                return False
            self.err_printer("Error while sending result '%s'" % err)
            return True

        return None
示例#31
0
    def start_cracking(work):
        Cracker.mac_ssid_job = "%s-%s" % (work["handshake"]["mac"],
                                          work["handshake"]["ssid"])
        msg = "Running '%s' with rule '%s'" % (Cracker.mac_ssid_job,
                                               work["rule"]["name"])
        Comunicator.enable(interactive=False)
        Comunicator.dual_printer(Comunicator.logger.info, msg)

        _, Cracker.path_temp_file = mkstemp(prefix="psknow_crack")

        if work["handshake"]["file_type"] == "16800":
            with open(Cracker.path_temp_file, "w") as fd:
                fd.write(work["handshake"]["data"])
        else:
            with open(Cracker.path_temp_file, "wb") as fd:
                fd.write(b64decode(work["handshake"]["data"].encode("utf8")))

        # Memorize attack type - we need it to decode the output
        attack_type = work["handshake"]["handshake_type"]
        Cracker.crt_rule = work["rule"]

        attacked_file = Cracker.path_temp_file

        # Get commands needed to run hashcat
        generator_command, Cracker.attack_command, Cracker.scrambler =\
            Cracker.get_attack_command(Cracker.crt_rule, attack_type, attacked_file, work["handshake"]["ssid"])

        Comunicator.info_logger(
            "Trying rule %s on '%s-%s'" %
            (Cracker.crt_rule["name"], work["handshake"]["mac"],
             work["handshake"]["ssid"]))

        if Cracker.is_already_cracked(Cracker.attack_command):
            Comunicator.warning_logger(
                "'%s' has already been cracked. Attempting to send result." %
                Cracker.mac_ssid_job)
            Cracker.process_result()
            return

        if generator_command == "":
            Cracker.crt_process = SingleProcess(Cracker.attack_command)
        else:
            Cracker.crt_process = DoubleProcess(generator_command,
                                                Cracker.attack_command)
示例#32
0
文件: switcher.py 项目: balucio/smac
class Switcher(Daemon):

    DEF_LOG_LEVEL = WARNING

    def __init__(
        self, pidfile, stdin='/dev/null', stdout='/dev/null',
        stderr='/dev/null', logfile='/dev/null', invert_state=False
    ):
        super(Switcher, self).__init__(pidfile, stdin, stdout, stderr, logfile)
        self.invert_state = invert_state

    def run(self):

        # Configuro le pipe di comunicazione
        self.comm = Comunicator(
            Comunicator.MODE_SERVER, SWITCHER_PIPE_IN,
            SWITCHER_PIPE_OUT, self.log)

        if self.invert_state:

            self.STATE_ON, self.STATE_OFF = GPIO.LOW, GPIO.HIGH
            self.log.debug(
                'Stato ON -> GPIO.LOW (%s), Stato OFF -> GPIO.HIGH (%s)',
                GPIO.LOW, GPIO.HIGH)
        else:

            self.STATE_ON, self.STATE_OFF = GPIO.HIGH, GPIO.LOW
            self.log.debug(
                'Stato ON -> GPIO.HIGH (%s), Stato OFF -> GPIO.LOW (%s)',
                GPIO.HIGH, GPIO.LOW)

        # Init GPIO Board
        self.log.debug(
            'Inizializzazione GPIO: revisione %s', GPIO.RPI_REVISION)

        # Registro funzioni reload e uscita
        signal.signal(signal.SIGHUP, self._load_config)
        signal.signal(signal.SIGTERM, self._cleanup)

        state = self.STATE_OFF
        self.reset_state = True
        self.pin = None

        while True:

            if self.reset_state:
                # In attesa di configurazione pin GPIO
                self.pin = self._wait_for_gpio_pin()
                state = self.STATE_OFF
                self.reset_state = False

            # Attendo un nuovo comando
            msg = self.comm.read_message(None)
            cmd = msg[1]
            self.log.debug("Ricevuto comando: %s", cmd)

            if cmd == 'ON' or cmd == 'OFF':

                response = 'OK:%s' % (cmd)
                res = True

                if cmd == 'ON' and state != self.STATE_ON:
                    res = self._set_pin_on(self.pin)

                elif cmd == 'OFF' and state != self.STATE_OFF:
                    res = self._set_pin_off(self.pin)

                if not res:
                    response = "ERROR"
                else:
                    state = self.STATE_ON if cmd == 'ON' else self.STATE_OFF

            elif cmd == 'STATUS':
                response = 'OK:%s' % (self._get_pin_status(self.pin, state))

            elif cmd == 'RELOAD':
                self.log.warning("Ricarico configurazione...")
                self.reset_state = True
                response = "OK:RELOADING"
                GPIO.cleanup()

            elif cmd == 'TIMEOUT':
                self.log.info("Timeout in lettura")
                continue

            else:
                response = 'ERROR'

            self.log.debug("Invio risposta: %s", response)
            # Attendo qualche istante per sincronizzare l'actuator
            time.sleep(0.5)
            self.comm.send_message(getpid(), response, timeout=15)

    def _load_config(self, signum, frame):
        self.log.warning(
            "Ricevuto segnale %s frame %s: ricarico configurazione",
            signum, frame)

        GPIO.cleanup()
        self.reset_state = True

    def _cleanup(self, signum, frame):

        self.log.warning(
            "Ricevuto segnale %s frame %s: uscita", signum, frame)
        GPIO.setwarnings(False)
        GPIO.cleanup()
        exit(0)

    def _set_pin_on(self, pin):
        return self._set_pin_state(pin, self.STATE_ON)

    def _set_pin_off(self, pin):
        return self._set_pin_state(pin, self.STATE_OFF)

    def _set_pin_state(self, pin, state):

        stato_raw = 'HIGH' if state == GPIO.HIGH else 'LOW'

        try:
            GPIO.output(pin, state)
            self.log.debug("Pin: %s impostato in %s", pin, stato_raw)
            ret = True

        except Exception as e:
            self.log.error(
                "Impossibile commutare pin %s in %s: %s",
                pin, stato_raw, repr(e))
            ret = False

        return ret

    def _get_pin_status(self, pin, raw_state):

        state = 'ON' if raw_state == self.STATE_ON else 'OFF'
        self.log.debug("Pin: %s stato %s", pin, state)
        return state

    def _wait_for_gpio_pin(self):

        pin = None

        self.log.info("Attendo configurazione pin GPIO")

        while pin is None:
            msg = self.comm.read_message(None)
            gpio = msg[1]

            if 'GPIO' in gpio:
                try:
                    pin = int(gpio[-2:])
                    # Modo numerazione pin: Broadcom's SoC
                    GPIO.setmode(GPIO.BCM)
                    # Init del relè default off
                    GPIO.setup(pin, GPIO.OUT, initial=self.STATE_OFF)
                    self.log.info('Configuro GPIO %s per Relè', pin)
                    self.comm.send_message(getpid(), 'OK:CONFIGURED')

                except Exception as e:
                    pin = None
                    self.log.error(
                        'Impossibile inizializzare il pin GPIO %s', repr(e))
            else:
                self.comm.send_message(getpid(), 'ERROR', timeout=5)
                self.log.warning('Ignorato messaggio %s', msg)

        return pin
示例#33
0
 def __init__(self, log):
     self._log = log
     self.comm = Comunicator(
         Comunicator.MODE_CLIENT, SWITCHER_PIPE_IN, SWITCHER_PIPE_OUT, log
     )
示例#34
0
文件: switcher.py 项目: balucio/smac
    def run(self):

        # Configuro le pipe di comunicazione
        self.comm = Comunicator(
            Comunicator.MODE_SERVER, SWITCHER_PIPE_IN,
            SWITCHER_PIPE_OUT, self.log)

        if self.invert_state:

            self.STATE_ON, self.STATE_OFF = GPIO.LOW, GPIO.HIGH
            self.log.debug(
                'Stato ON -> GPIO.LOW (%s), Stato OFF -> GPIO.HIGH (%s)',
                GPIO.LOW, GPIO.HIGH)
        else:

            self.STATE_ON, self.STATE_OFF = GPIO.HIGH, GPIO.LOW
            self.log.debug(
                'Stato ON -> GPIO.HIGH (%s), Stato OFF -> GPIO.LOW (%s)',
                GPIO.HIGH, GPIO.LOW)

        # Init GPIO Board
        self.log.debug(
            'Inizializzazione GPIO: revisione %s', GPIO.RPI_REVISION)

        # Registro funzioni reload e uscita
        signal.signal(signal.SIGHUP, self._load_config)
        signal.signal(signal.SIGTERM, self._cleanup)

        state = self.STATE_OFF
        self.reset_state = True
        self.pin = None

        while True:

            if self.reset_state:
                # In attesa di configurazione pin GPIO
                self.pin = self._wait_for_gpio_pin()
                state = self.STATE_OFF
                self.reset_state = False

            # Attendo un nuovo comando
            msg = self.comm.read_message(None)
            cmd = msg[1]
            self.log.debug("Ricevuto comando: %s", cmd)

            if cmd == 'ON' or cmd == 'OFF':

                response = 'OK:%s' % (cmd)
                res = True

                if cmd == 'ON' and state != self.STATE_ON:
                    res = self._set_pin_on(self.pin)

                elif cmd == 'OFF' and state != self.STATE_OFF:
                    res = self._set_pin_off(self.pin)

                if not res:
                    response = "ERROR"
                else:
                    state = self.STATE_ON if cmd == 'ON' else self.STATE_OFF

            elif cmd == 'STATUS':
                response = 'OK:%s' % (self._get_pin_status(self.pin, state))

            elif cmd == 'RELOAD':
                self.log.warning("Ricarico configurazione...")
                self.reset_state = True
                response = "OK:RELOADING"
                GPIO.cleanup()

            elif cmd == 'TIMEOUT':
                self.log.info("Timeout in lettura")
                continue

            else:
                response = 'ERROR'

            self.log.debug("Invio risposta: %s", response)
            # Attendo qualche istante per sincronizzare l'actuator
            time.sleep(0.5)
            self.comm.send_message(getpid(), response, timeout=15)