diff --git a/infection_monkey/config.py b/infection_monkey/config.py index e62820816..633534b84 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -116,6 +116,8 @@ class Configuration(object): dropper_date_reference_path_windows = r"%windir%\system32\kernel32.dll" dropper_date_reference_path_linux = '/bin/sh' dropper_target_path = r"C:\Windows\monkey.exe" + # TODO: move and rename + dropper_upgrade_win_64_temp_path = r"C:\Windows\monkey64.exe" dropper_target_path_linux = '/tmp/monkey' ########################### diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index 6f70f888a..3ebe3f122 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -23,6 +23,7 @@ "dropper_log_path_linux": "/tmp/user-1562", "dropper_set_date": true, "dropper_target_path": "C:\\Windows\\monkey.exe", + "dropper_upgrade_win_64_temp_path": "C:\\Windows\\monkey64.exe", "dropper_target_path_linux": "/tmp/monkey", diff --git a/infection_monkey/monkey.py b/infection_monkey/monkey.py index 22be2cf46..b05d94fd4 100644 --- a/infection_monkey/monkey.py +++ b/infection_monkey/monkey.py @@ -13,6 +13,7 @@ from network.firewall import app as firewall from network.network_scanner import NetworkScanner from system_info import SystemInfoCollector from system_singleton import SystemSingleton +from windows_upgrader import WindowsUpgrader __author__ = 'itamar' @@ -34,6 +35,7 @@ class InfectionMonkey(object): self._fingerprint = None self._default_server = None self._depth = 0 + self._opts = None def initialize(self): LOG.info("Monkey is initializing...") @@ -46,13 +48,13 @@ class InfectionMonkey(object): arg_parser.add_argument('-t', '--tunnel') arg_parser.add_argument('-s', '--server') arg_parser.add_argument('-d', '--depth') - opts, self._args = arg_parser.parse_known_args(self._args) + self._opts, self._args = arg_parser.parse_known_args(self._args) - self._parent = opts.parent - self._default_tunnel = opts.tunnel - self._default_server = opts.server - if opts.depth: - WormConfiguration.depth = int(opts.depth) + self._parent = self._opts.parent + self._default_tunnel = self._opts.tunnel + self._default_server = self._opts.server + if self._opts.depth: + WormConfiguration.depth = int(self._opts.depth) WormConfiguration._depth_from_commandline = True self._keep_running = True self._network = NetworkScanner() @@ -66,6 +68,10 @@ class InfectionMonkey(object): LOG.debug("Default server: %s is already in command servers list" % self._default_server) def start(self): + if WindowsUpgrader.should_upgrade(): + WindowsUpgrader.upgrade(self._opts) + return + LOG.info("Monkey is running...") if firewall.is_enabled(): @@ -226,9 +232,11 @@ class InfectionMonkey(object): firewall.close() - self._singleton.unlock() + if not WindowsUpgrader.should_upgrade(): + self._singleton.unlock() - if WormConfiguration.self_delete_in_cleanup and -1 == sys.executable.find('python'): + if WormConfiguration.self_delete_in_cleanup \ + and -1 == sys.executable.find('python') and not WindowsUpgrader.should_upgrade(): try: if "win32" == sys.platform: from _subprocess import SW_HIDE, STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE diff --git a/infection_monkey/windows_upgrader.py b/infection_monkey/windows_upgrader.py new file mode 100644 index 000000000..1c6049cfd --- /dev/null +++ b/infection_monkey/windows_upgrader.py @@ -0,0 +1,53 @@ +import os +import struct +import sys + +import monkeyfs +from config import WormConfiguration +from control import ControlClient +from exploit.tools import build_monkey_commandline_explicitly +from model import DROPPER_CMDLINE_WINDOWS + +__author__ = 'itay.mizeretz' + +if "win32" == sys.platform: + from win32process import DETACHED_PROCESS +else: + DETACHED_PROCESS = 0 + + +class WindowsUpgrader(object): + @staticmethod + def is_64bit_os(): + return os.environ.has_key('PROGRAMFILES(X86)') + + @staticmethod + def is_64bit_python(): + return struct.calcsize("P") == 8 + + @staticmethod + def is_windows_os(): + return sys.platform.startswith("win") + + @staticmethod + def should_upgrade(): + return WindowsUpgrader.is_windows_os() and WindowsUpgrader.is_64bit_os() \ + and not WindowsUpgrader.is_64bit_python() + + @staticmethod + def upgrade(opts): + monkey_64_path = ControlClient.download_monkey_exe_by_os(True, False) + with monkeyfs.open(monkey_64_path, "rb") as downloaded_monkey_file: + monkey_bin = downloaded_monkey_file.read() + with open(WormConfiguration.dropper_upgrade_win_64_temp_path, 'wb') as written_monkey_file: + written_monkey_file.write(monkey_bin) + + monkey_options = build_monkey_commandline_explicitly( + opts.parent, opts.tunnel, opts.server, int(opts.depth)) + + monkey_cmdline = DROPPER_CMDLINE_WINDOWS % { + 'monkey_path': WormConfiguration.dropper_target_path} + monkey_options + monkey_process = os.subprocess.Popen(monkey_cmdline, shell=True, + stdin=None, stdout=None, stderr=None, + close_fds=True, creationflags=DETACHED_PROCESS) + diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index f9a7d80d2..f558eb8dc 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -446,6 +446,13 @@ SCHEMA = { "default": "C:\\Windows\\monkey.exe", "description": "Determines where should the dropper place the monkey on a Windows machine" }, + "dropper_upgrade_win_64_temp_path": { + "title": "Temporary upgrade path for 64bit monkey on Windows", + "type": "string", + "default": "C:\\Windows\\monkey64.exe", + "description": "Determines where should the dropper place the 64 bit monkey while" + " upgrading on a Windows machine" + }, "dropper_try_move_first": { "title": "Try to move first", "type": "boolean",