2015-08-30 15:27:35 +08:00
|
|
|
import os
|
|
|
|
import sys
|
2017-09-25 20:13:36 +08:00
|
|
|
import types
|
|
|
|
import uuid
|
2015-09-29 22:55:54 +08:00
|
|
|
from abc import ABCMeta
|
2017-08-21 00:32:18 +08:00
|
|
|
from itertools import product
|
2017-09-25 20:13:36 +08:00
|
|
|
|
|
|
|
from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter, \
|
|
|
|
SambaCryExploiter
|
2017-09-25 23:23:31 +08:00
|
|
|
from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger
|
2017-09-25 20:13:36 +08:00
|
|
|
from network.range import FixedRange
|
2015-11-30 16:56:20 +08:00
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
__author__ = 'itamar'
|
|
|
|
|
2015-09-29 22:55:54 +08:00
|
|
|
GUID = str(uuid.getnode())
|
|
|
|
|
2016-06-07 23:14:38 +08:00
|
|
|
EXTERNAL_CONFIG_FILE = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'monkey.bin')
|
2015-09-29 22:55:54 +08:00
|
|
|
|
2017-09-25 20:13:36 +08:00
|
|
|
|
2015-09-29 22:55:54 +08:00
|
|
|
def _cast_by_example(value, example):
|
2016-01-14 17:58:15 +08:00
|
|
|
"""
|
|
|
|
a method that casts a value to the type of the parameter given as example
|
|
|
|
"""
|
2015-09-29 22:55:54 +08:00
|
|
|
example_type = type(example)
|
|
|
|
if example_type is str:
|
|
|
|
return str(os.path.expandvars(value))
|
|
|
|
elif example_type is tuple and len(example) != 0:
|
2016-07-06 16:44:33 +08:00
|
|
|
if value is None or value == tuple(None):
|
|
|
|
return tuple()
|
2015-09-29 22:55:54 +08:00
|
|
|
return tuple([_cast_by_example(x, example[0]) for x in value])
|
|
|
|
elif example_type is list and len(example) != 0:
|
2016-07-06 16:44:33 +08:00
|
|
|
if value is None or value == [None]:
|
|
|
|
return []
|
2015-09-29 22:55:54 +08:00
|
|
|
return [_cast_by_example(x, example[0]) for x in value]
|
|
|
|
elif example_type is type(value):
|
|
|
|
return value
|
|
|
|
elif example_type is bool:
|
|
|
|
return value.lower() == 'true'
|
|
|
|
elif example_type is int:
|
|
|
|
return int(value)
|
|
|
|
elif example_type is float:
|
|
|
|
return float(value)
|
|
|
|
elif example_type is types.ClassType or example_type is ABCMeta:
|
|
|
|
return globals()[value]
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
2015-11-26 21:48:47 +08:00
|
|
|
|
2015-09-29 22:55:54 +08:00
|
|
|
class Configuration(object):
|
|
|
|
def from_dict(self, data):
|
2016-09-28 04:50:47 +08:00
|
|
|
"""
|
|
|
|
Get a dict of config variables, set known variables as attributes on self.
|
|
|
|
Return dict of unknown variables encountered.
|
|
|
|
"""
|
|
|
|
unknown_variables = {}
|
2015-11-26 21:48:47 +08:00
|
|
|
for key, value in data.items():
|
2015-09-29 22:55:54 +08:00
|
|
|
if key.startswith('_'):
|
|
|
|
continue
|
2016-07-06 16:44:33 +08:00
|
|
|
if key in ["name", "id", "current_server"]:
|
2016-01-14 17:58:15 +08:00
|
|
|
continue
|
2016-08-20 20:28:14 +08:00
|
|
|
if self._depth_from_commandline and key == "depth":
|
2016-08-01 21:52:27 +08:00
|
|
|
continue
|
2015-09-29 22:55:54 +08:00
|
|
|
try:
|
|
|
|
default_value = getattr(Configuration, key)
|
|
|
|
except AttributeError:
|
2016-09-28 04:50:47 +08:00
|
|
|
unknown_variables[key] = value
|
|
|
|
continue
|
2016-01-14 17:58:15 +08:00
|
|
|
|
2015-09-29 22:55:54 +08:00
|
|
|
setattr(self, key, _cast_by_example(value, default_value))
|
2016-09-28 04:50:47 +08:00
|
|
|
return unknown_variables
|
2015-09-29 22:55:54 +08:00
|
|
|
|
|
|
|
def as_dict(self):
|
|
|
|
result = {}
|
|
|
|
for key in dir(Configuration):
|
|
|
|
if key.startswith('_'):
|
|
|
|
continue
|
|
|
|
try:
|
|
|
|
value = getattr(self, key)
|
|
|
|
except AttributeError:
|
|
|
|
continue
|
|
|
|
|
|
|
|
val_type = type(value)
|
|
|
|
|
|
|
|
if val_type is types.FunctionType or val_type is types.MethodType:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if val_type is types.ClassType or val_type is ABCMeta:
|
|
|
|
value = value.__name__
|
|
|
|
elif val_type is tuple or val_type is list:
|
2016-07-06 16:44:33 +08:00
|
|
|
if len(value) != 0 and (type(value[0]) is types.ClassType or type(value[0]) is ABCMeta):
|
2015-09-29 22:55:54 +08:00
|
|
|
value = val_type([x.__name__ for x in value])
|
|
|
|
|
|
|
|
result[key] = value
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
2016-08-20 22:56:23 +08:00
|
|
|
# Used to keep track of our depth if manually specified
|
2016-08-01 21:52:27 +08:00
|
|
|
_depth_from_commandline = False
|
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
###########################
|
2015-11-30 21:29:30 +08:00
|
|
|
# logging config
|
2015-11-30 16:56:20 +08:00
|
|
|
###########################
|
2015-08-30 15:27:35 +08:00
|
|
|
|
|
|
|
use_file_logging = True
|
2016-03-02 23:13:36 +08:00
|
|
|
dropper_log_path_windows = os.path.expandvars("%temp%\~df1562.tmp")
|
|
|
|
dropper_log_path_linux = '/tmp/user-1562'
|
|
|
|
monkey_log_path_windows = os.path.expandvars("%temp%\~df1563.tmp")
|
|
|
|
monkey_log_path_linux = '/tmp/user-1563'
|
2015-08-30 15:27:35 +08:00
|
|
|
|
|
|
|
###########################
|
2015-11-30 21:29:30 +08:00
|
|
|
# dropper config
|
2015-08-30 15:27:35 +08:00
|
|
|
###########################
|
|
|
|
|
|
|
|
dropper_try_move_first = sys.argv[0].endswith(".exe")
|
|
|
|
dropper_set_date = True
|
2015-09-29 22:55:54 +08:00
|
|
|
dropper_date_reference_path = r"\windows\system32\kernel32.dll" if sys.platform == "win32" else '/bin/sh'
|
|
|
|
dropper_target_path = r"C:\Windows\monkey.exe"
|
2016-08-20 20:28:14 +08:00
|
|
|
dropper_target_path_linux = '/tmp/monkey'
|
2015-08-30 15:27:35 +08:00
|
|
|
|
2016-07-19 04:43:17 +08:00
|
|
|
###########################
|
|
|
|
# Kill file
|
|
|
|
###########################
|
2016-07-31 19:33:48 +08:00
|
|
|
kill_file_path_windows = os.path.expandvars("%windir%\monkey.not")
|
|
|
|
kill_file_path_linux = '/var/run/monkey.not'
|
2016-07-19 04:43:17 +08:00
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
###########################
|
2015-11-30 21:29:30 +08:00
|
|
|
# monkey config
|
2015-08-30 15:27:35 +08:00
|
|
|
###########################
|
2016-07-15 22:00:55 +08:00
|
|
|
# sets whether or not the monkey is alive. if false will stop scanning and exploiting
|
2015-09-30 20:05:30 +08:00
|
|
|
alive = True
|
|
|
|
|
2016-07-15 22:00:55 +08:00
|
|
|
# sets whether or not to self delete the monkey executable when stopped
|
2016-07-06 16:44:33 +08:00
|
|
|
self_delete_in_cleanup = False
|
2015-10-14 22:22:05 +08:00
|
|
|
|
2016-07-15 22:00:55 +08:00
|
|
|
# string of the mutex name for single instance
|
2015-08-30 15:27:35 +08:00
|
|
|
singleton_mutex_name = "{2384ec59-0df8-4ab9-918c-843740924a28}"
|
|
|
|
|
|
|
|
# how long to wait between scan iterations
|
2016-01-14 17:58:15 +08:00
|
|
|
timeout_between_iterations = 100
|
2015-08-30 15:27:35 +08:00
|
|
|
|
|
|
|
# how many scan iterations to perform on each run
|
2016-01-13 16:27:49 +08:00
|
|
|
max_iterations = 1
|
2015-08-30 15:27:35 +08:00
|
|
|
|
2016-01-14 17:58:15 +08:00
|
|
|
scanner_class = TcpScanner
|
2017-09-25 23:23:31 +08:00
|
|
|
finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger, MySQLFinger, ElasticFinger]
|
2016-08-30 16:04:44 +08:00
|
|
|
exploiter_classes = [SmbExploiter, WmiExploiter, RdpExploiter, Ms08_067_Exploiter, # Windows exploits
|
2017-09-25 20:13:36 +08:00
|
|
|
SSHExploiter, ShellShockExploiter, SambaCryExploiter, # Linux
|
2016-08-30 16:04:44 +08:00
|
|
|
]
|
2015-08-30 15:27:35 +08:00
|
|
|
|
|
|
|
# how many victims to look for in a single scan iteration
|
|
|
|
victims_max_find = 14
|
|
|
|
|
|
|
|
# how many victims to exploit before stopping
|
|
|
|
victims_max_exploit = 7
|
|
|
|
|
2015-12-08 01:08:15 +08:00
|
|
|
# depth of propagation
|
2016-01-14 17:58:15 +08:00
|
|
|
depth = 2
|
2015-09-29 22:55:54 +08:00
|
|
|
current_server = ""
|
|
|
|
|
2016-08-20 20:28:14 +08:00
|
|
|
# Configuration servers to try to connect to, in this order.
|
2015-12-02 17:18:27 +08:00
|
|
|
command_servers = [
|
2016-07-31 19:33:13 +08:00
|
|
|
"41.50.73.31:5000"
|
2015-12-02 17:18:27 +08:00
|
|
|
]
|
2015-09-29 22:55:54 +08:00
|
|
|
|
2016-07-23 13:59:26 +08:00
|
|
|
# sets whether or not to locally save the running configuration after finishing
|
|
|
|
serialize_config = False
|
|
|
|
|
2016-07-15 22:00:55 +08:00
|
|
|
# sets whether or not to retry failed hosts on next scan
|
2015-10-14 22:22:05 +08:00
|
|
|
retry_failed_explotation = True
|
2015-08-30 15:27:35 +08:00
|
|
|
|
2016-08-24 23:31:16 +08:00
|
|
|
# addresses of internet servers to ping and check if the monkey has internet acccess.
|
2016-07-10 16:47:07 +08:00
|
|
|
internet_services = ["monkey.guardicore.com", "www.google.com"]
|
2016-06-28 16:13:24 +08:00
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
###########################
|
2015-11-30 21:29:30 +08:00
|
|
|
# scanners config
|
2015-08-30 15:27:35 +08:00
|
|
|
###########################
|
|
|
|
|
2016-07-15 21:54:46 +08:00
|
|
|
# Auto detect and scan local subnets
|
2016-08-30 16:04:44 +08:00
|
|
|
local_network_scan = True
|
2016-07-15 21:54:46 +08:00
|
|
|
|
2016-01-14 17:58:15 +08:00
|
|
|
range_class = FixedRange
|
|
|
|
range_size = 1
|
2017-09-25 20:13:36 +08:00
|
|
|
range_fixed = ['', ]
|
2015-08-30 15:27:35 +08:00
|
|
|
|
2016-09-21 16:35:41 +08:00
|
|
|
blocked_ips = ['', ]
|
|
|
|
|
2015-08-30 15:27:35 +08:00
|
|
|
# TCP Scanner
|
2016-08-24 23:31:16 +08:00
|
|
|
HTTP_PORTS = [80, 8080, 443,
|
|
|
|
8008, # HTTP alternate
|
|
|
|
]
|
2017-09-25 20:13:36 +08:00
|
|
|
tcp_target_ports = [22,
|
2017-09-25 23:02:21 +08:00
|
|
|
2222,
|
2017-09-25 20:13:36 +08:00
|
|
|
445,
|
|
|
|
135,
|
|
|
|
3389,
|
|
|
|
80,
|
|
|
|
8080,
|
|
|
|
443,
|
|
|
|
8008,
|
2017-09-25 23:23:31 +08:00
|
|
|
3306,
|
2017-09-25 20:13:36 +08:00
|
|
|
9200]
|
2016-08-24 23:31:16 +08:00
|
|
|
tcp_target_ports.extend(HTTP_PORTS)
|
2015-12-02 17:18:27 +08:00
|
|
|
tcp_scan_timeout = 3000 # 3000 Milliseconds
|
2015-08-30 15:27:35 +08:00
|
|
|
tcp_scan_interval = 200
|
2015-09-29 22:55:54 +08:00
|
|
|
tcp_scan_get_banner = True
|
2015-08-30 15:27:35 +08:00
|
|
|
|
|
|
|
# Ping Scanner
|
|
|
|
ping_scan_timeout = 1000
|
|
|
|
|
|
|
|
###########################
|
2015-11-30 21:29:30 +08:00
|
|
|
# exploiters config
|
2015-08-30 15:27:35 +08:00
|
|
|
###########################
|
|
|
|
|
|
|
|
skip_exploit_if_file_exist = True
|
|
|
|
|
|
|
|
ms08_067_exploit_attempts = 5
|
2016-06-14 22:06:17 +08:00
|
|
|
ms08_067_remote_user_add = "Monkey_IUSER_SUPPORT"
|
2015-08-30 15:27:35 +08:00
|
|
|
ms08_067_remote_user_pass = "Password1!"
|
|
|
|
|
2015-11-30 21:29:30 +08:00
|
|
|
# rdp exploiter
|
2015-09-30 20:05:30 +08:00
|
|
|
rdp_use_vbs_download = True
|
2015-09-29 22:55:54 +08:00
|
|
|
|
2017-08-16 20:14:26 +08:00
|
|
|
# User and password dictionaries for exploits.
|
2017-08-21 00:32:18 +08:00
|
|
|
|
2017-08-21 16:51:47 +08:00
|
|
|
def get_exploit_user_password_pairs(self):
|
2017-09-25 20:13:36 +08:00
|
|
|
"""
|
|
|
|
Returns all combinations of the configurations users and passwords
|
|
|
|
:return:
|
|
|
|
"""
|
2017-08-21 00:32:18 +08:00
|
|
|
return product(self.exploit_user_list, self.exploit_password_list)
|
|
|
|
|
|
|
|
exploit_user_list = ['Administrator', 'root', 'user']
|
|
|
|
exploit_password_list = ["Password1!", "1234", "password", "12345678"]
|
2017-08-16 20:14:26 +08:00
|
|
|
|
2016-09-05 22:45:27 +08:00
|
|
|
# smb/wmi exploiter
|
2017-09-25 20:13:36 +08:00
|
|
|
smb_download_timeout = 300 # timeout in seconds
|
2016-09-08 00:10:30 +08:00
|
|
|
smb_service_name = "InfectionMonkey"
|
|
|
|
|
2017-09-01 01:03:32 +08:00
|
|
|
# Timeout (in seconds) for sambacry's trigger to yield results.
|
|
|
|
sambacry_trigger_timeout = 5
|
|
|
|
# Folder paths to guess share lies inside.
|
2017-09-04 21:36:15 +08:00
|
|
|
sambacry_folder_paths_to_guess = ['/', '/mnt', '/tmp', '/storage', '/export', '/share', '/shares', '/home']
|
2017-09-01 01:03:32 +08:00
|
|
|
# Shares to not check if they're writable.
|
|
|
|
sambacry_shares_not_to_check = ["IPC$", "print$"]
|
|
|
|
# Name of file which contains the monkey's commandline
|
|
|
|
sambacry_commandline_filename = "monkey_commandline.txt"
|
|
|
|
# Name of file which contains the runner's result
|
|
|
|
sambacry_runner_result_filename = "monkey_runner_result"
|
|
|
|
# SambaCry runner filename (32 bit)
|
|
|
|
sambacry_runner_filename_32 = "sc_monkey_runner32.so"
|
|
|
|
# SambaCry runner filename (64 bit)
|
|
|
|
sambacry_runner_filename_64 = "sc_monkey_runner64.so"
|
|
|
|
# Monkey filename on share (32 bit)
|
|
|
|
sambacry_monkey_filename_32 = "monkey32"
|
|
|
|
# Monkey filename on share (64 bit)
|
|
|
|
sambacry_monkey_filename_64 = "monkey64"
|
|
|
|
# Monkey copy filename on share (32 bit)
|
|
|
|
sambacry_monkey_copy_filename_32 = "monkey32_2"
|
|
|
|
# Monkey copy filename on share (64 bit)
|
|
|
|
sambacry_monkey_copy_filename_64 = "monkey64_2"
|
|
|
|
|
2015-11-30 21:29:30 +08:00
|
|
|
# system info collection
|
|
|
|
collect_system_info = True
|
|
|
|
|
2017-08-16 20:14:26 +08:00
|
|
|
###########################
|
|
|
|
# systeminfo config
|
|
|
|
###########################
|
|
|
|
|
|
|
|
mimikatz_dll_name = "mk.dll"
|
|
|
|
|
2017-09-25 20:13:36 +08:00
|
|
|
|
2015-11-26 21:48:47 +08:00
|
|
|
WormConfiguration = Configuration()
|