# Conflicts:
#	chaos_monkey/example.conf
This commit is contained in:
acepace 2016-08-03 09:24:55 +03:00
commit 2ed7cc359e
17 changed files with 297 additions and 46 deletions

View File

@ -1,12 +1,14 @@
Infection Monkey Infection Monkey
==================== ====================
Datacenter Security Tool ### Data center Security Testing Tool
------------------------ ------------------------
### http://www.guardicore.com/the-infected-chaos-monkey/ Welcome to the Infection Monkey!
The Infection Monkey is a security tool which tests your Data Center's ability to withstand perimeter breaches and internal server infection. It uses various methods to propagate through a data center, and reports its success to a centralized C&C server. The Infection Monkey is an open source security tool for testing a data center's resiliency to perimeter breaches and internal server infection. The Monkey uses various methods to self propagate across a data center and reports success to a centralized C&C server. To read more about the Monkey, visit https://www.guardicore.com/infectionmonkey/
### http://www.guardicore.com/the-infected-chaos-monkey/
Features include: Features include:
@ -32,52 +34,52 @@ The Monkey itself has been tested on Windows XP, 7, 8.1 and 10. The Linux build
### Installation ### Installation
For off the shelf use, download our pre-compiled binaries from our website, to setup the C&C server follow the instructions in [Monkey Island readme](monkey_island/readme.txt). If you with to compile the binaries yourself, follow the build instructions later on in this readme. For off-the-shelf use, download our pre-compiled binaries from our website. To set up the C&C server follow the instructions on [Monkey Island readme](monkey_island/readme.txt). If you wish to compile the binaries yourself, follow the instructions under Building the Monkey from Source.
### Initial configuration. ### Initial configuration.
Whether by downloading or building from source, the Infection Monkey is basically 4 executable files for different platforms and a default configuration file. Whether you're downloading or building the Monkey from source, the Infection Monkey is comprised of 4 executable files for different platforms plus a default configuration file.
Monkey configuration is stored in two places: Monkey configuration is stored in two places:
1. By default, the monkey uses a local configuration file (usually, config.bin). This configuration file must include the address of the Monkey's C&C server. 1. By default, the Monkey uses a local configuration file (usually, config.bin). This configuration file must include the address of the Monkey's C&C server.
2. After successfully connecting to the C&C server, the monkey downloads a new configuration from the server and discards the local configuration. It is possible to change the default configuration from the C&C server's UI. 2. After successfully connecting to the C&C server, the monkey downloads a new configuration from the server and discards the local configuration. It is possible to change the default configuration from the C&C server's UI.
In both cases the command server hostname should be modified to point at your local instance of the Monkey Island (note this doesn't require connectivity right off the bat). In addition, to improve the Monkey's chances of spreading, you can pre-seed it with credentials and usernames commonly used. In both cases the command server hostname should be modified to point to your local instance of the Monkey Island (note that this doesn't require connectivity right off the bat). In addition, to improve the Monkey's chances of spreading, you can pre-seed it with credentials and usernames commonly used.
Both configuration options use a JSON format for specifying options; see "Options" below for details. Both configuration options use a JSON format for specifying options; see "Options" below for details.
### Running the C&C Server ### Running the C&C Server
Running the C&C Server is as simple as installing our infected monkey debian package on a specific server. The initial infected machine doesn not require a direct link to this server. To run the C&C Server, install our infected Monkey debian package on a specific server. The initial infected machine doesn't require a direct link to this server.
### Unleashing the Monkey ### Unleashing the Monkey
Once configured, run the monkey using ```./monkey-linux-64 m0nk3y -c config.bin -s 41.50.73.31:5000``` (Windows is identical). This can be done at multiple points in the network at once. Once configured, run the monkey using ```./monkey-linux-64 m0nk3y -c config.bin -s 41.50.73.31:5000``` (Windows is identical). This can be done at multiple points in the network simultaneously.
Command line options include: Command line options include:
* `-c`, `--config`: set configuration file. JSON file with configuration values, will override compiled configuration. * `-c`, `--config`: set configuration file. JSON file with configuration values, will override compiled configuration.
* `-p`, `--parent`: set monkeys parent uuid, allows better recognition of exploited monkeys in c&c * `-p`, `--parent`: set monkeys parent uuid, allows better recognition of exploited monkeys in c&c
* `-t`, `--tunnel`: ip:port, set default tunnel for monkey when connecting to c&c. * `-t`, `--tunnel`: ip:port, set default tunnel for Monkey when connecting to c&c.
* `-d`, `--depth` : sets the monkeys current operation depth. * `-d`, `--depth` : sets the Monkey's current operation depth.
Monkey Modus Operandi How the Monkey works
--------------------- ---------------------
1. Wakeup connection to c&c, sends basic info of the current machine and the configuration the monkey uses to the c&c. 1. Wakeup connection to c&c, sends basic info of the current machine and the configuration the monkey uses to the c&c.
1. First try direct connection to c&c. 1. First try direct connection to c&c.
2. If direct connection fails, try connection through a tunnel, a tunnel is found according to specified parameter (the default tunnel) or by sending a multicast query and waiting for another monkey to answer. 2. If direct connection fails, try connection through a tunnel, a tunnel is found according to specified parameter (the default tunnel) or by sending a multicast query and waiting for another monkey to answer.
3. If no connection can be made to c&c, continue without it. 3. If no connection can be made to c&c, continue without it.
2. If a firewall app is running on the machine (supports Windows Firewall for Win XP and Windows Advanced Firewall for Win 7+), try to add a rule to allow all our traffic. 2. If a firewall app is running on the machine (supports Windows Firewall for Win XP and Windows Advanced Firewall for Win 7+), try to add a rule to allow all our traffic.
3. Startup of tunnel for other monkeys (if connection to c&c works). 3. Startup of tunnel for other Monkeys (if connection to c&c works).
1. firewall is checked to allow listening sockets (if we failed to add a rule to windows firewall for example, the tunnel will not be created) 1. Firewall is checked to allow listening sockets (if we failed to add a rule to Windows firewall for example, the tunnel will not be created)
2. will answer multicast requests from other monkeys in search of a tunnel. 2. Will answer multicast requests from other Monkeys in search of a tunnel.
4. Running exploitation sessions, will run x sessions according to configuration: 4. Running exploitation sessions, will run x sessions according to configuration:
1. Connect to c&c and get the latest configuration 1. Connect to c&c and get the latest configuration
2. Scan ip ranges according to configuration. 2. Scan ip ranges according to configuration.
3. Try fingerprinting each host that answer, using the classes defined in the configuration (SMBFinger, SSHFinger, etc) 3. Try fingerprinting each host that answers, using the classes defined in the configuration (SMBFinger, SSHFinger, etc)
4. Try exploitation on each host found, for each exploit class in configuration: 4. Try exploitation on each host found, for each exploit class in configuration:
1. check exploit class supports target host (can be disabled by configuration) 1. check exploit class supports target host (can be disabled by configuration)
2. each exploitation class will use the data acquired in fingerprinting, or during the exploit, to find the suitable monkey executable for the host from the c&c. 2. each exploitation class will use the data acquired in fingerprinting, or during the exploit, to find the suitable Monkey executable for the host from the c&c.
1. If c&c connection fails, and the source monkeys executable is suitable, we use it. 1. If c&c connection fails, and the source monkeys executable is suitable, we use it.
2. If a suitable executable isnt found, exploitation will fail. 2. If a suitable executable isnt found, exploitation will fail.
3. Executables are cached in memory. 3. Executables are cached in memory.
@ -129,7 +131,7 @@ ssh_passwords | list of strings | list of passwords to use when trying to exploi
Building the Monkey from source Building the Monkey from source
------------------------------- -------------------------------
If you want to build the monkey from source and not use our provided packages, look at the readme files under [chaos_monkey](chaos_monkey) and [monkey_island](monkey_island). If you want to build the monkey from source instead of using our provided packages, follow the instructions at the readme files under [chaos_monkey](chaos_monkey) and [monkey_island](monkey_island).
License License

View File

@ -51,6 +51,8 @@ class Configuration(object):
continue continue
if key in ["name", "id", "current_server"]: if key in ["name", "id", "current_server"]:
continue continue
if self._depth_from_commandline and key=="depth":
continue
try: try:
default_value = getattr(Configuration, key) default_value = getattr(Configuration, key)
except AttributeError: except AttributeError:
@ -83,6 +85,8 @@ class Configuration(object):
return result return result
_depth_from_commandline = False
########################### ###########################
# logging config # logging config
########################### ###########################

View File

@ -22,7 +22,7 @@ class ControlClient(object):
proxies = {} proxies = {}
@staticmethod @staticmethod
def wakeup(parent=None, default_tunnel=None): def wakeup(parent=None, default_tunnel=None, has_internet_access=None):
LOG.debug("Trying to wake up with C&C servers list: %r" % WormConfiguration.command_servers) LOG.debug("Trying to wake up with C&C servers list: %r" % WormConfiguration.command_servers)
if parent or default_tunnel: if parent or default_tunnel:
LOG.debug("parent: %s, default_tunnel: %s" % (parent, default_tunnel)) LOG.debug("parent: %s, default_tunnel: %s" % (parent, default_tunnel))
@ -30,6 +30,9 @@ class ControlClient(object):
if not parent: if not parent:
parent = GUID parent = GUID
if has_internet_access is None:
has_internet_access = check_internet_access(WormConfiguration.internet_services)
for server in WormConfiguration.command_servers: for server in WormConfiguration.command_servers:
try: try:
WormConfiguration.current_server = server WormConfiguration.current_server = server
@ -38,7 +41,7 @@ class ControlClient(object):
'hostname': hostname, 'hostname': hostname,
'ip_addresses': local_ips(), 'ip_addresses': local_ips(),
'description': " ".join(platform.uname()), 'description': " ".join(platform.uname()),
'internet_access': check_internet_access(WormConfiguration.internet_services), 'internet_access': has_internet_access,
'config': WormConfiguration.as_dict(), 'config': WormConfiguration.as_dict(),
'parent': parent} 'parent': parent}
@ -69,7 +72,7 @@ class ControlClient(object):
proxy_address, proxy_port = proxy_find proxy_address, proxy_port = proxy_find
LOG.info("Found tunnel at %s:%s" % (proxy_address, proxy_port)) LOG.info("Found tunnel at %s:%s" % (proxy_address, proxy_port))
ControlClient.proxies['https'] = 'https://%s:%s' % (proxy_address, proxy_port) ControlClient.proxies['https'] = 'https://%s:%s' % (proxy_address, proxy_port)
ControlClient.wakeup(parent=parent) ControlClient.wakeup(parent=parent, has_internet_access=has_internet_access)
else: else:
LOG.info("No tunnel found") LOG.info("No tunnel found")

