From 03b7b9f2f3e0129c4685c9aa1ed3dff2ccf522b3 Mon Sep 17 00:00:00 2001 From: itay Date: Sun, 14 Apr 2019 16:39:15 +0300 Subject: [PATCH] Merge branch 'master' into develop # Conflicts: # monkey/monkey_island/cc/app.py # monkey/monkey_island/cc/resources/root.py # monkey/monkey_island/requirements.txt --- monkey/monkey_island/cc/app.py | 49 ++++----- monkey/monkey_island/cc/auth.py | 2 +- monkey/monkey_island/cc/consts.py | 5 + monkey/monkey_island/cc/encryptor.py | 4 +- monkey/monkey_island/cc/environment/aws.py | 6 +- .../cc/environment/environment.py | 10 +- .../monkey_island/cc/environment/password.py | 6 +- .../monkey_island/cc/environment/standard.py | 6 +- monkey/monkey_island/cc/exporter_init.py | 6 +- monkey/monkey_island/cc/main.py | 25 +++-- .../cc/resources/attack_telem.py | 2 +- .../cc/resources/aws_exporter.py | 6 +- .../monkey_island/cc/resources/client_run.py | 2 +- monkey/monkey_island/cc/resources/edge.py | 2 +- .../cc/resources/island_configuration.py | 4 +- .../monkey_island/cc/resources/island_logs.py | 4 +- .../monkey_island/cc/resources/local_run.py | 14 +-- monkey/monkey_island/cc/resources/log.py | 8 +- monkey/monkey_island/cc/resources/monkey.py | 6 +- .../cc/resources/monkey_configuration.py | 4 +- .../cc/resources/monkey_download.py | 6 +- monkey/monkey_island/cc/resources/netmap.py | 8 +- monkey/monkey_island/cc/resources/node.py | 4 +- .../cc/resources/pba_file_download.py | 2 +- .../cc/resources/pba_file_upload.py | 6 +- .../monkey_island/cc/resources/remote_run.py | 4 +- monkey/monkey_island/cc/resources/report.py | 4 +- monkey/monkey_island/cc/resources/root.py | 14 +-- .../monkey_island/cc/resources/telemetry.py | 16 +-- .../cc/resources/telemetry_feed.py | 6 +- .../cc/services/attack/attack_telem.py | 2 +- monkey/monkey_island/cc/services/config.py | 14 +-- monkey/monkey_island/cc/services/edge.py | 10 +- monkey/monkey_island/cc/services/log.py | 8 +- monkey/monkey_island/cc/services/node.py | 10 +- .../cc/services/post_breach_files.py | 14 +-- .../monkey_island/cc/services/pth_report.py | 6 +- .../cc/services/remote_run_aws.py | 2 +- monkey/monkey_island/cc/services/report.py | 12 +-- .../monkey_island/cc/services/wmi_handler.py | 4 +- monkey/monkey_island/monkey_island.ico | Bin 0 -> 110568 bytes monkey/monkey_island/monkey_island.spec | 93 ++++++++++++++++++ monkey/monkey_island/requirements.txt | 6 +- .../windows/build_pyinstaller.bat | 5 + monkey/monkey_island/windows/run_cc.bat | 1 + monkey/monkey_island/windows/run_cc_exe.bat | 5 + monkey/monkey_island/windows/run_mongodb.bat | 1 + monkey/monkey_island/windows/run_server.bat | 3 +- .../monkey_island/windows/run_server_py.bat | 5 + 49 files changed, 287 insertions(+), 155 deletions(-) create mode 100644 monkey/monkey_island/cc/consts.py create mode 100644 monkey/monkey_island/monkey_island.ico create mode 100644 monkey/monkey_island/monkey_island.spec create mode 100644 monkey/monkey_island/windows/build_pyinstaller.bat create mode 100644 monkey/monkey_island/windows/run_cc_exe.bat create mode 100644 monkey/monkey_island/windows/run_server_py.bat diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index e8238185e..4f055fec6 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -8,29 +8,30 @@ from bson.json_util import dumps from flask import Flask, send_from_directory, make_response, Response from werkzeug.exceptions import NotFound -from cc.auth import init_jwt -from cc.database import mongo, database -from cc.environment.environment import env -from cc.resources.client_run import ClientRun -from cc.resources.edge import Edge -from cc.resources.local_run import LocalRun -from cc.resources.log import Log -from cc.resources.island_logs import IslandLog -from cc.resources.monkey import Monkey -from cc.resources.monkey_configuration import MonkeyConfiguration -from cc.resources.island_configuration import IslandConfiguration -from cc.resources.monkey_download import MonkeyDownload -from cc.resources.netmap import NetMap -from cc.resources.node import Node -from cc.resources.remote_run import RemoteRun -from cc.resources.report import Report -from cc.resources.root import Root -from cc.resources.telemetry import Telemetry -from cc.resources.telemetry_feed import TelemetryFeed -from cc.resources.pba_file_download import PBAFileDownload -from cc.services.config import ConfigService -from cc.resources.pba_file_upload import FileUpload -from cc.resources.attack_telem import AttackTelem +from monkey_island.cc.auth import init_jwt +from monkey_island.cc.database import mongo, database +from monkey_island.cc.environment.environment import env +from monkey_island.cc.resources.client_run import ClientRun +from monkey_island.cc.resources.edge import Edge +from monkey_island.cc.resources.local_run import LocalRun +from monkey_island.cc.resources.log import Log +from monkey_island.cc.resources.island_logs import IslandLog +from monkey_island.cc.resources.monkey import Monkey +from monkey_island.cc.resources.monkey_configuration import MonkeyConfiguration +from monkey_island.cc.resources.island_configuration import IslandConfiguration +from monkey_island.cc.resources.monkey_download import MonkeyDownload +from monkey_island.cc.resources.netmap import NetMap +from monkey_island.cc.resources.node import Node +from monkey_island.cc.resources.remote_run import RemoteRun +from monkey_island.cc.resources.report import Report +from monkey_island.cc.resources.root import Root +from monkey_island.cc.resources.telemetry import Telemetry +from monkey_island.cc.resources.telemetry_feed import TelemetryFeed +from monkey_island.cc.resources.pba_file_download import PBAFileDownload +from monkey_island.cc.services.config import ConfigService +from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH +from monkey_island.cc.resources.pba_file_upload import FileUpload +from monkey_island.cc.resources.attack_telem import AttackTelem __author__ = 'Barak' @@ -42,7 +43,7 @@ def serve_static_file(static_path): if static_path.startswith('api/'): raise NotFound() try: - return send_from_directory(os.path.join(os.getcwd(), 'monkey_island/cc/ui/dist'), static_path) + return send_from_directory(os.path.join(MONKEY_ISLAND_ABS_PATH, '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: diff --git a/monkey/monkey_island/cc/auth.py b/monkey/monkey_island/cc/auth.py index f12a7f8cd..2e7eb69ff 100644 --- a/monkey/monkey_island/cc/auth.py +++ b/monkey/monkey_island/cc/auth.py @@ -4,7 +4,7 @@ from flask import current_app, abort from flask_jwt import JWT, _jwt_required, JWTError from werkzeug.security import safe_str_cmp -from cc.environment.environment import env +from monkey_island.cc.environment.environment import env __author__ = 'itay.mizeretz' diff --git a/monkey/monkey_island/cc/consts.py b/monkey/monkey_island/cc/consts.py new file mode 100644 index 000000000..deb1db449 --- /dev/null +++ b/monkey/monkey_island/cc/consts.py @@ -0,0 +1,5 @@ +import os + +__author__ = 'itay.mizeretz' + +MONKEY_ISLAND_ABS_PATH = os.path.join(os.getcwd(), 'monkey_island') diff --git a/monkey/monkey_island/cc/encryptor.py b/monkey/monkey_island/cc/encryptor.py index 84e6fba9d..98473b60a 100644 --- a/monkey/monkey_island/cc/encryptor.py +++ b/monkey/monkey_island/cc/encryptor.py @@ -4,12 +4,14 @@ import os from Crypto import Random from Crypto.Cipher import AES +from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH + __author__ = "itay.mizeretz" class Encryptor: _BLOCK_SIZE = 32 - _DB_PASSWORD_FILENAME = "monkey_island/cc/mongo_key.bin" + _DB_PASSWORD_FILENAME = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc/mongo_key.bin') def __init__(self): self._load_key() diff --git a/monkey/monkey_island/cc/environment/aws.py b/monkey/monkey_island/cc/environment/aws.py index 7a53fadb2..3d3544a32 100644 --- a/monkey/monkey_island/cc/environment/aws.py +++ b/monkey/monkey_island/cc/environment/aws.py @@ -1,5 +1,5 @@ -import cc.auth -from cc.environment import Environment +import monkey_island.cc.auth +from monkey_island.cc.environment import Environment from common.cloud.aws_instance import AwsInstance from Crypto.Hash import SHA3_512 @@ -21,5 +21,5 @@ class AwsEnvironment(Environment): def get_auth_users(self): return [ - cc.auth.User(1, 'monkey', self.hash_secret(self._instance_id)) + monkey_island.cc.auth.User(1, 'monkey', self.hash_secret(self._instance_id)) ] diff --git a/monkey/monkey_island/cc/environment/environment.py b/monkey/monkey_island/cc/environment/environment.py index 27413a98c..3cd6bb587 100644 --- a/monkey/monkey_island/cc/environment/environment.py +++ b/monkey/monkey_island/cc/environment/environment.py @@ -1,9 +1,11 @@ import json import logging +import os -from cc.environment import standard -from cc.environment import aws -from cc.environment import password +from monkey_island.cc.environment import standard +from monkey_island.cc.environment import aws +from monkey_island.cc.environment import password +from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH __author__ = 'itay.mizeretz' @@ -21,7 +23,7 @@ ENV_DICT = { def load_server_configuration_from_file(): - with open('monkey_island/cc/server_config.json', 'r') as f: + with open(os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc/server_config.json'), 'r') as f: config_content = f.read() return json.loads(config_content) diff --git a/monkey/monkey_island/cc/environment/password.py b/monkey/monkey_island/cc/environment/password.py index 30ddd8267..89abfea8c 100644 --- a/monkey/monkey_island/cc/environment/password.py +++ b/monkey/monkey_island/cc/environment/password.py @@ -1,5 +1,5 @@ -from cc.environment import Environment -import cc.auth +from monkey_island.cc.environment import Environment +import monkey_island.cc.auth __author__ = 'itay.mizeretz' @@ -8,5 +8,5 @@ class PasswordEnvironment(Environment): def get_auth_users(self): return [ - cc.auth.User(1, self.config['user'], self.config['hash']) + monkey_island.cc.auth.User(1, self.config['user'], self.config['hash']) ] diff --git a/monkey/monkey_island/cc/environment/standard.py b/monkey/monkey_island/cc/environment/standard.py index 532ced959..f84aeaeef 100644 --- a/monkey/monkey_island/cc/environment/standard.py +++ b/monkey/monkey_island/cc/environment/standard.py @@ -1,5 +1,5 @@ -import cc.auth -from cc.environment import Environment +import monkey_island.cc.auth +from monkey_island.cc.environment import Environment __author__ = 'itay.mizeretz' @@ -11,5 +11,5 @@ class StandardEnvironment(Environment): def get_auth_users(self): return [ - cc.auth.User(1, StandardEnvironment.NO_AUTH_CREDS, StandardEnvironment.NO_AUTH_CREDS) + monkey_island.cc.auth.User(1, StandardEnvironment.NO_AUTH_CREDS, StandardEnvironment.NO_AUTH_CREDS) ] diff --git a/monkey/monkey_island/cc/exporter_init.py b/monkey/monkey_island/cc/exporter_init.py index 9b25469f9..3450e98f2 100644 --- a/monkey/monkey_island/cc/exporter_init.py +++ b/monkey/monkey_island/cc/exporter_init.py @@ -1,6 +1,6 @@ -from cc.environment.environment import load_env_from_file, AWS -from cc.report_exporter_manager import ReportExporterManager -from cc.resources.aws_exporter import AWSExporter +from monkey_island.cc.environment.environment import load_env_from_file, AWS +from monkey_island.cc.report_exporter_manager import ReportExporterManager +from monkey_island.cc.resources.aws_exporter import AWSExporter __author__ = 'maor.rayzin' diff --git a/monkey/monkey_island/cc/main.py b/monkey/monkey_island/cc/main.py index 713e83b96..412c3c399 100644 --- a/monkey/monkey_island/cc/main.py +++ b/monkey/monkey_island/cc/main.py @@ -11,17 +11,18 @@ BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if BASE_PATH not in sys.path: sys.path.insert(0, BASE_PATH) -from cc.island_logger import json_setup_logging +from monkey_island.cc.island_logger import json_setup_logging +from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH # This is here in order to catch EVERYTHING, some functions are being called on imports the log init needs to be on top. -json_setup_logging(default_path=os.path.join(BASE_PATH, 'cc', 'island_logger_default_config.json'), +json_setup_logging(default_path=os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'island_logger_default_config.json'), default_level=logging.DEBUG) logger = logging.getLogger(__name__) -from cc.app import init_app -from cc.exporter_init import populate_exporter_list -from cc.utils import local_ip_addresses -from cc.environment.environment import env -from cc.database import is_db_server_up +from monkey_island.cc.app import init_app +from monkey_island.cc.exporter_init import populate_exporter_list +from monkey_island.cc.utils import local_ip_addresses +from monkey_island.cc.environment.environment import env +from monkey_island.cc.database import is_db_server_up def main(): @@ -37,12 +38,16 @@ def main(): populate_exporter_list() app = init_app(mongo_url) + + crt_path = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'server.crt') + key_path = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'server.key') + if env.is_debug(): - app.run(host='0.0.0.0', debug=True, ssl_context=('monkey_island/cc/server.crt', 'monkey_island/cc/server.key')) + app.run(host='0.0.0.0', debug=True, ssl_context=(crt_path, key_path)) else: http_server = HTTPServer(WSGIContainer(app), - ssl_options={'certfile': os.environ.get('SERVER_CRT', 'monkey_island/cc/server.crt'), - 'keyfile': os.environ.get('SERVER_KEY', 'monkey_island/cc/server.key')}) + ssl_options={'certfile': os.environ.get('SERVER_CRT', crt_path), + 'keyfile': os.environ.get('SERVER_KEY', key_path)}) 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())) diff --git a/monkey/monkey_island/cc/resources/attack_telem.py b/monkey/monkey_island/cc/resources/attack_telem.py index 0dfa013e8..bef0a8585 100644 --- a/monkey/monkey_island/cc/resources/attack_telem.py +++ b/monkey/monkey_island/cc/resources/attack_telem.py @@ -1,7 +1,7 @@ import flask_restful from flask import request import json -from cc.services.attack.attack_telem import set_results +from monkey_island.cc.services.attack.attack_telem import set_results import logging __author__ = 'VakarisZ' diff --git a/monkey/monkey_island/cc/resources/aws_exporter.py b/monkey/monkey_island/cc/resources/aws_exporter.py index 9b820cf51..b08c16ae6 100644 --- a/monkey/monkey_island/cc/resources/aws_exporter.py +++ b/monkey/monkey_island/cc/resources/aws_exporter.py @@ -4,9 +4,9 @@ from datetime import datetime import boto3 from botocore.exceptions import UnknownServiceError -from cc.resources.exporter import Exporter -from cc.services.config import ConfigService -from cc.environment.environment import load_server_configuration_from_file +from monkey_island.cc.resources.exporter import Exporter +from monkey_island.cc.services.config import ConfigService +from monkey_island.cc.environment.environment import load_server_configuration_from_file from common.cloud.aws_instance import AwsInstance __author__ = 'maor.rayzin' diff --git a/monkey/monkey_island/cc/resources/client_run.py b/monkey/monkey_island/cc/resources/client_run.py index 0e4be42e7..4b2c03105 100644 --- a/monkey/monkey_island/cc/resources/client_run.py +++ b/monkey/monkey_island/cc/resources/client_run.py @@ -2,7 +2,7 @@ import logging from flask import request, jsonify import flask_restful -from cc.services.node import NodeService +from monkey_island.cc.services.node import NodeService __author__ = 'itay.mizeretz' diff --git a/monkey/monkey_island/cc/resources/edge.py b/monkey/monkey_island/cc/resources/edge.py index 2ef0c15bc..f3ce94ee3 100644 --- a/monkey/monkey_island/cc/resources/edge.py +++ b/monkey/monkey_island/cc/resources/edge.py @@ -1,7 +1,7 @@ from flask import request import flask_restful -from cc.services.edge import EdgeService +from monkey_island.cc.services.edge import EdgeService __author__ = 'Barak' diff --git a/monkey/monkey_island/cc/resources/island_configuration.py b/monkey/monkey_island/cc/resources/island_configuration.py index 57fda34fe..28ef32c46 100644 --- a/monkey/monkey_island/cc/resources/island_configuration.py +++ b/monkey/monkey_island/cc/resources/island_configuration.py @@ -3,8 +3,8 @@ import json import flask_restful from flask import request, jsonify, abort -from cc.auth import jwt_required -from cc.services.config import ConfigService +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.services.config import ConfigService class IslandConfiguration(flask_restful.Resource): diff --git a/monkey/monkey_island/cc/resources/island_logs.py b/monkey/monkey_island/cc/resources/island_logs.py index 971306c14..724087e52 100644 --- a/monkey/monkey_island/cc/resources/island_logs.py +++ b/monkey/monkey_island/cc/resources/island_logs.py @@ -2,8 +2,8 @@ import logging import flask_restful -from cc.auth import jwt_required -from cc.services.island_logs import IslandLogService +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.services.island_logs import IslandLogService __author__ = "Maor.Rayzin" diff --git a/monkey/monkey_island/cc/resources/local_run.py b/monkey/monkey_island/cc/resources/local_run.py index 6e7d44cb9..d402a440c 100644 --- a/monkey/monkey_island/cc/resources/local_run.py +++ b/monkey/monkey_island/cc/resources/local_run.py @@ -6,16 +6,18 @@ import sys from flask import request, jsonify, make_response import flask_restful -from cc.environment.environment import env -from cc.resources.monkey_download import get_monkey_executable -from cc.services.node import NodeService -from cc.utils import local_ip_addresses +from monkey_island.cc.environment.environment import env +from monkey_island.cc.resources.monkey_download import get_monkey_executable +from monkey_island.cc.services.node import NodeService +from monkey_island.cc.utils import local_ip_addresses +from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH __author__ = 'Barak' import logging logger = logging.getLogger(__name__) + def run_local_monkey(): import platform import subprocess @@ -26,8 +28,8 @@ def run_local_monkey(): if not result: return False, "OS Type not found" - monkey_path = os.path.join(os.getcwd(), 'monkey_island', 'cc', 'binaries', result['filename']) - target_path = os.path.join(os.getcwd(), 'monkey_island', result['filename']) + monkey_path = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'binaries', result['filename']) + target_path = os.path.join(MONKEY_ISLAND_ABS_PATH, result['filename']) # copy the executable to temp path (don't run the monkey from its current location as it may delete itself) try: diff --git a/monkey/monkey_island/cc/resources/log.py b/monkey/monkey_island/cc/resources/log.py index 62dee1168..cbce92a37 100644 --- a/monkey/monkey_island/cc/resources/log.py +++ b/monkey/monkey_island/cc/resources/log.py @@ -4,10 +4,10 @@ import flask_restful from bson import ObjectId from flask import request -from cc.auth import jwt_required -from cc.database import mongo -from cc.services.log import LogService -from cc.services.node import NodeService +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.database import mongo +from monkey_island.cc.services.log import LogService +from monkey_island.cc.services.node import NodeService __author__ = "itay.mizeretz" diff --git a/monkey/monkey_island/cc/resources/monkey.py b/monkey/monkey_island/cc/resources/monkey.py index 80dd14604..7eb7ecc69 100644 --- a/monkey/monkey_island/cc/resources/monkey.py +++ b/monkey/monkey_island/cc/resources/monkey.py @@ -5,9 +5,9 @@ import dateutil.parser from flask import request import flask_restful -from cc.database import mongo -from cc.services.config import ConfigService -from cc.services.node import NodeService +from monkey_island.cc.database import mongo +from monkey_island.cc.services.config import ConfigService +from monkey_island.cc.services.node import NodeService __author__ = 'Barak' diff --git a/monkey/monkey_island/cc/resources/monkey_configuration.py b/monkey/monkey_island/cc/resources/monkey_configuration.py index 7032ba643..1c067892f 100644 --- a/monkey/monkey_island/cc/resources/monkey_configuration.py +++ b/monkey/monkey_island/cc/resources/monkey_configuration.py @@ -3,8 +3,8 @@ import json import flask_restful from flask import request, jsonify, abort -from cc.auth import jwt_required -from cc.services.config import ConfigService +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.services.config import ConfigService __author__ = 'Barak' diff --git a/monkey/monkey_island/cc/resources/monkey_download.py b/monkey/monkey_island/cc/resources/monkey_download.py index 305d8c6e9..78a092a26 100644 --- a/monkey/monkey_island/cc/resources/monkey_download.py +++ b/monkey/monkey_island/cc/resources/monkey_download.py @@ -5,6 +5,8 @@ import os import flask_restful from flask import request, send_from_directory +from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH + __author__ = 'Barak' logger = logging.getLogger(__name__) @@ -70,7 +72,7 @@ class MonkeyDownload(flask_restful.Resource): # Used by monkey. can't secure. def get(self, path): - return send_from_directory('binaries', path) + return send_from_directory(os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'binaries'), path) # Used by monkey. can't secure. def post(self): @@ -81,7 +83,7 @@ class MonkeyDownload(flask_restful.Resource): if result: # change resulting from new base path - real_path = os.path.join("monkey_island", "cc", 'binaries', result['filename']) + real_path = os.path.join(MONKEY_ISLAND_ABS_PATH, "cc", 'binaries', result['filename']) if os.path.isfile(real_path): result['size'] = os.path.getsize(real_path) return result diff --git a/monkey/monkey_island/cc/resources/netmap.py b/monkey/monkey_island/cc/resources/netmap.py index 3ba7fafa8..ed83414f5 100644 --- a/monkey/monkey_island/cc/resources/netmap.py +++ b/monkey/monkey_island/cc/resources/netmap.py @@ -1,9 +1,9 @@ import flask_restful -from cc.auth import jwt_required -from cc.services.edge import EdgeService -from cc.services.node import NodeService -from cc.database import mongo +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.services.edge import EdgeService +from monkey_island.cc.services.node import NodeService +from monkey_island.cc.database import mongo __author__ = 'Barak' diff --git a/monkey/monkey_island/cc/resources/node.py b/monkey/monkey_island/cc/resources/node.py index bc00c40cf..e4c2761c9 100644 --- a/monkey/monkey_island/cc/resources/node.py +++ b/monkey/monkey_island/cc/resources/node.py @@ -1,8 +1,8 @@ from flask import request import flask_restful -from cc.auth import jwt_required -from cc.services.node import NodeService +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.services.node import NodeService __author__ = 'Barak' diff --git a/monkey/monkey_island/cc/resources/pba_file_download.py b/monkey/monkey_island/cc/resources/pba_file_download.py index b4a33984e..5b567e8e4 100644 --- a/monkey/monkey_island/cc/resources/pba_file_download.py +++ b/monkey/monkey_island/cc/resources/pba_file_download.py @@ -1,6 +1,6 @@ import flask_restful from flask import send_from_directory -from cc.resources.pba_file_upload import GET_FILE_DIR +from monkey_island.cc.resources.pba_file_upload import GET_FILE_DIR __author__ = 'VakarisZ' diff --git a/monkey/monkey_island/cc/resources/pba_file_upload.py b/monkey/monkey_island/cc/resources/pba_file_upload.py index 9a24a9a90..0d924a742 100644 --- a/monkey/monkey_island/cc/resources/pba_file_upload.py +++ b/monkey/monkey_island/cc/resources/pba_file_upload.py @@ -1,8 +1,8 @@ import flask_restful from flask import request, send_from_directory, Response -from cc.services.config import ConfigService -from cc.services.post_breach_files import PBA_WINDOWS_FILENAME_PATH, PBA_LINUX_FILENAME_PATH, UPLOADS_DIR -from cc.auth import jwt_required +from monkey_island.cc.services.config import ConfigService +from monkey_island.cc.services.post_breach_files import PBA_WINDOWS_FILENAME_PATH, PBA_LINUX_FILENAME_PATH, UPLOADS_DIR +from monkey_island.cc.auth import jwt_required import os from werkzeug.utils import secure_filename import logging diff --git a/monkey/monkey_island/cc/resources/remote_run.py b/monkey/monkey_island/cc/resources/remote_run.py index 5484d23d2..ccd9fbbbe 100644 --- a/monkey/monkey_island/cc/resources/remote_run.py +++ b/monkey/monkey_island/cc/resources/remote_run.py @@ -2,8 +2,8 @@ import json from flask import request, jsonify, make_response import flask_restful -from cc.auth import jwt_required -from cc.services.remote_run_aws import RemoteRunAwsService +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService from common.cloud.aws_service import AwsService diff --git a/monkey/monkey_island/cc/resources/report.py b/monkey/monkey_island/cc/resources/report.py index 1a00fa609..62a014fef 100644 --- a/monkey/monkey_island/cc/resources/report.py +++ b/monkey/monkey_island/cc/resources/report.py @@ -1,7 +1,7 @@ import flask_restful -from cc.auth import jwt_required -from cc.services.report import ReportService +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.services.report import ReportService __author__ = "itay.mizeretz" diff --git a/monkey/monkey_island/cc/resources/root.py b/monkey/monkey_island/cc/resources/root.py index 923535096..828a97682 100644 --- a/monkey/monkey_island/cc/resources/root.py +++ b/monkey/monkey_island/cc/resources/root.py @@ -4,13 +4,13 @@ import logging import flask_restful from flask import request, make_response, jsonify -from cc.auth import jwt_required -from cc.database import mongo -from cc.services.config import ConfigService -from cc.services.node import NodeService -from cc.services.report import ReportService -from cc.utils import local_ip_addresses -from cc.services.post_breach_files import remove_PBA_files +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.database import mongo +from monkey_island.cc.services.config import ConfigService +from monkey_island.cc.services.node import NodeService +from monkey_island.cc.services.report import ReportService +from monkey_island.cc.utils import local_ip_addresses +from monkey_island.cc.services.post_breach_files import remove_PBA_files __author__ = 'Barak' diff --git a/monkey/monkey_island/cc/resources/telemetry.py b/monkey/monkey_island/cc/resources/telemetry.py index 3e2824d3b..04a6ddbd1 100644 --- a/monkey/monkey_island/cc/resources/telemetry.py +++ b/monkey/monkey_island/cc/resources/telemetry.py @@ -7,14 +7,14 @@ import dateutil import flask_restful from flask import request -from cc.auth import jwt_required -from cc.database import mongo -from cc.services import mimikatz_utils -from cc.services.config import ConfigService -from cc.services.edge import EdgeService -from cc.services.node import NodeService -from cc.encryptor import encryptor -from cc.services.wmi_handler import WMIHandler +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.database import mongo +from monkey_island.cc.services import mimikatz_utils +from monkey_island.cc.services.config import ConfigService +from monkey_island.cc.services.edge import EdgeService +from monkey_island.cc.services.node import NodeService +from monkey_island.cc.encryptor import encryptor +from monkey_island.cc.services.wmi_handler import WMIHandler __author__ = 'Barak' diff --git a/monkey/monkey_island/cc/resources/telemetry_feed.py b/monkey/monkey_island/cc/resources/telemetry_feed.py index 8286bba00..f01ff90d6 100644 --- a/monkey/monkey_island/cc/resources/telemetry_feed.py +++ b/monkey/monkey_island/cc/resources/telemetry_feed.py @@ -5,9 +5,9 @@ import flask_restful from flask import request import flask_pymongo -from cc.auth import jwt_required -from cc.database import mongo -from cc.services.node import NodeService +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.database import mongo +from monkey_island.cc.services.node import NodeService __author__ = 'itay.mizeretz' diff --git a/monkey/monkey_island/cc/services/attack/attack_telem.py b/monkey/monkey_island/cc/services/attack/attack_telem.py index 295100c23..a4e219270 100644 --- a/monkey/monkey_island/cc/services/attack/attack_telem.py +++ b/monkey/monkey_island/cc/services/attack/attack_telem.py @@ -2,7 +2,7 @@ File that contains ATT&CK telemetry storing/retrieving logic """ import logging -from cc.database import mongo +from monkey_island.cc.database import mongo __author__ = "VakarisZ" diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index 87b4bf914..171fbb7bf 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -4,12 +4,12 @@ import functools import logging from jsonschema import Draft4Validator, validators from six import string_types -import cc.services.post_breach_files +import monkey_island.cc.services.post_breach_files -from cc.database import mongo -from cc.encryptor import encryptor -from cc.environment.environment import env -from cc.utils import local_ip_addresses +from monkey_island.cc.database import mongo +from monkey_island.cc.encryptor import encryptor +from monkey_island.cc.environment.environment import env +from monkey_island.cc.utils import local_ip_addresses from config_schema import SCHEMA __author__ = "itay.mizeretz" @@ -146,7 +146,7 @@ class ConfigService: @staticmethod def update_config(config_json, should_encrypt): # PBA file upload happens on pba_file_upload endpoint and corresponding config options are set there - cc.services.post_breach_files.set_config_PBA_files(config_json) + monkey_island.cc.services.post_breach_files.set_config_PBA_files(config_json) if should_encrypt: try: ConfigService.encrypt_config(config_json) @@ -182,7 +182,7 @@ class ConfigService: @staticmethod def reset_config(): - cc.services.post_breach_files.remove_PBA_files() + monkey_island.cc.services.post_breach_files.remove_PBA_files() config = ConfigService.get_default_config(True) ConfigService.set_server_ips_in_config(config) ConfigService.update_config(config, should_encrypt=False) diff --git a/monkey/monkey_island/cc/services/edge.py b/monkey/monkey_island/cc/services/edge.py index 520808be8..eb23c3901 100644 --- a/monkey/monkey_island/cc/services/edge.py +++ b/monkey/monkey_island/cc/services/edge.py @@ -1,7 +1,7 @@ from bson import ObjectId -from cc.database import mongo -import cc.services.node +from monkey_island.cc.database import mongo +import monkey_island.cc.services.node __author__ = "itay.mizeretz" @@ -87,7 +87,7 @@ class EdgeService: @staticmethod def get_infected_monkey_island_pseudo_edges(): - monkey = cc.services.node.NodeService.get_monkey_island_monkey() + monkey = monkey_island.cc.services.node.NodeService.get_monkey_island_monkey() existing_ids = [x["from"] for x in mongo.db.edge.find({"to": monkey["_id"]})] monkey_ids = [x["_id"] for x in mongo.db.monkey.find({}) if ("tunnel" not in x) and (x["_id"] not in existing_ids) and (x["_id"] != monkey["_id"])] @@ -136,11 +136,11 @@ class EdgeService: {"_id": edge["_id"]}, {"$set": {"exploited": True}} ) - cc.services.node.NodeService.set_node_exploited(edge["to"]) + monkey_island.cc.services.node.NodeService.set_node_exploited(edge["to"]) @staticmethod def get_edge_label(edge): - NodeService = cc.services.node.NodeService + NodeService = monkey_island.cc.services.node.NodeService from_label = NodeService.get_monkey_label(NodeService.get_monkey_by_id(edge["from"])) if edge["to"] == ObjectId("000000000000000000000000"): to_label = 'MonkeyIsland' diff --git a/monkey/monkey_island/cc/services/log.py b/monkey/monkey_island/cc/services/log.py index 81603e62e..a685e45b6 100644 --- a/monkey/monkey_island/cc/services/log.py +++ b/monkey/monkey_island/cc/services/log.py @@ -1,7 +1,7 @@ from datetime import datetime -import cc.services.node -from cc.database import mongo, database +import monkey_island.cc.services.node +from monkey_island.cc.database import mongo, database __author__ = "itay.mizeretz" @@ -15,8 +15,8 @@ class LogService: log = mongo.db.log.find_one({'monkey_id': monkey_id}) if log: log_file = database.gridfs.get(log['file_id']) - monkey_label = cc.services.node.NodeService.get_monkey_label( - cc.services.node.NodeService.get_monkey_by_id(log['monkey_id'])) + monkey_label = monkey_island.cc.services.node.NodeService.get_monkey_label( + monkey_island.cc.services.node.NodeService.get_monkey_by_id(log['monkey_id'])) return \ { 'monkey_label': monkey_label, diff --git a/monkey/monkey_island/cc/services/node.py b/monkey/monkey_island/cc/services/node.py index b2a264f33..fa500aab5 100644 --- a/monkey/monkey_island/cc/services/node.py +++ b/monkey/monkey_island/cc/services/node.py @@ -2,10 +2,10 @@ from datetime import datetime, timedelta from bson import ObjectId -import cc.services.log -from cc.database import mongo -from cc.services.edge import EdgeService -from cc.utils import local_ip_addresses +import monkey_island.cc.services.log +from monkey_island.cc.database import mongo +from monkey_island.cc.services.edge import EdgeService +from monkey_island.cc.utils import local_ip_addresses import socket __author__ = "itay.mizeretz" @@ -59,7 +59,7 @@ class NodeService: else: new_node["services"] = [] - new_node['has_log'] = cc.services.log.LogService.log_exists(ObjectId(node_id)) + new_node['has_log'] = monkey_island.cc.services.log.LogService.log_exists(ObjectId(node_id)) return new_node @staticmethod diff --git a/monkey/monkey_island/cc/services/post_breach_files.py b/monkey/monkey_island/cc/services/post_breach_files.py index 076fa7159..7d88d9d85 100644 --- a/monkey/monkey_island/cc/services/post_breach_files.py +++ b/monkey/monkey_island/cc/services/post_breach_files.py @@ -1,4 +1,4 @@ -import cc.services.config +import monkey_island.cc.services.config import logging import os @@ -13,9 +13,9 @@ UPLOADS_DIR = 'monkey_island/cc/userUploads' def remove_PBA_files(): - if cc.services.config.ConfigService.get_config(): - windows_filename = cc.services.config.ConfigService.get_config_value(PBA_WINDOWS_FILENAME_PATH) - linux_filename = cc.services.config.ConfigService.get_config_value(PBA_LINUX_FILENAME_PATH) + if monkey_island.cc.services.config.ConfigService.get_config(): + windows_filename = monkey_island.cc.services.config.ConfigService.get_config_value(PBA_WINDOWS_FILENAME_PATH) + linux_filename = monkey_island.cc.services.config.ConfigService.get_config_value(PBA_LINUX_FILENAME_PATH) if linux_filename: remove_file(linux_filename) if windows_filename: @@ -36,8 +36,8 @@ def set_config_PBA_files(config_json): Sets PBA file info in config_json to current config's PBA file info values. :param config_json: config_json that will be modified """ - if cc.services.config.ConfigService.get_config(): - linux_filename = cc.services.config.ConfigService.get_config_value(PBA_LINUX_FILENAME_PATH) - windows_filename = cc.services.config.ConfigService.get_config_value(PBA_WINDOWS_FILENAME_PATH) + if monkey_island.cc.services.config.ConfigService.get_config(): + linux_filename = monkey_island.cc.services.config.ConfigService.get_config_value(PBA_LINUX_FILENAME_PATH) + windows_filename = monkey_island.cc.services.config.ConfigService.get_config_value(PBA_WINDOWS_FILENAME_PATH) config_json['monkey']['behaviour']['PBA_linux_filename'] = linux_filename config_json['monkey']['behaviour']['PBA_windows_filename'] = windows_filename diff --git a/monkey/monkey_island/cc/services/pth_report.py b/monkey/monkey_island/cc/services/pth_report.py index 3d7375dc1..93fd51989 100644 --- a/monkey/monkey_island/cc/services/pth_report.py +++ b/monkey/monkey_island/cc/services/pth_report.py @@ -1,10 +1,10 @@ from itertools import product -from cc.database import mongo +from monkey_island.cc.database import mongo from bson import ObjectId -from cc.services.groups_and_users_consts import USERTYPE -from cc.services.node import NodeService +from monkey_island.cc.services.groups_and_users_consts import USERTYPE +from monkey_island.cc.services.node import NodeService __author__ = 'maor.rayzin' diff --git a/monkey/monkey_island/cc/services/remote_run_aws.py b/monkey/monkey_island/cc/services/remote_run_aws.py index 0310cd9f9..7cc26008d 100644 --- a/monkey/monkey_island/cc/services/remote_run_aws.py +++ b/monkey/monkey_island/cc/services/remote_run_aws.py @@ -1,4 +1,4 @@ -from cc.services.config import ConfigService +from monkey_island.cc.services.config import ConfigService from common.cloud.aws_instance import AwsInstance from common.cloud.aws_service import AwsService from common.cmd.aws.aws_cmd_runner import AwsCmdRunner diff --git a/monkey/monkey_island/cc/services/report.py b/monkey/monkey_island/cc/services/report.py index 595d566f8..a19dc03c0 100644 --- a/monkey/monkey_island/cc/services/report.py +++ b/monkey/monkey_island/cc/services/report.py @@ -9,12 +9,12 @@ from enum import Enum from six import text_type -from cc.database import mongo -from cc.report_exporter_manager import ReportExporterManager -from cc.services.config import ConfigService -from cc.services.edge import EdgeService -from cc.services.node import NodeService -from cc.utils import local_ip_addresses, get_subnets +from monkey_island.cc.database import mongo +from monkey_island.cc.report_exporter_manager import ReportExporterManager +from monkey_island.cc.services.config import ConfigService +from monkey_island.cc.services.edge import EdgeService +from monkey_island.cc.services.node import NodeService +from monkey_island.cc.utils import local_ip_addresses, get_subnets from pth_report import PTHReportService from common.network.network_range import NetworkRange diff --git a/monkey/monkey_island/cc/services/wmi_handler.py b/monkey/monkey_island/cc/services/wmi_handler.py index fec12c152..227bd18da 100644 --- a/monkey/monkey_island/cc/services/wmi_handler.py +++ b/monkey/monkey_island/cc/services/wmi_handler.py @@ -1,5 +1,5 @@ -from cc.database import mongo -from cc.services.groups_and_users_consts import USERTYPE, GROUPTYPE +from monkey_island.cc.database import mongo +from monkey_island.cc.services.groups_and_users_consts import USERTYPE, GROUPTYPE __author__ = 'maor.rayzin' diff --git a/monkey/monkey_island/monkey_island.ico b/monkey/monkey_island/monkey_island.ico new file mode 100644 index 0000000000000000000000000000000000000000..0a9976256ebb3e9bafe05e6208e233a02b63e5d8 GIT binary patch literal 110568 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 literal 0 HcmV?d00001 diff --git a/monkey/monkey_island/monkey_island.spec b/monkey/monkey_island/monkey_island.spec new file mode 100644 index 000000000..342df5ab3 --- /dev/null +++ b/monkey/monkey_island/monkey_island.spec @@ -0,0 +1,93 @@ +# -*- mode: python -*- +import os +import platform + + +__author__ = 'itay.mizeretz' + +block_cipher = None + + +def main(): + a = Analysis(['cc/main.py'], + pathex=['..'], + hiddenimports=get_hidden_imports(), + hookspath=None, + runtime_hooks=None, + binaries=None, + datas=None, + excludes=None, + win_no_prefer_redirects=None, + win_private_assemblies=None, + cipher=block_cipher + ) + + a.binaries += get_binaries() + a.datas = process_datas(a.datas) + + pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) + exe = EXE(pyz, + a.scripts, + a.binaries, + a.zipfiles, + a.datas, + name=get_monkey_filename(), + debug=False, + strip=get_exe_strip(), + upx=True, + console=True, + icon=get_exe_icon()) + + +def is_windows(): + return platform.system().find("Windows") >= 0 + + +def is_32_bit(): + return platform.architecture()[0] == "32bit" + + +def process_datas(orig_datas): + datas = orig_datas + if is_windows(): + datas = [i for i in datas if i[0].find('Include') < 0] + return datas + + +def get_binaries(): + binaries = get_windows_only_binaries() if is_windows() else get_linux_only_binaries() + return binaries + + +def get_windows_only_binaries(): + binaries = [] + binaries += get_msvcr() + return binaries + + +def get_linux_only_binaries(): + binaries = [] + return binaries + + +def get_hidden_imports(): + return ['_cffi_backend', 'queue'] if is_windows() else ['_cffi_backend'] + + +def get_msvcr(): + return [('msvcr100.dll', os.environ['WINDIR'] + '\\system32\\msvcr100.dll', 'BINARY')] + + +def get_monkey_filename(): + return 'monkey_island.exe' if is_windows() else 'monkey_island' + + +def get_exe_strip(): + return not is_windows() + + +def get_exe_icon(): + return 'monkey_island.ico' if is_windows() else None + + +main() # We don't check if __main__ because this isn't the main script. diff --git a/monkey/monkey_island/requirements.txt b/monkey/monkey_island/requirements.txt index b910f87cb..147f3481c 100644 --- a/monkey/monkey_island/requirements.txt +++ b/monkey/monkey_island/requirements.txt @@ -9,11 +9,13 @@ flask Flask-Pymongo Flask-Restful Flask-JWT -jsonschema +jsonschema==2.6.0 netifaces ipaddress enum34 pycryptodome boto3 awscli -bson \ No newline at end of file +bson +cffi +PyInstaller \ No newline at end of file diff --git a/monkey/monkey_island/windows/build_pyinstaller.bat b/monkey/monkey_island/windows/build_pyinstaller.bat new file mode 100644 index 000000000..58ec101d0 --- /dev/null +++ b/monkey/monkey_island/windows/build_pyinstaller.bat @@ -0,0 +1,5 @@ +REM - Builds Monkey Island Server EXE using pyinstaller - +bin\Python27\Scripts\pyinstaller.exe -F --log-level=DEBUG --clean --upx-dir=.\bin monkey_island.spec +move /Y dist\monkey_island.exe monkey_island.exe +rmdir /S /Q build +rmdir /S /Q dist \ No newline at end of file diff --git a/monkey/monkey_island/windows/run_cc.bat b/monkey/monkey_island/windows/run_cc.bat index f674376a1..c1a2fd88e 100644 --- a/monkey/monkey_island/windows/run_cc.bat +++ b/monkey/monkey_island/windows/run_cc.bat @@ -1,3 +1,4 @@ +REM - Runs Monkey Island Server using python - @title C^&C Server @pushd .. @monkey_island\bin\Python27\Scripts\python monkey_island.py diff --git a/monkey/monkey_island/windows/run_cc_exe.bat b/monkey/monkey_island/windows/run_cc_exe.bat new file mode 100644 index 000000000..a8b2cb14b --- /dev/null +++ b/monkey/monkey_island/windows/run_cc_exe.bat @@ -0,0 +1,5 @@ +REM - Runs Monkey Island Server using built pyinstaller EXE - +@title C^&C Server +@pushd .. +@monkey_island\monkey_island.exe +@popd \ No newline at end of file diff --git a/monkey/monkey_island/windows/run_mongodb.bat b/monkey/monkey_island/windows/run_mongodb.bat index ca33c22d7..970e98874 100644 --- a/monkey/monkey_island/windows/run_mongodb.bat +++ b/monkey/monkey_island/windows/run_mongodb.bat @@ -1,2 +1,3 @@ +REM - Runs MongoDB Server - @title MongoDB @bin\mongodb\mongod.exe --dbpath db \ No newline at end of file diff --git a/monkey/monkey_island/windows/run_server.bat b/monkey/monkey_island/windows/run_server.bat index a15fbcc04..ab2ad274c 100644 --- a/monkey/monkey_island/windows/run_server.bat +++ b/monkey/monkey_island/windows/run_server.bat @@ -1,4 +1,5 @@ +REM - Runs MongoDB Server & Monkey Island Server using built pyinstaller EXE - if not exist db mkdir db start windows\run_mongodb.bat -start windows\run_cc.bat +start windows\run_cc_exe.bat start https://localhost:5000 \ No newline at end of file diff --git a/monkey/monkey_island/windows/run_server_py.bat b/monkey/monkey_island/windows/run_server_py.bat new file mode 100644 index 000000000..07a587f49 --- /dev/null +++ b/monkey/monkey_island/windows/run_server_py.bat @@ -0,0 +1,5 @@ +REM - Runs MongoDB Server & Monkey Island Server using python - +if not exist db mkdir db +start windows\run_mongodb.bat +start windows\run_cc.bat +start https://localhost:5000 \ No newline at end of file