forked from p15670423/monkey
Agent: Remove monkeyfs and download methods from ControlClient
This commit is contained in:
parent
1b1b68f6a6
commit
279aed36af
|
@ -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:
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue