From 047191070cb97f0a64fc0a30dcb1ce7fee23e43c Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 17 Oct 2019 19:33:30 +0300 Subject: [PATCH 1/5] Small CR fixes --- monkey/common/network/network_range.py | 16 ++++++++-------- monkey/infection_monkey/exploit/sambacry.py | 1 + .../system_info/windows_info_collector.py | 4 +--- monkey/monkey_island/cc/models/monkey.py | 2 +- .../monkey_island/cc/services/config_schema.py | 2 +- monkey/monkey_island/cc/services/edge.py | 2 +- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/monkey/common/network/network_range.py b/monkey/common/network/network_range.py index 60178a3dc..21a1fa83b 100644 --- a/monkey/common/network/network_range.py +++ b/monkey/common/network/network_range.py @@ -151,10 +151,10 @@ class SingleIpRange(NetworkRange): return self._ip_address @staticmethod - def string_to_host(string): + def string_to_host(string_): """ Converts the string that user entered in "Scan IP/subnet list" to a tuple of domain name and ip - :param string: String that was entered in "Scan IP/subnet list" + :param string_: String that was entered in "Scan IP/subnet list" :return: A tuple in format (IP, domain_name). Eg. (192.168.55.1, www.google.com) """ # The most common use case is to enter ip/range into "Scan IP/subnet list" @@ -162,16 +162,16 @@ class SingleIpRange(NetworkRange): # Try casting user's input as IP try: - ip = ipaddress.ip_address(string).exploded + ip = ipaddress.ip_address(string_).exploded except ValueError: # Exception means that it's a domain name try: - ip = socket.gethostbyname(string) - domain_name = string + ip = socket.gethostbyname(string_) + domain_name = string_ except socket.error: LOG.error("Your specified host: {} is not found as a domain name and" - " it's not an IP address".format(string)) - return None, string - # If a string was entered instead of IP we presume that it was domain name and translate it + " it's not an IP address".format(string_)) + return None, string_ + # If a string_ was entered instead of IP we presume that it was domain name and translate it return ip, domain_name diff --git a/monkey/infection_monkey/exploit/sambacry.py b/monkey/infection_monkey/exploit/sambacry.py index 16366c586..e48a21616 100644 --- a/monkey/infection_monkey/exploit/sambacry.py +++ b/monkey/infection_monkey/exploit/sambacry.py @@ -217,6 +217,7 @@ class SambaCryExploiter(HostExploiter): pattern = re.compile(r'\d*\.\d*\.\d*') smb_server_name = self.host.services[SMB_SERVICE].get('name') if not smb_server_name: + LOG.info("Host: %s refused SMB connection" % self.host.ip_addr) return False samba_version = "unknown" pattern_result = pattern.search(smb_server_name) diff --git a/monkey/infection_monkey/system_info/windows_info_collector.py b/monkey/infection_monkey/system_info/windows_info_collector.py index 9d6f6a1f2..08ca6ff29 100644 --- a/monkey/infection_monkey/system_info/windows_info_collector.py +++ b/monkey/infection_monkey/system_info/windows_info_collector.py @@ -1,6 +1,7 @@ import os import logging import sys +sys.coinit_flags = 0 # needed for proper destruction of the wmi python module import infection_monkey.config from infection_monkey.system_info.mimikatz_collector import MimikatzCollector @@ -8,9 +9,6 @@ from infection_monkey.system_info import InfoCollector from infection_monkey.system_info.wmi_consts import WMI_CLASSES from common.utils.wmi_utils import WMIUtils - -sys.coinit_flags = 0 # needed for proper destruction of the wmi python module - LOG = logging.getLogger(__name__) LOG.info('started windows info collector') diff --git a/monkey/monkey_island/cc/models/monkey.py b/monkey/monkey_island/cc/models/monkey.py index fe0745496..324903809 100644 --- a/monkey/monkey_island/cc/models/monkey.py +++ b/monkey/monkey_island/cc/models/monkey.py @@ -48,7 +48,7 @@ class Monkey(Document): @staticmethod def __ring_key__(): """ - Cash key representation + Cache key representation https://ring-cache.readthedocs.io/en/stable/quickstart.html#method-classmethod-staticmethod-property :return: """ diff --git a/monkey/monkey_island/cc/services/config_schema.py b/monkey/monkey_island/cc/services/config_schema.py index 3318783b0..32ee13b12 100644 --- a/monkey/monkey_island/cc/services/config_schema.py +++ b/monkey/monkey_island/cc/services/config_schema.py @@ -1,4 +1,4 @@ -WARNING_SIGN = " \\u26A0" +WARNING_SIGN = " \u26A0" SCHEMA = { "title": "Monkey", diff --git a/monkey/monkey_island/cc/services/edge.py b/monkey/monkey_island/cc/services/edge.py index a2023d4d2..ae3d2a2de 100644 --- a/monkey/monkey_island/cc/services/edge.py +++ b/monkey/monkey_island/cc/services/edge.py @@ -155,7 +155,7 @@ class EdgeService: else: to_label = NodeService.get_node_label(NodeService.get_node_by_id(to_id)) - RIGHT_ARROW = "\\u2192" + RIGHT_ARROW = "\u2192" return "%s %s %s" % (from_label, RIGHT_ARROW, to_label) From c56dea39a91f0c0b844dbb0a2d7df136e639cb34 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 17 Oct 2019 19:39:27 +0300 Subject: [PATCH 2/5] Removed six from requirements --- monkey/infection_monkey/requirements_linux.txt | 1 - monkey/infection_monkey/requirements_windows.txt | 1 - 2 files changed, 2 deletions(-) diff --git a/monkey/infection_monkey/requirements_linux.txt b/monkey/infection_monkey/requirements_linux.txt index f30131267..e9872b396 100644 --- a/monkey/infection_monkey/requirements_linux.txt +++ b/monkey/infection_monkey/requirements_linux.txt @@ -7,7 +7,6 @@ odict paramiko psutil==3.4.2 PyInstaller -six ecdsa netifaces ipaddress diff --git a/monkey/infection_monkey/requirements_windows.txt b/monkey/infection_monkey/requirements_windows.txt index ce5021923..61fff177d 100644 --- a/monkey/infection_monkey/requirements_windows.txt +++ b/monkey/infection_monkey/requirements_windows.txt @@ -7,7 +7,6 @@ odict paramiko psutil PyInstaller -six ecdsa netifaces ipaddress From f60cdd116b49f9dc3b88e2db578c163905bdd621 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 18 Oct 2019 09:10:14 +0300 Subject: [PATCH 3/5] Replaced six package usages with py3 --- monkey/common/network/network_range.py | 3 +-- monkey/infection_monkey/network/tools.py | 2 -- monkey/monkey_island/cc/services/config.py | 5 ++--- monkey/monkey_island/cc/services/reporting/report.py | 11 +++++------ .../telemetry/zero_trust_tests/segmentation.py | 6 ++---- 5 files changed, 10 insertions(+), 17 deletions(-) diff --git a/monkey/common/network/network_range.py b/monkey/common/network/network_range.py index 21a1fa83b..7393ceda2 100644 --- a/monkey/common/network/network_range.py +++ b/monkey/common/network/network_range.py @@ -4,7 +4,6 @@ import struct from abc import ABCMeta, abstractmethod import ipaddress -from six import text_type import logging __author__ = 'itamar' @@ -78,7 +77,7 @@ class CidrRange(NetworkRange): def __init__(self, cidr_range, shuffle=True): super(CidrRange, self).__init__(shuffle=shuffle) self._cidr_range = cidr_range.strip() - self._ip_network = ipaddress.ip_network(text_type(self._cidr_range), strict=False) + self._ip_network = ipaddress.ip_network(str(self._cidr_range), strict=False) def __repr__(self): return "" % (self._cidr_range,) diff --git a/monkey/infection_monkey/network/tools.py b/monkey/infection_monkey/network/tools.py index 8fcc2892e..075babb60 100644 --- a/monkey/infection_monkey/network/tools.py +++ b/monkey/infection_monkey/network/tools.py @@ -7,8 +7,6 @@ import struct import time import re -from six.moves import range - from infection_monkey.pyinstaller_utils import get_binary_file_path from infection_monkey.utils.environment import is_64bit_python diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index a6759b15b..2d38b6498 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -3,7 +3,6 @@ import collections import functools import logging from jsonschema import Draft4Validator, validators -from six import string_types import monkey_island.cc.services.post_breach_files from monkey_island.cc.database import mongo @@ -236,7 +235,7 @@ class ConfigService: keys = [config_arr_as_array[2] for config_arr_as_array in ENCRYPTED_CONFIG_ARRAYS] for key in keys: - if isinstance(flat_config[key], collections.Sequence) and not isinstance(flat_config[key], string_types): + if isinstance(flat_config[key], collections.Sequence) and not isinstance(flat_config[key], str): # Check if we are decrypting ssh key pair if flat_config[key] and isinstance(flat_config[key][0], dict) and 'public_key' in flat_config[key][0]: flat_config[key] = [ConfigService.decrypt_ssh_key_pair(item) for item in flat_config[key]] @@ -257,7 +256,7 @@ class ConfigService: parent_config_arr = config_arr config_arr = config_arr[config_key_part] - if isinstance(config_arr, collections.Sequence) and not isinstance(config_arr, string_types): + if isinstance(config_arr, collections.Sequence) and not isinstance(config_arr, str): for i in range(len(config_arr)): # Check if array of shh key pairs and then decrypt if isinstance(config_arr[i], dict) and 'public_key' in config_arr[i]: diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index 0d2b6858d..01be940c4 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -5,7 +5,6 @@ import logging import ipaddress from bson import json_util from enum import Enum -from six import text_type from common.network.network_range import NetworkRange from common.network.segmentation_utils import get_ip_in_src_and_not_in_dst @@ -396,7 +395,7 @@ class ReportService: return \ [ - ipaddress.ip_interface(text_type(network['addr'] + '/' + network['netmask'])).network + ipaddress.ip_interface(str(network['addr'] + '/' + network['netmask'])).network for network in network_info['data']['network_info']['networks'] ] @@ -409,7 +408,7 @@ class ReportService: monkey_subnets = ReportService.get_monkey_subnets(monkey['guid']) for subnet in monkey_subnets: for ip in island_ips: - if ipaddress.ip_address(text_type(ip)) in subnet: + if ipaddress.ip_address(str(ip)) in subnet: found_good_ip = True break if found_good_ip: @@ -438,7 +437,7 @@ class ReportService: ip_in_src = None ip_in_dst = None for ip_addr in monkey['ip_addresses']: - if source_subnet_range.is_in_range(text_type(ip_addr)): + if source_subnet_range.is_in_range(str(ip_addr)): ip_in_src = ip_addr break @@ -447,7 +446,7 @@ class ReportService: continue for ip_addr in monkey['ip_addresses']: - if target_subnet_range.is_in_range(text_type(ip_addr)): + if target_subnet_range.is_in_range(str(ip_addr)): ip_in_dst = ip_addr break @@ -483,7 +482,7 @@ class ReportService: scans.rewind() # If we iterated over scans already we need to rewind. for scan in scans: target_ip = scan['data']['machine']['ip_addr'] - if target_subnet_range.is_in_range(text_type(target_ip)): + if target_subnet_range.is_in_range(str(target_ip)): monkey = NodeService.get_monkey_by_guid(scan['monkey_guid']) cross_segment_ip = get_ip_in_src_and_not_in_dst(monkey['ip_addresses'], source_subnet_range, diff --git a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/segmentation.py b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/segmentation.py index 50e60e493..b4efd3c3a 100644 --- a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/segmentation.py +++ b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/segmentation.py @@ -1,5 +1,4 @@ import itertools -from six import text_type from common.data.zero_trust_consts import STATUS_FAILED, EVENT_TYPE_MONKEY_NETWORK, STATUS_PASSED from common.network.network_range import NetworkRange @@ -34,8 +33,7 @@ def test_segmentation_violation(current_monkey, target_ip): ) -def is_segmentation_violation(current_monkey, target_ip, source_subnet, target_subnet): - # type: (Monkey, str, str, str) -> bool +def is_segmentation_violation(current_monkey: Monkey, target_ip: str, source_subnet: str, target_subnet: str) -> bool: """ Checks is a specific communication is a segmentation violation. :param current_monkey: The source monkey which originated the communication. @@ -49,7 +47,7 @@ def is_segmentation_violation(current_monkey, target_ip, source_subnet, target_s source_subnet_range = NetworkRange.get_range_obj(source_subnet) target_subnet_range = NetworkRange.get_range_obj(target_subnet) - if target_subnet_range.is_in_range(text_type(target_ip)): + if target_subnet_range.is_in_range(str(target_ip)): cross_segment_ip = get_ip_in_src_and_not_in_dst( current_monkey.ip_addresses, source_subnet_range, From c0f661d33791114e1bfeb7983fd04e008df76a68 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 18 Oct 2019 18:14:42 +0300 Subject: [PATCH 4/5] More python3 fixes --- monkey/infection_monkey/control.py | 60 +++++++++---------- monkey/infection_monkey/dropper.py | 10 ++-- monkey/infection_monkey/exploit/__init__.py | 5 +- monkey/infection_monkey/exploit/mssqlexec.py | 1 - monkey/infection_monkey/exploit/smbexec.py | 4 +- .../infection_monkey/exploit/win_ms08_067.py | 10 ++-- monkey/infection_monkey/monkey.py | 1 - monkey/infection_monkey/network/info.py | 1 - .../actions/communicate_as_new_user.py | 1 - .../infection_monkey/telemetry/base_telem.py | 3 +- monkey/infection_monkey/tunnel.py | 18 +++--- 11 files changed, 56 insertions(+), 58 deletions(-) diff --git a/monkey/infection_monkey/control.py b/monkey/infection_monkey/control.py index 4e917e5a6..54d528976 100644 --- a/monkey/infection_monkey/control.py +++ b/monkey/infection_monkey/control.py @@ -9,7 +9,7 @@ from requests.exceptions import ConnectionError import infection_monkey.monkeyfs as monkeyfs import infection_monkey.tunnel as tunnel from infection_monkey.config import WormConfiguration, GUID -from infection_monkey.network.info import local_ips, check_internet_access, TIMEOUT +from infection_monkey.network.info import local_ips, check_internet_access from infection_monkey.transport.http import HTTPConnectProxy from infection_monkey.transport.tcp import TcpProxy @@ -85,7 +85,7 @@ class ControlClient(object): except ConnectionError as exc: current_server = "" - LOG.warn("Error connecting to control server %s: %s", server, exc) + LOG.warning("Error connecting to control server %s: %s", server, exc) if current_server: return True @@ -112,14 +112,14 @@ class ControlClient(object): monkey = {} if ControlClient.proxies: monkey['tunnel'] = ControlClient.proxies.get('https') - reply = requests.patch("https://%s/api/monkey/%s" % (WormConfiguration.current_server, GUID), - data=json.dumps(monkey), - headers={'content-type': 'application/json'}, - verify=False, - proxies=ControlClient.proxies) + requests.patch("https://%s/api/monkey/%s" % (WormConfiguration.current_server, GUID), + data=json.dumps(monkey), + headers={'content-type': 'application/json'}, + verify=False, + proxies=ControlClient.proxies) except Exception as exc: - LOG.warn("Error connecting to control server %s: %s", - WormConfiguration.current_server, exc) + LOG.warning("Error connecting to control server %s: %s", + WormConfiguration.current_server, exc) return {} @staticmethod @@ -129,14 +129,14 @@ class ControlClient(object): return try: telemetry = {'monkey_guid': GUID, 'telem_category': telem_category, 'data': data} - reply = requests.post("https://%s/api/telemetry" % (WormConfiguration.current_server,), - data=json.dumps(telemetry), - headers={'content-type': 'application/json'}, - verify=False, - proxies=ControlClient.proxies) + requests.post("https://%s/api/telemetry" % (WormConfiguration.current_server,), + data=json.dumps(telemetry), + headers={'content-type': 'application/json'}, + verify=False, + proxies=ControlClient.proxies) except Exception as exc: - LOG.warn("Error connecting to control server %s: %s", - WormConfiguration.current_server, exc) + LOG.warning("Error connecting to control server %s: %s", + WormConfiguration.current_server, exc) @staticmethod def send_log(log): @@ -144,14 +144,14 @@ class ControlClient(object): return try: telemetry = {'monkey_guid': GUID, 'log': json.dumps(log)} - reply = requests.post("https://%s/api/log" % (WormConfiguration.current_server,), - data=json.dumps(telemetry), - headers={'content-type': 'application/json'}, - verify=False, - proxies=ControlClient.proxies) + requests.post("https://%s/api/log" % (WormConfiguration.current_server,), + data=json.dumps(telemetry), + headers={'content-type': 'application/json'}, + verify=False, + proxies=ControlClient.proxies) except Exception as exc: - LOG.warn("Error connecting to control server %s: %s", - WormConfiguration.current_server, exc) + LOG.warning("Error connecting to control server %s: %s", + WormConfiguration.current_server, exc) @staticmethod def load_control_config(): @@ -163,8 +163,8 @@ class ControlClient(object): proxies=ControlClient.proxies) except Exception as exc: - LOG.warn("Error connecting to control server %s: %s", - WormConfiguration.current_server, exc) + LOG.warning("Error connecting to control server %s: %s", + WormConfiguration.current_server, exc) return try: @@ -191,7 +191,7 @@ class ControlClient(object): verify=False, proxies=ControlClient.proxies) except Exception as exc: - LOG.warn("Error connecting to control server %s: %s", WormConfiguration.current_server, exc) + LOG.warning("Error connecting to control server %s: %s", WormConfiguration.current_server, exc) return {} @staticmethod @@ -261,8 +261,8 @@ class ControlClient(object): return dest_file except Exception as exc: - LOG.warn("Error connecting to control server %s: %s", - WormConfiguration.current_server, exc) + LOG.warning("Error connecting to control server %s: %s", + WormConfiguration.current_server, exc) @staticmethod def get_monkey_exe_filename_and_size_by_host(host): @@ -288,8 +288,8 @@ class ControlClient(object): return None, None except Exception as exc: - LOG.warn("Error connecting to control server %s: %s", - WormConfiguration.current_server, exc) + LOG.warning("Error connecting to control server %s: %s", + WormConfiguration.current_server, exc) return None, None diff --git a/monkey/infection_monkey/dropper.py b/monkey/infection_monkey/dropper.py index 7c576fc30..ee1194035 100644 --- a/monkey/infection_monkey/dropper.py +++ b/monkey/infection_monkey/dropper.py @@ -26,7 +26,7 @@ else: try: WindowsError except NameError: - WindowsError = None + WindowsError = IOError __author__ = 'itamar' @@ -104,14 +104,14 @@ class MonkeyDrops(object): try: ref_stat = os.stat(dropper_date_reference_path) except OSError as exc: - LOG.warn("Cannot set reference date using '%s', file not found", - dropper_date_reference_path) + LOG.warning("Cannot set reference date using '%s', file not found", + dropper_date_reference_path) else: try: os.utime(self._config['destination_path'], (ref_stat.st_atime, ref_stat.st_mtime)) except: - LOG.warn("Cannot set reference date to destination file") + LOG.warning("Cannot set reference date to destination file") monkey_options =\ build_monkey_commandline_explicitly(self.opts.parent, self.opts.tunnel, self.opts.server, self.opts.depth) @@ -135,7 +135,7 @@ class MonkeyDrops(object): time.sleep(3) if monkey_process.poll() is not None: - LOG.warn("Seems like monkey died too soon") + LOG.warning("Seems like monkey died too soon") def cleanup(self): try: diff --git a/monkey/infection_monkey/exploit/__init__.py b/monkey/infection_monkey/exploit/__init__.py index 312b747b0..9e899b140 100644 --- a/monkey/infection_monkey/exploit/__init__.py +++ b/monkey/infection_monkey/exploit/__init__.py @@ -12,7 +12,8 @@ class HostExploiter(object, metaclass=ABCMeta): # Usual values are 'vulnerability' or 'brute_force' EXPLOIT_TYPE = ExploitType.VULNERABILITY - @abstractproperty + @property + @abstractmethod def _EXPLOITED_SERVICE(self): pass @@ -73,7 +74,7 @@ class HostExploiter(object, metaclass=ABCMeta): """ powershell = True if "powershell" in cmd.lower() else False self.exploit_info['executed_cmds'].append({'cmd': cmd, 'powershell': powershell}) - + from infection_monkey.exploit.win_ms08_067 import Ms08_067_Exploiter from infection_monkey.exploit.wmiexec import WmiExploiter diff --git a/monkey/infection_monkey/exploit/mssqlexec.py b/monkey/infection_monkey/exploit/mssqlexec.py index c860326bc..dcad2adf1 100644 --- a/monkey/infection_monkey/exploit/mssqlexec.py +++ b/monkey/infection_monkey/exploit/mssqlexec.py @@ -10,7 +10,6 @@ from infection_monkey.exploit import HostExploiter from infection_monkey.exploit.tools.http_tools import MonkeyHTTPServer from infection_monkey.exploit.tools.helpers import get_monkey_dest_path, build_monkey_commandline, get_monkey_depth from infection_monkey.model import DROPPER_ARG -from infection_monkey.utils.monkey_dir import get_monkey_dir_path from infection_monkey.exploit.tools.payload_parsing import LimitedSizePayload from infection_monkey.exploit.tools.exceptions import ExploitingVulnerableMachineError diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 61c0b0a1e..18331e994 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -125,8 +125,8 @@ class SmbExploiter(HostExploiter): try: scmr_rpc.connect() except Exception as exc: - LOG.warn("Error connecting to SCM on exploited machine %r: %s", - self.host, exc) + LOG.warning("Error connecting to SCM on exploited machine %r: %s", + self.host, exc) return False smb_conn = rpctransport.get_smb_connection() diff --git a/monkey/infection_monkey/exploit/win_ms08_067.py b/monkey/infection_monkey/exploit/win_ms08_067.py index 047574d7e..7148ba965 100644 --- a/monkey/infection_monkey/exploit/win_ms08_067.py +++ b/monkey/infection_monkey/exploit/win_ms08_067.py @@ -191,11 +191,11 @@ class Ms08_067_Exploiter(HostExploiter): try: sock = exploit.start() - sock.send("cmd /c (net user %s %s /add) &&" - " (net localgroup administrators %s /add)\r\n" % - (self._config.user_to_add, - self._config.remote_user_pass, - self._config.user_to_add)) + sock.send("cmd /c (net user {} {} /add) &&" + " (net localgroup administrators {} /add)\r\n".format( + self._config.user_to_add, + self._config.remote_user_pass, + self._config.user_to_add).encode()) time.sleep(2) reply = sock.recv(1000) diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index db9ef76d4..3985c8a2e 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -6,7 +6,6 @@ import sys import time import infection_monkey.tunnel as tunnel -from infection_monkey.utils.environment import is_windows_os from infection_monkey.utils.monkey_dir import create_monkey_dir, get_monkey_dir_path, remove_monkey_dir from infection_monkey.utils.monkey_log_path import get_monkey_log_path from infection_monkey.utils.environment import is_windows_os diff --git a/monkey/infection_monkey/network/info.py b/monkey/infection_monkey/network/info.py index e41be20ac..cc198312c 100644 --- a/monkey/infection_monkey/network/info.py +++ b/monkey/infection_monkey/network/info.py @@ -1,4 +1,3 @@ -import sys import socket import struct import psutil diff --git a/monkey/infection_monkey/post_breach/actions/communicate_as_new_user.py b/monkey/infection_monkey/post_breach/actions/communicate_as_new_user.py index 04dff1441..94241e30a 100644 --- a/monkey/infection_monkey/post_breach/actions/communicate_as_new_user.py +++ b/monkey/infection_monkey/post_breach/actions/communicate_as_new_user.py @@ -1,5 +1,4 @@ import logging -import os import random import string import subprocess diff --git a/monkey/infection_monkey/telemetry/base_telem.py b/monkey/infection_monkey/telemetry/base_telem.py index 17cf6cb63..2d59b9cbf 100644 --- a/monkey/infection_monkey/telemetry/base_telem.py +++ b/monkey/infection_monkey/telemetry/base_telem.py @@ -25,7 +25,8 @@ class BaseTelem(object, metaclass=abc.ABCMeta): logger.debug("Sending {} telemetry. Data: {}".format(self.telem_category, json.dumps(data))) ControlClient.send_telemetry(self.telem_category, data) - @abc.abstractproperty + @property + @abc.abstractmethod def telem_category(self): """ :return: Telemetry type diff --git a/monkey/infection_monkey/tunnel.py b/monkey/infection_monkey/tunnel.py index 722dea50e..f2124f9fc 100644 --- a/monkey/infection_monkey/tunnel.py +++ b/monkey/infection_monkey/tunnel.py @@ -48,7 +48,7 @@ def _check_tunnel(address, port, existing_sock=None): return False try: - sock.sendto("+", (address, MCAST_PORT)) + sock.sendto(b"+", (address, MCAST_PORT)) except Exception as exc: LOG.debug("Caught exception in tunnel registration: %s", exc) @@ -71,13 +71,13 @@ def find_tunnel(default=None, attempts=3, timeout=DEFAULT_TIMEOUT): try: LOG.info("Trying to find using adapter %s", adapter) sock = _set_multicast_socket(timeout, adapter) - sock.sendto("?", (MCAST_GROUP, MCAST_PORT)) + sock.sendto(b"?", (MCAST_GROUP, MCAST_PORT)) tunnels = [] while True: try: answer, address = sock.recvfrom(BUFFER_READ) - if answer not in ['?', '+', '-']: + if answer not in [b'?', b'+', b'-']: tunnels.append(answer) except socket.timeout: break @@ -102,7 +102,7 @@ def find_tunnel(default=None, attempts=3, timeout=DEFAULT_TIMEOUT): def quit_tunnel(address, timeout=DEFAULT_TIMEOUT): try: sock = _set_multicast_socket(timeout) - sock.sendto("-", (address, MCAST_PORT)) + sock.sendto(b"-", (address, MCAST_PORT)) sock.close() LOG.debug("Success quitting tunnel") except Exception as exc: @@ -147,17 +147,17 @@ class MonkeyTunnel(Thread): while not self._stopped: try: search, address = self._broad_sock.recvfrom(BUFFER_READ) - if '?' == search: + if b'?' == search: ip_match = get_interface_to_target(address[0]) if ip_match: answer = '%s:%d' % (ip_match, self.local_port) LOG.debug("Got tunnel request from %s, answering with %s", address[0], answer) - self._broad_sock.sendto(answer, (address[0], MCAST_PORT)) - elif '+' == search: + self._broad_sock.sendto(answer.encode(), (address[0], MCAST_PORT)) + elif b'+' == search: if not address[0] in self._clients: LOG.debug("Tunnel control: Added %s to watchlist", address[0]) self._clients.append(address[0]) - elif '-' == search: + elif b'-' == search: LOG.debug("Tunnel control: Removed %s from watchlist", address[0]) self._clients = [client for client in self._clients if client != address[0]] @@ -170,7 +170,7 @@ class MonkeyTunnel(Thread): while self._clients and (time.time() - get_last_serve_time() < QUIT_TIMEOUT): try: search, address = self._broad_sock.recvfrom(BUFFER_READ) - if '-' == search: + if b'-' == search: LOG.debug("Tunnel control: Removed %s from watchlist", address[0]) self._clients = [client for client in self._clients if client != address[0]] except socket.timeout: From 3d332c7d6608e247898df8672e212fdf53c9b37c Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Mon, 21 Oct 2019 17:38:39 +0300 Subject: [PATCH 5/5] More python3 outdated decorators and bytes-string mixup fixes --- monkey/common/cloud/aws_instance.py | 7 ++++--- monkey/infection_monkey/exploit/sshexec.py | 2 +- monkey/infection_monkey/exploit/struts2.py | 5 +---- monkey/infection_monkey/monkey.spec | 1 + monkey/infection_monkey/network/tools.py | 2 +- .../post_breach/actions/communicate_as_new_user.py | 2 +- monkey/infection_monkey/post_breach/pba.py | 5 +++-- monkey/monkey_island/cc/resources/remote_run.py | 4 ++-- .../cc/services/attack/technique_reports/__init__.py | 12 ++++++++---- 9 files changed, 22 insertions(+), 18 deletions(-) diff --git a/monkey/common/cloud/aws_instance.py b/monkey/common/cloud/aws_instance.py index 6b13b69bb..ac4fe633e 100644 --- a/monkey/common/cloud/aws_instance.py +++ b/monkey/common/cloud/aws_instance.py @@ -27,16 +27,17 @@ class AwsInstance(object): try: self.instance_id = urllib.request.urlopen( - AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/instance-id', timeout=2).read() + AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/instance-id', timeout=2).read().decode() self.region = self._parse_region( - urllib.request.urlopen(AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/placement/availability-zone').read()) + urllib.request.urlopen(AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/placement/availability-zone').read(). + decode()) except (urllib.error.URLError, IOError) as e: logger.debug("Failed init of AwsInstance while getting metadata: {}".format(e)) try: self.account_id = self._extract_account_id( urllib.request.urlopen( - AWS_LATEST_METADATA_URI_PREFIX + 'dynamic/instance-identity/document', timeout=2).read()) + AWS_LATEST_METADATA_URI_PREFIX + 'dynamic/instance-identity/document', timeout=2).read().decode()) except (urllib.error.URLError, IOError) as e: logger.debug("Failed init of AwsInstance while getting dynamic instance data: {}".format(e)) diff --git a/monkey/infection_monkey/exploit/sshexec.py b/monkey/infection_monkey/exploit/sshexec.py index f7abd3ce0..ce2e0d13c 100644 --- a/monkey/infection_monkey/exploit/sshexec.py +++ b/monkey/infection_monkey/exploit/sshexec.py @@ -125,7 +125,7 @@ class SSHExploiter(HostExploiter): if not self.host.os.get('type'): try: _, stdout, _ = ssh.exec_command('uname -o') - uname_os = stdout.read().lower().strip() + uname_os = stdout.read().lower().strip().decode() if 'linux' in uname_os: self.host.os['type'] = 'linux' else: diff --git a/monkey/infection_monkey/exploit/struts2.py b/monkey/infection_monkey/exploit/struts2.py index 4be2d0acd..fc2fd764d 100644 --- a/monkey/infection_monkey/exploit/struts2.py +++ b/monkey/infection_monkey/exploit/struts2.py @@ -79,9 +79,6 @@ class Struts2Exploiter(WebRCE): "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." \ "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." \ "(#ros.flush())}" % cmd - # Turns payload ascii just for consistency - if isinstance(payload, str): - payload = unicodedata.normalize('NFKD', payload).encode('ascii', 'ignore') headers = {'User-Agent': 'Mozilla/5.0', 'Content-Type': payload} try: request = urllib.request.Request(url, headers=headers) @@ -91,6 +88,6 @@ class Struts2Exploiter(WebRCE): # If url does not exist return False except http.client.IncompleteRead as e: - page = e.partial + page = e.partial.decode() return page diff --git a/monkey/infection_monkey/monkey.spec b/monkey/infection_monkey/monkey.spec index d29adddb1..0ada7f403 100644 --- a/monkey/infection_monkey/monkey.spec +++ b/monkey/infection_monkey/monkey.spec @@ -38,6 +38,7 @@ def main(): debug=False, strip=get_exe_strip(), upx=True, + upx_exclude=['vcruntime140.dll'], console=True, icon=get_exe_icon()) diff --git a/monkey/infection_monkey/network/tools.py b/monkey/infection_monkey/network/tools.py index 075babb60..0cac7b627 100644 --- a/monkey/infection_monkey/network/tools.py +++ b/monkey/infection_monkey/network/tools.py @@ -71,7 +71,7 @@ def check_tcp_port(ip, port, timeout=DEFAULT_TIMEOUT, get_banner=False): if get_banner: read_ready, _, _ = select.select([sock], [], [], timeout) if len(read_ready) > 0: - banner = sock.recv(BANNER_READ) + banner = sock.recv(BANNER_READ).decode() except socket.error: pass diff --git a/monkey/infection_monkey/post_breach/actions/communicate_as_new_user.py b/monkey/infection_monkey/post_breach/actions/communicate_as_new_user.py index 94241e30a..2a1a79b91 100644 --- a/monkey/infection_monkey/post_breach/actions/communicate_as_new_user.py +++ b/monkey/infection_monkey/post_breach/actions/communicate_as_new_user.py @@ -38,7 +38,7 @@ class CommunicateAsNewUser(PBA): exit_status = new_user.run_as(ping_commandline) self.send_ping_result_telemetry(exit_status, ping_commandline, username) except subprocess.CalledProcessError as e: - PostBreachTelem(self, (e.output, False)).send() + PostBreachTelem(self, (e.output.decode(), False)).send() except NewUserError as e: PostBreachTelem(self, (str(e), False)).send() diff --git a/monkey/infection_monkey/post_breach/pba.py b/monkey/infection_monkey/post_breach/pba.py index 8d7723df2..73b8a3221 100644 --- a/monkey/infection_monkey/post_breach/pba.py +++ b/monkey/infection_monkey/post_breach/pba.py @@ -14,6 +14,7 @@ __author__ = 'VakarisZ' EXECUTION_WITHOUT_OUTPUT = "(PBA execution produced no output)" + class PBA(object): """ Post breach action object. Can be extended to support more than command execution on target machine. @@ -75,13 +76,13 @@ class PBA(object): :return: Tuple of command's output string and boolean, indicating if it succeeded """ try: - output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True) + output = subprocess.check_output(self.command, stderr=subprocess.STDOUT, shell=True).decode() if not output: output = EXECUTION_WITHOUT_OUTPUT return output, True except subprocess.CalledProcessError as e: # Return error output of the command - return e.output, False + return e.output.decode(), False @staticmethod def choose_command(linux_cmd, windows_cmd): diff --git a/monkey/monkey_island/cc/resources/remote_run.py b/monkey/monkey_island/cc/resources/remote_run.py index 675c292c1..c41699add 100644 --- a/monkey/monkey_island/cc/resources/remote_run.py +++ b/monkey/monkey_island/cc/resources/remote_run.py @@ -34,10 +34,10 @@ class RemoteRun(flask_restful.Resource): try: resp['instances'] = AwsService.get_instances() except NoCredentialsError as e: - resp['error'] = NO_CREDS_ERROR_FORMAT.format(e.message) + resp['error'] = NO_CREDS_ERROR_FORMAT.format(e) return jsonify(resp) except ClientError as e: - resp['error'] = CLIENT_ERROR_FORMAT.format(e.message) + resp['error'] = CLIENT_ERROR_FORMAT.format(e) return jsonify(resp) return jsonify(resp) diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py index b5f100bd1..b9a2fd795 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py @@ -12,28 +12,32 @@ logger = logging.getLogger(__name__) class AttackTechnique(object, metaclass=abc.ABCMeta): """ Abstract class for ATT&CK report components """ - @abc.abstractproperty + @property + @abc.abstractmethod def unscanned_msg(self): """ :return: Message that will be displayed in case attack technique was not scanned. """ pass - @abc.abstractproperty + @property + @abc.abstractmethod def scanned_msg(self): """ :return: Message that will be displayed in case attack technique was scanned. """ pass - @abc.abstractproperty + @property + @abc.abstractmethod def used_msg(self): """ :return: Message that will be displayed in case attack technique was used by the scanner. """ pass - @abc.abstractproperty + @property + @abc.abstractmethod def tech_id(self): """ :return: Message that will be displayed in case of attack technique not being scanned.