Agent: Rename IAgentRepository -> IAgentBinaryRepository

PR #2239
This commit is contained in:
Mike Salvatore 2022-09-01 14:08:11 -04:00
parent 453f45e403
commit 765ce858fb
17 changed files with 59 additions and 47 deletions

View File

@ -9,7 +9,7 @@ from common.utils.exceptions import FailedExploitationError
from infection_monkey.i_puppet import ExploiterResultData
from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger
from . import IAgentRepository
from . import IAgentBinaryRepository
logger = logging.getLogger(__name__)
@ -61,7 +61,7 @@ class HostExploiter:
current_depth: int,
telemetry_messenger: ITelemetryMessenger,
event_queue: IEventQueue,
agent_repository: IAgentRepository,
agent_binary_repository: IAgentBinaryRepository,
options: Dict,
interrupt: threading.Event,
):
@ -69,7 +69,7 @@ class HostExploiter:
self.current_depth = current_depth
self.telemetry_messenger = telemetry_messenger
self.event_queue = event_queue
self.agent_repository = agent_repository
self.agent_binary_repository = agent_binary_repository
self.options = options
self.interrupt = interrupt

View File

@ -1,3 +1,3 @@
from .i_agent_repository import IAgentRepository
from .caching_agent_repository import CachingAgentRepository
from .i_agent_binary_repository import IAgentBinaryRepository
from .caching_agent_binary_repository import CachingAgentBinaryRepository
from .exploiter_wrapper import ExploiterWrapper

View File

@ -8,14 +8,14 @@ import requests
from common import OperatingSystem
from common.common_consts.timeouts import MEDIUM_REQUEST_TIMEOUT
from . import IAgentRepository
from . import IAgentBinaryRepository
class CachingAgentRepository(IAgentRepository):
class CachingAgentBinaryRepository(IAgentBinaryRepository):
"""
CachingAgentRepository implements the IAgentRepository interface and downloads the requested
agent binary from the island on request. The agent binary is cached so that only one request is
actually sent to the island for each requested binary.
CachingAgentBinaryRepository implements the IAgentBinaryRepository interface and downloads the
requested agent binary from the island on request. The agent binary is cached so that only one
request is actually sent to the island for each requested binary.
"""
def __init__(self, island_url: str, proxies: Mapping[str, str]):

View File

@ -5,7 +5,7 @@ from common.event_queue import IEventQueue
from infection_monkey.model import VictimHost
from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger
from . import IAgentRepository
from . import IAgentBinaryRepository
from .HostExploiter import HostExploiter
@ -23,12 +23,12 @@ class ExploiterWrapper:
exploit_class: Type[HostExploiter],
telemetry_messenger: ITelemetryMessenger,
event_queue: IEventQueue,
agent_repository: IAgentRepository,
agent_binary_repository: IAgentBinaryRepository,
):
self._exploit_class = exploit_class
self._telemetry_messenger = telemetry_messenger
self._event_queue = event_queue
self._agent_repository = agent_repository
self._agent_binary_repository = agent_binary_repository
def exploit_host(
self, host: VictimHost, current_depth: int, options: Dict, interrupt: threading.Event
@ -39,7 +39,7 @@ class ExploiterWrapper:
current_depth,
self._telemetry_messenger,
self._event_queue,
self._agent_repository,
self._agent_binary_repository,
options,
interrupt,
)
@ -48,13 +48,16 @@ class ExploiterWrapper:
self,
telemetry_messenger: ITelemetryMessenger,
event_queue: IEventQueue,
agent_repository: IAgentRepository,
agent_binary_repository: IAgentBinaryRepository,
):
self._telemetry_messenger = telemetry_messenger
self._event_queue = event_queue
self._agent_repository = agent_repository
self._agent_binary_repository = agent_binary_repository
def wrap(self, exploit_class: Type[HostExploiter]):
return ExploiterWrapper.Inner(
exploit_class, self._telemetry_messenger, self._event_queue, self._agent_repository
exploit_class,
self._telemetry_messenger,
self._event_queue,
self._agent_binary_repository,
)

View File

@ -48,7 +48,7 @@ class HadoopExploiter(WebRCE):
return self.exploit_result
http_path, http_thread = HTTPTools.create_locked_transfer(
self.host, str(monkey_path_on_victim), self.agent_repository
self.host, str(monkey_path_on_victim), self.agent_binary_repository
)
try:

View File

@ -3,15 +3,15 @@ import io
from common import OperatingSystem
# TODO: The Island also has an IAgentRepository with a totally different interface. At the moment,
# the Island and Agent have different needs, but at some point we should unify these.
# TODO: The Island also has an IAgentBinaryRepository with a totally different interface. At the
# moment, the Island and Agent have different needs, but at some point we should unify these.
class IAgentRepository(metaclass=abc.ABCMeta):
class IAgentBinaryRepository(metaclass=abc.ABCMeta):
"""
IAgentRepository provides an interface for other components to access agent binaries. Notably,
this is used by exploiters during propagation to retrieve the appropriate agent binary so that
it can be uploaded to a victim and executed.
IAgentBinaryRepository provides an interface for other components to access agent binaries.
Notably, this is used by exploiters during propagation to retrieve the appropriate agent binary
so that it can be uploaded to a victim and executed.
"""
@abc.abstractmethod

View File

@ -79,7 +79,7 @@ class Log4ShellExploiter(WebRCE):
def _start_agent_http_server(self, dropper_target_path) -> str:
# Create server for http download and wait for it's startup.
http_path, http_thread = HTTPTools.try_create_locked_transfer(
self.host, dropper_target_path, self.agent_repository
self.host, dropper_target_path, self.agent_binary_repository
)
self._agent_http_server_thread = http_thread
return http_path

View File

@ -147,7 +147,7 @@ class MSSQLExploiter(HostExploiter):
def _start_agent_server(self, agent_path_on_victim: PureWindowsPath) -> LockedHTTPServer:
self.agent_http_path, http_thread = HTTPTools.create_locked_transfer(
self.host, str(agent_path_on_victim), self.agent_repository
self.host, str(agent_path_on_victim), self.agent_binary_repository
)
return http_thread

View File

@ -163,7 +163,7 @@ class PowerShellExploiter(HostExploiter):
temp_monkey_binary_filepath.unlink()
def _create_local_agent_file(self, binary_path):
agent_binary_bytes = self.agent_repository.get_agent_binary(OperatingSystem.WINDOWS)
agent_binary_bytes = self.agent_binary_repository.get_agent_binary(OperatingSystem.WINDOWS)
with open(binary_path, "wb") as f:
f.write(agent_binary_bytes.getvalue())

View File

@ -30,7 +30,7 @@ class SMBExploiter(HostExploiter):
SMB_SERVICE_NAME = "InfectionMonkey"
def _exploit_host(self):
agent_binary = self.agent_repository.get_agent_binary(self.host.os["type"])
agent_binary = self.agent_binary_repository.get_agent_binary(self.host.os["type"])
dest_path = get_agent_dst_path(self.host)
creds = generate_brute_force_combinations(self.options["credentials"])

View File

