forked from p15670423/monkey
parent
453f45e403
commit
765ce858fb
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]):
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
||||
|
|
|
@ -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"])
|
||||
|
||||
|
|
|
@ -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 = (
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue