Пример #1
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
Пример #2
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
Пример #3
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:
            Comunicator.fatal_regular_message("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
Пример #4
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
Пример #5
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
Пример #6
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
Пример #7
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()
Пример #8
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)
Пример #9
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)
Пример #10
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)
Пример #11
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
Пример #12
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
Пример #13
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
Пример #14
0
def signal_handler(signum, _):
    if signum == signal.SIGINT or signum == signal.SIGTERM:
        Comunicator.info_logger("Received signal %d. Exitting!" % signum)
        fast_stop()
    else:
        Comunicator.info_logger("Received %s signal" % signum)
Пример #15
0
def slow_stop(signum, _):
    global slow_stop_flag

    Comunicator.info_logger("Received %s signal. Slow stopping!" % signum)
    slow_stop_flag = True
Пример #16
0
    def __init__(self, cmd, crit=True, nolog=False):
        super(SingleProcess, self).__init__()
        if len(cmd) == 0:
            Comunicator.fatal_debug_printer(
                "Empty command '%s' send to SingleProcess" % cmd)

        self.critical = crit

        # Logging data
        self.cmd = cmd

        if not nolog:
            if type(cmd) is str:
                Comunicator.info_logger("Executing command: '%s'" % self.cmd)
            else:
                Comunicator.info_logger("Executing command: '%s'" %
                                        " ".join(self.cmd))

        # Output variables need to be mutable in order to modify them
        # from generic thread
        self.out = []
        self.err = []

        self.out_r, self.out_w = SingleProcess.get_pipe_wrapper()
        self.err_r, self.err_w = SingleProcess.get_pipe_wrapper()
        self.in_r, self.in_w = None, None
        self.in_writer_thread = None

        self.reaped = False
        self.stop_in_thread = False
        self.ended = False

        # Why an entire thread just to read from pipes?
        # Because if a pipe is full the program writing to the pipe will
        # get stuck until data is read from the pipe. If we simply call
        # wait for the process without reading data it will get stuck.
        # If we call readlines before we wait we might get stuck because
        # the writing end of the pipe is never closed... despite the program
        # not running anymore.
        self.err_reader_thread = Thread(target=self._all_reader_thread,
                                        args=(self.err_r, self.err))

        if SingleProcess.command_is_hashcat(self.cmd):
            self.in_r, self.in_w = SingleProcess.get_pipe_wrapper()
            self.in_w.write("s")
            self.in_writer_thread = Thread(
                target=self.___hashcat_writer_thread, args=(self.in_w, ))
            self.out_reader_thread = Thread(target=self._hashcat_out_thread,
                                            args=(self.out_r, self.out,
                                                  self.hashcat_progress, self))
        else:
            self.out_reader_thread = Thread(target=self._all_reader_thread,
                                            args=(self.out_r, self.out))

        if type(cmd) is str:
            cmd = cmd.split(' ')
        try:
            self.proc = Popen(cmd,
                              stdin=self.in_r,
                              stdout=self.out_w,
                              stderr=self.err_w)
        except Exception as e:
            Comunicator.fatal_debug_printer(
                "Error while trying to run command '%s':\n%s" % (cmd, e))

        if self.in_writer_thread is not None:
            self.in_writer_thread.start()
        self.err_reader_thread.start()
        self.out_reader_thread.start()