Agent: Remove monkeyfs and download methods from ControlClient

This commit is contained in:
Mike Salvatore 2022-03-01 14:57:00 -05:00
parent 1b1b68f6a6
commit 279aed36af
6 changed files with 16 additions and 153 deletions

View File

@ -8,7 +8,6 @@ from urllib.parse import urljoin
import requests
from requests.exceptions import ConnectionError
import infection_monkey.monkeyfs as monkeyfs
import infection_monkey.tunnel as tunnel
from common.common_consts.api_url_consts import T1216_PBA_FILE_DOWNLOAD_PATH
from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT, MEDIUM_REQUEST_TIMEOUT
@ -258,22 +257,6 @@ class ControlClient(object):
ControlClient.load_control_config()
return not WormConfiguration.alive
@staticmethod
def download_monkey_exe(host):
filename, size = ControlClient.get_monkey_exe_filename_and_size_by_host(host)
if filename is None:
return None
return ControlClient.download_monkey_exe_by_filename(filename, size)
@staticmethod
def download_monkey_exe_by_os(is_windows, is_32bit):
filename, size = ControlClient.get_monkey_exe_filename_and_size_by_host_dict(
ControlClient.spoof_host_os_info(is_windows, is_32bit)
)
if filename is None:
return None
return ControlClient.download_monkey_exe_by_filename(filename, size)
@staticmethod
def spoof_host_os_info(is_windows, is_32bit):
if is_windows:
@ -291,70 +274,6 @@ class ControlClient(object):
return {"os": {"type": os, "machine": arch}}
@staticmethod
def download_monkey_exe_by_filename(filename, size):
if not WormConfiguration.current_server:
return None
try:
dest_file = monkeyfs.virtual_path(filename)
if (monkeyfs.isfile(dest_file)) and (size == monkeyfs.getsize(dest_file)):
return dest_file
else:
download = requests.get( # noqa: DUO123
"https://%s/api/monkey/download/%s"
% (WormConfiguration.current_server, filename),
verify=False,
proxies=ControlClient.proxies,
timeout=MEDIUM_REQUEST_TIMEOUT,
)
with monkeyfs.open(dest_file, "wb") as file_obj:
for chunk in download.iter_content(chunk_size=DOWNLOAD_CHUNK):
if chunk:
file_obj.write(chunk)
file_obj.flush()
if size == monkeyfs.getsize(dest_file):
return dest_file
except Exception as exc:
logger.warning(
"Error connecting to control server %s: %s", WormConfiguration.current_server, exc
)
@staticmethod
def get_monkey_exe_filename_and_size_by_host(host):
return ControlClient.get_monkey_exe_filename_and_size_by_host_dict(host.as_dict())
@staticmethod
def get_monkey_exe_filename_and_size_by_host_dict(host_dict):
if not WormConfiguration.current_server:
return None, None
try:
reply = requests.post( # noqa: DUO123
"https://%s/api/monkey/download" % (WormConfiguration.current_server,),
data=json.dumps(host_dict),
headers={"content-type": "application/json"},
verify=False,
proxies=ControlClient.proxies,
timeout=LONG_REQUEST_TIMEOUT,
)
if 200 == reply.status_code:
result_json = reply.json()
filename = result_json.get("filename")
if not filename:
return None, None
size = result_json.get("size")
return filename, size
else:
return None, None
except Exception as exc:
logger.warning(
"Error connecting to control server %s: %s", WormConfiguration.current_server, exc
)
return None, None
@staticmethod
def create_control_tunnel():
if not WormConfiguration.current_server:

View File

