From a4c5e73a7365c980e2fa92ba2d137a1fa22b4102 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Mon, 27 Mar 2023 16:59:11 +0530 Subject: [PATCH 1/8] Agent: Pass Agent ID to exploiter wrapper and then HostExploiter from monkey.py --- monkey/infection_monkey/exploit/HostExploiter.py | 5 ++++- monkey/infection_monkey/exploit/exploiter_wrapper.py | 8 +++++++- monkey/infection_monkey/monkey.py | 6 +++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/monkey/infection_monkey/exploit/HostExploiter.py b/monkey/infection_monkey/exploit/HostExploiter.py index 6f7bdbff6fb..683c3e24738 100644 --- a/monkey/infection_monkey/exploit/HostExploiter.py +++ b/monkey/infection_monkey/exploit/HostExploiter.py @@ -6,7 +6,7 @@ from common.agent_events import ExploitationEvent, PropagationEvent from common.event_queue import IAgentEventQueue -from common.types import Event +from common.types import AgentID, Event from common.utils.exceptions import FailedExploitationError from infection_monkey.exploit import IAgentOTPProvider from infection_monkey.i_puppet import ExploiterResultData, TargetHost @@ -35,6 +35,7 @@ def _PROPAGATION_TAGS(self) -> Tuple[str, ...]: pass def __init__(self): + self.agent_id = None self.exploit_info = { "display_name": self._EXPLOITED_SERVICE, "started": "", @@ -70,6 +71,7 @@ def report_login_attempt(self, result, user, password="", lm_hash="", ntlm_hash= def exploit_host( self, + agent_id: AgentID, host: TargetHost, servers: Sequence[str], current_depth: int, @@ -80,6 +82,7 @@ def exploit_host( interrupt: Event, otp_provider: IAgentOTPProvider, ): + self.agent_id = agent_id self.host = host self.servers = servers self.current_depth = current_depth diff --git a/monkey/infection_monkey/exploit/exploiter_wrapper.py b/monkey/infection_monkey/exploit/exploiter_wrapper.py index a9037d82aeb..d170f0d709e 100644 --- a/monkey/infection_monkey/exploit/exploiter_wrapper.py +++ b/monkey/infection_monkey/exploit/exploiter_wrapper.py @@ -1,7 +1,7 @@ from typing import Dict, Sequence, Type from common.event_queue import IAgentEventQueue -from common.types import Event +from common.types import AgentID, Event from infection_monkey.i_puppet import TargetHost from infection_monkey.network import TCPPortSelector @@ -21,11 +21,13 @@ class Inner: def __init__( self, exploit_class: Type[HostExploiter], + agent_id: AgentID, event_queue: IAgentEventQueue, agent_binary_repository: IAgentBinaryRepository, tcp_port_selector: TCPPortSelector, otp_provider: IAgentOTPProvider, ): + self._agent_id = agent_id self._exploit_class = exploit_class self._event_queue = event_queue self._agent_binary_repository = agent_binary_repository @@ -42,6 +44,7 @@ def run( ): exploiter = self._exploit_class() return exploiter.exploit_host( + self._agent_id, host, servers, current_depth, @@ -55,11 +58,13 @@ def run( def __init__( self, + agent_id: AgentID, event_queue: IAgentEventQueue, agent_binary_repository: IAgentBinaryRepository, tcp_port_selector: TCPPortSelector, otp_provider: IAgentOTPProvider, ): + self._agent_id = agent_id self._event_queue = event_queue self._agent_binary_repository = agent_binary_repository self._tcp_port_selector = tcp_port_selector @@ -68,6 +73,7 @@ def __init__( def wrap(self, exploit_class: Type[HostExploiter]): return ExploiterWrapper.Inner( exploit_class, + self._agent_id, self._event_queue, self._agent_binary_repository, self._tcp_port_selector, diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 6ca87e4dbd1..190de0b437d 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -425,7 +425,11 @@ def _build_puppet(self, operating_system: OperatingSystem) -> IPuppet: puppet.load_plugin(AgentPluginType.FINGERPRINTER, "ssh", SSHFingerprinter()) exploit_wrapper = ExploiterWrapper( - self._agent_event_queue, agent_binary_repository, self._tcp_port_selector, otp_provider + self._agent_id, + self._agent_event_queue, + agent_binary_repository, + self._tcp_port_selector, + otp_provider, ) puppet.load_plugin( From 145e33812f9f3b07d6df6b3526461bd16ee5e2d6 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Mon, 27 Mar 2023 17:31:22 +0530 Subject: [PATCH 2/8] Agent: Don't call 'get_agent_id()' in HostExploiter when publishing events --- monkey/infection_monkey/exploit/HostExploiter.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/monkey/infection_monkey/exploit/HostExploiter.py b/monkey/infection_monkey/exploit/HostExploiter.py index 683c3e24738..3e62039d22b 100644 --- a/monkey/infection_monkey/exploit/HostExploiter.py +++ b/monkey/infection_monkey/exploit/HostExploiter.py @@ -11,7 +11,6 @@ from infection_monkey.exploit import IAgentOTPProvider from infection_monkey.i_puppet import ExploiterResultData, TargetHost from infection_monkey.network import TCPPortSelector -from infection_monkey.utils.ids import get_agent_id from . import IAgentBinaryRepository @@ -143,7 +142,7 @@ def _publish_exploitation_event( error_message: str = "", ): exploitation_event = ExploitationEvent( - source=get_agent_id(), + source=self.agent_id, target=self.host.ip, success=success, exploiter_name=self.__class__.__name__, @@ -161,7 +160,7 @@ def _publish_propagation_event( error_message: str = "", ): propagation_event = PropagationEvent( - source=get_agent_id(), + source=self.agent_id, target=self.host.ip, success=success, exploiter_name=self.__class__.__name__, From 83c2a98dfb8dd211eab30029e98d2a8b7b41e950 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Mon, 27 Mar 2023 17:36:51 +0530 Subject: [PATCH 3/8] Agent: Don't use 'get_agent_id()' in SSH and Zerologon exploiters --- monkey/infection_monkey/exploit/sshexec.py | 4 +--- monkey/infection_monkey/exploit/zerologon.py | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/monkey/infection_monkey/exploit/sshexec.py b/monkey/infection_monkey/exploit/sshexec.py index a023e14c092..590474b5c1a 100644 --- a/monkey/infection_monkey/exploit/sshexec.py +++ b/monkey/infection_monkey/exploit/sshexec.py @@ -29,7 +29,6 @@ from infection_monkey.network.tools import check_tcp_port from infection_monkey.utils.brute_force import generate_identity_secret_pairs from infection_monkey.utils.commands import build_monkey_commandline -from infection_monkey.utils.ids import get_agent_id from infection_monkey.utils.threading import interruptible_iter logger = logging.getLogger(__name__) @@ -141,7 +140,6 @@ def exploit_with_login_creds(self, port: NetworkPort) -> paramiko.SSHClient: ) for user, current_password in credentials_iterator: - ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.WarningPolicy()) @@ -264,7 +262,7 @@ def _is_port_open(self, ip: IPv4Address, port: NetworkPort) -> bool: is_open, _ = check_tcp_port(ip, port) status = PortStatus.OPEN if is_open else PortStatus.CLOSED self.agent_event_queue.publish( - TCPScanEvent(source=get_agent_id(), target=ip, ports={port: status}) + TCPScanEvent(source=self.agent_id, target=ip, ports={port: status}) ) return is_open diff --git a/monkey/infection_monkey/exploit/zerologon.py b/monkey/infection_monkey/exploit/zerologon.py index 68b6036a40e..267f47ec0ad 100644 --- a/monkey/infection_monkey/exploit/zerologon.py +++ b/monkey/infection_monkey/exploit/zerologon.py @@ -31,7 +31,6 @@ from infection_monkey.exploit.zerologon_utils.wmiexec import Wmiexec from infection_monkey.i_puppet import ExploiterResultData from infection_monkey.utils.capture_output import StdoutCapture -from infection_monkey.utils.ids import get_agent_id from infection_monkey.utils.threading import interruptible_iter logger = logging.getLogger(__name__) @@ -399,7 +398,7 @@ def _publish_credentials_stolen_event( self, extracted_credentials: Sequence[Credentials] ) -> None: credentials_stolen_event = CredentialsStolenEvent( - source=get_agent_id(), + source=self.agent_id, target=self.host.ip, tags=CREDENTIALS_STOLEN_EVENT_TAGS, stolen_credentials=extracted_credentials, @@ -578,7 +577,7 @@ def assess_restoration_attempt_result(self, restoration_attempt_result) -> bool: def _publish_password_restoration_event(self, success: bool): password_restoration_event = PasswordRestorationEvent( - source=get_agent_id(), + source=self.agent_id, target=self.host.ip, tags=PASSWORD_RESTORATION_EVENT_TAGS, success=success, From b559cc28489c4ab734d420cc9b455840e48f57d1 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Mon, 27 Mar 2023 17:38:41 +0530 Subject: [PATCH 4/8] Agent: Don't use 'get_agent_id()' in build_monkey_commandline() --- monkey/infection_monkey/utils/commands.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/utils/commands.py b/monkey/infection_monkey/utils/commands.py index 38e011c6e31..c1416d7a480 100644 --- a/monkey/infection_monkey/utils/commands.py +++ b/monkey/infection_monkey/utils/commands.py @@ -4,7 +4,6 @@ from common.types import AgentID 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.utils.ids import get_agent_id # Dropper target paths DROPPER_TARGET_PATH_LINUX = AGENT_BINARY_PATH_LINUX @@ -12,12 +11,11 @@ def build_monkey_commandline( - servers: List[str], depth: int, location: Union[str, PurePath, None] = None + agent_id: AgentID, servers: List[str], depth: int, location: Union[str, PurePath, None] = None ) -> str: - return " " + " ".join( build_monkey_commandline_explicitly( - get_agent_id(), + agent_id, servers, depth, location, From 18fb13540b817c6e62fec52fad77885c97a000b4 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Mon, 27 Mar 2023 17:50:23 +0530 Subject: [PATCH 5/8] Agent: Modify build_monkey_commandline() to accept Agent ID --- monkey/infection_monkey/exploit/log4shell.py | 5 +++-- monkey/infection_monkey/exploit/mssqlexec.py | 2 +- monkey/infection_monkey/exploit/powershell.py | 13 +++++++------ monkey/infection_monkey/exploit/sshexec.py | 2 +- monkey/infection_monkey/exploit/web_rce.py | 6 ++++-- monkey/infection_monkey/exploit/wmiexec.py | 5 ++--- 6 files changed, 18 insertions(+), 15 deletions(-) diff --git a/monkey/infection_monkey/exploit/log4shell.py b/monkey/infection_monkey/exploit/log4shell.py index 74e894ac590..5e0cbfcc098 100644 --- a/monkey/infection_monkey/exploit/log4shell.py +++ b/monkey/infection_monkey/exploit/log4shell.py @@ -136,7 +136,9 @@ def _build_ldap_payload(self) -> str: def _build_command(self, path: PurePath, http_path) -> str: # Build command to execute - monkey_cmd = build_monkey_commandline(self.servers, self.current_depth + 1, location=path) + monkey_cmd = build_monkey_commandline( + self.agent_id, self.servers, self.current_depth + 1, location=path + ) if OperatingSystem.WINDOWS == self.host.operating_system: base_command = LOG4SHELL_WINDOWS_COMMAND else: @@ -161,7 +163,6 @@ def exploit(self, url, command) -> None: for exploit in get_log4shell_service_exploiters(): intr_ports = interruptible_iter(self._open_ports, self.interrupt) for port in intr_ports: - logger.debug( f'Attempting Log4Shell exploit on for service "{exploit.service_name}"' f"on port {port}" diff --git a/monkey/infection_monkey/exploit/mssqlexec.py b/monkey/infection_monkey/exploit/mssqlexec.py index 5158032fe8b..4fd162914c4 100644 --- a/monkey/infection_monkey/exploit/mssqlexec.py +++ b/monkey/infection_monkey/exploit/mssqlexec.py @@ -205,7 +205,7 @@ def _run_agent(self, agent_path_on_victim: PureWindowsPath): def _build_agent_launch_command(self, agent_path_on_victim: PureWindowsPath) -> str: agent_args = build_monkey_commandline( - self.servers, self.current_depth + 1, str(agent_path_on_victim) + self.agent_id, self.servers, self.current_depth + 1, str(agent_path_on_victim) ) return f"{agent_path_on_victim} {DROPPER_ARG} {agent_args}" diff --git a/monkey/infection_monkey/exploit/powershell.py b/monkey/infection_monkey/exploit/powershell.py index b302f7f197c..93eb92cdc53 100644 --- a/monkey/infection_monkey/exploit/powershell.py +++ b/monkey/infection_monkey/exploit/powershell.py @@ -9,7 +9,7 @@ T1105_ATTACK_TECHNIQUE_TAG, T1110_ATTACK_TECHNIQUE_TAG, ) -from common.types import NetworkPort, PortStatus +from common.types import AgentID, NetworkPort, PortStatus from common.utils.environment import is_windows_os from infection_monkey.exploit.HostExploiter import HostExploiter from infection_monkey.exploit.powershell_utils.auth_options import AuthOptions, get_auth_options @@ -127,8 +127,7 @@ def _authenticate_via_brute_force( self, credentials: List[Credentials], auth_options: List[AuthOptions] ) -> Optional[IPowerShellClient]: creds_opts_pairs = filter(self.check_ssl_setting_is_valid, zip(credentials, auth_options)) - for (creds, opts) in interruptible_iter(creds_opts_pairs, self.interrupt): - + for creds, opts in interruptible_iter(creds_opts_pairs, self.interrupt): try: client = PowerShellClient(str(self.host.ip), creds, opts) connect_timestamp = time() @@ -191,7 +190,6 @@ def _execute_monkey_agent_on_victim(self): ) def _copy_monkey_binary_to_victim(self, monkey_path_on_victim: PurePath): - temp_monkey_binary_filepath = Path(f"./monkey_temp_bin_{get_random_file_suffix()}") self._create_local_agent_file(temp_monkey_binary_filepath) @@ -212,7 +210,7 @@ def _create_local_agent_file(self, binary_path): def _run_monkey_executable_on_victim(self, executable_path): monkey_execution_command = build_monkey_execution_command( - self.servers, self.current_depth + 1, executable_path + self.agent_id, self.servers, self.current_depth + 1, executable_path ) logger.info(f"Attempting to execute the monkey agent on remote host " f"{self.host.ip}") @@ -220,8 +218,11 @@ def _run_monkey_executable_on_victim(self, executable_path): self._client.execute_cmd_as_detached_process(monkey_execution_command) -def build_monkey_execution_command(servers: List[str], depth: int, executable_path: str) -> str: +def build_monkey_execution_command( + agent_id: AgentID, servers: List[str], depth: int, executable_path: str +) -> str: monkey_params = build_monkey_commandline( + agent_id, servers, depth=depth, location=executable_path, diff --git a/monkey/infection_monkey/exploit/sshexec.py b/monkey/infection_monkey/exploit/sshexec.py index 590474b5c1a..155c8477259 100644 --- a/monkey/infection_monkey/exploit/sshexec.py +++ b/monkey/infection_monkey/exploit/sshexec.py @@ -237,7 +237,7 @@ def _propagate(self, ssh: paramiko.SSHClient): try: cmdline = f"{monkey_path_on_victim} {MONKEY_ARG}" - cmdline += build_monkey_commandline(self.servers, self.current_depth + 1) + cmdline += build_monkey_commandline(self.agent_id, self.servers, self.current_depth + 1) cmdline += " > /dev/null 2>&1 &" timestamp = time() ssh.exec_command(cmdline, timeout=SSH_EXEC_TIMEOUT) diff --git a/monkey/infection_monkey/exploit/web_rce.py b/monkey/infection_monkey/exploit/web_rce.py index d08a80f687c..a92739711fa 100644 --- a/monkey/infection_monkey/exploit/web_rce.py +++ b/monkey/infection_monkey/exploit/web_rce.py @@ -352,7 +352,7 @@ def execute_remote_monkey(self, url, path, dropper=False): if default_path is False: return False monkey_cmd = build_monkey_commandline( - self.servers, self.current_depth + 1, default_path + self.agent_id, self.servers, self.current_depth + 1, default_path ) command = RUN_MONKEY % { "monkey_path": path, @@ -360,7 +360,9 @@ def execute_remote_monkey(self, url, path, dropper=False): "parameters": monkey_cmd, } else: - monkey_cmd = build_monkey_commandline(self.servers, self.current_depth + 1) + monkey_cmd = build_monkey_commandline( + self.agent_id, self.servers, self.current_depth + 1 + ) command = RUN_MONKEY % { "monkey_path": path, "monkey_type": MONKEY_ARG, diff --git a/monkey/infection_monkey/exploit/wmiexec.py b/monkey/infection_monkey/exploit/wmiexec.py index e908d85289f..48b69a8b6ab 100644 --- a/monkey/infection_monkey/exploit/wmiexec.py +++ b/monkey/infection_monkey/exploit/wmiexec.py @@ -39,7 +39,6 @@ class WmiExploiter(HostExploiter): @WmiTools.impacket_user @WmiTools.dcom_wrap def _exploit_host(self) -> ExploiterResultData: - creds = generate_brute_force_combinations(self.options["credentials"]) intp_creds = interruptible_iter( creds, @@ -49,7 +48,6 @@ def _exploit_host(self) -> ExploiterResultData: ) for user, password, lm_hash, ntlm_hash in intp_creds: - creds_for_log = get_credential_string([user, password, lm_hash, ntlm_hash]) logger.debug(f"Attempting to connect to {self.host} using WMI with {creds_for_log}") @@ -130,6 +128,7 @@ def _exploit_host(self) -> ExploiterResultData: cmdline = DROPPER_CMDLINE_WINDOWS % { "dropper_path": remote_full_path } + build_monkey_commandline( + self.agent_id, self.servers, self.current_depth + 1, DROPPER_TARGET_PATH_WIN64, @@ -137,7 +136,7 @@ def _exploit_host(self) -> ExploiterResultData: else: cmdline = MONKEY_CMDLINE_WINDOWS % { "monkey_path": remote_full_path - } + build_monkey_commandline(self.servers, self.current_depth + 1) + } + build_monkey_commandline(self.agent_id, self.servers, self.current_depth + 1) # execute the remote monkey result = WmiTools.get_object(wmi_connection, "Win32_Process").Create( From 35308be284205700d9a08e0829915f8c8484e427 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Mon, 27 Mar 2023 18:05:58 +0530 Subject: [PATCH 6/8] Hadoop: Modify command builder to accept and use Agent ID --- .../exploiters/hadoop/src/hadoop_command_builder.py | 4 +++- .../exploiters/hadoop/src/hadoop_exploiter.py | 10 ++++++++-- monkey/agent_plugins/exploiters/hadoop/src/plugin.py | 4 +++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/monkey/agent_plugins/exploiters/hadoop/src/hadoop_command_builder.py b/monkey/agent_plugins/exploiters/hadoop/src/hadoop_command_builder.py index c6a33d17aac..1cefa96bfea 100644 --- a/monkey/agent_plugins/exploiters/hadoop/src/hadoop_command_builder.py +++ b/monkey/agent_plugins/exploiters/hadoop/src/hadoop_command_builder.py @@ -1,6 +1,7 @@ from typing import Sequence from common import OperatingSystem +from common.types import AgentID from infection_monkey.exploit.tools.helpers import get_agent_dst_path from infection_monkey.i_puppet import TargetHost from infection_monkey.model import MONKEY_ARG @@ -39,12 +40,13 @@ def build_hadoop_command( + agent_id: AgentID, target_host: TargetHost, servers: Sequence[str], current_depth: int, agent_download_url: str, ) -> str: - monkey_cmd = build_monkey_commandline(servers, current_depth + 1) + monkey_cmd = build_monkey_commandline(agent_id, servers, current_depth + 1) if OperatingSystem.WINDOWS == target_host.operating_system: base_command = HADOOP_WINDOWS_COMMAND_TEMPLATE diff --git a/monkey/agent_plugins/exploiters/hadoop/src/hadoop_exploiter.py b/monkey/agent_plugins/exploiters/hadoop/src/hadoop_exploiter.py index f9626d3e706..82dfdc3865e 100644 --- a/monkey/agent_plugins/exploiters/hadoop/src/hadoop_exploiter.py +++ b/monkey/agent_plugins/exploiters/hadoop/src/hadoop_exploiter.py @@ -1,7 +1,7 @@ import logging from typing import Callable, Sequence -from common.types import Event, NetworkPort, NetworkService, PortStatus +from common.types import AgentID, Event, NetworkPort, NetworkService, PortStatus from infection_monkey.exploit.tools import HTTPBytesServer from infection_monkey.exploit.tools.web_tools import build_urls from infection_monkey.i_puppet import ExploiterResultData, TargetHost @@ -19,9 +19,11 @@ class HadoopExploiter: def __init__( self, + agent_id: AgentID, hadoop_exploit_client: HadoopExploitClient, start_agent_binary_server: AgentBinaryServerFactory, ): + self._agent_id = agent_id self._hadoop_exploit_client = hadoop_exploit_client self._start_agent_binary_server = start_agent_binary_server @@ -54,7 +56,11 @@ def exploit_host( return ExploiterResultData(error_message=msg) command = build_hadoop_command( - target_host, servers, current_depth, agent_binary_http_server.download_url + self._agent_id, + target_host, + servers, + current_depth, + agent_binary_http_server.download_url, ) logger.debug(f"Command: {command}") diff --git a/monkey/agent_plugins/exploiters/hadoop/src/plugin.py b/monkey/agent_plugins/exploiters/hadoop/src/plugin.py index ec860d53ad5..057d5a03fc5 100644 --- a/monkey/agent_plugins/exploiters/hadoop/src/plugin.py +++ b/monkey/agent_plugins/exploiters/hadoop/src/plugin.py @@ -47,7 +47,9 @@ def __init__( tcp_port_selector=tcp_port_selector, ) - self._hadoop_exploiter = HadoopExploiter(hadoop_exploit_client, agent_binary_server_factory) + self._hadoop_exploiter = HadoopExploiter( + agent_id, hadoop_exploit_client, agent_binary_server_factory + ) def run( self, From dc674337c83d79bdb652b163bd072ca98544c127 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Mon, 27 Mar 2023 18:11:34 +0530 Subject: [PATCH 7/8] SMB: Modify command builder to accept and use Agent ID --- monkey/agent_plugins/exploiters/smb/src/plugin.py | 1 + .../agent_plugins/exploiters/smb/src/smb_command_builder.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/monkey/agent_plugins/exploiters/smb/src/plugin.py b/monkey/agent_plugins/exploiters/smb/src/plugin.py index 6291097a3fa..cf5b76bd260 100644 --- a/monkey/agent_plugins/exploiters/smb/src/plugin.py +++ b/monkey/agent_plugins/exploiters/smb/src/plugin.py @@ -85,6 +85,7 @@ def run( command_builder = partial( build_smb_command, + self._agent_id, servers, current_depth, remote_agent_binary_destination_path=get_agent_dst_path(host), diff --git a/monkey/agent_plugins/exploiters/smb/src/smb_command_builder.py b/monkey/agent_plugins/exploiters/smb/src/smb_command_builder.py index 2e2ad8228c4..b2308765c93 100644 --- a/monkey/agent_plugins/exploiters/smb/src/smb_command_builder.py +++ b/monkey/agent_plugins/exploiters/smb/src/smb_command_builder.py @@ -3,12 +3,14 @@ from common import OperatingSystem from common.common_consts import AGENT_OTP_ENVIRONMENT_VARIABLE +from common.types import AgentID from infection_monkey.exploit import IAgentOTPProvider from infection_monkey.model import CMD_PREFIX, DROPPER_ARG, MONKEY_ARG, SET_OTP_WINDOWS from infection_monkey.utils.commands import build_monkey_commandline def build_smb_command( + agent_id: AgentID, servers: Sequence[str], current_depth: int, operating_system: OperatingSystem, @@ -31,6 +33,7 @@ def build_smb_command( cmdline = ( f"{CMD_PREFIX} {otp} start cmd /c {str(remote_agent_binary_full_path)} {DROPPER_ARG}" + build_monkey_commandline( + agent_id, servers, current_depth + 1, str(remote_agent_binary_destination_path), @@ -39,7 +42,7 @@ def build_smb_command( else: cmdline = ( f"{CMD_PREFIX} {otp} start cmd /c {str(remote_agent_binary_full_path)} {MONKEY_ARG}" - + build_monkey_commandline(servers, current_depth + 1) + + build_monkey_commandline(agent_id, servers, current_depth + 1) ) return cmdline From eac038dccc76cbd48358ca38fbbf56c998f55501 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Mon, 27 Mar 2023 18:44:13 +0530 Subject: [PATCH 8/8] UT: Fix tests to work with new Agent ID logic --- .../hadoop/test_hadoop_exploiter.py | 4 +++- .../smb/test_smb_command_builder.py | 14 +++++++++++- .../exploit/test_powershell.py | 5 ++++- .../exploit/test_zerologon.py | 2 ++ .../infection_monkey/utils/test_commands.py | 22 +++++++++++++------ 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/monkey/tests/unit_tests/agent_plugins/exploiters/hadoop/test_hadoop_exploiter.py b/monkey/tests/unit_tests/agent_plugins/exploiters/hadoop/test_hadoop_exploiter.py index 10bf6b1498e..77663416e42 100644 --- a/monkey/tests/unit_tests/agent_plugins/exploiters/hadoop/test_hadoop_exploiter.py +++ b/monkey/tests/unit_tests/agent_plugins/exploiters/hadoop/test_hadoop_exploiter.py @@ -18,7 +18,9 @@ TargetHost, TargetHostPorts, ) +from infection_monkey.utils.ids import get_agent_id +AGENT_ID = get_agent_id() TARGET_IP = IPv4Address("1.1.1.1") SERVERS = ["10.10.10.10"] DOWNLOAD_URL = "http://download.me" @@ -83,7 +85,7 @@ def hadoop_exploiter( mock_hadoop_exploit_client: HadoopExploitClient, mock_start_agent_binary_server: Callable[[TargetHost], HTTPBytesServer], ) -> HadoopExploiter: - return HadoopExploiter(mock_hadoop_exploit_client, mock_start_agent_binary_server) + return HadoopExploiter(AGENT_ID, mock_hadoop_exploit_client, mock_start_agent_binary_server) @pytest.fixture diff --git a/monkey/tests/unit_tests/agent_plugins/exploiters/smb/test_smb_command_builder.py b/monkey/tests/unit_tests/agent_plugins/exploiters/smb/test_smb_command_builder.py index 4918646ad69..fdc6022dd69 100644 --- a/monkey/tests/unit_tests/agent_plugins/exploiters/smb/test_smb_command_builder.py +++ b/monkey/tests/unit_tests/agent_plugins/exploiters/smb/test_smb_command_builder.py @@ -7,10 +7,12 @@ from common import OperatingSystem from infection_monkey.exploit import IAgentOTPProvider from infection_monkey.model import DROPPER_ARG, MONKEY_ARG +from infection_monkey.utils.ids import get_agent_id DROPPER_EXE_PATH = PureWindowsPath("C:\\dropper.exe") AGENT_EXE_PATH = PureWindowsPath("C:\\agent.exe") OTP = "123456" +AGENT_ID = get_agent_id() @pytest.fixture @@ -23,6 +25,7 @@ def otp_provider() -> IAgentOTPProvider: def test_exception_raised_for_linux(otp_provider: IAgentOTPProvider): with pytest.raises(Exception): build_smb_command( + AGENT_ID, ["127.0.0.1"], 2, OperatingSystem.LINUX, @@ -46,7 +49,13 @@ def test_servers( ): servers = ["127.0.0.1", "192.168.1.100", "172.1.2.3"] command = build_smb_command( - servers, 2, OperatingSystem.WINDOWS, DROPPER_EXE_PATH, AGENT_EXE_PATH, otp_provider + AGENT_ID, + servers, + 2, + OperatingSystem.WINDOWS, + DROPPER_EXE_PATH, + AGENT_EXE_PATH, + otp_provider, ) for s in servers: @@ -55,6 +64,7 @@ def test_servers( def test_dropper_used(otp_provider: IAgentOTPProvider): command = build_smb_command( + AGENT_ID, ["127.0.0.1"], 2, OperatingSystem.WINDOWS, @@ -68,6 +78,7 @@ def test_dropper_used(otp_provider: IAgentOTPProvider): def test_monkey_used(otp_provider: IAgentOTPProvider): command = build_smb_command( + AGENT_ID, ["127.0.0.1"], 2, OperatingSystem.WINDOWS, @@ -81,6 +92,7 @@ def test_monkey_used(otp_provider: IAgentOTPProvider): def test_otp_used(otp_provider: IAgentOTPProvider): command = build_smb_command( + AGENT_ID, ["127.0.0.1"], 2, OperatingSystem.WINDOWS, 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 679d175959d..babdc61d016 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/test_powershell.py @@ -7,6 +7,7 @@ from infection_monkey.exploit import powershell from infection_monkey.exploit.tools.helpers import AGENT_BINARY_PATH_WIN64 +from infection_monkey.utils.ids import get_agent_id # Use the path_win32api_get_user_name fixture for all tests in this module pytestmark = pytest.mark.usefixtures("patch_win32api_get_user_name") @@ -18,6 +19,7 @@ bogus_servers = ["1.1.1.1:5000", "2.2.2.2:5007"] VICTIM_IP = IPv4Address("10.10.10.1") +AGENT_ID = get_agent_id() mock_agent_binary_repository = MagicMock() @@ -53,6 +55,7 @@ def powershell_arguments(host_with_ip_address): }, } arguments = { + "agent_id": AGENT_ID, "host": host_with_ip_address, "servers": bogus_servers, "options": options, @@ -186,7 +189,7 @@ def test_build_monkey_execution_command(): depth = 2 executable_path = "/tmp/test-monkey" - cmd = powershell.build_monkey_execution_command(bogus_servers, depth, executable_path) + cmd = powershell.build_monkey_execution_command(AGENT_ID, bogus_servers, depth, executable_path) assert f"-d {depth}" in cmd assert executable_path in cmd diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/test_zerologon.py b/monkey/tests/unit_tests/infection_monkey/exploit/test_zerologon.py index 9b31e9f913a..45f1b25e693 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/test_zerologon.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/test_zerologon.py @@ -6,6 +6,7 @@ from common.agent_events import ExploitationEvent, PasswordRestorationEvent from common.event_queue import IAgentEventQueue from infection_monkey.i_puppet import TargetHost +from infection_monkey.utils.ids import get_agent_id NETBIOS_NAME = "NetBIOS Name" @@ -32,6 +33,7 @@ def mock_report_login_attempt(**kwargs): monkeypatch.setattr(obj, "report_login_attempt", mock_report_login_attempt) monkeypatch.setattr(obj, "host", TargetHost(ip=IPv4Address("1.1.1.1"))) monkeypatch.setattr(obj, "agent_event_queue", mock_agent_event_queue) + monkeypatch.setattr(obj, "agent_id", get_agent_id()) return obj diff --git a/monkey/tests/unit_tests/infection_monkey/utils/test_commands.py b/monkey/tests/unit_tests/infection_monkey/utils/test_commands.py index ac2318852e9..e0f9504c516 100644 --- a/monkey/tests/unit_tests/infection_monkey/utils/test_commands.py +++ b/monkey/tests/unit_tests/infection_monkey/utils/test_commands.py @@ -9,6 +9,11 @@ from infection_monkey.utils.ids import get_agent_id +@pytest.fixture +def agent_id(): + return get_agent_id() + + def test_build_monkey_commandline_explicitly_arguments(): expected = [ "-p", @@ -73,19 +78,22 @@ def test_get_monkey_commandline_linux(): assert expected == actual -def test_build_monkey_commandline(): +def test_build_monkey_commandline(agent_id): servers = ["10.10.10.10:5000", "11.11.11.11:5007"] - expected = f" -p {get_agent_id()} -s 10.10.10.10:5000,11.11.11.11:5007 -d 0 -l /home/bla" - actual = build_monkey_commandline(servers=servers, depth=0, location="/home/bla") + expected = f" -p {agent_id} -s 10.10.10.10:5000,11.11.11.11:5007 -d 0 -l /home/bla" + actual = build_monkey_commandline( + agent_id=agent_id, servers=servers, depth=0, location="/home/bla" + ) assert expected == actual @pytest.mark.parametrize("servers", [None, []]) -def test_build_monkey_commandline_empty_servers(servers): - - expected = f" -p {get_agent_id()} -d 0 -l /home/bla" - actual = build_monkey_commandline(servers, depth=0, location="/home/bla") +def test_build_monkey_commandline_empty_servers(agent_id, servers): + expected = f" -p {agent_id} -d 0 -l /home/bla" + actual = build_monkey_commandline( + agent_id=agent_id, servers=servers, depth=0, location="/home/bla" + ) assert expected == actual