Merge branch 'develop' into nadler/pth

This commit is contained in:
maor.rayzin 2018-09-16 14:21:28 +03:00
commit 81694862b6
212 changed files with 2097 additions and 372 deletions

10
.gitignore vendored
View File

@ -62,9 +62,9 @@ docs/_build/
# PyBuilder
target/
db
bin
/monkey_island/cc/server.key
/monkey_island/cc/server.crt
/monkey_island/cc/server.csr
monkey_island/cc/ui/node_modules/
/monkey/monkey_island/db
/monkey/monkey_island/cc/server.key
/monkey/monkey_island/cc/server.crt
/monkey/monkey_island/cc/server.csr
/monkey/monkey_island/cc/ui/node_modules/

View File

@ -1,30 +0,0 @@
from abc import ABCMeta, abstractmethod
__author__ = 'itamar'
class HostScanner(object):
__metaclass__ = ABCMeta
@abstractmethod
def is_host_alive(self, host):
raise NotImplementedError()
class HostFinger(object):
__metaclass__ = ABCMeta
@abstractmethod
def get_host_fingerprint(self, host):
raise NotImplementedError()
from ping_scanner import PingScanner
from tcp_scanner import TcpScanner
from smbfinger import SMBFinger
from sshfinger import SSHFinger
from httpfinger import HTTPFinger
from elasticfinger import ElasticFinger
from mysqlfinger import MySQLFinger
from info import local_ips
from info import get_free_tcp_port
from mssql_fingerprint import MSSQLFinger

View File

@ -1,3 +0,0 @@
from http import HTTPServer, LockedHTTPServer
__author__ = 'hoffer'

View File

@ -0,0 +1 @@
__author__ = 'itay.mizeretz'

View File

@ -0,0 +1,4 @@
import infection_monkey.main
if "__main__" == __name__:
infection_monkey.main.main()

View File

@ -0,0 +1 @@
__author__ = 'itay.mizeretz'

View File

@ -1,15 +1,13 @@
import os
import struct
import json
import sys
import types
import uuid
from abc import ABCMeta
from itertools import product
import importlib
from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter, \
SambaCryExploiter, ElasticGroovyExploiter, Struts2Exploiter, WebLogicExploiter, HadoopExploiter
from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger, \
MSSQLFinger
importlib.import_module('infection_monkey', 'network')
__author__ = 'itamar'
@ -18,57 +16,47 @@ GUID = str(uuid.getnode())
EXTERNAL_CONFIG_FILE = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'monkey.bin')
def _cast_by_example(value, example):
"""
a method that casts a value to the type of the parameter given as example
"""
example_type = type(example)
if example_type is str:
return os.path.expandvars(value).encode("utf8")
elif example_type is tuple and len(example) != 0:
if value is None or value == tuple([None]):
return tuple()
return tuple([_cast_by_example(x, example[0]) for x in value])
elif example_type is list and len(example) != 0:
if value is None or value == [None]:
return []
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 in (type, ABCMeta):
return globals()[value]
else:
return None
class Configuration(object):
def from_dict(self, data):
"""
Get a dict of config variables, set known variables as attributes on self.
Return dict of unknown variables encountered.
"""
unknown_variables = {}
for key, value in data.items():
def from_kv(self, formatted_data):
# now we won't work at <2.7 for sure
network_import = importlib.import_module('infection_monkey.network')
exploit_import = importlib.import_module('infection_monkey.exploit')
unknown_items = []
for key, value in formatted_data.items():
if key.startswith('_'):
continue
if key in ["name", "id", "current_server"]:
continue
if self._depth_from_commandline and key == "depth":
continue
try:
default_value = getattr(Configuration, key)
except AttributeError:
unknown_variables[key] = value
continue
# handle in cases
if key == 'finger_classes':
class_objects = [getattr(network_import, val) for val in value]
setattr(self, key, class_objects)
elif key == 'scanner_class':
scanner_object = getattr(network_import, value)
setattr(self, key, scanner_object)
elif key == 'exploiter_classes':
class_objects = [getattr(exploit_import, val) for val in value]
setattr(self, key, class_objects)
else:
if hasattr(self, key):
setattr(self, key, value)
else:
unknown_items.append(key)
return unknown_items
setattr(self, key, _cast_by_example(value, default_value))
return unknown_variables
def from_json(self, json_data):
"""
Gets a json data object, parses it and applies it to the configuration
:param json_data:
:return:
"""
formatted_data = json.loads(json_data)
result = self.from_kv(formatted_data)
return result
def as_dict(self):
result = {}
@ -145,12 +133,9 @@ class Configuration(object):
# how many scan iterations to perform on each run
max_iterations = 1
scanner_class = TcpScanner
finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger, MySQLFinger, ElasticFinger, MSSQLFinger]
exploiter_classes = [SmbExploiter, WmiExploiter, # Windows exploits
SSHExploiter, ShellShockExploiter, SambaCryExploiter, # Linux
ElasticGroovyExploiter, Struts2Exploiter, WebLogicExploiter, HadoopExploiter # multi
]
scanner_class = None
finger_classes = []
exploiter_classes = []
# how many victims to look for in a single scan iteration
victims_max_find = 30