@ -195,7 +195,9 @@ class SSHExploiter(HostExploiter):
logger.error(self.exploit_result.error_message)
return self.exploit_result
agent_binary_file_object = self.agent_repository.get_agent_binary(self.exploit_result.os)
agent_binary_file_object = self.agent_binary_repository.get_agent_binary(
self.exploit_result.os
)
if not agent_binary_file_object:
self.exploit_result.error_message = (

View File

@ -15,10 +15,10 @@ logger = logging.getLogger(__name__)
class HTTPTools(object):
@staticmethod
def try_create_locked_transfer(
host, src_path, agent_repository, local_ip=None, local_port=None
host, src_path, agent_binary_repository, local_ip=None, local_port=None
):
http_path, http_thread = HTTPTools.create_locked_transfer(
host, src_path, agent_repository, local_ip, local_port
host, src_path, agent_binary_repository, local_ip, local_port
)
if not http_path:
raise Exception("Http transfer creation failed.")
@ -27,13 +27,13 @@ class HTTPTools(object):
@staticmethod
def create_locked_transfer(
host, dropper_target_path, agent_repository, local_ip=None, local_port=None
host, dropper_target_path, agent_binary_repository, local_ip=None, local_port=None
) -> LockedHTTPServer:
"""
Create http server for file transfer with a lock
:param host: Variable with target's information
:param src_path: Monkey's path on current system
:param agent_repository: Repository to download Monkey agents
:param agent_binary_repository: Repository to download Monkey agents
:param local_ip: IP where to host server
:param local_port: Port at which to host monkey's download
:return: Server address in http://%s:%s/%s format and LockedHTTPServer handler
@ -52,7 +52,12 @@ class HTTPTools(object):
return None, None
httpd = LockedHTTPServer(
local_ip, local_port, host.os["type"], dropper_target_path, agent_repository, lock
local_ip,
local_port,
host.os["type"],
dropper_target_path,
agent_binary_repository,
lock,
)
httpd.start()
lock.acquire()

View File

@ -295,7 +295,7 @@ class WebRCE(HostExploiter):
dropper_target_path = self.monkey_target_paths[self.host.os["type"]]
# Create server for http download and wait for it's startup.
http_path, http_thread = HTTPTools.create_locked_transfer(
self.host, dropper_target_path, self.agent_repository
self.host, dropper_target_path, self.agent_binary_repository
)
if not http_path:
logger.debug("Exploiter failed, http transfer creation failed.")

View File

@ -68,7 +68,7 @@ class WmiExploiter(HostExploiter):
self.report_login_attempt(True, user, password, lm_hash, ntlm_hash)
self.exploit_result.exploitation_success = True
downloaded_agent = self.agent_repository.get_agent_binary(self.host.os["type"])
downloaded_agent = self.agent_binary_repository.get_agent_binary(self.host.os["type"])
if self._is_interrupted():
self._set_interrupted()

View File

@ -27,7 +27,7 @@ from infection_monkey.credential_repository import (
IPropagationCredentialsRepository,
add_credentials_from_event_to_propagation_credentials_repository,
)
from infection_monkey.exploit import CachingAgentRepository, ExploiterWrapper
from infection_monkey.exploit import CachingAgentBinaryRepository, ExploiterWrapper
from infection_monkey.exploit.hadoop import HadoopExploiter
from infection_monkey.exploit.log4shell import Log4ShellExploiter
from infection_monkey.exploit.mssqlexec import MSSQLExploiter
@ -270,10 +270,12 @@ class InfectionMonkey:
puppet.load_plugin("smb", SMBFingerprinter(), PluginType.FINGERPRINTER)
puppet.load_plugin("ssh", SSHFingerprinter(), PluginType.FINGERPRINTER)
agent_repository = CachingAgentRepository(
agent_binary_repository = CachingAgentBinaryRepository(
f"https://{self._control_client.server_address}", self._control_client.proxies
)
exploit_wrapper = ExploiterWrapper(self._telemetry_messenger, event_queue, agent_repository)
exploit_wrapper = ExploiterWrapper(
self._telemetry_messenger, event_queue, agent_binary_repository
)
puppet.load_plugin(
"HadoopExploiter", exploit_wrapper.wrap(HadoopExploiter), PluginType.EXPLOITER

View File

@ -19,7 +19,7 @@ logger = getLogger(__name__)
class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
protocol_version = "HTTP/1.1"
victim_os = ""
agent_repository = None
agent_binary_repository = None
def version_string(self):
return "Microsoft-IIS/7.5."
@ -66,7 +66,7 @@ class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
self.send_error(500, "")
return None, 0, 0
try:
f = self.agent_repository.get_agent_binary(self.victim_os)
f = self.agent_binary_repository.get_agent_binary(self.victim_os)
except IOError:
self.send_error(404, "File not found")
return None, 0, 0
@ -178,7 +178,7 @@ class LockedHTTPServer(threading.Thread):
local_port,
victim_os,
dropper_target_path,
agent_repository,
agent_binary_repository,
lock,
max_downloads=1,
):
@ -186,7 +186,7 @@ class LockedHTTPServer(threading.Thread):
self._local_port = local_port
self._victim_os = victim_os
self._dropper_target_path = dropper_target_path
self._agent_repository = agent_repository
self._agent_binary_repository = agent_binary_repository
self.max_downloads = max_downloads
self.downloads = 0
self._stopped = False
@ -200,7 +200,7 @@ class LockedHTTPServer(threading.Thread):
from infection_monkey.telemetry.attack.t1105_telem import T1105Telem
victim_os = self._victim_os
agent_repository = self._agent_repository
agent_binary_repository = self._agent_binary_repository
@staticmethod
def report_download(dest=None):

View File

@ -17,8 +17,8 @@ LM_HASH_LIST = ["bogo_lm_1"]
NT_HASH_LIST = ["bogo_nt_1", "bogo_nt_2"]
mock_agent_repository = MagicMock()
mock_agent_repository.get_agent_binary.return_value = BytesIO(b"BINARY_EXECUTABLE")
mock_agent_binary_repository = MagicMock()
mock_agent_binary_repository.get_agent_binary.return_value = BytesIO(b"BINARY_EXECUTABLE")
@pytest.fixture
@ -37,7 +37,7 @@ def powershell_arguments(http_and_https_both_enabled_host):
"current_depth": 2,
"telemetry_messenger": MagicMock(),
"event_queue": MagicMock(),
"agent_repository": mock_agent_repository,
"agent_binary_repository": mock_agent_binary_repository,
"interrupt": threading.Event(),
}
return arguments