# Conflicts:
#	chaos_monkey/config.py
#	chaos_monkey/network/info.py
This commit is contained in:
acepace 2016-07-18 23:45:02 +03:00
commit 5eb2379fa2
16 changed files with 313 additions and 100 deletions

View File

@ -33,7 +33,8 @@ 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 in the appropiate [readme](build_env/readme.txt). 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.
Usage Usage
----- -----
@ -148,7 +149,7 @@ Dependency | License |
----------------------------|---------------------------- ----------------------------|----------------------------
libffi-dev | https://github.com/atgreen/libffi/blob/master/LICENSE libffi-dev | https://github.com/atgreen/libffi/blob/master/LICENSE
PyCrypto | Public domain PyCrypto | Public domain
upx | Custom license, http://upx.sourceforge.net/upx-license.html, according to it (IANL) we're fine as long as we're not modifying UPX upx | Custom license, http://upx.sourceforge.net/upx-license.html
bson | BSD bson | BSD
enum34 | BSD enum34 | BSD
pyasn1 | BSD pyasn1 | BSD

View File

@ -1,2 +1,2 @@
REM c:\Python27\python -m PyInstaller.main --name monkey -F -y --clean -i monkey.ico main.py REM c:\Python27\python -m PyInstaller.main --name monkey -F -y --clean -i monkey.ico main.py
c:\python27\Scripts\pyinstaller --upx-dir=.\bin monkey.spec c:\python27\Scripts\pyinstaller --log-level=DEBUG --clean --upx-dir=.\bin monkey.spec

View File

@ -112,13 +112,13 @@ class Configuration(object):
########################### ###########################
# monkey config # monkey config
########################### ###########################
#sets whether or not the monkey is alive. if false will stop scanning and exploiting # sets whether or not the monkey is alive. if false will stop scanning and exploiting
alive = True alive = True
#sets whether or not to self delete the monkey executable when stopped # sets whether or not to self delete the monkey executable when stopped
self_delete_in_cleanup = False self_delete_in_cleanup = False
#string of the mutex name for single instance # string of the mutex name for single instance
singleton_mutex_name = "{2384ec59-0df8-4ab9-918c-843740924a28}" singleton_mutex_name = "{2384ec59-0df8-4ab9-918c-843740924a28}"
# how long to wait between scan iterations # how long to wait between scan iterations
@ -146,7 +146,7 @@ class Configuration(object):
"127.0.0.1:5000" "127.0.0.1:5000"
] ]
#sets whether or not to retry failed hosts on next scan # sets whether or not to retry failed hosts on next scan
retry_failed_explotation = True retry_failed_explotation = True
#addresses of internet servers to ping and check if the monkey has internet acccess. #addresses of internet servers to ping and check if the monkey has internet acccess.
@ -156,6 +156,9 @@ class Configuration(object):
# scanners config # scanners config
########################### ###########################
# Auto detect and scan local subnets
local_network_scan = True
range_class = FixedRange range_class = FixedRange
range_size = 1 range_size = 1
range_fixed = ["", ] range_fixed = ["", ]

View File

@ -53,7 +53,8 @@ class ControlClient(object):
data=json.dumps(monkey), data=json.dumps(monkey),
headers={'content-type': 'application/json'}, headers={'content-type': 'application/json'},
verify=False, verify=False,
proxies=ControlClient.proxies) proxies=ControlClient.proxies,
timeout=20)
break break
except Exception, exc: except Exception, exc:

View File

@ -68,6 +68,7 @@
"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,
"ssh_user": "root", "ssh_user": "root",
"local_network_scan": true,
"tcp_scan_get_banner": true, "tcp_scan_get_banner": true,
"tcp_scan_interval": 200, "tcp_scan_interval": 200,
"tcp_scan_timeout": 10000, "tcp_scan_timeout": 10000,

View File