View File

@ -6,12 +6,12 @@ from socket import gethostname
import requests
from requests.exceptions import ConnectionError
import monkeyfs
import tunnel
from config import WormConfiguration, GUID
from network.info import local_ips, check_internet_access
from transport.http import HTTPConnectProxy
from transport.tcp import TcpProxy
import infection_monkey.monkeyfs as monkeyfs
import infection_monkey.tunnel as tunnel
from infection_monkey.config import WormConfiguration, GUID
from infection_monkey.network.info import local_ips, check_internet_access
from infection_monkey.transport.http import HTTPConnectProxy
from infection_monkey.transport.tcp import TcpProxy
__author__ = 'hoffer'
@ -160,7 +160,7 @@ class ControlClient(object):
return
try:
unknown_variables = WormConfiguration.from_dict(reply.json().get('config'))
unknown_variables = WormConfiguration.from_kv(reply.json().get('config'))
LOG.info("New configuration was loaded from server: %r" % (WormConfiguration.as_dict(),))
except Exception as exc:
# we don't continue with default conf here because it might be dangerous

View File

@ -10,10 +10,10 @@ import time
from ctypes import c_char_p
import filecmp
from config import WormConfiguration
from exploit.tools import build_monkey_commandline_explicitly
from model import MONKEY_CMDLINE_WINDOWS, MONKEY_CMDLINE_LINUX, GENERAL_CMDLINE_LINUX
from system_info import SystemInfoCollector, OperatingSystem
from infection_monkey.config import WormConfiguration
from infection_monkey.exploit.tools import build_monkey_commandline_explicitly
from infection_monkey.model import MONKEY_CMDLINE_WINDOWS, MONKEY_CMDLINE_LINUX, GENERAL_CMDLINE_LINUX
from infection_monkey.system_info import SystemInfoCollector, OperatingSystem
if "win32" == sys.platform:
from win32process import DETACHED_PROCESS

View File

