From 7c504d220d3c0df54172712a190a3aa6350cc2d9 Mon Sep 17 00:00:00 2001 From: vakaris_zilius Date: Wed, 23 Mar 2022 13:11:54 +0000 Subject: [PATCH 1/4] Agent: Upload binary with random string when using powershell --- monkey/infection_monkey/exploit/powershell.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/exploit/powershell.py b/monkey/infection_monkey/exploit/powershell.py index 1c496fc68..1c3536821 100644 --- a/monkey/infection_monkey/exploit/powershell.py +++ b/monkey/infection_monkey/exploit/powershell.py @@ -1,5 +1,6 @@ import logging import os +from pathlib import Path from typing import List, Optional from infection_monkey.exploit.HostExploiter import HostExploiter @@ -19,7 +20,7 @@ from infection_monkey.exploit.powershell_utils.powershell_client import ( IPowerShellClient, PowerShellClient, ) -from infection_monkey.exploit.tools.helpers import get_random_file_suffix +from infection_monkey.exploit.tools.helpers import get_agent_dest_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 @@ -170,7 +171,7 @@ class PowerShellExploiter(HostExploiter): raise ValueError(f"Unknown secret type {credentials.secret_type}") def _execute_monkey_agent_on_victim(self): - monkey_path_on_victim = self.options["dropper_target_path_win_64"] + monkey_path_on_victim = get_agent_dest_path(self.host, self.options) self._copy_monkey_binary_to_victim(monkey_path_on_victim) logger.info("Successfully copied the monkey binary to the victim.") @@ -182,7 +183,7 @@ class PowerShellExploiter(HostExploiter): f"Failed to execute the agent binary on the victim: {ex}" ) - def _copy_monkey_binary_to_victim(self, monkey_path_on_victim): + def _copy_monkey_binary_to_victim(self, monkey_path_on_victim: Path): temp_monkey_binary_filepath = f"monkey_temp_bin_{get_random_file_suffix()}" @@ -190,7 +191,7 @@ class PowerShellExploiter(HostExploiter): try: logger.info(f"Attempting to copy the monkey agent binary to {self.host.ip_addr}") - self._client.copy_file(temp_monkey_binary_filepath, monkey_path_on_victim) + self._client.copy_file(temp_monkey_binary_filepath, str(monkey_path_on_victim)) except Exception as ex: raise RemoteAgentCopyError(f"Failed to copy the agent binary to the victim: {ex}") finally: From 7001977a884873c86478198d994421274e54e413 Mon Sep 17 00:00:00 2001 From: vakaris_zilius Date: Wed, 23 Mar 2022 15:24:36 +0000 Subject: [PATCH 2/4] Agent: Change powershell client to work with Path not str --- monkey/infection_monkey/exploit/powershell.py | 2 +- .../exploit/powershell_utils/powershell_client.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/monkey/infection_monkey/exploit/powershell.py b/monkey/infection_monkey/exploit/powershell.py index 1c3536821..12974aae5 100644 --- a/monkey/infection_monkey/exploit/powershell.py +++ b/monkey/infection_monkey/exploit/powershell.py @@ -191,7 +191,7 @@ class PowerShellExploiter(HostExploiter): try: logger.info(f"Attempting to copy the monkey agent binary to {self.host.ip_addr}") - self._client.copy_file(temp_monkey_binary_filepath, str(monkey_path_on_victim)) + self._client.copy_file(temp_monkey_binary_filepath, monkey_path_on_victim) except Exception as ex: raise RemoteAgentCopyError(f"Failed to copy the agent binary to the victim: {ex}") finally: diff --git a/monkey/infection_monkey/exploit/powershell_utils/powershell_client.py b/monkey/infection_monkey/exploit/powershell_utils/powershell_client.py index c0ae8b260..b1fa000c7 100644 --- a/monkey/infection_monkey/exploit/powershell_utils/powershell_client.py +++ b/monkey/infection_monkey/exploit/powershell_utils/powershell_client.py @@ -1,5 +1,6 @@ import abc import logging +from pathlib import Path from typing import Optional import pypsrp @@ -63,7 +64,7 @@ class IPowerShellClient(Protocol, metaclass=abc.ABCMeta): pass @abc.abstractmethod - def copy_file(self, src: str, dest: str) -> bool: + def copy_file(self, src: str, dest: Path) -> bool: pass @abc.abstractmethod @@ -101,7 +102,8 @@ class PowerShellClient(IPowerShellClient): output, _, _ = self._client.execute_cmd(cmd) return output - def copy_file(self, src: str, dest: str): + def copy_file(self, src: str, dest: Path): + dest = str(dest) try: self._client.copy(src, dest) logger.debug(f"Successfully copied {src} to {dest} on {self._ip_addr}") From d3fc8338137fd35cc8aed601180818b9c8cd4a56 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Wed, 23 Mar 2022 14:25:28 -0400 Subject: [PATCH 3/4] Agent: Use Paths in IPowerShellClient.copy_file() --- monkey/infection_monkey/exploit/powershell.py | 7 +++---- .../exploit/powershell_utils/powershell_client.py | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/monkey/infection_monkey/exploit/powershell.py b/monkey/infection_monkey/exploit/powershell.py index 12974aae5..8bdf7e571 100644 --- a/monkey/infection_monkey/exploit/powershell.py +++ b/monkey/infection_monkey/exploit/powershell.py @@ -1,5 +1,4 @@ import logging -import os from pathlib import Path from typing import List, Optional @@ -185,7 +184,7 @@ class PowerShellExploiter(HostExploiter): def _copy_monkey_binary_to_victim(self, monkey_path_on_victim: Path): - temp_monkey_binary_filepath = f"monkey_temp_bin_{get_random_file_suffix()}" + temp_monkey_binary_filepath = Path(f"./monkey_temp_bin_{get_random_file_suffix()}") self._create_local_agent_file(temp_monkey_binary_filepath) @@ -195,8 +194,8 @@ class PowerShellExploiter(HostExploiter): except Exception as ex: raise RemoteAgentCopyError(f"Failed to copy the agent binary to the victim: {ex}") finally: - if os.path.isfile(temp_monkey_binary_filepath): - os.remove(temp_monkey_binary_filepath) + if temp_monkey_binary_filepath.is_file(): + temp_monkey_binary_filepath.unlink() def _create_local_agent_file(self, binary_path): agent_binary_bytes = self.agent_repository.get_agent_binary("windows") diff --git a/monkey/infection_monkey/exploit/powershell_utils/powershell_client.py b/monkey/infection_monkey/exploit/powershell_utils/powershell_client.py index b1fa000c7..70e82bb66 100644 --- a/monkey/infection_monkey/exploit/powershell_utils/powershell_client.py +++ b/monkey/infection_monkey/exploit/powershell_utils/powershell_client.py @@ -64,7 +64,7 @@ class IPowerShellClient(Protocol, metaclass=abc.ABCMeta): pass @abc.abstractmethod - def copy_file(self, src: str, dest: Path) -> bool: + def copy_file(self, src: Path, dest: Path) -> bool: pass @abc.abstractmethod @@ -102,10 +102,9 @@ class PowerShellClient(IPowerShellClient): output, _, _ = self._client.execute_cmd(cmd) return output - def copy_file(self, src: str, dest: Path): - dest = str(dest) + def copy_file(self, src: Path, dest: Path): try: - self._client.copy(src, dest) + self._client.copy(str(src), str(dest)) logger.debug(f"Successfully copied {src} to {dest} on {self._ip_addr}") except Exception as ex: logger.error(f"Failed to copy {src} to {dest} on {self._ip_addr}: {ex}") From 99b8321271a84a16f55963ffea1a96c9f81ccb85 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Wed, 23 Mar 2022 14:32:08 -0400 Subject: [PATCH 4/4] Tests: Fix broken PowerShellExploiter tests --- .../unit_tests/infection_monkey/exploit/test_powershell.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 21a0bdeb3..c88ce99d7 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py @@ -26,6 +26,9 @@ class AuthenticationErrorForTests(Exception): mock_agent_repository = MagicMock() mock_agent_repository.get_agent_binary.return_value = BytesIO(b"BINARY_EXECUTABLE") +victim_host = VictimHost("127.0.0.1") +victim_host.os["type"] = "windows" + @pytest.fixture def powershell_arguments(): @@ -39,7 +42,7 @@ def powershell_arguments(): }, } arguments = { - "host": VictimHost("127.0.0.1"), + "host": victim_host, "options": options, "current_depth": 2, "telemetry_messenger": MagicMock(), @@ -141,7 +144,7 @@ def test_successful_copy(monkeypatch, powershell_exploiter, powershell_arguments exploit_result = powershell_exploiter.exploit_host(**powershell_arguments) - assert DROPPER_TARGET_PATH_64 in mock_client.return_value.copy_file.call_args[0][1] + assert DROPPER_TARGET_PATH_64 in str(mock_client.return_value.copy_file.call_args[0][1]) assert exploit_result.exploitation_success