@ -3,46 +3,74 @@ import sys
import socket import socket
import struct import struct
import array import array
import ipaddress
from random import randint from random import randint
__author__ = 'hoffer'
if sys.platform == "win32": if sys.platform == "win32":
import netifaces
def local_ips(): def local_ips():
local_hostname = socket.gethostname() local_hostname = socket.gethostname()
return socket.gethostbyname_ex(local_hostname)[2] return socket.gethostbyname_ex(local_hostname)[2]
def get_host_subnets(only_ips=False):
network_adapters = []
valid_ips = local_ips()
if only_ips:
return valid_ips
interfaces = [netifaces.ifaddresses(x) for x in netifaces.interfaces()]
for inte in interfaces:
if netifaces.AF_INET in inte:
for add in inte[netifaces.AF_INET]:
if "netmask" in add and add["addr"] in valid_ips:
network_adapters.append((add["addr"], add["netmask"]))
return network_adapters
else: else:
import fcntl import fcntl
def local_ips(): def get_host_subnets(only_ips=False):
result = [] """Get the list of Linux network adapters."""
try: import fcntl
is_64bits = sys.maxsize > 2**32 max_bytes = 8096
struct_size = 40 if is_64bits else 32 is_64bits = sys.maxsize > 2 ** 32
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) if is_64bits:
max_possible = 8 # initial value offset1 = 16
while True: offset2 = 40
bytes = max_possible * struct_size else:
names = array.array('B', '\0' * bytes) offset1 = 32
outbytes = struct.unpack('iL', fcntl.ioctl( offset2 = 32
s.fileno(), sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
0x8912, # SIOCGIFCONF names = array.array('B', '\0' * max_bytes)
struct.pack('iL', bytes, names.buffer_info()[0]) outbytes = struct.unpack('iL', fcntl.ioctl(
))[0] sock.fileno(),
if outbytes == bytes: 0x8912,
max_possible *= 2 struct.pack('iL', max_bytes, names.buffer_info()[0])))[0]
else: adapter_names = [names.tostring()[n_cnt:n_cnt + offset1].split('\0', 1)[0]
break for n_cnt in xrange(0, outbytes, offset2)]
namestr = names.tostring() network_adapters = []
for adapter_name in adapter_names:
ip_address = socket.inet_ntoa(fcntl.ioctl(
sock.fileno(),
0x8915,
struct.pack('256s', adapter_name))[20:24])
if ip_address.startswith('127'):
continue
subnet_mask = socket.inet_ntoa(fcntl.ioctl(
sock.fileno(),
0x891b,
struct.pack('256s', adapter_name))[20:24])
for i in range(0, outbytes, struct_size): if only_ips:
addr = socket.inet_ntoa(namestr[i+20:i+24]) network_adapters.append(ip_address)
if not addr.startswith('127'): else:
result.append(addr) network_adapters.append((ip_address, subnet_mask))
# name of interface is (namestr[i:i+16].split('\0', 1)[0]
finally: return network_adapters
return result
def local_ips():
return get_host_subnets(only_ips=True)
def get_free_tcp_port(min_range=1000, max_range=65535): def get_free_tcp_port(min_range=1000, max_range=65535):
@ -59,9 +87,25 @@ def get_free_tcp_port(min_range=1000, max_range=65535):
return None return None
def check_internet_access(services): def check_internet_access(services):
ping_str = "-n 1" if sys.platform.startswith("win") else "-c 1" ping_str = "-n 1" if sys.platform.startswith("win") else "-c 1"
for host in services: for host in services:
if os.system("ping " + ping_str + " " + host) == 0: if os.system("ping " + ping_str + " " + host) == 0:
return True return True
return False return False
def get_ips_from_interfaces():
res = []
ifs = get_host_subnets()
for interface in ifs:
ipint = ipaddress.ip_interface(u"%s/%s" % interface)
# limit subnet scans to class C only
if ipint.network.num_addresses > 255:
ipint = ipaddress.ip_interface(u"%s/24" % interface[0])
for addr in ipint.network.hosts():
if str(addr) == interface[0]:
continue
res.append(str(addr))
return res

View File