@ -1,4 +1,5 @@
from abc import ABCMeta, abstractmethod
import infection_monkey.config
__author__ = 'itamar'
@ -9,7 +10,7 @@ class HostExploiter(object):
_TARGET_OS_TYPE = []
def __init__(self, host):
self._config = infection_monkey.config.WormConfiguration
self._exploit_info = {}
self._exploit_attempts = []
self.host = host
@ -18,7 +19,7 @@ class HostExploiter(object):
return self.host.os.get('type') in self._TARGET_OS_TYPE
def send_exploit_telemetry(self, result):
from control import ControlClient
from infection_monkey.control import ControlClient
ControlClient.send_telemetry(
'exploit',
{'result': result, 'machine': self.host.__dict__, 'exploiter': self.__class__.__name__,
@ -33,14 +34,14 @@ class HostExploiter(object):
raise NotImplementedError()
from win_ms08_067 import Ms08_067_Exploiter
from wmiexec import WmiExploiter
from smbexec import SmbExploiter
from rdpgrinder import RdpExploiter
from sshexec import SSHExploiter
from shellshock import ShellShockExploiter
from sambacry import SambaCryExploiter
from elasticgroovy import ElasticGroovyExploiter
from struts2 import Struts2Exploiter
from weblogic import WebLogicExploiter
from hadoop import HadoopExploiter
from infection_monkey.exploit.win_ms08_067 import Ms08_067_Exploiter
from infection_monkey.exploit.wmiexec import WmiExploiter
from infection_monkey.exploit.smbexec import SmbExploiter
from infection_monkey.exploit.rdpgrinder import RdpExploiter
from infection_monkey.exploit.sshexec import SSHExploiter
from infection_monkey.exploit.shellshock import ShellShockExploiter
from infection_monkey.exploit.sambacry import SambaCryExploiter
from infection_monkey.exploit.elasticgroovy import ElasticGroovyExploiter
from infection_monkey.exploit.struts2 import Struts2Exploiter
from infection_monkey.exploit.weblogic import WebLogicExploiter
from infection_monkey.exploit.hadoop import HadoopExploiter

View File

@ -7,9 +7,9 @@
import json
import logging
import requests
from exploit.web_rce import WebRCE
from model import WGET_HTTP_UPLOAD, RDP_CMDLINE_HTTP
from network.elasticfinger import ES_PORT, ES_SERVICE
from infection_monkey.exploit.web_rce import WebRCE
from infection_monkey.model import WGET_HTTP_UPLOAD, RDP_CMDLINE_HTTP
from infection_monkey.network.elasticfinger import ES_PORT, ES_SERVICE
import re

View File

@ -8,10 +8,11 @@ import json
import random
import string
import logging
from exploit.web_rce import WebRCE
from tools import HTTPTools, build_monkey_commandline, get_monkey_depth
import posixpath
from model import MONKEY_ARG, ID_STRING
from infection_monkey.exploit.web_rce import WebRCE
from infection_monkey.exploit.tools import HTTPTools, build_monkey_commandline, get_monkey_depth
from infection_monkey.model import MONKEY_ARG, ID_STRING
__author__ = 'VakarisZ'

View File

@ -9,12 +9,12 @@ from rdpy.core.error import RDPSecurityNegoFail
from rdpy.protocol.rdp import rdp
from twisted.internet import reactor
from exploit import HostExploiter
from exploit.tools import HTTPTools, get_monkey_depth
from exploit.tools import get_target_monkey
from model import RDP_CMDLINE_HTTP_BITS, RDP_CMDLINE_HTTP_VBS
from network.tools import check_tcp_port
from tools import build_monkey_commandline
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.tools import HTTPTools, get_monkey_depth
from infection_monkey.exploit.tools import get_target_monkey
from infection_monkey.model import RDP_CMDLINE_HTTP_BITS, RDP_CMDLINE_HTTP_VBS
from infection_monkey.network.tools import check_tcp_port
from infection_monkey.exploit.tools import build_monkey_commandline
__author__ = 'hoffer'
@ -237,8 +237,6 @@ class RdpExploiter(HostExploiter):
def __init__(self, host):
super(RdpExploiter, self).__init__(host)
self._config = __import__('config').WormConfiguration
self._guid = __import__('config').GUID
def is_os_supported(self):
if super(RdpExploiter, self).is_os_supported():

View File

@ -15,12 +15,12 @@ from impacket.smb3structs import SMB2_IL_IMPERSONATION, SMB2_CREATE, SMB2_FLAGS_
SMB2Packet, SMB2Create_Response, SMB2_OPLOCK_LEVEL_NONE
from impacket.smbconnection import SMBConnection
import monkeyfs
from exploit import HostExploiter
from model import DROPPER_ARG
from network.smbfinger import SMB_SERVICE
from tools import build_monkey_commandline, get_target_monkey_by_os, get_monkey_depth
from pyinstaller_utils import get_binary_file_path
import infection_monkey.monkeyfs as monkeyfs
from infection_monkey.exploit import HostExploiter
from infection_monkey.model import DROPPER_ARG
from infection_monkey.network.smbfinger import SMB_SERVICE
from infection_monkey.exploit.tools import build_monkey_commandline, get_target_monkey_by_os, get_monkey_depth
from infection_monkey.pyinstaller_utils import get_binary_file_path
__author__ = 'itay.mizeretz'
@ -53,7 +53,6 @@ class SambaCryExploiter(HostExploiter):
def __init__(self, host):
super(SambaCryExploiter, self).__init__(host)
self._config = __import__('config').WormConfiguration
def exploit_host(self):
if not self.is_vulnerable():

View File

@ -6,11 +6,11 @@ from random import choice
import requests
from exploit import HostExploiter
from exploit.tools import get_target_monkey, HTTPTools, get_monkey_depth
from model import DROPPER_ARG
from shellshock_resources import CGI_FILES
from tools import build_monkey_commandline
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.tools import get_target_monkey, HTTPTools, get_monkey_depth
from infection_monkey.model import DROPPER_ARG
from infection_monkey.exploit.shellshock_resources import CGI_FILES
from infection_monkey.exploit.tools import build_monkey_commandline
__author__ = 'danielg'
@ -29,7 +29,6 @@ class ShellShockExploiter(HostExploiter):
def __init__(self, host):
super(ShellShockExploiter, self).__init__(host)
self._config = __import__('config').WormConfiguration
self.HTTP = [str(port) for port in self._config.HTTP_PORTS]
self.success_flag = ''.join(
choice(string.ascii_uppercase + string.digits

View File

@ -3,12 +3,12 @@ from logging import getLogger
from impacket.dcerpc.v5 import transport, scmr
from impacket.smbconnection import SMB_DIALECT
from exploit import HostExploiter
from exploit.tools import SmbTools, get_target_monkey, get_monkey_depth
from model import MONKEY_CMDLINE_DETACHED_WINDOWS, DROPPER_CMDLINE_DETACHED_WINDOWS
from network import SMBFinger
from network.tools import check_tcp_port
from tools import build_monkey_commandline
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.tools import SmbTools, get_target_monkey, get_monkey_depth
from infection_monkey.model import MONKEY_CMDLINE_DETACHED_WINDOWS, DROPPER_CMDLINE_DETACHED_WINDOWS
from infection_monkey.network import SMBFinger
from infection_monkey.network.tools import check_tcp_port
from infection_monkey.exploit.tools import build_monkey_commandline
LOG = getLogger(__name__)
@ -23,8 +23,6 @@ class SmbExploiter(HostExploiter):
def __init__(self, host):
super(SmbExploiter, self).__init__(host)
self._config = __import__('config').WormConfiguration
self._guid = __import__('config').GUID
def is_os_supported(self):
if super(SmbExploiter, self).is_os_supported():

View File

@ -4,12 +4,12 @@ import time
import paramiko
import StringIO
import monkeyfs
from exploit import HostExploiter
from exploit.tools import get_target_monkey, get_monkey_depth
from model import MONKEY_ARG
from network.tools import check_tcp_port
from tools import build_monkey_commandline
import infection_monkey.monkeyfs as monkeyfs
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.tools import get_target_monkey, get_monkey_depth
from infection_monkey.model import MONKEY_ARG
from infection_monkey.network.tools import check_tcp_port
from infection_monkey.exploit.tools import build_monkey_commandline
__author__ = 'hoffer'
@ -23,7 +23,6 @@ class SSHExploiter(HostExploiter):
def __init__(self, host):
super(SSHExploiter, self).__init__(host)
self._config = __import__('config').WormConfiguration
self._update_timestamp = 0
self.skip_exist = self._config.skip_exploit_if_file_exist

View File

@ -9,7 +9,7 @@ import unicodedata
import re
import logging
from web_rce import WebRCE
from infection_monkey.exploit.web_rce import WebRCE
__author__ = "VakarisZ"

View File

@ -17,11 +17,12 @@ from impacket.dcerpc.v5.dtypes import NULL
from impacket.smb3structs import SMB2_DIALECT_002, SMB2_DIALECT_21
from impacket.smbconnection import SMBConnection, SMB_DIALECT
import monkeyfs
from network import local_ips
from network.firewall import app as firewall
from network.info import get_free_tcp_port, get_routes
from transport import HTTPServer, LockedHTTPServer
import infection_monkey.config
import infection_monkey.monkeyfs as monkeyfs
from infection_monkey.network import local_ips
from infection_monkey.network.firewall import app as firewall
from infection_monkey.network.info import get_free_tcp_port, get_routes
from infection_monkey.transport import HTTPServer, LockedHTTPServer
from threading import Lock
@ -174,8 +175,7 @@ class SmbTools(object):
@staticmethod
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,)
config = __import__('config').WormConfiguration
config = infection_monkey.config.WormConfiguration
src_file_size = monkeyfs.getsize(src_path)
smb, dialect = SmbTools.new_smb_connection(host, username, password, lm_hash, ntlm_hash, timeout)
@ -407,6 +407,7 @@ class HTTPTools(object):
local_ip = get_interface_to_target(host.ip_addr)
if not firewall.listen_allowed():
LOG.error("Firewall is not allowed to listen for incomming ports. Aborting")
return None, None
httpd = LockedHTTPServer(local_ip, local_port, src_path, lock)
@ -444,7 +445,7 @@ def get_interface_to_target(dst):
def get_target_monkey(host):
from control import ControlClient
from infection_monkey.control import ControlClient
import platform
import sys
@ -470,7 +471,7 @@ def get_target_monkey(host):
def get_target_monkey_by_os(is_windows, is_32bit):
from control import ControlClient
from infection_monkey.control import ControlClient
return ControlClient.download_monkey_exe_by_os(is_windows, is_32bit)
@ -494,13 +495,13 @@ def build_monkey_commandline_explicitly(parent=None, tunnel=None, server=None, d
def build_monkey_commandline(target_host, depth, location=None):
from config import GUID
from infection_monkey.config import GUID
return build_monkey_commandline_explicitly(
GUID, target_host.default_tunnel, target_host.default_server, depth, location)
def get_monkey_depth():
from config import WormConfiguration
from infection_monkey.config import WormConfiguration
return WormConfiguration.depth
@ -510,7 +511,7 @@ def get_monkey_dest_path(url_to_monkey):
:param url_to_monkey: Hosted monkey's url. egz : http://localserver:9999/monkey/windows-32.exe
:return: Corresponding monkey path from configuration
"""
from config import WormConfiguration
from infection_monkey.config import WormConfiguration
if not url_to_monkey or ('linux' not in url_to_monkey and 'windows' not in url_to_monkey):
LOG.error("Can't get destination path because source path %s is invalid.", url_to_monkey)
return False

View File

@ -1,12 +1,12 @@
import logging
from exploit import HostExploiter
from model import *
from posixpath import join
import re
from posixpath import join
from abc import abstractmethod
from exploit.tools import get_target_monkey, get_monkey_depth, build_monkey_commandline, HTTPTools
from network.tools import check_tcp_port, tcp_port_to_service
from infection_monkey.exploit import HostExploiter
from infection_monkey.model import *
from infection_monkey.exploit.tools import get_target_monkey, get_monkey_depth, build_monkey_commandline, HTTPTools
from infection_monkey.network.tools import check_tcp_port, tcp_port_to_service
__author__ = 'VakarisZ'
@ -95,7 +95,7 @@ class WebRCE(HostExploiter):
# Upload the right monkey to target
data = self.upload_monkey(self.vulnerable_urls[0], exploit_config['upload_commands'])
if data is not False and data['response'] is False:
if data is False:
return False
# Change permissions to transform monkey into executable file
@ -341,7 +341,11 @@ class WebRCE(HostExploiter):
http_thread.join(DOWNLOAD_TIMEOUT)
http_thread.stop()
LOG.info("Uploading process finished")
return {'response': resp, 'path': paths['dest_path']}
# If response is false exploiter failed
if resp is False:
return resp
else:
return {'response': resp, 'path': paths['dest_path']}
def change_permissions(self, url, path, command=None):
"""

View File

@ -7,8 +7,8 @@
# CVE: CVE-2017-10271
from requests import post, exceptions
from web_rce import WebRCE
from exploit.tools import get_free_tcp_port, get_interface_to_target
from infection_monkey.exploit.web_rce import WebRCE
from infection_monkey.exploit.tools import get_free_tcp_port, get_interface_to_target
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import threading

View File

@ -14,11 +14,11 @@ from enum import IntEnum
from impacket import uuid
from impacket.dcerpc.v5 import transport
from exploit.tools import SmbTools, get_target_monkey, get_monkey_depth
from model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS
from network import SMBFinger
from network.tools import check_tcp_port
from tools import build_monkey_commandline
from infection_monkey.exploit.tools import SmbTools, get_target_monkey, get_monkey_depth
from infection_monkey.model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS
from infection_monkey.network import SMBFinger
from infection_monkey.network.tools import check_tcp_port
from infection_monkey.exploit.tools import build_monkey_commandline
from . import HostExploiter
LOG = getLogger(__name__)
@ -158,8 +158,6 @@ class Ms08_067_Exploiter(HostExploiter):
def __init__(self, host):
super(Ms08_067_Exploiter, self).__init__(host)
self._config = __import__('config').WormConfiguration
self._guid = __import__('config').GUID
def is_os_supported(self):
if self.host.os.get('type') in self._TARGET_OS_TYPE and \

View File

@ -5,10 +5,10 @@ import traceback
from impacket.dcerpc.v5.rpcrt import DCERPCException
from exploit import HostExploiter
from exploit.tools import SmbTools, WmiTools, AccessDeniedException, get_target_monkey, get_monkey_depth
from model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS
from tools import build_monkey_commandline
from infection_monkey.exploit import HostExploiter
from infection_monkey.exploit.tools import SmbTools, WmiTools, AccessDeniedException, get_target_monkey, \
get_monkey_depth, build_monkey_commandline
from infection_monkey.model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS
LOG = logging.getLogger(__name__)
@ -18,8 +18,6 @@ class WmiExploiter(HostExploiter):
def __init__(self, host):
super(WmiExploiter, self).__init__(host)
self._config = __import__('config').WormConfiguration
self._guid = __import__('config').GUID
@WmiTools.dcom_wrap
def exploit_host(self):

View File

@ -8,14 +8,11 @@ import os
import sys
import traceback
from config import WormConfiguration, EXTERNAL_CONFIG_FILE
from dropper import MonkeyDrops
from model import MONKEY_ARG, DROPPER_ARG
from monkey import InfectionMonkey
import utils
if __name__ == "__main__":
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import infection_monkey.utils as utils
from infection_monkey.config import WormConfiguration, EXTERNAL_CONFIG_FILE
from infection_monkey.dropper import MonkeyDrops
from infection_monkey.model import MONKEY_ARG, DROPPER_ARG
from infection_monkey.monkey import InfectionMonkey
__author__ = 'itamar'
@ -63,7 +60,7 @@ def main():
try:
with open(config_file) as config_fo:
json_dict = json.load(config_fo)
WormConfiguration.from_dict(json_dict)
WormConfiguration.from_kv(json_dict)
except ValueError as e:
print("Error loading config: %s, using default" % (e,))
else:

View File

@ -1,4 +1,4 @@
from host import VictimHost
from infection_monkey.model.host import VictimHost
__author__ = 'itamar'

View File

@ -4,7 +4,7 @@ block_cipher = None
a = Analysis(['main.py'],
pathex=['.', '..'],
pathex=['..'],
binaries=None,
datas=None,
hiddenimports=['_cffi_backend'],

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

@ -4,18 +4,18 @@ import os
import subprocess
import sys
import time
import tunnel
import utils
from config import WormConfiguration
from control import ControlClient
from model import DELAY_DELETE_CMD
from network.firewall import app as firewall
from network.network_scanner import NetworkScanner
from six.moves import xrange
from system_info import SystemInfoCollector
from system_singleton import SystemSingleton
from windows_upgrader import WindowsUpgrader
import infection_monkey.tunnel as tunnel
import infection_monkey.utils as utils
from infection_monkey.config import WormConfiguration
from infection_monkey.control import ControlClient
from infection_monkey.model import DELAY_DELETE_CMD
from infection_monkey.network.firewall import app as firewall
from infection_monkey.network.network_scanner import NetworkScanner
from infection_monkey.system_info import SystemInfoCollector
from infection_monkey.system_singleton import SystemSingleton
from infection_monkey.windows_upgrader import WindowsUpgrader
__author__ = 'itamar'

View File

@ -14,7 +14,7 @@ def get_mimikatz_zip_path():
a = Analysis(['main.py'],
pathex=['.', '..'],
pathex=['..'],
hiddenimports=['_cffi_backend', 'queue'],
hookspath=None,
runtime_hooks=None)

View File

@ -0,0 +1,29 @@
from abc import ABCMeta, abstractmethod
__author__ = 'itamar'
class HostScanner(object):
__metaclass__ = ABCMeta
@abstractmethod
def is_host_alive(self, host):
raise NotImplementedError()
class HostFinger(object):
__metaclass__ = ABCMeta
@abstractmethod
def get_host_fingerprint(self, host):
raise NotImplementedError()
from infection_monkey.network.ping_scanner import PingScanner
from infection_monkey.network.tcp_scanner import TcpScanner
from infection_monkey.network.smbfinger import SMBFinger
from infection_monkey.network.sshfinger import SSHFinger
from infection_monkey.network.httpfinger import HTTPFinger
from infection_monkey.network.elasticfinger import ElasticFinger
from infection_monkey.network.mysqlfinger import MySQLFinger
from infection_monkey.network.info import local_ips, get_free_tcp_port
from infection_monkey.network.mssql_fingerprint import MSSQLFinger

View File

@ -5,8 +5,9 @@ from contextlib import closing
import requests
from requests.exceptions import Timeout, ConnectionError
from model.host import VictimHost
from network import HostFinger
import infection_monkey.config
from infection_monkey.model.host import VictimHost
from infection_monkey.network import HostFinger
ES_PORT = 9200
ES_SERVICE = 'elastic-search-9200'
@ -21,7 +22,7 @@ class ElasticFinger(HostFinger):
"""
def __init__(self):
self._config = __import__('config').WormConfiguration
self._config = infection_monkey.config.WormConfiguration
def get_host_fingerprint(self, host):
"""

View File

@ -1,16 +1,18 @@
from network import HostFinger
from model.host import VictimHost
import infection_monkey.config
from infection_monkey.network import HostFinger
from infection_monkey.model.host import VictimHost
import logging
LOG = logging.getLogger(__name__)
class HTTPFinger(HostFinger):
"""
Goal is to recognise HTTP servers, where what we currently care about is apache.
"""
def __init__(self):
self._config = __import__('config').WormConfiguration
self._config = infection_monkey.config.WormConfiguration
self.HTTP = [(port, str(port)) for port in self._config.HTTP_PORTS]
@staticmethod

View File

@ -1,8 +1,9 @@
import logging
import socket
from model.host import VictimHost
from network import HostFinger
from infection_monkey.model.host import VictimHost
from infection_monkey.network import HostFinger
import infection_monkey.config
__author__ = 'Maor Rayzin'
@ -18,7 +19,7 @@ class MSSQLFinger(HostFinger):
SERVICE_NAME = 'MSSQL'
def __init__(self):
self._config = __import__('config').WormConfiguration
self._config = infection_monkey.config.WormConfiguration
def get_host_fingerprint(self, host):
"""Gets Microsoft SQL Server instance information by querying the SQL Browser service.

View File

@ -1,9 +1,10 @@
import logging
import socket
from model.host import VictimHost
from network import HostFinger
from .tools import struct_unpack_tracker, struct_unpack_tracker_string
import infection_monkey.config
from infection_monkey.model.host import VictimHost
from infection_monkey.network import HostFinger
from infection_monkey.network.tools import struct_unpack_tracker, struct_unpack_tracker_string
MYSQL_PORT = 3306
SQL_SERVICE = 'mysqld-3306'
@ -20,7 +21,7 @@ class MySQLFinger(HostFinger):
HEADER_SIZE = 4 # in bytes
def __init__(self):
self._config = __import__('config').WormConfiguration
self._config = infection_monkey.config.WormConfiguration
def get_host_fingerprint(self, host):
"""

View File

@ -1,11 +1,11 @@
import logging
import time
from config import WormConfiguration
from info import local_ips, get_interfaces_ranges
from common.network.network_range import *
from model import VictimHost
from . import HostScanner
from infection_monkey.config import WormConfiguration
from infection_monkey.network.info import local_ips, get_interfaces_ranges
from infection_monkey.model import VictimHost
from infection_monkey.network import HostScanner
__author__ = 'itamar'
@ -63,7 +63,15 @@ class NetworkScanner(object):
return subnets_to_scan
def get_victim_machines(self, scan_type, max_find=5, stop_callback=None):
assert issubclass(scan_type, HostScanner)
"""
Finds machines according to the ranges specified in the object
:param scan_type: A hostscanner class, will be instanced and used to scan for new machines
:param max_find: Max number of victims to find regardless of ranges
:param stop_callback: A callback to check at any point if we should stop scanning
:return: yields a sequence of VictimHost instances
"""
if not scan_type:
return
scanner = scan_type()
victims_count = 0

View File

@ -4,8 +4,9 @@ import re
import subprocess
import sys
from model.host import VictimHost
from . import HostScanner, HostFinger
import infection_monkey.config
from infection_monkey.model.host import VictimHost
from infection_monkey.network import HostScanner, HostFinger
__author__ = 'itamar'
@ -20,7 +21,7 @@ LOG = logging.getLogger(__name__)
class PingScanner(HostScanner, HostFinger):
def __init__(self):
self._config = __import__('config').WormConfiguration
self._config = infection_monkey.config.WormConfiguration
self._devnull = open(os.devnull, "w")
self._ttl_regex = re.compile(TTL_REGEX_STR, re.IGNORECASE)

View File

@ -1,10 +1,11 @@
import socket
import struct
import logging
from network import HostFinger
from model.host import VictimHost
from odict import odict
from infection_monkey.network import HostFinger
from infection_monkey.model.host import VictimHost
SMB_PORT = 445
SMB_SERVICE = 'tcp-445'
@ -100,7 +101,8 @@ class SMBSessionFingerData(Packet):
class SMBFinger(HostFinger):
def __init__(self):
self._config = __import__('config').WormConfiguration
from infection_monkey.config import WormConfiguration
self._config = WormConfiguration
def get_host_fingerprint(self, host):
assert isinstance(host, VictimHost)

View File

@ -1,8 +1,9 @@
import re
from model.host import VictimHost
from network import HostFinger
from network.tools import check_tcp_port
import infection_monkey.config
from infection_monkey.model.host import VictimHost
from infection_monkey.network import HostFinger
from infection_monkey.network.tools import check_tcp_port
SSH_PORT = 22
SSH_SERVICE_DEFAULT = 'tcp-22'
@ -14,7 +15,7 @@ LINUX_DIST_SSH = ['ubuntu', 'debian']
class SSHFinger(HostFinger):
def __init__(self):
self._config = __import__('config').WormConfiguration
self._config = infection_monkey.config.WormConfiguration
self._banner_regex = re.compile(SSH_REGEX, re.IGNORECASE)
@staticmethod

View File

@ -1,8 +1,9 @@
from itertools import izip_longest
from random import shuffle
from network import HostScanner, HostFinger
from network.tools import check_tcp_ports, tcp_port_to_service
import infection_monkey.config
from infection_monkey.network import HostScanner, HostFinger
from infection_monkey.network.tools import check_tcp_ports, tcp_port_to_service
__author__ = 'itamar'
@ -11,7 +12,7 @@ BANNER_READ = 1024
class TcpScanner(HostScanner, HostFinger):
def __init__(self):
self._config = __import__('config').WormConfiguration
self._config = infection_monkey.config.WormConfiguration
def is_host_alive(self, host):
return self.get_host_fingerprint(host, True)

View File

@ -5,8 +5,8 @@ import sys
import psutil
from enum import IntEnum
from network.info import get_host_subnets
from azure_cred_collector import AzureCollector
from infection_monkey.network.info import get_host_subnets
from infection_monkey.system_info.azure_cred_collector import AzureCollector
LOG = logging.getLogger(__name__)
@ -112,7 +112,7 @@ class InfoCollector(object):
Updates the credentials structure, creating it if neccesary (compat with mimikatz)
:return: None. Updates class information
"""
from config import WormConfiguration
from infection_monkey.config import WormConfiguration
if not WormConfiguration.extract_azure_creds:
return
LOG.debug("Harvesting creds if on an Azure machine")

View File

@ -1,7 +1,7 @@
import logging
from . import InfoCollector
from SSH_info_collector import SSHCollector
from infection_monkey.system_info import InfoCollector
from infection_monkey.system_info.SSH_info_collector import SSHCollector
__author__ = 'uri'

View File

@ -4,7 +4,9 @@ import logging
import socket
import zipfile
from pyinstaller_utils import get_binary_file_path, get_binaries_dir_path
import infection_monkey.config
from infection_monkey.pyinstaller_utils import get_binary_file_path, get_binaries_dir_path
__author__ = 'itay.mizeretz'
@ -26,7 +28,7 @@ class MimikatzCollector(object):
MIMIKATZ_ZIP_PASSWORD = r'VTQpsJPXgZuXhX6x3V84G'
def __init__(self):
self._config = __import__('config').WormConfiguration
self._config = infection_monkey.config.WormConfiguration
self._isInit = False
self._dll = None
self._collect = None

View File

@ -9,6 +9,9 @@ import _winreg
from mimikatz_collector import MimikatzCollector
from . import InfoCollector
import infection_monkey.config
from infection_monkey.system_info.mimikatz_collector import MimikatzCollector
from infection_monkey.system_info import InfoCollector
LOG = logging.getLogger(__name__)
LOG.info('started windows info collector')
@ -125,8 +128,8 @@ class WindowsInfoCollector(InfoCollector):
def __init__(self):
super(WindowsInfoCollector, self).__init__()
self._config = infection_monkey.config.WormConfiguration
self.info['reg'] = {}
self._config = __import__('config').WormConfiguration
def get_info(self):
"""

View File

@ -3,7 +3,7 @@ import logging
import sys
from abc import ABCMeta, abstractmethod
from config import WormConfiguration
from infection_monkey.config import WormConfiguration
__author__ = 'itamar'

View File

@ -0,0 +1,4 @@
from infection_monkey.transport.http import HTTPServer, LockedHTTPServer
__author__ = 'hoffer'

View File

@ -3,6 +3,7 @@ from threading import Thread
g_last_served = None
class TransportProxyBase(Thread):
def __init__(self, local_port, dest_host=None, dest_port=None, local_host=''):
global g_last_served

View File

@ -8,8 +8,8 @@ from logging import getLogger
from urlparse import urlsplit
from threading import Lock
import monkeyfs
from base import TransportProxyBase, update_last_serve_time
import infection_monkey.monkeyfs as monkeyfs
from infection_monkey.transport.base import TransportProxyBase, update_last_serve_time
__author__ = 'hoffer'

View File

@ -1,9 +1,10 @@
import socket
import select
from threading import Thread
from base import TransportProxyBase, update_last_serve_time
from logging import getLogger
from infection_monkey.transport.base import TransportProxyBase, update_last_serve_time
READ_BUFFER_SIZE = 8192
DEFAULT_TIMEOUT = 30

View File

@ -5,11 +5,11 @@ import time
from difflib import get_close_matches
from threading import Thread
from model import VictimHost
from network.firewall import app as firewall
from network.info import local_ips, get_free_tcp_port
from network.tools import check_tcp_port
from transport.base import get_last_serve_time
from infection_monkey.model import VictimHost
from infection_monkey.network.firewall import app as firewall
from infection_monkey.network.info import local_ips, get_free_tcp_port
from infection_monkey.network.tools import check_tcp_port
from infection_monkey.transport.base import get_last_serve_time
__author__ = 'hoffer'

View File

@ -2,7 +2,7 @@ import os
import sys
import struct
from config import WormConfiguration
from infection_monkey.config import WormConfiguration
def get_monkey_log_path():

View File

@ -5,12 +5,12 @@ import shutil
import time
import monkeyfs
from config import WormConfiguration
from control import ControlClient
from exploit.tools import build_monkey_commandline_explicitly
from model import MONKEY_CMDLINE_WINDOWS
from utils import is_windows_os, is_64bit_windows_os, is_64bit_python
import infection_monkey.monkeyfs as monkeyfs
from infection_monkey.config import WormConfiguration
from infection_monkey.control import ControlClient
from infection_monkey.exploit.tools import build_monkey_commandline_explicitly
from infection_monkey.model import MONKEY_CMDLINE_WINDOWS
from infection_monkey.utils import is_windows_os, is_64bit_windows_os, is_64bit_python
__author__ = 'itay.mizeretz'

4
monkey/monkey_island.py Normal file
View File

@ -0,0 +1,4 @@
import monkey_island.cc.main
if "__main__" == __name__:
monkey_island.cc.main.main()

View File

@ -0,0 +1 @@
__author__ = 'itay.mizeretz'

View File

@ -4,7 +4,7 @@ from datetime import datetime
import bson
import flask_restful
from bson.json_util import dumps
from flask import Flask, send_from_directory, make_response
from flask import Flask, send_from_directory, make_response, Response
from werkzeug.exceptions import NotFound
from cc.auth import init_jwt
@ -29,18 +29,24 @@ from cc.services.config import ConfigService
__author__ = 'Barak'
HOME_FILE = 'index.html'
def serve_static_file(static_path):
if static_path.startswith('api/'):
raise NotFound()
try:
return send_from_directory('ui/dist', static_path)
return send_from_directory(os.path.join(os.getcwd(), 'monkey_island/cc/ui/dist'), static_path)
except NotFound:
# Because react uses various urls for same index page, this is probably the user's intention.
if static_path == HOME_FILE:
flask_restful.abort(
Response("Page not found. Make sure you ran the npm script and the cwd is monkey\\monkey.", 500))
return serve_home()
def serve_home():
return serve_static_file('index.html')
return serve_static_file(HOME_FILE)
def normalize_obj(obj):

View File

@ -9,7 +9,7 @@ __author__ = "itay.mizeretz"
class Encryptor:
_BLOCK_SIZE = 32
_DB_PASSWORD_FILENAME = "mongo_key.bin"
_DB_PASSWORD_FILENAME = "monkey_island/cc/mongo_key.bin"
def __init__(self):
self._load_key()

View File

@ -13,7 +13,7 @@ ENV_DICT = {
def load_env_from_file():
with open('server_config.json', 'r') as f:
with open('monkey_island/cc/server_config.json', 'r') as f:
config_content = f.read()
config_json = json.loads(config_content)
return config_json['server_config']

View File

@ -6,10 +6,6 @@ import time
import logging
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PARENT_PATH = os.path.dirname(BASE_PATH)
if PARENT_PATH not in sys.path:
sys.path.insert(0, PARENT_PATH)
if BASE_PATH not in sys.path:
sys.path.insert(0, BASE_PATH)
@ -38,11 +34,11 @@ def main():
app = init_app(mongo_url)
if env.is_debug():
app.run(host='0.0.0.0', debug=True, ssl_context=('server.crt', 'server.key'))
app.run(host='0.0.0.0', debug=True, ssl_context=('monkey_island/cc/server.crt', 'monkey_island/cc/server.key'))
else:
http_server = HTTPServer(WSGIContainer(app),
ssl_options={'certfile': os.environ.get('SERVER_CRT', 'server.crt'),
'keyfile': os.environ.get('SERVER_KEY', 'server.key')})
ssl_options={'certfile': os.environ.get('SERVER_CRT', 'monkey_island/cc/server.crt'),
'keyfile': os.environ.get('SERVER_KEY', 'monkey_island/cc/server.key')})
http_server.listen(env.get_island_port())
logger.info(
'Monkey Island Server is running on https://{}:{}'.format(local_ip_addresses()[0], env.get_island_port()))

View File

@ -26,8 +26,8 @@ def run_local_monkey():
if not result:
return False, "OS Type not found"
monkey_path = os.path.join('binaries', result['filename'])
target_path = os.path.join(os.getcwd(), result['filename'])
monkey_path = os.path.join(os.getcwd(), 'monkey_island', 'cc', 'binaries', result['filename'])
target_path = os.path.join(os.getcwd(), 'monkey_island', result['filename'])
# copy the executable to temp path (don't run the monkey from its current location as it may delete itself)
try:

Some files were not shown because too many files have changed in this diff Show More