From 49654d4dfe5e358d407ae086eeb3a9a1c3e9ca9e Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 30 May 2022 15:14:58 +0200 Subject: [PATCH 1/7] Island, Agent: Move dropper option from WormConfiguration to consts * Remove dropper_set_date, dropper_date_reference_path_windows dropper_date_reference_path_linux from internal config in the Island * Remove all references to these options from data for tests --- monkey/infection_monkey/config.py | 8 ------- monkey/infection_monkey/dropper.py | 22 ++++++----------- .../cc/services/config_schema/internal.py | 24 ------------------- .../automated_master_config.json | 1 - .../monkey_configs/flat_config.json | 3 --- .../monkey_config_standard.json | 3 --- 6 files changed, 7 insertions(+), 54 deletions(-) diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index 1f8c46311..5b5ce3722 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -65,14 +65,6 @@ class Configuration(object): return result - ########################### - # dropper config - ########################### - - dropper_set_date = True - dropper_date_reference_path_windows = r"%windir%\system32\kernel32.dll" - dropper_date_reference_path_linux = "/bin/sh" - ########################### # monkey config ########################### diff --git a/monkey/infection_monkey/dropper.py b/monkey/infection_monkey/dropper.py index 4bbc272ea..57259950f 100644 --- a/monkey/infection_monkey/dropper.py +++ b/monkey/infection_monkey/dropper.py @@ -10,7 +10,6 @@ import time from pathlib import WindowsPath from common.utils.attack_utils import UsageEnum -from infection_monkey.config import WormConfiguration from infection_monkey.utils.commands import ( build_monkey_commandline_explicitly, get_monkey_commandline_linux, @@ -35,6 +34,8 @@ except NameError: logger = logging.getLogger(__name__) MOVEFILE_DELAY_UNTIL_REBOOT = 4 +DATE_REFERENCE_PATH_WINDOWS = r"%windir%\system32\kernel32.dll" +DATE_REFERENCE_PATH_LINUX = "/bin/sh" class MonkeyDrops(object): @@ -110,27 +111,18 @@ class MonkeyDrops(object): return False - if WormConfiguration.dropper_set_date: - if sys.platform == "win32": - dropper_date_reference_path = os.path.expandvars( - WormConfiguration.dropper_date_reference_path_windows - ) - else: - dropper_date_reference_path = WormConfiguration.dropper_date_reference_path_linux + if sys.platform == "win32": + dropper_date_reference_path = os.path.expandvars(DATE_REFERENCE_PATH_WINDOWS) + else: + dropper_date_reference_path = DATE_REFERENCE_PATH_LINUX try: ref_stat = os.stat(dropper_date_reference_path) + os.utime(self._config["destination_path"], (ref_stat.st_atime, ref_stat.st_mtime)) except OSError: logger.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 OSError: - logger.warning("Cannot set reference date to destination file") monkey_options = build_monkey_commandline_explicitly( parent=self.opts.parent, diff --git a/monkey/monkey_island/cc/services/config_schema/internal.py b/monkey/monkey_island/cc/services/config_schema/internal.py index 86a0089ec..1b684b31f 100644 --- a/monkey/monkey_island/cc/services/config_schema/internal.py +++ b/monkey/monkey_island/cc/services/config_schema/internal.py @@ -144,30 +144,6 @@ INTERNAL = { "title": "Dropper", "type": "object", "properties": { - "dropper_set_date": { - "title": "Dropper sets date", - "type": "boolean", - "default": True, - "description": "Determines whether the dropper should set the monkey's file " - "date to be the same as" - " another file", - }, - "dropper_date_reference_path_windows": { - "title": "Dropper date reference path (Windows)", - "type": "string", - "default": "%windir%\\system32\\kernel32.dll", - "description": "Determines which file the dropper should copy the date from if " - "it's configured to do" - " so on Windows (use fullpath)", - }, - "dropper_date_reference_path_linux": { - "title": "Dropper date reference path (Linux)", - "type": "string", - "default": "/bin/sh", - "description": "Determines which file the dropper should copy the date from if " - "it's configured to do" - " so on Linux (use fullpath)", - }, "dropper_target_path_linux": { "title": "Dropper target path on Linux", "type": "string", diff --git a/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json b/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json index 8ed5eb8b8..eb61845cf 100644 --- a/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json +++ b/monkey/tests/data_for_tests/monkey_configs/automated_master_config.json @@ -69,7 +69,6 @@ "windows_command": "" }, "depth": 2, - "dropper_set_date": true, "exploit_lm_hash_list": ["DEADBEEF", "FACADE"], "exploit_ntlm_hash_list": ["BEADED", "ACCEDE", "DECADE"], "exploit_password_list": ["p1", "p2", "p3"], diff --git a/monkey/tests/data_for_tests/monkey_configs/flat_config.json b/monkey/tests/data_for_tests/monkey_configs/flat_config.json index 2f48f30a6..7faa69069 100644 --- a/monkey/tests/data_for_tests/monkey_configs/flat_config.json +++ b/monkey/tests/data_for_tests/monkey_configs/flat_config.json @@ -21,9 +21,6 @@ "custom_PBA_linux_cmd": "bash test.sh", "custom_PBA_windows_cmd": "powershell test.ps1", "depth": 2, - "dropper_date_reference_path_linux": "/bin/sh", - "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", - "dropper_set_date": true, "dropper_target_path_linux": "/tmp/monkey", "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", "exploit_lm_hash_list": ["lm_hash_1", "lm_hash_2"], diff --git a/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json b/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json index 1ffce78cf..31a2beace 100644 --- a/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json +++ b/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json @@ -97,9 +97,6 @@ ] }, "dropper": { - "dropper_set_date": true, - "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", - "dropper_date_reference_path_linux": "/bin/sh", "dropper_target_path_linux": "/tmp/monkey", "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe" }, From b8e943f7a80e2c81888fae51c0f1904edc65526d Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 31 May 2022 13:59:08 +0200 Subject: [PATCH 2/7] Agent: Decouple dropper target paths from the config * Dropper target paths are now part of infection_monkey.model --- monkey/infection_monkey/exploit/hadoop.py | 2 +- monkey/infection_monkey/exploit/log4shell.py | 2 +- monkey/infection_monkey/exploit/mssqlexec.py | 2 +- monkey/infection_monkey/exploit/powershell.py | 2 +- monkey/infection_monkey/exploit/smbexec.py | 2 +- monkey/infection_monkey/exploit/sshexec.py | 2 +- .../infection_monkey/exploit/tools/helpers.py | 9 +++---- monkey/infection_monkey/exploit/web_rce.py | 11 ++++---- monkey/infection_monkey/exploit/wmiexec.py | 12 ++++++--- monkey/infection_monkey/model/__init__.py | 4 +++ .../monkey_configs/flat_config.json | 2 -- .../monkey_config_standard.json | 4 --- .../exploit/test_powershell.py | 9 ++++--- .../exploit/tools/test_helpers.py | 27 ++++++++++--------- 14 files changed, 48 insertions(+), 42 deletions(-) diff --git a/monkey/infection_monkey/exploit/hadoop.py b/monkey/infection_monkey/exploit/hadoop.py index c704f9814..318e37d67 100644 --- a/monkey/infection_monkey/exploit/hadoop.py +++ b/monkey/infection_monkey/exploit/hadoop.py @@ -43,7 +43,7 @@ class HadoopExploiter(WebRCE): return self.exploit_result try: - monkey_path_on_victim = get_agent_dest_path(self.host, self.options) + monkey_path_on_victim = get_agent_dest_path(self.host) except KeyError: return self.exploit_result diff --git a/monkey/infection_monkey/exploit/log4shell.py b/monkey/infection_monkey/exploit/log4shell.py index dc8fe0c66..b59c72dd4 100644 --- a/monkey/infection_monkey/exploit/log4shell.py +++ b/monkey/infection_monkey/exploit/log4shell.py @@ -61,7 +61,7 @@ class Log4ShellExploiter(WebRCE): self._agent_http_server_thread = None def _start_servers(self): - target_path = get_agent_dest_path(self.host, self.options) + target_path = get_agent_dest_path(self.host) # Start http server, to serve agent to victims agent_http_path = self._start_agent_http_server(target_path) diff --git a/monkey/infection_monkey/exploit/mssqlexec.py b/monkey/infection_monkey/exploit/mssqlexec.py index c765c2de5..147403580 100644 --- a/monkey/infection_monkey/exploit/mssqlexec.py +++ b/monkey/infection_monkey/exploit/mssqlexec.py @@ -59,7 +59,7 @@ class MSSQLExploiter(HostExploiter): Also, don't forget to start_monkey_server() before self.upload_monkey() and self.stop_monkey_server() after """ - monkey_path_on_victim = get_agent_dest_path(self.host, self.options) + monkey_path_on_victim = get_agent_dest_path(self.host) # Brute force to get connection creds = generate_identity_secret_pairs( diff --git a/monkey/infection_monkey/exploit/powershell.py b/monkey/infection_monkey/exploit/powershell.py index d711bec19..16073a014 100644 --- a/monkey/infection_monkey/exploit/powershell.py +++ b/monkey/infection_monkey/exploit/powershell.py @@ -134,7 +134,7 @@ class PowerShellExploiter(HostExploiter): raise ValueError(f"Unknown secret type {credentials.secret_type}") def _execute_monkey_agent_on_victim(self): - monkey_path_on_victim = get_agent_dest_path(self.host, self.options) + monkey_path_on_victim = get_agent_dest_path(self.host) self._copy_monkey_binary_to_victim(monkey_path_on_victim) logger.info("Successfully copied the monkey binary to the victim.") diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 10b7009b0..825cb37ce 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -31,7 +31,7 @@ class SMBExploiter(HostExploiter): def _exploit_host(self): agent_binary = self.agent_repository.get_agent_binary(self.host.os["type"]) - dest_path = get_agent_dest_path(self.host, self.options) + dest_path = get_agent_dest_path(self.host) creds = generate_brute_force_combinations(self.options["credentials"]) for user, password, lm_hash, ntlm_hash in interruptible_iter(creds, self.interrupt): diff --git a/monkey/infection_monkey/exploit/sshexec.py b/monkey/infection_monkey/exploit/sshexec.py index 3c4c46641..7f9619e95 100644 --- a/monkey/infection_monkey/exploit/sshexec.py +++ b/monkey/infection_monkey/exploit/sshexec.py @@ -209,7 +209,7 @@ class SSHExploiter(HostExploiter): self._set_interrupted() return self.exploit_result - monkey_path_on_victim = get_agent_dest_path(self.host, self.options) + monkey_path_on_victim = get_agent_dest_path(self.host) try: with ssh.open_sftp() as ftp: diff --git a/monkey/infection_monkey/exploit/tools/helpers.py b/monkey/infection_monkey/exploit/tools/helpers.py index 05a15aed7..2739da215 100644 --- a/monkey/infection_monkey/exploit/tools/helpers.py +++ b/monkey/infection_monkey/exploit/tools/helpers.py @@ -2,9 +2,8 @@ import logging import random import string from pathlib import PurePath, PurePosixPath, PureWindowsPath -from typing import Any, Mapping -from infection_monkey.model import VictimHost +from infection_monkey.model import DROPPER_TARGET_PATH_LINUX, DROPPER_TARGET_PATH_WIN64, VictimHost logger = logging.getLogger(__name__) @@ -18,11 +17,11 @@ def get_random_file_suffix() -> str: return random_string -def get_agent_dest_path(host: VictimHost, options: Mapping[str, Any]) -> PurePath: +def get_agent_dest_path(host: VictimHost) -> PurePath: if host.os["type"] == "windows": - path = PureWindowsPath(options["dropper_target_path_win_64"]) + path = PureWindowsPath(DROPPER_TARGET_PATH_WIN64) else: - path = PurePosixPath(options["dropper_target_path_linux"]) + path = PurePosixPath(DROPPER_TARGET_PATH_LINUX) return _add_random_suffix(path) diff --git a/monkey/infection_monkey/exploit/web_rce.py b/monkey/infection_monkey/exploit/web_rce.py index 4f32a2f3f..9363f5b32 100644 --- a/monkey/infection_monkey/exploit/web_rce.py +++ b/monkey/infection_monkey/exploit/web_rce.py @@ -12,6 +12,8 @@ from infection_monkey.model import ( CHMOD_MONKEY, DOWNLOAD_TIMEOUT, DROPPER_ARG, + DROPPER_TARGET_PATH_LINUX, + DROPPER_TARGET_PATH_WIN64, ID_STRING, MONKEY_ARG, POWERSHELL_HTTP_UPLOAD, @@ -109,8 +111,8 @@ class WebRCE(HostExploiter): def pre_exploit(self): if not self.monkey_target_paths: self.monkey_target_paths = { - "linux": self.options["dropper_target_path_linux"], - "windows": self.options["dropper_target_path_win_64"], + "linux": DROPPER_TARGET_PATH_LINUX, + "windows": DROPPER_TARGET_PATH_WIN64, } self.HTTP = [str(port) for port in self.options["http_ports"]] super().pre_exploit() @@ -405,7 +407,6 @@ class WebRCE(HostExploiter): """ Gets default dropper path for the host. :return: Default monkey's destination path for corresponding host or False if failed. - E.g. config.dropper_target_path_linux(/tmp/monkey.sh) for linux host """ if not self.host.os.get("type") or ( self.host.os["type"] != "linux" and self.host.os["type"] != "windows" @@ -413,9 +414,9 @@ class WebRCE(HostExploiter): logger.error("Target's OS was either unidentified or not supported. Aborting") return False if self.host.os["type"] == "linux": - return self.options["dropper_target_path_linux"] + return DROPPER_TARGET_PATH_LINUX if self.host.os["type"] == "windows": - return self.options["dropper_target_path_win_64"] + return DROPPER_TARGET_PATH_WIN64 def get_target_url(self): """ diff --git a/monkey/infection_monkey/exploit/wmiexec.py b/monkey/infection_monkey/exploit/wmiexec.py index 753dc511b..a008beee2 100644 --- a/monkey/infection_monkey/exploit/wmiexec.py +++ b/monkey/infection_monkey/exploit/wmiexec.py @@ -10,7 +10,11 @@ from infection_monkey.exploit.tools.helpers import get_agent_dest_path from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.exploit.tools.wmi_tools import AccessDeniedException, WmiTools from infection_monkey.i_puppet import ExploiterResultData -from infection_monkey.model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS +from infection_monkey.model import ( + DROPPER_CMDLINE_WINDOWS, + DROPPER_TARGET_PATH_WIN64, + MONKEY_CMDLINE_WINDOWS, +) from infection_monkey.utils.brute_force import ( generate_brute_force_combinations, get_credential_string, @@ -74,7 +78,7 @@ class WmiExploiter(HostExploiter): self._set_interrupted() return self.exploit_result - target_path = get_agent_dest_path(self.host, self.options) + target_path = get_agent_dest_path(self.host) remote_full_path = SmbTools.copy_file( self.host, @@ -91,13 +95,13 @@ class WmiExploiter(HostExploiter): wmi_connection.close() return self.exploit_result # execute the remote dropper in case the path isn't final - elif remote_full_path.lower() != self.options["dropper_target_path_win_64"]: + elif remote_full_path.lower() != DROPPER_TARGET_PATH_WIN64: cmdline = DROPPER_CMDLINE_WINDOWS % { "dropper_path": remote_full_path } + build_monkey_commandline( self.host, self.current_depth - 1, - self.options["dropper_target_path_win_64"], + DROPPER_TARGET_PATH_WIN64, ) else: cmdline = MONKEY_CMDLINE_WINDOWS % { diff --git a/monkey/infection_monkey/model/__init__.py b/monkey/infection_monkey/model/__init__.py index 138dbf92a..e81861ee7 100644 --- a/monkey/infection_monkey/model/__init__.py +++ b/monkey/infection_monkey/model/__init__.py @@ -5,6 +5,10 @@ MONKEY_ARG = "m0nk3y" DROPPER_ARG = "dr0pp3r" ID_STRING = "M0NK3Y3XPL0ITABLE" +# Dropper target paths +DROPPER_TARGET_PATH_LINUX = "/tmp/monkey" +DROPPER_TARGET_PATH_WIN64 = r"C:\Windows\temp\monkey64.exe" + # Username prefix for users created by Infection Monkey USERNAME_PREFIX = "somenewuser" diff --git a/monkey/tests/data_for_tests/monkey_configs/flat_config.json b/monkey/tests/data_for_tests/monkey_configs/flat_config.json index 7faa69069..c1b924439 100644 --- a/monkey/tests/data_for_tests/monkey_configs/flat_config.json +++ b/monkey/tests/data_for_tests/monkey_configs/flat_config.json @@ -21,8 +21,6 @@ "custom_PBA_linux_cmd": "bash test.sh", "custom_PBA_windows_cmd": "powershell test.ps1", "depth": 2, - "dropper_target_path_linux": "/tmp/monkey", - "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", "exploit_lm_hash_list": ["lm_hash_1", "lm_hash_2"], "exploit_ntlm_hash_list": ["nt_hash_1", "nt_hash_2", "nt_hash_3"], "exploit_password_list": [ diff --git a/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json b/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json index 31a2beace..f62cb5dcb 100644 --- a/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json +++ b/monkey/tests/data_for_tests/monkey_configs/monkey_config_standard.json @@ -96,10 +96,6 @@ "ElasticFinger" ] }, - "dropper": { - "dropper_target_path_linux": "/tmp/monkey", - "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe" - }, "exploits": { "exploit_lm_hash_list": [], "exploit_ntlm_hash_list": [], diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py index 78ba133af..ea211444c 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py @@ -5,6 +5,8 @@ from unittest.mock import MagicMock import pytest from infection_monkey.exploit import powershell +from infection_monkey.exploit.tools.helpers import RAND_SUFFIX_LEN +from infection_monkey.model import DROPPER_TARGET_PATH_WIN64 from infection_monkey.model.host import VictimHost # Use the path_win32api_get_user_name fixture for all tests in this module @@ -14,7 +16,6 @@ USER_LIST = ["user1", "user2"] PASSWORD_LIST = ["pass1", "pass2"] LM_HASH_LIST = ["bogo_lm_1"] NT_HASH_LIST = ["bogo_nt_1", "bogo_nt_2"] -DROPPER_TARGET_PATH_64 = "C:\\agent64" mock_agent_repository = MagicMock() @@ -24,7 +25,6 @@ mock_agent_repository.get_agent_binary.return_value = BytesIO(b"BINARY_EXECUTABL @pytest.fixture def powershell_arguments(http_and_https_both_enabled_host): options = { - "dropper_target_path_win_64": DROPPER_TARGET_PATH_64, "credentials": { "exploit_user_list": USER_LIST, "exploit_password_list": PASSWORD_LIST, @@ -114,7 +114,10 @@ def test_successful_copy(monkeypatch, powershell_exploiter, powershell_arguments exploit_result = powershell_exploiter.exploit_host(**powershell_arguments) - assert DROPPER_TARGET_PATH_64 in str(mock_client.return_value.copy_file.call_args[0][1]) + # Check if the copied agent name has randomness of 8 plus dash + assert len(str(DROPPER_TARGET_PATH_WIN64)) + RAND_SUFFIX_LEN + 1 == len( + str(mock_client.return_value.copy_file.call_args[0][1]) + ) assert exploit_result.exploitation_success diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py b/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py index 2c1441961..21629f683 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py @@ -3,38 +3,39 @@ from unittest.mock import Mock import pytest from infection_monkey.exploit.tools.helpers import RAND_SUFFIX_LEN, get_agent_dest_path +from infection_monkey.model import DROPPER_TARGET_PATH_LINUX, DROPPER_TARGET_PATH_WIN64 -def _get_host_and_options(os, path): +def _get_host(os): host = Mock() host.os = {"type": os} - options = {"dropper_target_path_win_64": path, "dropper_target_path_linux": path} - return host, options + return host -@pytest.mark.parametrize("os", ["windows", "linux"]) -@pytest.mark.parametrize("path", ["C:\\monkey.exe", "/tmp/monkey-linux-64", "mon.key.exe"]) +@pytest.mark.parametrize( + "os, path", [("linux", DROPPER_TARGET_PATH_LINUX), ("windows", DROPPER_TARGET_PATH_WIN64)] +) def test_get_agent_dest_path(os, path): - host, options = _get_host_and_options(os, path) - rand_path = get_agent_dest_path(host, options) + host = _get_host(os) + rand_path = get_agent_dest_path(host) # Assert that filename got longer by RAND_SUFFIX_LEN and one dash assert len(str(rand_path)) == (len(str(path)) + RAND_SUFFIX_LEN + 1) def test_get_agent_dest_path_randomness(): - host, options = _get_host_and_options("windows", "monkey.exe") + host = _get_host("windows") - path1 = get_agent_dest_path(host, options) - path2 = get_agent_dest_path(host, options) + path1 = get_agent_dest_path(host) + path2 = get_agent_dest_path(host) assert path1 != path2 def test_get_agent_dest_path_str_place(): - host, options = _get_host_and_options("windows", "C:\\abc\\monkey.exe") + host = _get_host("windows") - rand_path = get_agent_dest_path(host, options) + rand_path = get_agent_dest_path(host) - assert str(rand_path).startswith("C:\\abc\\monkey-") + assert str(rand_path).startswith(r"C:\Windows\temp\monkey") assert str(rand_path).endswith(".exe") From f7c2e903b868b67dbcf758e96c9536856a4a464d Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 31 May 2022 14:00:05 +0200 Subject: [PATCH 3/7] Island: Remove dropper target paths from the config --- monkey/monkey_island/cc/services/config.py | 6 ------ .../cc/services/config_schema/internal.py | 21 ------------------- .../monkey_island/cc/services/test_config.py | 2 -- 3 files changed, 29 deletions(-) diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index 1a0d9c4a1..608c21d99 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -617,12 +617,6 @@ class ConfigService: exploit_options = {} - for dropper_target in [ - "dropper_target_path_linux", - "dropper_target_path_win_64", - ]: - exploit_options[dropper_target] = config.get(dropper_target, "") - exploit_options["http_ports"] = sorted(config["HTTP_PORTS"]) formatted_exploiters_config = { diff --git a/monkey/monkey_island/cc/services/config_schema/internal.py b/monkey/monkey_island/cc/services/config_schema/internal.py index 1b684b31f..d8be19e06 100644 --- a/monkey/monkey_island/cc/services/config_schema/internal.py +++ b/monkey/monkey_island/cc/services/config_schema/internal.py @@ -140,27 +140,6 @@ INTERNAL = { } }, }, - "dropper": { - "title": "Dropper", - "type": "object", - "properties": { - "dropper_target_path_linux": { - "title": "Dropper target path on Linux", - "type": "string", - "default": "/tmp/monkey", - "description": "Determines where should the dropper place the monkey on a " - "Linux machine", - }, - "dropper_target_path_win_64": { - "title": "Dropper target path on Windows (64bit)", - "type": "string", - "default": "C:\\Windows\\temp\\monkey64.exe", - "description": "Determines where should the dropper place the monkey on a " - "Windows machine " - "(64 bit)", - }, - }, - }, "exploits": { "title": "Exploits", "type": "object", diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py b/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py index 84ea942f4..1a3c52527 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py +++ b/monkey/tests/unit_tests/monkey_island/cc/services/test_config.py @@ -179,8 +179,6 @@ def test_format_config_for_agent__network_scan(flat_monkey_config): def test_format_config_for_agent__exploiters(flat_monkey_config): expected_exploiters_config = { "options": { - "dropper_target_path_linux": "/tmp/monkey", - "dropper_target_path_win_64": r"C:\Windows\temp\monkey64.exe", "http_ports": [80, 443, 7001, 8008, 8080, 9200], }, "brute_force": [ From 711cab5f386a105c9796a2f408f54ae0049a913d Mon Sep 17 00:00:00 2001 From: vakarisz Date: Wed, 1 Jun 2022 13:04:57 +0300 Subject: [PATCH 4/7] Agent: Separate dropper path from agent binary path --- .../infection_monkey/exploit/tools/helpers.py | 24 +++++++++++-------- monkey/infection_monkey/exploit/web_rce.py | 8 ++++--- monkey/infection_monkey/exploit/wmiexec.py | 8 ++----- monkey/infection_monkey/model/__init__.py | 4 ---- monkey/infection_monkey/utils/commands.py | 5 ++++ .../exploit/test_powershell.py | 5 ++-- .../exploit/tools/test_helpers.py | 10 +++++--- 7 files changed, 35 insertions(+), 29 deletions(-) diff --git a/monkey/infection_monkey/exploit/tools/helpers.py b/monkey/infection_monkey/exploit/tools/helpers.py index 2739da215..17d76607a 100644 --- a/monkey/infection_monkey/exploit/tools/helpers.py +++ b/monkey/infection_monkey/exploit/tools/helpers.py @@ -3,12 +3,25 @@ import random import string from pathlib import PurePath, PurePosixPath, PureWindowsPath -from infection_monkey.model import DROPPER_TARGET_PATH_LINUX, DROPPER_TARGET_PATH_WIN64, VictimHost +from infection_monkey.model import VictimHost logger = logging.getLogger(__name__) RAND_SUFFIX_LEN = 8 +# Where to upload agent binaries on victims +AGENT_BINARY_PATH_LINUX = "/tmp/monkey" +AGENT_BINARY_PATH_WIN64 = r"C:\Windows\temp\monkey64.exe" + + +def get_agent_dest_path(host: VictimHost) -> PurePath: + if host.os["type"] == "windows": + path = PureWindowsPath(AGENT_BINARY_PATH_WIN64) + else: + path = PurePosixPath(AGENT_BINARY_PATH_LINUX) + + return _add_random_suffix(path) + def get_random_file_suffix() -> str: character_set = list(string.ascii_letters + string.digits + "_" + "-") @@ -17,15 +30,6 @@ def get_random_file_suffix() -> str: return random_string -def get_agent_dest_path(host: VictimHost) -> PurePath: - if host.os["type"] == "windows": - path = PureWindowsPath(DROPPER_TARGET_PATH_WIN64) - else: - path = PurePosixPath(DROPPER_TARGET_PATH_LINUX) - - return _add_random_suffix(path) - - # Turns C:\\monkey.exe into C:\\monkey-.exe # Useful to avoid duplicate file paths def _add_random_suffix(path: PurePath) -> PurePath: diff --git a/monkey/infection_monkey/exploit/web_rce.py b/monkey/infection_monkey/exploit/web_rce.py index 9363f5b32..957ed361d 100644 --- a/monkey/infection_monkey/exploit/web_rce.py +++ b/monkey/infection_monkey/exploit/web_rce.py @@ -12,8 +12,6 @@ from infection_monkey.model import ( CHMOD_MONKEY, DOWNLOAD_TIMEOUT, DROPPER_ARG, - DROPPER_TARGET_PATH_LINUX, - DROPPER_TARGET_PATH_WIN64, ID_STRING, MONKEY_ARG, POWERSHELL_HTTP_UPLOAD, @@ -24,7 +22,11 @@ from infection_monkey.model import ( from infection_monkey.network.tools import tcp_port_to_service from infection_monkey.telemetry.attack.t1197_telem import T1197Telem from infection_monkey.telemetry.attack.t1222_telem import T1222Telem -from infection_monkey.utils.commands import build_monkey_commandline +from infection_monkey.utils.commands import ( + DROPPER_TARGET_PATH_LINUX, + DROPPER_TARGET_PATH_WIN64, + build_monkey_commandline, +) from infection_monkey.utils.threading import interruptible_iter logger = logging.getLogger(__name__) diff --git a/monkey/infection_monkey/exploit/wmiexec.py b/monkey/infection_monkey/exploit/wmiexec.py index a008beee2..50f8deb6b 100644 --- a/monkey/infection_monkey/exploit/wmiexec.py +++ b/monkey/infection_monkey/exploit/wmiexec.py @@ -10,16 +10,12 @@ from infection_monkey.exploit.tools.helpers import get_agent_dest_path from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.exploit.tools.wmi_tools import AccessDeniedException, WmiTools from infection_monkey.i_puppet import ExploiterResultData -from infection_monkey.model import ( - DROPPER_CMDLINE_WINDOWS, - DROPPER_TARGET_PATH_WIN64, - MONKEY_CMDLINE_WINDOWS, -) +from infection_monkey.model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS from infection_monkey.utils.brute_force import ( generate_brute_force_combinations, get_credential_string, ) -from infection_monkey.utils.commands import build_monkey_commandline +from infection_monkey.utils.commands import DROPPER_TARGET_PATH_WIN64, build_monkey_commandline from infection_monkey.utils.threading import interruptible_iter logger = logging.getLogger(__name__) diff --git a/monkey/infection_monkey/model/__init__.py b/monkey/infection_monkey/model/__init__.py index e81861ee7..138dbf92a 100644 --- a/monkey/infection_monkey/model/__init__.py +++ b/monkey/infection_monkey/model/__init__.py @@ -5,10 +5,6 @@ MONKEY_ARG = "m0nk3y" DROPPER_ARG = "dr0pp3r" ID_STRING = "M0NK3Y3XPL0ITABLE" -# Dropper target paths -DROPPER_TARGET_PATH_LINUX = "/tmp/monkey" -DROPPER_TARGET_PATH_WIN64 = r"C:\Windows\temp\monkey64.exe" - # Username prefix for users created by Infection Monkey USERNAME_PREFIX = "somenewuser" diff --git a/monkey/infection_monkey/utils/commands.py b/monkey/infection_monkey/utils/commands.py index 284729206..ddd07dc8d 100644 --- a/monkey/infection_monkey/utils/commands.py +++ b/monkey/infection_monkey/utils/commands.py @@ -1,7 +1,12 @@ from infection_monkey.config import GUID +from infection_monkey.exploit.tools.helpers import AGENT_BINARY_PATH_LINUX, AGENT_BINARY_PATH_WIN64 from infection_monkey.model import CMD_CARRY_OUT, CMD_EXE, MONKEY_ARG from infection_monkey.model.host import VictimHost +# Dropper target paths +DROPPER_TARGET_PATH_LINUX = AGENT_BINARY_PATH_LINUX +DROPPER_TARGET_PATH_WIN64 = AGENT_BINARY_PATH_WIN64 + def build_monkey_commandline(target_host: VictimHost, depth: int, location: str = None) -> str: diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py index ea211444c..24afebc85 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py @@ -5,8 +5,7 @@ from unittest.mock import MagicMock import pytest from infection_monkey.exploit import powershell -from infection_monkey.exploit.tools.helpers import RAND_SUFFIX_LEN -from infection_monkey.model import DROPPER_TARGET_PATH_WIN64 +from infection_monkey.exploit.tools.helpers import AGENT_BINARY_PATH_WIN64, RAND_SUFFIX_LEN from infection_monkey.model.host import VictimHost # Use the path_win32api_get_user_name fixture for all tests in this module @@ -115,7 +114,7 @@ def test_successful_copy(monkeypatch, powershell_exploiter, powershell_arguments exploit_result = powershell_exploiter.exploit_host(**powershell_arguments) # Check if the copied agent name has randomness of 8 plus dash - assert len(str(DROPPER_TARGET_PATH_WIN64)) + RAND_SUFFIX_LEN + 1 == len( + assert len(str(AGENT_BINARY_PATH_WIN64)) + RAND_SUFFIX_LEN + 1 == len( str(mock_client.return_value.copy_file.call_args[0][1]) ) assert exploit_result.exploitation_success diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py b/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py index 21629f683..68cba4598 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py @@ -2,8 +2,12 @@ from unittest.mock import Mock import pytest -from infection_monkey.exploit.tools.helpers import RAND_SUFFIX_LEN, get_agent_dest_path -from infection_monkey.model import DROPPER_TARGET_PATH_LINUX, DROPPER_TARGET_PATH_WIN64 +from infection_monkey.exploit.tools.helpers import ( + AGENT_BINARY_PATH_LINUX, + AGENT_BINARY_PATH_WIN64, + RAND_SUFFIX_LEN, + get_agent_dest_path, +) def _get_host(os): @@ -13,7 +17,7 @@ def _get_host(os): @pytest.mark.parametrize( - "os, path", [("linux", DROPPER_TARGET_PATH_LINUX), ("windows", DROPPER_TARGET_PATH_WIN64)] + "os, path", [("linux", AGENT_BINARY_PATH_LINUX), ("windows", AGENT_BINARY_PATH_WIN64)] ) def test_get_agent_dest_path(os, path): host = _get_host(os) From 8ef0b44841b3d8d7b069a2586317209d1ddd2169 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 1 Jun 2022 12:40:00 +0200 Subject: [PATCH 5/7] Agent: Fix dropper date referencing * Make dropper date reference path from strings to Path objects * Fix try/except block logic and indentation --- monkey/infection_monkey/dropper.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/monkey/infection_monkey/dropper.py b/monkey/infection_monkey/dropper.py index 57259950f..d76a7bc66 100644 --- a/monkey/infection_monkey/dropper.py +++ b/monkey/infection_monkey/dropper.py @@ -7,7 +7,7 @@ import shutil import subprocess import sys import time -from pathlib import WindowsPath +from pathlib import PosixPath, WindowsPath from common.utils.attack_utils import UsageEnum from infection_monkey.utils.commands import ( @@ -34,8 +34,8 @@ except NameError: logger = logging.getLogger(__name__) MOVEFILE_DELAY_UNTIL_REBOOT = 4 -DATE_REFERENCE_PATH_WINDOWS = r"%windir%\system32\kernel32.dll" -DATE_REFERENCE_PATH_LINUX = "/bin/sh" +DATE_REFERENCE_PATH_WINDOWS = WindowsPath(r"%windir%\system32\kernel32.dll") +DATE_REFERENCE_PATH_LINUX = PosixPath("/bin/sh") class MonkeyDrops(object): @@ -115,14 +115,19 @@ class MonkeyDrops(object): dropper_date_reference_path = os.path.expandvars(DATE_REFERENCE_PATH_WINDOWS) else: dropper_date_reference_path = DATE_REFERENCE_PATH_LINUX + + try: + ref_stat = os.stat(dropper_date_reference_path) + except OSError: + logger.warning( + "Cannot set reference date using '%s', file not found", + dropper_date_reference_path, + ) + else: try: - ref_stat = os.stat(dropper_date_reference_path) os.utime(self._config["destination_path"], (ref_stat.st_atime, ref_stat.st_mtime)) except OSError: - logger.warning( - "Cannot set reference date using '%s', file not found", - dropper_date_reference_path, - ) + logger.warning("Cannot set reference date to destination file") monkey_options = build_monkey_commandline_explicitly( parent=self.opts.parent, From e4a2a54c710ea637365a03bdba952634f55d9108 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 1 Jun 2022 13:05:03 +0200 Subject: [PATCH 6/7] Agent: Rename get_agent_dest_path to get_agent_dst_path --- monkey/infection_monkey/exploit/hadoop.py | 4 ++-- monkey/infection_monkey/exploit/log4shell.py | 4 ++-- monkey/infection_monkey/exploit/mssqlexec.py | 4 ++-- monkey/infection_monkey/exploit/powershell.py | 4 ++-- monkey/infection_monkey/exploit/smbexec.py | 4 ++-- monkey/infection_monkey/exploit/sshexec.py | 4 ++-- monkey/infection_monkey/exploit/tools/helpers.py | 2 +- monkey/infection_monkey/exploit/wmiexec.py | 4 ++-- .../exploit/tools/test_helpers.py | 16 ++++++++-------- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/monkey/infection_monkey/exploit/hadoop.py b/monkey/infection_monkey/exploit/hadoop.py index 318e37d67..15e801452 100644 --- a/monkey/infection_monkey/exploit/hadoop.py +++ b/monkey/infection_monkey/exploit/hadoop.py @@ -12,7 +12,7 @@ import string import requests from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT -from infection_monkey.exploit.tools.helpers import get_agent_dest_path +from infection_monkey.exploit.tools.helpers import get_agent_dst_path from infection_monkey.exploit.tools.http_tools import HTTPTools from infection_monkey.exploit.web_rce import WebRCE from infection_monkey.model import ( @@ -43,7 +43,7 @@ class HadoopExploiter(WebRCE): return self.exploit_result try: - monkey_path_on_victim = get_agent_dest_path(self.host) + monkey_path_on_victim = get_agent_dst_path(self.host) except KeyError: return self.exploit_result diff --git a/monkey/infection_monkey/exploit/log4shell.py b/monkey/infection_monkey/exploit/log4shell.py index b59c72dd4..198635976 100644 --- a/monkey/infection_monkey/exploit/log4shell.py +++ b/monkey/infection_monkey/exploit/log4shell.py @@ -12,7 +12,7 @@ from infection_monkey.exploit.log4shell_utils import ( build_exploit_bytecode, get_log4shell_service_exploiters, ) -from infection_monkey.exploit.tools.helpers import get_agent_dest_path +from infection_monkey.exploit.tools.helpers import get_agent_dst_path from infection_monkey.exploit.tools.http_tools import HTTPTools from infection_monkey.exploit.web_rce import WebRCE from infection_monkey.i_puppet.i_puppet import ExploiterResultData @@ -61,7 +61,7 @@ class Log4ShellExploiter(WebRCE): self._agent_http_server_thread = None def _start_servers(self): - target_path = get_agent_dest_path(self.host) + target_path = get_agent_dst_path(self.host) # Start http server, to serve agent to victims agent_http_path = self._start_agent_http_server(target_path) diff --git a/monkey/infection_monkey/exploit/mssqlexec.py b/monkey/infection_monkey/exploit/mssqlexec.py index 147403580..526c85caa 100644 --- a/monkey/infection_monkey/exploit/mssqlexec.py +++ b/monkey/infection_monkey/exploit/mssqlexec.py @@ -8,7 +8,7 @@ import pymssql from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT from common.utils.exceptions import FailedExploitationError from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import get_agent_dest_path +from infection_monkey.exploit.tools.helpers import get_agent_dst_path from infection_monkey.exploit.tools.http_tools import HTTPTools from infection_monkey.exploit.tools.payload_parsing import LimitedSizePayload from infection_monkey.i_puppet import ExploiterResultData @@ -59,7 +59,7 @@ class MSSQLExploiter(HostExploiter): Also, don't forget to start_monkey_server() before self.upload_monkey() and self.stop_monkey_server() after """ - monkey_path_on_victim = get_agent_dest_path(self.host) + monkey_path_on_victim = get_agent_dst_path(self.host) # Brute force to get connection creds = generate_identity_secret_pairs( diff --git a/monkey/infection_monkey/exploit/powershell.py b/monkey/infection_monkey/exploit/powershell.py index 16073a014..7b33df9ed 100644 --- a/monkey/infection_monkey/exploit/powershell.py +++ b/monkey/infection_monkey/exploit/powershell.py @@ -13,7 +13,7 @@ from infection_monkey.exploit.powershell_utils.powershell_client import ( IPowerShellClient, PowerShellClient, ) -from infection_monkey.exploit.tools.helpers import get_agent_dest_path, get_random_file_suffix +from infection_monkey.exploit.tools.helpers import get_agent_dst_path, get_random_file_suffix from infection_monkey.model import DROPPER_ARG, RUN_MONKEY, VictimHost from infection_monkey.utils.commands import build_monkey_commandline from infection_monkey.utils.environment import is_windows_os @@ -134,7 +134,7 @@ class PowerShellExploiter(HostExploiter): raise ValueError(f"Unknown secret type {credentials.secret_type}") def _execute_monkey_agent_on_victim(self): - monkey_path_on_victim = get_agent_dest_path(self.host) + monkey_path_on_victim = get_agent_dst_path(self.host) self._copy_monkey_binary_to_victim(monkey_path_on_victim) logger.info("Successfully copied the monkey binary to the victim.") diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 825cb37ce..03b6bfb3e 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -6,7 +6,7 @@ from impacket.dcerpc.v5.scmr import DCERPCSessionError from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT from common.utils.attack_utils import ScanStatus, UsageEnum from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import get_agent_dest_path +from infection_monkey.exploit.tools.helpers import get_agent_dst_path from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.model import DROPPER_CMDLINE_DETACHED_WINDOWS, MONKEY_CMDLINE_DETACHED_WINDOWS from infection_monkey.telemetry.attack.t1035_telem import T1035Telem @@ -31,7 +31,7 @@ class SMBExploiter(HostExploiter): def _exploit_host(self): agent_binary = self.agent_repository.get_agent_binary(self.host.os["type"]) - dest_path = get_agent_dest_path(self.host) + dest_path = get_agent_dst_path(self.host) creds = generate_brute_force_combinations(self.options["credentials"]) for user, password, lm_hash, ntlm_hash in interruptible_iter(creds, self.interrupt): diff --git a/monkey/infection_monkey/exploit/sshexec.py b/monkey/infection_monkey/exploit/sshexec.py index 7f9619e95..f76147fd1 100644 --- a/monkey/infection_monkey/exploit/sshexec.py +++ b/monkey/infection_monkey/exploit/sshexec.py @@ -9,7 +9,7 @@ from common.utils import Timer from common.utils.attack_utils import ScanStatus from common.utils.exceptions import FailedExploitationError from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import get_agent_dest_path +from infection_monkey.exploit.tools.helpers import get_agent_dst_path from infection_monkey.i_puppet import ExploiterResultData from infection_monkey.model import MONKEY_ARG from infection_monkey.network.tools import check_tcp_port, get_interface_to_target @@ -209,7 +209,7 @@ class SSHExploiter(HostExploiter): self._set_interrupted() return self.exploit_result - monkey_path_on_victim = get_agent_dest_path(self.host) + monkey_path_on_victim = get_agent_dst_path(self.host) try: with ssh.open_sftp() as ftp: diff --git a/monkey/infection_monkey/exploit/tools/helpers.py b/monkey/infection_monkey/exploit/tools/helpers.py index 17d76607a..8334f33a6 100644 --- a/monkey/infection_monkey/exploit/tools/helpers.py +++ b/monkey/infection_monkey/exploit/tools/helpers.py @@ -14,7 +14,7 @@ AGENT_BINARY_PATH_LINUX = "/tmp/monkey" AGENT_BINARY_PATH_WIN64 = r"C:\Windows\temp\monkey64.exe" -def get_agent_dest_path(host: VictimHost) -> PurePath: +def get_agent_dst_path(host: VictimHost) -> PurePath: if host.os["type"] == "windows": path = PureWindowsPath(AGENT_BINARY_PATH_WIN64) else: diff --git a/monkey/infection_monkey/exploit/wmiexec.py b/monkey/infection_monkey/exploit/wmiexec.py index 50f8deb6b..b8d577365 100644 --- a/monkey/infection_monkey/exploit/wmiexec.py +++ b/monkey/infection_monkey/exploit/wmiexec.py @@ -6,7 +6,7 @@ import traceback from impacket.dcerpc.v5.rpcrt import DCERPCException from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import get_agent_dest_path +from infection_monkey.exploit.tools.helpers import get_agent_dst_path from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.exploit.tools.wmi_tools import AccessDeniedException, WmiTools from infection_monkey.i_puppet import ExploiterResultData @@ -74,7 +74,7 @@ class WmiExploiter(HostExploiter): self._set_interrupted() return self.exploit_result - target_path = get_agent_dest_path(self.host) + target_path = get_agent_dst_path(self.host) remote_full_path = SmbTools.copy_file( self.host, diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py b/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py index 68cba4598..a339ec17f 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py @@ -6,7 +6,7 @@ from infection_monkey.exploit.tools.helpers import ( AGENT_BINARY_PATH_LINUX, AGENT_BINARY_PATH_WIN64, RAND_SUFFIX_LEN, - get_agent_dest_path, + get_agent_dst_path, ) @@ -19,27 +19,27 @@ def _get_host(os): @pytest.mark.parametrize( "os, path", [("linux", AGENT_BINARY_PATH_LINUX), ("windows", AGENT_BINARY_PATH_WIN64)] ) -def test_get_agent_dest_path(os, path): +def test_get_agent_dst_path(os, path): host = _get_host(os) - rand_path = get_agent_dest_path(host) + rand_path = get_agent_dst_path(host) # Assert that filename got longer by RAND_SUFFIX_LEN and one dash assert len(str(rand_path)) == (len(str(path)) + RAND_SUFFIX_LEN + 1) -def test_get_agent_dest_path_randomness(): +def test_get_agent_dst_path_randomness(): host = _get_host("windows") - path1 = get_agent_dest_path(host) - path2 = get_agent_dest_path(host) + path1 = get_agent_dst_path(host) + path2 = get_agent_dst_path(host) assert path1 != path2 -def test_get_agent_dest_path_str_place(): +def test_get_agent_dst_path_str_place(): host = _get_host("windows") - rand_path = get_agent_dest_path(host) + rand_path = get_agent_dst_path(host) assert str(rand_path).startswith(r"C:\Windows\temp\monkey") assert str(rand_path).endswith(".exe") From 09958c21c6b935c01202b652729f1586828fa2ac Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 1 Jun 2022 17:09:56 +0200 Subject: [PATCH 7/7] Agent: Make agent target paths a Path objects --- monkey/infection_monkey/dropper.py | 7 ++++--- monkey/infection_monkey/exploit/tools/helpers.py | 4 ++-- .../unit_tests/infection_monkey/exploit/test_powershell.py | 7 ++----- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/monkey/infection_monkey/dropper.py b/monkey/infection_monkey/dropper.py index d76a7bc66..6407c08de 100644 --- a/monkey/infection_monkey/dropper.py +++ b/monkey/infection_monkey/dropper.py @@ -20,8 +20,11 @@ from infection_monkey.utils.file_utils import mark_file_for_deletion_on_windows if "win32" == sys.platform: from win32process import DETACHED_PROCESS + + DATE_REFERENCE_PATH_WINDOWS = os.path.expandvars(WindowsPath(r"%windir%\system32\kernel32.dll")) else: DETACHED_PROCESS = 0 + DATE_REFERENCE_PATH_LINUX = PosixPath("/bin/sh") # Linux doesn't have WindowsError try: @@ -34,8 +37,6 @@ except NameError: logger = logging.getLogger(__name__) MOVEFILE_DELAY_UNTIL_REBOOT = 4 -DATE_REFERENCE_PATH_WINDOWS = WindowsPath(r"%windir%\system32\kernel32.dll") -DATE_REFERENCE_PATH_LINUX = PosixPath("/bin/sh") class MonkeyDrops(object): @@ -112,7 +113,7 @@ class MonkeyDrops(object): return False if sys.platform == "win32": - dropper_date_reference_path = os.path.expandvars(DATE_REFERENCE_PATH_WINDOWS) + dropper_date_reference_path = DATE_REFERENCE_PATH_WINDOWS else: dropper_date_reference_path = DATE_REFERENCE_PATH_LINUX diff --git a/monkey/infection_monkey/exploit/tools/helpers.py b/monkey/infection_monkey/exploit/tools/helpers.py index 8334f33a6..0ce1c474e 100644 --- a/monkey/infection_monkey/exploit/tools/helpers.py +++ b/monkey/infection_monkey/exploit/tools/helpers.py @@ -10,8 +10,8 @@ logger = logging.getLogger(__name__) RAND_SUFFIX_LEN = 8 # Where to upload agent binaries on victims -AGENT_BINARY_PATH_LINUX = "/tmp/monkey" -AGENT_BINARY_PATH_WIN64 = r"C:\Windows\temp\monkey64.exe" +AGENT_BINARY_PATH_LINUX = PurePosixPath("/tmp/monkey") +AGENT_BINARY_PATH_WIN64 = PureWindowsPath(r"C:\Windows\temp\monkey64.exe") def get_agent_dst_path(host: VictimHost) -> PurePath: diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py index 24afebc85..c5d428f47 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py @@ -5,7 +5,7 @@ from unittest.mock import MagicMock import pytest from infection_monkey.exploit import powershell -from infection_monkey.exploit.tools.helpers import AGENT_BINARY_PATH_WIN64, RAND_SUFFIX_LEN +from infection_monkey.exploit.tools.helpers import AGENT_BINARY_PATH_WIN64 from infection_monkey.model.host import VictimHost # Use the path_win32api_get_user_name fixture for all tests in this module @@ -113,10 +113,7 @@ def test_successful_copy(monkeypatch, powershell_exploiter, powershell_arguments exploit_result = powershell_exploiter.exploit_host(**powershell_arguments) - # Check if the copied agent name has randomness of 8 plus dash - assert len(str(AGENT_BINARY_PATH_WIN64)) + RAND_SUFFIX_LEN + 1 == len( - str(mock_client.return_value.copy_file.call_args[0][1]) - ) + assert AGENT_BINARY_PATH_WIN64.stem in str(mock_client.return_value.copy_file.call_args[0][1]) assert exploit_result.exploitation_success