@ -2,7 +2,6 @@ import logging
import os
from typing import List, Optional
import infection_monkey.monkeyfs as monkeyfs
from common.utils.exploit_enum import ExploitType
from infection_monkey.exploit.consts import WIN_ARCH_32
from infection_monkey.exploit.HostExploiter import HostExploiter
@ -22,7 +21,7 @@ from infection_monkey.exploit.powershell_utils.powershell_client import (
IPowerShellClient,
PowerShellClient,
)
from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey_by_os
from infection_monkey.exploit.tools.helpers import get_monkey_depth
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
@ -186,11 +185,15 @@ class PowerShellExploiter(HostExploiter):
return is_monkey_copy_successful
def _write_virtual_file_to_local_path(self) -> None:
"""
# TODO: monkeyfs has been removed. Fix this in issue #1740.
monkey_fs_path = get_target_monkey_by_os(is_windows=True, is_32bit=self.is_32bit)
with monkeyfs.open(monkey_fs_path) as monkey_virtual_file:
with open(TEMP_MONKEY_BINARY_FILEPATH, "wb") as monkey_local_file:
monkey_local_file.write(monkey_virtual_file.read())
"""
pass
def _run_monkey_executable_on_victim(self, executable_path) -> None:
monkey_execution_command = build_monkey_execution_command(

View File

@ -11,18 +11,13 @@ def try_get_target_monkey(host):
def get_target_monkey(host):
from infection_monkey.control import ControlClient
if not host.os.get("type"):
return None
return ControlClient.download_monkey_exe(host)
raise NotImplementedError("get_target_monkey() has been retired. Use IAgentRepository instead.")
def get_target_monkey_by_os(is_windows, is_32bit):
from infection_monkey.control import ControlClient
return ControlClient.download_monkey_exe_by_os(is_windows, is_32bit)
raise NotImplementedError(
"get_target_monkey_by_os() has been retired. Use IAgentRepository instead."
)
def get_monkey_depth():

View File

@ -6,7 +6,6 @@ from impacket.dcerpc.v5 import srvs, transport
from impacket.smb3structs import SMB2_DIALECT_002, SMB2_DIALECT_21
from impacket.smbconnection import SMB_DIALECT, SMBConnection
import infection_monkey.monkeyfs as monkeyfs
from common.utils.attack_utils import ScanStatus
from infection_monkey.config import Configuration
from infection_monkey.network.tools import get_interface_to_target
@ -20,7 +19,8 @@ class SmbTools(object):
def copy_file(
host, src_path, dst_path, username, password, lm_hash="", ntlm_hash="", timeout=60
):
assert monkeyfs.isfile(src_path), "Source file to copy (%s) is missing" % (src_path,)
# monkeyfs has been removed. Fix this in issue #1741
# assert monkeyfs.isfile(src_path), "Source file to copy (%s) is missing" % (src_path,)
smb, dialect = SmbTools.new_smb_connection(
host, username, password, lm_hash, ntlm_hash, timeout
@ -138,10 +138,13 @@ class SmbTools(object):
remote_full_path = ntpath.join(share_path, remote_path.strip(ntpath.sep))
try:
# monkeyfs has been removed. Fix this in issue #1741
"""
with monkeyfs.open(src_path, "rb") as source_file:
# make sure of the timeout
smb.setTimeout(timeout)
smb.putFile(share_name, remote_path, source_file.read)
"""
file_uploaded = True
T1105Telem(

View File

@ -1,58 +0,0 @@
import os
from io import BytesIO
MONKEYFS_PREFIX = "monkeyfs://"
open_orig = open
class VirtualFile(BytesIO):
_vfs = {} # virtual File-System
def __init__(self, name, mode="r", buffering=None):
if not name.startswith(MONKEYFS_PREFIX):
name = MONKEYFS_PREFIX + name
self.name = name
if name in VirtualFile._vfs:
super(VirtualFile, self).__init__(self._vfs[name])
else:
super(VirtualFile, self).__init__()
def flush(self):
super(VirtualFile, self).flush()
VirtualFile._vfs[self.name] = self.getvalue()
@staticmethod
def getsize(path):
return len(VirtualFile._vfs[path])
@staticmethod
def isfile(path):
return path in VirtualFile._vfs
def getsize(path):
if path.startswith(MONKEYFS_PREFIX):
return VirtualFile.getsize(path)
else:
return os.stat(path).st_size
def isfile(path):
if path.startswith(MONKEYFS_PREFIX):
return VirtualFile.isfile(path)
else:
return os.path.isfile(path)
def virtual_path(name):
return "%s%s" % (MONKEYFS_PREFIX, name)
# noinspection PyShadowingBuiltins
def open(name, mode="r", buffering=-1):
# use normal open for regular paths, and our "virtual" open for monkeyfs:// paths
if name.startswith(MONKEYFS_PREFIX):
return VirtualFile(name, mode, buffering)
else:
return open_orig(name, mode=mode, buffering=buffering)

View File

@ -51,7 +51,8 @@ def powershell_exploiter(monkeypatch):
monkeypatch.setattr(powershell, "AuthenticationError", AuthenticationErrorForTests)
monkeypatch.setattr(powershell, "is_windows_os", lambda: True)
# It's regrettable to mock out a private method on the PowerShellExploiter instance object, but
# it's necessary to avoid having to deal with the monkeyfs
# it's necessary to avoid having to deal with the monkeyfs. TODO: monkeyfs has been removed, so
# fix this.
monkeypatch.setattr(pe, "_write_virtual_file_to_local_path", lambda: None)
return pe