@ -2,7 +2,7 @@ import time
import logging import logging
from . import HostScanner from . import HostScanner
from config import WormConfiguration from config import WormConfiguration
from info import local_ips from info import local_ips, get_ips_from_interfaces
from range import * from range import *
__author__ = 'itamar' __author__ = 'itamar'
@ -27,10 +27,12 @@ class NetworkScanner(object):
LOG.info("Found local IP addresses of the machine: %r", self._ip_addresses) LOG.info("Found local IP addresses of the machine: %r", self._ip_addresses)
# for fixed range, only scan once. # for fixed range, only scan once.
if WormConfiguration.range_class is FixedRange: if WormConfiguration.range_class is FixedRange:
self._ranges = [WormConfiguration.range_class('0.0.0.0')] self._ranges = [WormConfiguration.range_class(None)]
else: else:
self._ranges = [WormConfiguration.range_class(ip_address) self._ranges = [WormConfiguration.range_class(ip_address)
for ip_address in self._ip_addresses] for ip_address in self._ip_addresses]
if WormConfiguration.local_network_scan:
self._ranges += [FixedRange([ip_address for ip_address in get_ips_from_interfaces()])]
LOG.info("Base local networks to scan are: %r", self._ranges) LOG.info("Base local networks to scan are: %r", self._ranges)
def get_victim_machines(self, scan_type, max_find=5, stop_callback=None): def get_victim_machines(self, scan_type, max_find=5, stop_callback=None):

View File

@ -58,10 +58,16 @@ class RelativeRange(NetworkRange):
class FixedRange(NetworkRange): class FixedRange(NetworkRange):
def __init__(self, base_address, shuffle=True): def __init__(self, fixed_addresses=None, shuffle=True):
base_address = 0 base_address = 0
super(FixedRange, self).__init__(base_address, shuffle=shuffle) super(FixedRange, self).__init__(base_address, shuffle=shuffle)
self._fixed_addresses = self._config.range_fixed if not fixed_addresses:
self._fixed_addresses = self._config.range_fixed
else:
if type(fixed_addresses) is str:
self._fixed_addresses = [fixed_addresses]
else:
self._fixed_addresses = list(fixed_addresses)
def __repr__(self): def __repr__(self):
return "<FixedRange %s>" % (",".join(self._fixed_addresses)) return "<FixedRange %s>" % (",".join(self._fixed_addresses))

View File