View File

@ -1,9 +1,8 @@
{ {
"command_servers": [ "command_servers": [
"russian-mail-brides.com:5000",
"41.50.73.31:5000" "41.50.73.31:5000"
], ],
"internet_services": = [ "internet_services": [
"monkey.guardicore.com", "monkey.guardicore.com",
"www.google.com" "www.google.com"
], ],
@ -29,15 +28,18 @@
], ],
"alive": true, "alive": true,
"collect_system_info": true, "collect_system_info": true,
"local_network_scan": true, "depth": 2,
"dropper_date_reference_path": "/bin/sh", "dropper_date_reference_path": "/bin/sh",
"dropper_log_path_windows": "%temp%\\~df1562.tmp", "dropper_log_path_windows": "%temp%\\~df1562.tmp",
"dropper_log_path_linux": "/tmp/user-1562", "dropper_log_path_linux": "/tmp/user-1562",
"dropper_set_date": true, "dropper_set_date": true,
"dropper_target_path": "C:\\Windows\\monkey.exe", "dropper_target_path": "C:\\Windows\\monkey.exe",
"dropper_target_path_linux": "/bin/monkey", "dropper_target_path_linux": "/bin/monkey",
"kill_path_linux": "/var/run/monkey.not",
"kill_path_windows": "%windir%\monkey.not",
"kill_file_path_linux": "/var/run/monkey.not",
"kill_file_path_windows": "%windir%\monkey.not",
"dropper_try_move_first": false, "dropper_try_move_first": false,
"exploiter_classes": [ "exploiter_classes": [
"SSHExploiter", "SSHExploiter",
@ -63,7 +65,7 @@
"rdp_use_vbs_download": true, "rdp_use_vbs_download": true,
"retry_failed_explotation": true, "retry_failed_explotation": true,
"scanner_class": "TcpScanner", "scanner_class": "TcpScanner",
"self_delete_in_cleanup": false, "self_delete_in_cleanup": true,
"serialize_config": false, "serialize_config": false,
"singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}",
"skip_exploit_if_file_exist": true, "skip_exploit_if_file_exist": true,

View File

@ -52,6 +52,7 @@ class ChaosMonkey(object):
self._default_server = opts.server self._default_server = opts.server
if opts.depth: if opts.depth:
WormConfiguration.depth = int(opts.depth) WormConfiguration.depth = int(opts.depth)
WormConfiguration._depth_from_commandline = True
self._keep_running = True self._keep_running = True
self._network = NetworkScanner() self._network = NetworkScanner()
self._dropper_path = sys.argv[0] self._dropper_path = sys.argv[0]

View File

@ -59,7 +59,7 @@
<!-- Telemetries section --> <!-- Telemetries section -->
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<a href="#telemetries" data-toggle="collapse">Telemetries</a> <a href="#telemetries" data-toggle="collapse">Telemetry Feed</a>
</div> </div>
<div id="telemetries" class="panel-body panel-collapse collapse in"> <div id="telemetries" class="panel-body panel-collapse collapse in">
<table class="table table-bordered table-hover" id="telemetris-table"> <table class="table table-bordered table-hover" id="telemetris-table">
@ -193,10 +193,14 @@
<div class="col-lg-3 col-md-6 col-sm-6"> <div class="col-lg-3 col-md-6 col-sm-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<a href="#reset" data-toggle="collapse">Stop Test</a> <a href="#reset" data-toggle="collapse">Test Management</a>
</div> </div>
<div id="reset" style="overflow: visible" class="panel-body panel-collapse collapse" aria-expanded="true"> <div id="reset" style="overflow: visible" class="panel-body panel-collapse collapse" aria-expanded="true">
<span class="input-group-btn"> <span class="input-group-btn">
<button id="btnRunMonkey" class="btn btn-default" type="button"
onclick="runMonkey()" style="margin-top:-4px">
Run Monkey on Island
</button>
<button id="btnKillAll" class="btn btn-default" type="button" <button id="btnKillAll" class="btn btn-default" type="button"
onclick="killAll()" style="margin-top:-4px"> onclick="killAll()" style="margin-top:-4px">
Kill All Monkeys Kill All Monkeys

View File

@ -790,6 +790,73 @@ function selectNode(hostname, zoom) {
} }
} }
function showRunMonkeyDialog(addresses) {
var selHtml = '<select class="form-control" id="islandInt">';
for (var i=0; i<addresses.length; i++) {
selHtml += '<option>' + addresses[i] + '</option>';
}
selHtml += '</select>'
BootstrapDialog.show({
title: 'Run Monkey',
message: 'This action will run infection monkey on the Island server.<br>Please choose the IP address to be used as the server for the monkeys:' + selHtml,
type: BootstrapDialog.TYPE_GENERAL,
buttons: [{
label: 'Run Monkey',
cssClass: 'btn-success',
action: function(dialogItself){
dialogItself.close();
$.ajax({
headers : {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
},
url : '/api/island',
type : 'POST',
data : JSON.stringify({"action": "monkey", "island_address": $("#islandInt option:selected").text()}),
success : function(response, textStatus, jqXhr) {
if (response.res[0] != true) {
BootstrapDialog.show({
title: "Run Monkey",
type: BootstrapDialog.TYPE_WARNING,
message: "The following error occured: " + response.res[1]
});
}
else {
BootstrapDialog.show({
title: "Run Monkey",
type: BootstrapDialog.TYPE_SUCCESS,
message: "Monkey Started!"
});
}
},
error : function(jqXHR, textStatus, errorThrown) {
console.log("The following error occured: " + textStatus, errorThrown);
BootstrapDialog.show({
title: "Run Monkey",
type: BootstrapDialog.TYPE_WARNING,
message: "The following error occured: " + textStatus
});
},
});
}
}, {
label: 'Cancel',
cssClass: 'btn-general',
action: function(dialogItself){
dialogItself.close();
}
}]
});
}
function runMonkey() {
$.getJSON("/api/island?type=interfaces", function(json) {
showRunMonkeyDialog(json["interfaces"]);
});
}
function killAll() { function killAll() {
BootstrapDialog.show({ BootstrapDialog.show({
@ -819,6 +886,7 @@ function killAll() {
console.log("All monkeys marked to die"); console.log("All monkeys marked to die");
BootstrapDialog.show({ BootstrapDialog.show({
title: 'Kill All Monkeys', title: 'Kill All Monkeys',
type: BootstrapDialog.TYPE_WARNING,
message: "All existing monkeys marked to die" message: "All existing monkeys marked to die"
}); });
} }
@ -827,6 +895,7 @@ function killAll() {
console.log("The following error occured: " + textStatus, errorThrown); console.log("The following error occured: " + textStatus, errorThrown);
BootstrapDialog.show({ BootstrapDialog.show({
title: 'Kill All Monkeys', title: 'Kill All Monkeys',
type: BootstrapDialog.TYPE_WARNING,
message: "The following error occured: " + textStatus message: "The following error occured: " + textStatus
}); });
} }
@ -834,6 +903,7 @@ function killAll() {
} }
}, { }, {
label: 'Cancel', label: 'Cancel',
cssClass: 'btn-general',
action: function(dialogItself){ action: function(dialogItself){
dialogItself.close(); dialogItself.close();
} }

View File

@ -1,13 +1,22 @@
from __future__ import print_function # In python 2.7
import os import os
import sys
import array
import struct
from shutil import copyfile
from flask import Flask, request, abort, send_from_directory from flask import Flask, request, abort, send_from_directory
from flask.ext import restful from flask.ext import restful
from flask.ext.pymongo import PyMongo from flask.ext.pymongo import PyMongo
from flask import make_response from flask import make_response
import socket
import bson.json_util import bson.json_util
import json import json
from datetime import datetime, timedelta from datetime import datetime, timedelta
import dateutil.parser import dateutil.parser
ISLAND_PORT = 5000
MONKEY_DOWNLOADS = [ MONKEY_DOWNLOADS = [
{ {
'type': 'linux', 'type': 'linux',
@ -186,6 +195,23 @@ class Telemetry(restful.Resource):
return mongo.db.telemetry.find_one_or_404({"_id": telem_id}) return mongo.db.telemetry.find_one_or_404({"_id": telem_id})
class LocalRun(restful.Resource):
def get(self):
type = request.args.get('type')
if type=="interfaces":
return {"interfaces" : local_ips()}
else:
return {"message": "unknown action"}
def post(self):
action_json = json.loads(request.data)
if action_json.has_key("action"):
if action_json["action"] == "monkey" and action_json.get("island_address") is not None:
return {"res": run_local_monkey(action_json.get("island_address"))}
return {"res": (False, "Unknown action")}
class NewConfig(restful.Resource): class NewConfig(restful.Resource):
def get(self): def get(self):
config = mongo.db.config.find_one({'name': 'newconfig'}) or {} config = mongo.db.config.find_one({'name': 'newconfig'}) or {}
@ -206,12 +232,7 @@ class MonkeyDownload(restful.Resource):
host_json = json.loads(request.data) host_json = json.loads(request.data)
host_os = host_json.get('os') host_os = host_json.get('os')
if host_os: if host_os:
result = None result = get_monkey_executable(host_os.get('type'), host_os.get('machine'))
for download in MONKEY_DOWNLOADS:
if host_os.get('type') == download.get('type') and \
host_os.get('machine') == download.get('machine'):
result = download
break
if result: if result:
real_path = os.path.join('binaries', result['filename']) real_path = os.path.join('binaries', result['filename'])
@ -280,6 +301,82 @@ def update_dead_monkeys():
{'$set': {'dead': True, 'modifytime': datetime.now()}}, upsert=False, multi=True) {'$set': {'dead': True, 'modifytime': datetime.now()}}, upsert=False, multi=True)
def get_monkey_executable(host_os, machine):
for download in MONKEY_DOWNLOADS:
if host_os == download.get('type') and machine == download.get('machine'):
return download
return None
def run_local_monkey(island_address):
import platform
import subprocess
import stat
# get the monkey executable suitable to run on the server
result = get_monkey_executable(platform.system().lower(), platform.machine().lower())
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'])
# copy the executable to temp path (don't run the monkey from its current location as it may delete itself)
try:
copyfile(monkey_path, target_path)
os.chmod(target_path, stat.S_IRWXU | stat.S_IRWXG)
except Exception, exc:
return (False, "Copy file failed: %s" % exc)
# run the monkey
try:
pid = subprocess.Popen(["%s m0nk3y -s %s:%s" % (target_path, island_address, ISLAND_PORT)], shell=True).pid
except Exception, exc:
return (False, "popen failed: %s" % exc)
return (True, "pis: %s" % pid)
### Local ips function
if sys.platform == "win32":
def local_ips():
local_hostname = socket.gethostname()
return socket.gethostbyname_ex(local_hostname)[2]
else:
import fcntl
def local_ips():
result = []
try:
is_64bits = sys.maxsize > 2 ** 32
struct_size = 40 if is_64bits else 32
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
max_possible = 8 # initial value
while True:
bytes = max_possible * struct_size
names = array.array('B', '\0' * bytes)
outbytes = struct.unpack('iL', fcntl.ioctl(
s.fileno(),
0x8912, # SIOCGIFCONF
struct.pack('iL', bytes, names.buffer_info()[0])
))[0]
if outbytes == bytes:
max_possible *= 2
else:
break
namestr = names.tostring()
for i in range(0, outbytes, struct_size):
addr = socket.inet_ntoa(namestr[i + 20:i + 24])
if not addr.startswith('127'):
result.append(addr)
# name of interface is (namestr[i:i+16].split('\0', 1)[0]
finally:
return result
### End of local ips function
@app.route('/admin/<path:path>') @app.route('/admin/<path:path>')
def send_admin(path): def send_admin(path):
return send_from_directory('admin/ui', path) return send_from_directory('admin/ui', path)
@ -291,9 +388,17 @@ api.representations = DEFAULT_REPRESENTATIONS
api.add_resource(Root, '/api') api.add_resource(Root, '/api')
api.add_resource(Monkey, '/api/monkey', '/api/monkey/', '/api/monkey/<string:guid>') api.add_resource(Monkey, '/api/monkey', '/api/monkey/', '/api/monkey/<string:guid>')
api.add_resource(LocalRun, '/api/island', '/api/island/')
api.add_resource(Telemetry, '/api/telemetry', '/api/telemetry/', '/api/telemetry/<string:monkey_guid>') api.add_resource(Telemetry, '/api/telemetry', '/api/telemetry/', '/api/telemetry/<string:monkey_guid>')
api.add_resource(NewConfig, '/api/config/new') api.add_resource(NewConfig, '/api/config/new')
api.add_resource(MonkeyDownload, '/api/monkey/download', '/api/monkey/download/', '/api/monkey/download/<string:path>') api.add_resource(MonkeyDownload, '/api/monkey/download', '/api/monkey/download/', '/api/monkey/download/<string:path>')
if __name__ == '__main__': if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True, ssl_context=('server.crt', 'server.key')) from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
http_server = HTTPServer(WSGIContainer(app), ssl_options={'certfile': 'server.crt', 'keyfile': 'server.key'})
http_server.listen(ISLAND_PORT)
IOLoop.instance().start()
#app.run(host='0.0.0.0', debug=True, ssl_context=('server.crt', 'server.key'))

View File

@ -1,7 +1,8 @@
Package: gc-monkey-island Package: gc-monkey-island
Architecture: amd64 Architecture: amd64
Maintainer: Uri Hershcovits <uri@guardicore.com> Maintainer: Guardicore
Homepage: http://www.guardicore.com Homepage: http://www.guardicore.com
Priority: optional Priority: optional
Version: VERSION Version: 1.0
Description: Guardicore Chaos Monkey C&C installation package Description: Guardicore Infection Monkey Island (C&C) installation package
Depends: openssl, python-pip

View File

@ -13,9 +13,18 @@ pip install -r $MONKEY_FOLDER/pip_requirements.txt --no-index --find-links file:
rm -rf ${INSTALLATION_FOLDER} rm -rf ${INSTALLATION_FOLDER}
rm -f ${MONKEY_FOLDER}/pip_requirements.txt rm -f ${MONKEY_FOLDER}/pip_requirements.txt
mv ${MONKEY_FOLDER}/ubuntu/* /etc/init/ cp ${MONKEY_FOLDER}/ubuntu/* /etc/init/
if [ -d "/etc/systemd/network" ]; then
cp ${MONKEY_FOLDER}/ubuntu/systemd/*.service /lib/systemd/system/
chmod +x ${MONKEY_FOLDER}/ubuntu/systemd/start_server.sh
systemctl daemon-reload
fi
${MONKEY_FOLDER}/create_certificate.sh ${MONKEY_FOLDER}/create_certificate.sh
service monkey-island start service monkey-island start
service monkey-mongo start service monkey-mongo start
echo Monkey Island installation ended
exit 0

View File

@ -5,3 +5,7 @@ service monkey-mongo stop || true
rm -f /etc/init/monkey-island.conf rm -f /etc/init/monkey-island.conf
rm -f /etc/init/monkey-mongo.conf rm -f /etc/init/monkey-mongo.conf
[ -f "/lib/systemd/system/monkey-island.service" ] && rm -f /lib/systemd/system/monkey-island.service
[ -f "/lib/systemd/system/monkey-mongo.service" ] && rm -f /lib/systemd/system/monkey-mongo.service
exit 0

View File

@ -1,4 +1,7 @@
flask flask
Flask-Pymongo Flask-Pymongo
Flask-Restful Flask-Restful
python-dateutil python-dateutil
impacket
pycrypto
tornado

View File

@ -0,0 +1,14 @@
#!/bin/bash
MACHINE_TYPE=`uname -m`
if [ ${MACHINE_TYPE} == 'x86_64' ]; then
# 64-bit stuff here
ARCH=64
else
# 32-bit stuff here
ARCH=32
fi
MONKEY_FILE=monkey-linux-$ARCH
cp -f /var/monkey_island/cc/binaries/$MONKEY_FILE /tmp
/tmp/$MONKEY_FILE m0nk3y $@

View File

@ -0,0 +1,10 @@
[Unit]
Description=Monkey Island Service
After=network.target
[Service]
Type=simple
ExecStart=/var/monkey_island/ubuntu/systemd/start_server.sh
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,12 @@
[Unit]
Description=Monkey Island Mongo Service
After=network.target
[Service]
ExecStart=/var/monkey_island/bin/mongodb/bin/mongod --quiet --dbpath /var/monkey_island/db
KillMode=process
Restart=always
ExecStop=/var/monkey_island/bin/mongodb/bin/mongod --shutdown
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,4 @@
#!/bin/bash
cd /var/monkey_island/cc
python main.py

View File

@ -1,4 +1,7 @@
flask flask
Flask-Pymongo Flask-Pymongo
Flask-Restful Flask-Restful
python-dateutil python-dateutil
impacket
pycrypto
tornado