diff --git a/monkey/infection_monkey/dropper.py b/monkey/infection_monkey/dropper.py index 902d30280..b3e5665c1 100644 --- a/monkey/infection_monkey/dropper.py +++ b/monkey/infection_monkey/dropper.py @@ -4,7 +4,6 @@ import filecmp import logging import os import pprint -import shlex import shutil import subprocess import sys @@ -13,10 +12,13 @@ from ctypes import c_char_p from common.utils.attack_utils import ScanStatus, UsageEnum from infection_monkey.config import WormConfiguration -from infection_monkey.exploit.tools.helpers import build_monkey_commandline_explicitly -from infection_monkey.model import MONKEY_CMDLINE_LINUX, MONKEY_CMDLINE_WINDOWS from infection_monkey.system_info import OperatingSystem, SystemInfoCollector from infection_monkey.telemetry.attack.t1106_telem import T1106Telem +from infection_monkey.utils.commands import ( + build_monkey_commandline_explicitly, + get_monkey_commandline_linux, + get_monkey_commandline_windows, +) if "win32" == sys.platform: from win32process import DETACHED_PROCESS @@ -143,19 +145,12 @@ class MonkeyDrops(object): ) if OperatingSystem.Windows == SystemInfoCollector.get_os(): - # TODO: Replace all of this string templating with a function that accepts - # the necessary parameters and returns a list of arguments. - monkey_cmdline = ( - MONKEY_CMDLINE_WINDOWS % {"monkey_path": self._config["destination_path"]} - + monkey_options - ) - monkey_cmdline_split = shlex.split( - monkey_cmdline, - posix=False, # won't try resolving "\" in paths as part of escape sequences + monkey_commandline = get_monkey_commandline_windows( + self._config["destination_path"], monkey_options ) monkey_process = subprocess.Popen( - monkey_cmdline_split, + monkey_commandline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -166,16 +161,11 @@ class MonkeyDrops(object): dest_path = self._config["destination_path"] # In Linux, we need to change the directory first, which is done # using thw `cwd` argument in `subprocess.Popen` below - # TODO: Replace all of this string templating with a function that accepts - # the necessary parameters and returns a list of arguments. - monkey_cmdline = ( - MONKEY_CMDLINE_LINUX % {"monkey_filename": dest_path.split("/")[-1]} - + monkey_options - ) - monkey_cmdline_split = shlex.split(monkey_cmdline) + + monkey_commandline = get_monkey_commandline_linux(dest_path, monkey_options) monkey_process = subprocess.Popen( - monkey_cmdline_split, + monkey_commandline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -187,7 +177,7 @@ class MonkeyDrops(object): LOG.info( "Executed monkey process (PID=%d) with command line: %s", monkey_process.pid, - monkey_cmdline, + " ".join(monkey_commandline), ) time.sleep(3) diff --git a/monkey/infection_monkey/exploit/hadoop.py b/monkey/infection_monkey/exploit/hadoop.py index 7a0264380..227638d5e 100644 --- a/monkey/infection_monkey/exploit/hadoop.py +++ b/monkey/infection_monkey/exploit/hadoop.py @@ -13,7 +13,7 @@ from random import SystemRandom import requests from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT -from infection_monkey.exploit.tools.helpers import build_monkey_commandline, get_monkey_depth +from infection_monkey.exploit.tools.helpers import get_monkey_depth from infection_monkey.exploit.tools.http_tools import HTTPTools from infection_monkey.exploit.web_rce import WebRCE from infection_monkey.model import ( @@ -22,6 +22,7 @@ from infection_monkey.model import ( ID_STRING, MONKEY_ARG, ) +from infection_monkey.utils.commands import build_monkey_commandline __author__ = "VakarisZ" diff --git a/monkey/infection_monkey/exploit/mssqlexec.py b/monkey/infection_monkey/exploit/mssqlexec.py index 24b46d278..6269a8778 100644 --- a/monkey/infection_monkey/exploit/mssqlexec.py +++ b/monkey/infection_monkey/exploit/mssqlexec.py @@ -8,14 +8,11 @@ import pymssql from common.utils.exceptions import ExploitingVulnerableMachineError, FailedExploitationError from common.utils.exploit_enum import ExploitType from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import ( - build_monkey_commandline, - get_monkey_depth, - get_monkey_dest_path, -) +from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_monkey_dest_path from infection_monkey.exploit.tools.http_tools import MonkeyHTTPServer from infection_monkey.exploit.tools.payload_parsing import LimitedSizePayload from infection_monkey.model import DROPPER_ARG +from infection_monkey.utils.commands import build_monkey_commandline LOG = logging.getLogger(__name__) diff --git a/monkey/infection_monkey/exploit/sambacry.py b/monkey/infection_monkey/exploit/sambacry.py index 11a2ab9c5..3ca5d9921 100644 --- a/monkey/infection_monkey/exploit/sambacry.py +++ b/monkey/infection_monkey/exploit/sambacry.py @@ -36,16 +36,13 @@ from impacket.smbconnection import SMBConnection import infection_monkey.monkeyfs as monkeyfs from common.utils.attack_utils import ScanStatus from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import ( - build_monkey_commandline, - get_monkey_depth, - get_target_monkey_by_os, -) +from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey_by_os from infection_monkey.model import DROPPER_ARG from infection_monkey.network.smbfinger import SMB_SERVICE from infection_monkey.network.tools import get_interface_to_target from infection_monkey.pyinstaller_utils import get_binary_file_path from infection_monkey.telemetry.attack.t1105_telem import T1105Telem +from infection_monkey.utils.commands import build_monkey_commandline __author__ = "itay.mizeretz" diff --git a/monkey/infection_monkey/exploit/shellshock.py b/monkey/infection_monkey/exploit/shellshock.py index 7bca6b04b..bf6c5589e 100644 --- a/monkey/infection_monkey/exploit/shellshock.py +++ b/monkey/infection_monkey/exploit/shellshock.py @@ -10,14 +10,11 @@ import requests from common.utils.attack_utils import ScanStatus from infection_monkey.exploit.HostExploiter import HostExploiter from infection_monkey.exploit.shellshock_resources import CGI_FILES -from infection_monkey.exploit.tools.helpers import ( - build_monkey_commandline, - get_monkey_depth, - get_target_monkey, -) +from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey from infection_monkey.exploit.tools.http_tools import HTTPTools from infection_monkey.model import DROPPER_ARG from infection_monkey.telemetry.attack.t1222_telem import T1222Telem +from infection_monkey.utils.commands import build_monkey_commandline __author__ = "danielg" diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py index 81fc2848c..189bc51ad 100644 --- a/monkey/infection_monkey/exploit/smbexec.py +++ b/monkey/infection_monkey/exploit/smbexec.py @@ -5,16 +5,13 @@ from impacket.dcerpc.v5 import scmr, transport from common.utils.attack_utils import ScanStatus, UsageEnum from common.utils.exploit_enum import ExploitType from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import ( - build_monkey_commandline, - get_monkey_depth, - get_target_monkey, -) +from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.model import DROPPER_CMDLINE_DETACHED_WINDOWS, MONKEY_CMDLINE_DETACHED_WINDOWS from infection_monkey.network.smbfinger import SMBFinger from infection_monkey.network.tools import check_tcp_port from infection_monkey.telemetry.attack.t1035_telem import T1035Telem +from infection_monkey.utils.commands import build_monkey_commandline LOG = getLogger(__name__) diff --git a/monkey/infection_monkey/exploit/sshexec.py b/monkey/infection_monkey/exploit/sshexec.py index 3dedae114..bfcab4a46 100644 --- a/monkey/infection_monkey/exploit/sshexec.py +++ b/monkey/infection_monkey/exploit/sshexec.py @@ -9,15 +9,12 @@ from common.utils.attack_utils import ScanStatus from common.utils.exceptions import FailedExploitationError from common.utils.exploit_enum import ExploitType from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import ( - build_monkey_commandline, - get_monkey_depth, - get_target_monkey, -) +from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey from infection_monkey.model import MONKEY_ARG from infection_monkey.network.tools import check_tcp_port, get_interface_to_target from infection_monkey.telemetry.attack.t1105_telem import T1105Telem from infection_monkey.telemetry.attack.t1222_telem import T1222Telem +from infection_monkey.utils.commands import build_monkey_commandline __author__ = "hoffer" diff --git a/monkey/infection_monkey/exploit/tools/helpers.py b/monkey/infection_monkey/exploit/tools/helpers.py index a863f9499..f7f6eadb8 100644 --- a/monkey/infection_monkey/exploit/tools/helpers.py +++ b/monkey/infection_monkey/exploit/tools/helpers.py @@ -45,42 +45,6 @@ def get_target_monkey_by_os(is_windows, is_32bit): return ControlClient.download_monkey_exe_by_os(is_windows, is_32bit) -def build_monkey_commandline_explicitly( - parent=None, tunnel=None, server=None, depth=None, location=None, vulnerable_port=None -): - cmdline = "" - - if parent is not None: - cmdline += f" -p {parent}" - if tunnel is not None: - cmdline += f" -t {tunnel}" - if server is not None: - cmdline += f" -s {server}" - if depth is not None: - if int(depth) < 0: - depth = 0 - cmdline += f" -d {depth}" - if location is not None: - cmdline += f" -l {location}" - if vulnerable_port is not None: - cmdline += f" -vp {vulnerable_port}" - - return cmdline - - -def build_monkey_commandline(target_host, depth, vulnerable_port, location=None): - from infection_monkey.config import GUID - - return build_monkey_commandline_explicitly( - GUID, - target_host.default_tunnel, - target_host.default_server, - depth, - location, - vulnerable_port, - ) - - def get_monkey_depth(): from infection_monkey.config import WormConfiguration diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index 8af8e24d9..7164a21c8 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -11,11 +11,7 @@ from logging import getLogger from common.utils.attack_utils import ScanStatus from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import ( - build_monkey_commandline, - get_monkey_depth, - get_target_monkey, -) +from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey from infection_monkey.exploit.tools.http_tools import HTTPTools from infection_monkey.model import ( CHMOD_MONKEY, @@ -25,6 +21,7 @@ from infection_monkey.model import ( WGET_HTTP_UPLOAD, ) from infection_monkey.telemetry.attack.t1222_telem import T1222Telem +from infection_monkey.utils.commands import build_monkey_commandline LOG = getLogger(__name__) diff --git a/monkey/infection_monkey/exploit/web_rce.py b/monkey/infection_monkey/exploit/web_rce.py index 5620c425a..1bd9fd6b4 100644 --- a/monkey/infection_monkey/exploit/web_rce.py +++ b/monkey/infection_monkey/exploit/web_rce.py @@ -5,11 +5,7 @@ from posixpath import join from common.utils.attack_utils import BITS_UPLOAD_STRING, ScanStatus from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import ( - build_monkey_commandline, - get_monkey_depth, - get_target_monkey, -) +from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey from infection_monkey.exploit.tools.http_tools import HTTPTools from infection_monkey.model import ( BITSADMIN_CMDLINE_HTTP, @@ -28,6 +24,7 @@ from infection_monkey.model import ( from infection_monkey.network.tools import tcp_port_to_service from infection_monkey.telemetry.attack.t1197_telem import T1197Telem from infection_monkey.telemetry.attack.t1222_telem import T1222Telem +from infection_monkey.utils.commands import build_monkey_commandline __author__ = "VakarisZ" diff --git a/monkey/infection_monkey/exploit/win_ms08_067.py b/monkey/infection_monkey/exploit/win_ms08_067.py index 2d005e543..1e92eadf5 100644 --- a/monkey/infection_monkey/exploit/win_ms08_067.py +++ b/monkey/infection_monkey/exploit/win_ms08_067.py @@ -16,15 +16,12 @@ from impacket.dcerpc.v5 import transport from common.utils.shellcode_obfuscator import clarify from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import ( - build_monkey_commandline, - get_monkey_depth, - get_target_monkey, -) +from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS from infection_monkey.network.smbfinger import SMBFinger from infection_monkey.network.tools import check_tcp_port +from infection_monkey.utils.commands import build_monkey_commandline from infection_monkey.utils.random_password_generator import get_random_password LOG = getLogger(__name__) diff --git a/monkey/infection_monkey/exploit/wmiexec.py b/monkey/infection_monkey/exploit/wmiexec.py index cad313f8c..c89b2d5ea 100644 --- a/monkey/infection_monkey/exploit/wmiexec.py +++ b/monkey/infection_monkey/exploit/wmiexec.py @@ -7,14 +7,11 @@ from impacket.dcerpc.v5.rpcrt import DCERPCException from common.utils.exploit_enum import ExploitType from infection_monkey.exploit.HostExploiter import HostExploiter -from infection_monkey.exploit.tools.helpers import ( - build_monkey_commandline, - get_monkey_depth, - get_target_monkey, -) +from infection_monkey.exploit.tools.helpers import get_monkey_depth, get_target_monkey from infection_monkey.exploit.tools.smb_tools import SmbTools from infection_monkey.exploit.tools.wmi_tools import AccessDeniedException, WmiTools from infection_monkey.model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS +from infection_monkey.utils.commands import build_monkey_commandline LOG = logging.getLogger(__name__) diff --git a/monkey/infection_monkey/model/__init__.py b/monkey/infection_monkey/model/__init__.py index 988edbc07..c7b8609b7 100644 --- a/monkey/infection_monkey/model/__init__.py +++ b/monkey/infection_monkey/model/__init__.py @@ -7,7 +7,9 @@ DROPPER_ARG = "dr0pp3r" ID_STRING = "M0NK3Y3XPL0ITABLE" # CMD prefix for windows commands -CMD_PREFIX = "cmd.exe /c" +CMD_EXE = "cmd.exe" +CMD_CARRY_OUT = "/c" +CMD_PREFIX = CMD_EXE + " " + CMD_CARRY_OUT DROPPER_CMDLINE_WINDOWS = "%s %%(dropper_path)s %s" % ( CMD_PREFIX, DROPPER_ARG, @@ -16,7 +18,6 @@ MONKEY_CMDLINE_WINDOWS = "%s %%(monkey_path)s %s" % ( CMD_PREFIX, MONKEY_ARG, ) -MONKEY_CMDLINE_LINUX = "./%%(monkey_filename)s %s" % (MONKEY_ARG,) DROPPER_CMDLINE_DETACHED_WINDOWS = "%s start cmd /c %%(dropper_path)s %s" % ( CMD_PREFIX, DROPPER_ARG, diff --git a/monkey/infection_monkey/utils/commands.py b/monkey/infection_monkey/utils/commands.py new file mode 100644 index 000000000..ee2f0153a --- /dev/null +++ b/monkey/infection_monkey/utils/commands.py @@ -0,0 +1,65 @@ +from infection_monkey.config import GUID +from infection_monkey.model import CMD_CARRY_OUT, CMD_EXE, MONKEY_ARG +from infection_monkey.model.host import VictimHost + + +def build_monkey_commandline( + target_host: VictimHost, depth: int, vulnerable_port: str, location: str = None +) -> str: + + return " " + " ".join( + build_monkey_commandline_explicitly( + GUID, + target_host.default_tunnel, + target_host.default_server, + depth, + location, + vulnerable_port, + ) + ) + + +def build_monkey_commandline_explicitly( + parent: str = None, + tunnel: str = None, + server: str = None, + depth: int = None, + location: str = None, + vulnerable_port: str = None, +) -> list: + cmdline = [] + + if parent is not None: + cmdline.append("-p") + cmdline.append(str(parent)) + if tunnel is not None: + cmdline.append("-t") + cmdline.append(str(tunnel)) + if server is not None: + cmdline.append("-s") + cmdline.append(str(server)) + if depth is not None: + if int(depth) < 0: + depth = 0 + cmdline.append("-d") + cmdline.append(str(depth)) + if location is not None: + cmdline.append("-l") + cmdline.append(str(location)) + if vulnerable_port is not None: + cmdline.append("-vp") + cmdline.append(str(vulnerable_port)) + + return cmdline + + +def get_monkey_commandline_windows(destination_path: str, monkey_cmd_args: list) -> list: + monkey_cmdline = [CMD_EXE, CMD_CARRY_OUT, destination_path, MONKEY_ARG] + + return monkey_cmdline + monkey_cmd_args + + +def get_monkey_commandline_linux(destination_path: str, monkey_cmd_args: list) -> list: + monkey_cmdline = [destination_path, MONKEY_ARG] + + return monkey_cmdline + monkey_cmd_args diff --git a/monkey/infection_monkey/windows_upgrader.py b/monkey/infection_monkey/windows_upgrader.py index d81b7dc52..6dfd01c11 100644 --- a/monkey/infection_monkey/windows_upgrader.py +++ b/monkey/infection_monkey/windows_upgrader.py @@ -1,5 +1,4 @@ import logging -import shlex import shutil import subprocess import sys @@ -8,8 +7,10 @@ import time import infection_monkey.monkeyfs as monkeyfs from infection_monkey.config import WormConfiguration from infection_monkey.control import ControlClient -from infection_monkey.exploit.tools.helpers import build_monkey_commandline_explicitly -from infection_monkey.model import MONKEY_CMDLINE_WINDOWS +from infection_monkey.utils.commands import ( + build_monkey_commandline_explicitly, + get_monkey_commandline_windows, +) from infection_monkey.utils.environment import is_64bit_python, is_64bit_windows_os, is_windows_os __author__ = "itay.mizeretz" @@ -46,20 +47,12 @@ class WindowsUpgrader(object): opts.parent, opts.tunnel, opts.server, opts.depth ) - # TODO: Replace all of this string templating with a function that accepts - # the necessary parameters and returns a list of arguments. - monkey_cmdline = ( - MONKEY_CMDLINE_WINDOWS % {"monkey_path": WormConfiguration.dropper_target_path_win_64} - + monkey_options - ) - - monkey_cmdline_split = shlex.split( - monkey_cmdline, - posix=False, # won't try resolving "\" in paths as part of escape sequences + monkey_cmdline = get_monkey_commandline_windows( + WormConfiguration.dropper_target_path_win_64, monkey_options ) monkey_process = subprocess.Popen( - monkey_cmdline_split, + monkey_cmdline, stdin=None, stdout=None, stderr=None, @@ -70,7 +63,7 @@ class WindowsUpgrader(object): LOG.info( "Executed 64bit monkey process (PID=%d) with command line: %s", monkey_process.pid, - monkey_cmdline, + " ".join(monkey_cmdline), ) time.sleep(WindowsUpgrader.__UPGRADE_WAIT_TIME__) diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py b/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py deleted file mode 100644 index 60cc136e5..000000000 --- a/monkey/tests/unit_tests/infection_monkey/exploit/tools/test_helpers.py +++ /dev/null @@ -1,23 +0,0 @@ -import unittest - -from infection_monkey.exploit.tools.helpers import build_monkey_commandline_explicitly - - -class TestHelpers(unittest.TestCase): - def test_build_monkey_commandline_explicitly(self): - test1 = " -p 101010 -t 10.10.101.10 -s 127.127.127.127:5000 -d 0 -l C:\\windows\\abc -vp 80" - result1 = build_monkey_commandline_explicitly( - 101010, "10.10.101.10", "127.127.127.127:5000", 0, "C:\\windows\\abc", 80 - ) - - test2 = " -p parent -s 127.127.127.127:5000 -d 0 -vp 80" - result2 = build_monkey_commandline_explicitly( - parent="parent", server="127.127.127.127:5000", depth="0", vulnerable_port="80" - ) - - self.assertEqual(test1, result1) - self.assertEqual(test2, result2) - - -if __name__ == "__main__": - unittest.main() diff --git a/monkey/tests/unit_tests/infection_monkey/utils/test_commands.py b/monkey/tests/unit_tests/infection_monkey/utils/test_commands.py new file mode 100644 index 000000000..a3f210533 --- /dev/null +++ b/monkey/tests/unit_tests/infection_monkey/utils/test_commands.py @@ -0,0 +1,108 @@ +from infection_monkey.config import GUID +from infection_monkey.model.host import VictimHost +from infection_monkey.utils.commands import ( + build_monkey_commandline, + build_monkey_commandline_explicitly, + get_monkey_commandline_linux, + get_monkey_commandline_windows, +) + + +def test_build_monkey_commandline_explicitly_arguments(): + expected = [ + "-p", + "101010", + "-t", + "10.10.101.10", + "-s", + "127.127.127.127:5000", + "-d", + "0", + "-l", + "C:\\windows\\abc", + "-vp", + "80", + ] + actual = build_monkey_commandline_explicitly( + "101010", "10.10.101.10", "127.127.127.127:5000", 0, "C:\\windows\\abc", "80" + ) + + assert expected == actual + + +def test_build_monkey_commandline_explicitly_depth_condition_less(): + expected = [ + "-d", + "0", + ] + actual = build_monkey_commandline_explicitly(depth=-50) + + assert expected == actual + + +def test_build_monkey_commandline_explicitly_depth_condition_greater(): + expected = [ + "-d", + "50", + ] + actual = build_monkey_commandline_explicitly(depth=50) + + assert expected == actual + + +def test_get_monkey_commandline_windows(): + expected = [ + "cmd.exe", + "/c", + "C:\\windows\\abc", + "m0nk3y", + "-p", + "101010", + "-t", + "10.10.101.10", + ] + actual = get_monkey_commandline_windows( + "C:\\windows\\abc", + [ + "-p", + "101010", + "-t", + "10.10.101.10", + ], + ) + + assert expected == actual + + +def test_get_monkey_commandline_linux(): + expected = [ + "/home/user/monkey-linux-64", + "m0nk3y", + "-p", + "101010", + "-t", + "10.10.101.10", + ] + actual = get_monkey_commandline_linux( + "/home/user/monkey-linux-64", + [ + "-p", + "101010", + "-t", + "10.10.101.10", + ], + ) + + assert expected == actual + + +def test_build_monkey_commandline(): + example_host = VictimHost(ip_addr="bla") + example_host.set_default_server("101010") + + expected = f" -p {GUID} -s 101010 -d 0 -l /home/bla -vp 80" + actual = build_monkey_commandline( + target_host=example_host, depth=0, vulnerable_port="80", location="/home/bla" + ) + + assert expected == actual