@ -21,7 +21,8 @@ Windows:
python -m pip install requests python -m pip install requests
python -m pip install odict python -m pip install odict
python -m pip install paramiko python -m pip install paramiko
python -m pip install psutil python -m pip install psutil
python -m pip install netifaces
python -m pip install PyInstaller python -m pip install PyInstaller
type > C:\Python27\Lib\site-packages\zope\__init__.py type > C:\Python27\Lib\site-packages\zope\__init__.py
7. Download and extract UPX binary to [source-path]\monkey\chaos_monkey\bin\upx.exe: 7. Download and extract UPX binary to [source-path]\monkey\chaos_monkey\bin\upx.exe:

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -10,6 +10,7 @@
<script type="text/javascript" src="./js/typeahead.bundle.min.js"></script> <script type="text/javascript" src="./js/typeahead.bundle.min.js"></script>
<script type="text/javascript" src="./js/bootstrap.min.js"></script> <script type="text/javascript" src="./js/bootstrap.min.js"></script>
<script type="text/javascript" src="./js/bootstrap-switch.min.js"></script>
<script type="text/javascript" src="./js/sb-admin-2/sb-admin-2.js"></script> <script type="text/javascript" src="./js/sb-admin-2/sb-admin-2.js"></script>
<script type="text/javascript" src="./js/sb-admin-2/metisMenu.js"></script> <script type="text/javascript" src="./js/sb-admin-2/metisMenu.js"></script>
<script type="text/javascript" src="./js/jsoneditor.js"></script> <script type="text/javascript" src="./js/jsoneditor.js"></script>
@ -23,6 +24,7 @@
<link type="text/css" href="./css/typeahead.css" rel="stylesheet"/> <link type="text/css" href="./css/typeahead.css" rel="stylesheet"/>
<!-- <link type="text/css" href="./css/font-awesome.min.css" rel="stylesheet"/> --> <!-- <link type="text/css" href="./css/font-awesome.min.css" rel="stylesheet"/> -->
<link type="text/css" href="./css/bootstrap.min.css" rel="stylesheet"/> <link type="text/css" href="./css/bootstrap.min.css" rel="stylesheet"/>
<link type="text/css" href="./css/bootstrap-switch.min.css" rel="stylesheet"/>
<link type="text/css" href="./css/sb-admin-2/sb-admin-2.css" rel="stylesheet"/> <link type="text/css" href="./css/sb-admin-2/sb-admin-2.css" rel="stylesheet"/>
<link type="text/css" href="./css/sb-admin-2/metisMenu.css" rel="stylesheet"/> <link type="text/css" href="./css/sb-admin-2/metisMenu.css" rel="stylesheet"/>
<link type="text/css" href="./css/jquery.dataTables.min.css" rel="stylesheet"/> <link type="text/css" href="./css/jquery.dataTables.min.css" rel="stylesheet"/>
@ -71,11 +73,33 @@
</div> </div>
<!-- /.Network section --> <!-- /.Network section -->
<!-- Info section -->
<div class="col-lg-3 col-md-6 col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<a href="#info" data-toggle="collapse">General Info</a>
</div>
<div id="info" class="panel-body panel-collapse collapse in">
<div>
Num of Monkeys: <label id="infoNumOfMonkeys">0</label> (<label id="infoNumOfParents">0</label> by exploiting)<br/>
Num of Hosts Detected: <label id="infoNumOfHosts">0</label><br/>
Num of Tunnels Used: <label id="infoNumOfTunnels">0</label><br/>
</div>
<div>
Display Scanned Hosts: <input type="checkbox" data-size="mini" name="chboxShowScanned" checked>
</div>
</div>
</div>
</div>
<!-- /.Info section -->
<!-- Details section --> <!-- Details section -->
<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="#details" data-toggle="collapse">Details</a> <a href="#details" data-toggle="collapse">Monkey Details</a>
</div> </div>
<div id="details" class="panel-body panel-collapse collapse in"> <div id="details" class="panel-body panel-collapse collapse in">
<div id="search" class="input-group custom-search-form"> <div id="search" class="input-group custom-search-form">
@ -99,24 +123,21 @@
<a href="#mconfig" data-toggle="collapse">Monkey Config</a> <a href="#mconfig" data-toggle="collapse">Monkey Config</a>
</div> </div>
<div id="mconfig" style="overflow: visible" class="panel-body panel-collapse collapse in" aria-expanded="true"> <div id="mconfig" style="overflow: visible" class="panel-body panel-collapse collapse in" aria-expanded="true">
<span class="input-group-btn"> <div style="display: none;" id="monkey-enabled">
<button id="btnConfigLoad" style="display: none;" class="btn btn-default" type="button" Allow running: <input type="checkbox" data-size="mini" name="chboxMonkeyEnabled" checked>
onclick="loadMonkeyConfig()" style="margin-top:-4px"> </div><br/>
Refresh <div>
</button> <span class="input-group-btn">
<button id="btnConfigUpdate" style="display: none;" class="btn btn-default" type="button" <button id="btnConfigLoad" style="display: none;" class="btn btn-default" type="button"
onclick="updateMonkeyConfig()" style="margin-top:-4px"> onclick="loadMonkeyConfig()" style="margin-top:-4px">
Update Refresh
</button> </button>
<button id="btnKillMonkey" style="display: none;" class="btn btn-default" type="button" <button id="btnConfigUpdate" style="display: none;" class="btn btn-default" type="button"
onclick="killMonkey()" style="margin-top:-4px"> onclick="updateMonkeyConfig()" style="margin-top:-4px">
Mark for Kill Update
</button> </button>
<button id="btnReviveMonkey" style="display: none;" class="btn btn-default" type="button" </span>
onclick="reviveMonkey()" style="margin-top:-4px"> </div>
Revive Monkey
</button>
</span>
<div style="display: none;" id="monkey-config"> <div style="display: none;" id="monkey-config">
</div> </div>
</div> </div>

File diff suppressed because one or more lines are too long

View File

@ -21,15 +21,27 @@ $.getJSON(jsonFile, function(json) {
var network = null; var network = null;
var nodes = []; var nodes = [];
var edges = []; var edges = [];
var numOfParentLinks = 0;
var numOfTunnelLinks = 0;
var numOfScanLinks = 0;
var showScannedHosts = true;
// Images/icons constants // Images/icons constants
const ICONS_DIR = "./css/img/objects/"; const ICONS_DIR = "./css/img/objects/";
const ICONS_EXT = ".png"; const ICONS_EXT = ".png";
const HOST_TYPE_MONKEY = "monkey";
const HOST_TYPE_SCAN = "scanned";
const EDGE_TYPE_PARENT = "parent"; const EDGE_TYPE_PARENT = "parent";
const EDGE_TYPE_TUNNEL = "tunnel"; const EDGE_TYPE_TUNNEL = "tunnel";
const EDGE_TYPE_SCAN = "scan"; const EDGE_TYPE_SCAN = "scan";
const EDGE_COLOR_PARENT = "red";
const EDGE_COLOR_TUNNEL = "blue";
const EDGE_COLOR_SCAN = "gray";
// General options // General options
// If variable from local storage != null, assign it, otherwise set it's default value. // If variable from local storage != null, assign it, otherwise set it's default value.
@ -59,6 +71,8 @@ function initAdmin() {
edges: edges edges: edges
}; };
updateCounters();
var options = { var options = {
}; };
@ -67,6 +81,9 @@ function initAdmin() {
network = new vis.Network(container, data, options); network = new vis.Network(container, data, options);
$("[name='chboxShowScanned']").bootstrapSwitch('onSwitchChange', toggleScannedHosts);
$("[name='chboxMonkeyEnabled']").bootstrapSwitch('onSwitchChange', toggleMonkeyEnabled);
prepareSearchEngine(); prepareSearchEngine();
monkeyCfg = new JSONEditor(document.getElementById('monkey-config'),{ monkeyCfg = new JSONEditor(document.getElementById('monkey-config'),{
@ -115,6 +132,55 @@ function initAdmin() {
addEventsListeners(); addEventsListeners();
} }
function toggleScannedHosts(event, state) {
if (event.type != "switchChange") {
return;
}
if (state) {
showScannedHosts = true;
}
else {
showScannedHosts = false;
}
refreshDrawing();
}
function refreshDrawing() {
// function called before first init
if (network == null) {
return;
}
// keep old selection
var selNode = network.getSelectedNodes();
if (showScannedHosts) {
network.setData({nodes: nodes, edges: edges});
}
else {
var selectiveNodes = [];
var selectiveEdges = [];
for (var i=0; i<nodes.length; i++) {
if (nodes[i].type != HOST_TYPE_SCAN) {
selectiveNodes.push(nodes[i])
}
}
for (var i=0; i<edges.length; i++) {
if (edges[i].type != EDGE_TYPE_SCAN) {
selectiveEdges.push(edges[i])
}
}
network.setData({nodes: selectiveNodes, edges: selectiveEdges});
}
if (selNode.length) {
var monkey = getMonkey(selNode[0]);
if (monkey) { // The selection might be no longer valid if the monkey was deleted
selectNode(monkey.hostname, false);
}
}
}
function updateMonkeys() { function updateMonkeys() {
$.getJSON(jsonFile + '?timestamp='+ generationDate, function(json) { $.getJSON(jsonFile + '?timestamp='+ generationDate, function(json) {
generationDate = json.timestamp; generationDate = json.timestamp;
@ -128,6 +194,7 @@ function updateMonkeys() {
{ {
monkeys.push(new_monkeys[i]); monkeys.push(new_monkeys[i]);
nodes.push(createMonkeyNode(new_monkeys[i])); nodes.push(createMonkeyNode(new_monkeys[i]));
updateCounters();
} }
} }
@ -135,16 +202,7 @@ function updateMonkeys() {
{ {
createEdges(); createEdges();
createTunnels(); createTunnels();
refreshDrawing();
// keep old selection
var selNode = network.getSelectedNodes();
network.setData({nodes: nodes, edges: edges});
if (selNode.length) {
var monkey = getMonkey(selNode[0]);
if (monkey) { // The selection might be no longer valid if the monkey was deleted
selectNode(monkey.hostname, false);
}
}
} }
createScanned(); createScanned();
window.setTimeout(updateMonkeys, 10000); window.setTimeout(updateMonkeys, 10000);
@ -163,7 +221,6 @@ function createNodes() {
return nodes; return nodes;
} }
function createMonkeyNode(monkey) { function createMonkeyNode(monkey) {
var title = undefined; var title = undefined;
var img = "monkey"; var img = "monkey";
@ -187,12 +244,24 @@ function createMonkeyNode(monkey) {
'image': img, 'image': img,
'title': title, 'title': title,
'value': undefined, 'value': undefined,
'type' : HOST_TYPE_MONKEY,
'mass': 1, 'mass': 1,
}; };
} }
function createMachineNode(machine) { function createMachineNode(machine) {
img = ICONS_DIR + "computer" + ICONS_EXT; img = "computer";
if (undefined != machine.os.type) {
if (machine.os.type == "linux") {
img += "-linux";
}
else if (machine.os.type == "windows") {
img += "-windows";
}
}
img = ICONS_DIR + img + ICONS_EXT;
return { return {
'id': machine.ip_addr, 'id': machine.ip_addr,
@ -202,6 +271,7 @@ function createMachineNode(machine) {
'image': img, 'image': img,
'title': undefined, 'title': undefined,
'value': undefined, 'value': undefined,
'type' : HOST_TYPE_SCAN,
'mass': 1, 'mass': 1,
}; };
} }
@ -213,7 +283,8 @@ function createEdges() {
var parent = getMonkeyByGuid(monkey.parent); var parent = getMonkeyByGuid(monkey.parent);
if(parent && !edgeExists([parent.id, monkey.id, EDGE_TYPE_PARENT])) { if(parent && !edgeExists([parent.id, monkey.id, EDGE_TYPE_PARENT])) {
edges.push({from: parent.id, to: monkey.id, arrows:'middle', type: EDGE_TYPE_PARENT, color: 'red'}); edges.push({from: parent.id, to: monkey.id, arrows:'middle', type: EDGE_TYPE_PARENT, color: EDGE_COLOR_PARENT});
numOfParentLinks++;
} }
} }
} }
@ -228,7 +299,8 @@ function createTunnels() {
var tunnel = getMonkeyByGuid(monkey.tunnel_guid); var tunnel = getMonkeyByGuid(monkey.tunnel_guid);
if(tunnel && !edgeExists([monkey.id, tunnel.id, EDGE_TYPE_TUNNEL])) { if(tunnel && !edgeExists([monkey.id, tunnel.id, EDGE_TYPE_TUNNEL])) {
edges.push({from: monkey.id, to: tunnel.id, arrows:'middle', type: EDGE_TYPE_TUNNEL, color:'blue'}); edges.push({from: monkey.id, to: tunnel.id, arrows:'middle', type: EDGE_TYPE_TUNNEL, color: EDGE_COLOR_TUNNEL});
numOfTunnelLinks++;
} }
} }
} }
@ -237,13 +309,14 @@ function createTunnels() {
} }
function createScanned() { function createScanned() {
//For each existing monkey, gets all the scans performed by it var genTime = temelGenerationDate; // save the initial value as it's going to be changed in each json call
//For each non exploited machine, adds a new node and connects it as a scanned node. // For each existing monkey, gets all the scans performed by it
// For each non exploited machine, adds a new node and connects it as a scanned node.
for (var i = 0; i < monkeys.length; i++) { for (var i = 0; i < monkeys.length; i++) {
var monkey = monkeys[i]; var monkey = monkeys[i];
//Get scans for each monkey // Get scans for each monkey
// Reading the JSON file containing the monkeys' informations // Reading the JSON file containing the monkeys' informations
$.getJSON(jsonFileTelemetry +'?timestamp='+ temelGenerationDate+ "&monkey_guid=" + monkey.guid+"&telem_type=scan", function(json) { $.getJSON(jsonFileTelemetry +'?timestamp='+ genTime + "&monkey_guid=" + monkey.guid+"&telem_type=scan", function(json) {
temelGenerationDate = json.timestamp; temelGenerationDate = json.timestamp;
var scans = json.objects; var scans = json.objects;
for (var i = 0; i < scans.length; i++) { for (var i = 0; i < scans.length; i++) {
@ -265,9 +338,14 @@ function createScanned() {
} }
if(!edgeExists([monkey.id, machineNode.id, EDGE_TYPE_SCAN])) { if(!edgeExists([monkey.id, machineNode.id, EDGE_TYPE_SCAN])) {
edges.push({from: monkey.id, to: machineNode.id, arrows:'middle', type: EDGE_TYPE_SCAN, color: 'red'}); edges.push({from: monkey.id, to: machineNode.id, arrows:'middle', type: EDGE_TYPE_SCAN, color: EDGE_COLOR_SCAN});
numOfScanLinks++;
} }
} }
if (scans.length > 0) {
refreshDrawing();
updateCounters();
}
}); });
} }
} }
@ -297,6 +375,13 @@ function buildMonkeyDescription(monkey) {
return html; return html;
} }
function updateCounters() {
$('#infoNumOfMonkeys').html(monkeys.length);
$('#infoNumOfHosts').html(scannedMachines.length);
$('#infoNumOfParents').html(numOfParentLinks);
$('#infoNumOfTunnels').html(numOfTunnelLinks);
}
/** /**
* Preparing the autocompletion search engine for the monkeys * Preparing the autocompletion search engine for the monkeys
@ -370,7 +455,8 @@ function onSelect(properties) {
var content = "<b>No selection</b>" var content = "<b>No selection</b>"
$("#selectionInfo").html(content); $("#selectionInfo").html(content);
$('#monkey-config').hide() $('#monkey-config').hide()
$('#btnConfigLoad, #btnConfigUpdate, #btnKillMonkey, #btnReviveMonkey').hide(); $('#btnConfigLoad, #btnConfigUpdate').hide();
$('#monkey-enabled').hide();
telemTable.clear(); telemTable.clear();
telemTable.draw(); telemTable.draw();
} }
@ -403,14 +489,12 @@ function onNodeSelect(nodeId) {
loadMonkeyConfig(); loadMonkeyConfig();
if (monkey.config.alive) { if (monkey.config.alive) {
$('#btnKillMonkey').show(); $("[name='chboxMonkeyEnabled']").bootstrapSwitch('state', true);
$('#btnReviveMonkey').hide();
} }
else { else {
$('#btnKillMonkey').hide(); $("[name='chboxMonkeyEnabled']").bootstrapSwitch('state', false);
$('#btnReviveMonkey').show();
} }
$('#monkey-enabled').show();
$.getJSON('/api/telemetry/' + monkey.guid, function(json) { $.getJSON('/api/telemetry/' + monkey.guid, function(json) {
telemTable.clear(); telemTable.clear();
@ -434,6 +518,19 @@ function onEdgeSelect(edge) {
} }
function toggleMonkeyEnabled(event, state) {
if (event.type != "switchChange") {
return;
}
if (state) {
reviveMonkey();
}
else {
killMonkey();
}
}
function killMonkey() { function killMonkey() {
var curr_config = monkeyCfg.getValue(); var curr_config = monkeyCfg.getValue();
curr_config.alive = false; curr_config.alive = false;

View File

@ -11,27 +11,19 @@ How to set C&C server:
python -m pip install Flask-Pymongo python -m pip install Flask-Pymongo
python -m pip install Flask-Restful python -m pip install Flask-Restful
python -m pip install python-dateutil python -m pip install python-dateutil
mkdir C:\MonkeyIsland\bin mkdir MonkeyIsland\bin
mkdir C:\MonkeyIsland\db mkdir MonkeyIsland\db
mkdir C:\MonkeyIsland\cc\binaries mkdir MonkeyIsland\cc\binaries
4. Put monkey binaries in C:\MonkeyIsland\cc\binaries: 4. Put monkey binaries in MonkeyIsland\cc\binaries:
monkey-linux-64 - monkey binary for linux 64bit monkey-linux-64 - monkey binary for linux 64bit
monkey-linux-32 - monkey binary for linux 32bit monkey-linux-32 - monkey binary for linux 32bit
monkey-windows-32.exe - monkey binary for windows 32bit monkey-windows-32.exe - monkey binary for windows 32bit
monkey-windows-64.exe - monkey binary for windows 64bit monkey-windows-64.exe - monkey binary for windows 64bit
4. Download MongoDB & Extract to C:\MonkeyIsland\bin\mongodb 4. Download MongoDB & Extract to MonkeyIsland\bin\mongodb
http://downloads.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-latest.zip http://downloads.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-latest.zip
5. Install OpenSSL 5. Install OpenSSL
https://slproweb.com/download/Win64OpenSSL_Light-1_0_2d.exe https://slproweb.com/download/Win64OpenSSL_Light-1_0_2d.exe
6. Generate SSL Certificate, Run create_certificate.bat 6. Generate SSL Certificate, run create_certificate.bat when your current working directory is MonkeyIsland
How to Connect to build environment:
1. set hostname to MONKEYCC
2. Put monkey source code at C:\Code\monkey
3. Run:
net share binaries=C:\MonkeyIsland\cc\binaries
net share sources=C:\Code\monkey\chaos_monkey
4. Run batch/sh script according to build environment readme
How to run: How to run:
1. start run_mongodb.bat 1. start run_mongodb.bat