diff --git a/README.md b/README.md index e2e36856a..a47e488f1 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,8 @@ The Monkey itself has been tested on Windows XP, 7, 8.1 and 10. The Linux build ### 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 ----- @@ -148,7 +149,7 @@ Dependency | License | ----------------------------|---------------------------- libffi-dev | https://github.com/atgreen/libffi/blob/master/LICENSE 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 enum34 | BSD pyasn1 | BSD diff --git a/chaos_monkey/build_windows.bat b/chaos_monkey/build_windows.bat index befb76a20..57435ce7c 100644 --- a/chaos_monkey/build_windows.bat +++ b/chaos_monkey/build_windows.bat @@ -1,2 +1,2 @@ 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 diff --git a/chaos_monkey/config.py b/chaos_monkey/config.py index 3ea1e37e7..572b4648f 100644 --- a/chaos_monkey/config.py +++ b/chaos_monkey/config.py @@ -112,13 +112,13 @@ class Configuration(object): ########################### # 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 - #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 - #string of the mutex name for single instance + # string of the mutex name for single instance singleton_mutex_name = "{2384ec59-0df8-4ab9-918c-843740924a28}" # how long to wait between scan iterations @@ -146,7 +146,7 @@ class Configuration(object): "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 #addresses of internet servers to ping and check if the monkey has internet acccess. @@ -156,6 +156,9 @@ class Configuration(object): # scanners config ########################### + # Auto detect and scan local subnets + local_network_scan = True + range_class = FixedRange range_size = 1 range_fixed = ["", ] diff --git a/chaos_monkey/control.py b/chaos_monkey/control.py index dc4bf198d..d262a78ee 100644 --- a/chaos_monkey/control.py +++ b/chaos_monkey/control.py @@ -53,7 +53,8 @@ class ControlClient(object): data=json.dumps(monkey), headers={'content-type': 'application/json'}, verify=False, - proxies=ControlClient.proxies) + proxies=ControlClient.proxies, + timeout=20) break except Exception, exc: diff --git a/chaos_monkey/example.conf b/chaos_monkey/example.conf index ef4c2ca0c..3d1e6d133 100644 --- a/chaos_monkey/example.conf +++ b/chaos_monkey/example.conf @@ -68,6 +68,7 @@ "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}", "skip_exploit_if_file_exist": true, "ssh_user": "root", + "local_network_scan": true, "tcp_scan_get_banner": true, "tcp_scan_interval": 200, "tcp_scan_timeout": 10000, diff --git a/chaos_monkey/network/info.py b/chaos_monkey/network/info.py index c59971faa..189991d1a 100644 --- a/chaos_monkey/network/info.py +++ b/chaos_monkey/network/info.py @@ -3,46 +3,74 @@ import sys import socket import struct import array +import ipaddress from random import randint -__author__ = 'hoffer' - if sys.platform == "win32": + import netifaces + def local_ips(): local_hostname = socket.gethostname() 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: 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() + def get_host_subnets(only_ips=False): + """Get the list of Linux network adapters.""" + import fcntl + max_bytes = 8096 + is_64bits = sys.maxsize > 2 ** 32 + if is_64bits: + offset1 = 16 + offset2 = 40 + else: + offset1 = 32 + offset2 = 32 + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + names = array.array('B', '\0' * max_bytes) + outbytes = struct.unpack('iL', fcntl.ioctl( + sock.fileno(), + 0x8912, + struct.pack('iL', max_bytes, names.buffer_info()[0])))[0] + adapter_names = [names.tostring()[n_cnt:n_cnt + offset1].split('\0', 1)[0] + for n_cnt in xrange(0, outbytes, offset2)] + 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): - 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 + if only_ips: + network_adapters.append(ip_address) + else: + network_adapters.append((ip_address, subnet_mask)) + + return network_adapters + + + def local_ips(): + return get_host_subnets(only_ips=True) 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 + def check_internet_access(services): ping_str = "-n 1" if sys.platform.startswith("win") else "-c 1" for host in services: if os.system("ping " + ping_str + " " + host) == 0: return True 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 diff --git a/chaos_monkey/network/network_scanner.py b/chaos_monkey/network/network_scanner.py index 430c4f68a..9c03ca4b8 100644 --- a/chaos_monkey/network/network_scanner.py +++ b/chaos_monkey/network/network_scanner.py @@ -2,7 +2,7 @@ import time import logging from . import HostScanner from config import WormConfiguration -from info import local_ips +from info import local_ips, get_ips_from_interfaces from range import * __author__ = 'itamar' @@ -27,10 +27,12 @@ class NetworkScanner(object): LOG.info("Found local IP addresses of the machine: %r", self._ip_addresses) # for fixed range, only scan once. if WormConfiguration.range_class is FixedRange: - self._ranges = [WormConfiguration.range_class('0.0.0.0')] + self._ranges = [WormConfiguration.range_class(None)] else: self._ranges = [WormConfiguration.range_class(ip_address) 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) def get_victim_machines(self, scan_type, max_find=5, stop_callback=None): diff --git a/chaos_monkey/network/range.py b/chaos_monkey/network/range.py index 0dfcf69ad..f62e895d1 100644 --- a/chaos_monkey/network/range.py +++ b/chaos_monkey/network/range.py @@ -58,10 +58,16 @@ class RelativeRange(NetworkRange): class FixedRange(NetworkRange): - def __init__(self, base_address, shuffle=True): + def __init__(self, fixed_addresses=None, shuffle=True): base_address = 0 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): return "" % (",".join(self._fixed_addresses)) diff --git a/chaos_monkey/readme.txt b/chaos_monkey/readme.txt index 23a1c2aa0..82bb61f9b 100644 --- a/chaos_monkey/readme.txt +++ b/chaos_monkey/readme.txt @@ -21,7 +21,8 @@ Windows: python -m pip install requests python -m pip install odict 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 type > C:\Python27\Lib\site-packages\zope\__init__.py 7. Download and extract UPX binary to [source-path]\monkey\chaos_monkey\bin\upx.exe: diff --git a/monkey_island/cc/admin/ui/css/bootstrap-switch.min.css b/monkey_island/cc/admin/ui/css/bootstrap-switch.min.css new file mode 100644 index 000000000..c63cfe2f9 --- /dev/null +++ b/monkey_island/cc/admin/ui/css/bootstrap-switch.min.css @@ -0,0 +1,22 @@ +/* ======================================================================== + * bootstrap-switch - v3.3.2 + * http://www.bootstrap-switch.org + * ======================================================================== + * Copyright 2012-2013 Mattia Larentis + * + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== + */ + +.bootstrap-switch{display:inline-block;direction:ltr;cursor:pointer;border-radius:4px;border:1px solid #ccc;position:relative;text-align:left;overflow:hidden;line-height:8px;z-index:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.bootstrap-switch .bootstrap-switch-container{display:inline-block;top:0;border-radius:4px;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bootstrap-switch .bootstrap-switch-handle-off,.bootstrap-switch .bootstrap-switch-handle-on,.bootstrap-switch .bootstrap-switch-label{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;display:inline-block!important;height:100%;padding:6px 12px;font-size:14px;line-height:20px}.bootstrap-switch .bootstrap-switch-handle-off,.bootstrap-switch .bootstrap-switch-handle-on{text-align:center;z-index:1}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary{color:#fff;background:#337ab7}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info{color:#fff;background:#5bc0de}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success{color:#fff;background:#5cb85c}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning{background:#f0ad4e;color:#fff}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger{color:#fff;background:#d9534f}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default{color:#000;background:#eee}.bootstrap-switch .bootstrap-switch-label{text-align:center;margin-top:-1px;margin-bottom:-1px;z-index:100;color:#333;background:#fff}.bootstrap-switch .bootstrap-switch-handle-on{border-bottom-left-radius:3px;border-top-left-radius:3px}.bootstrap-switch .bootstrap-switch-handle-off{border-bottom-right-radius:3px;border-top-right-radius:3px}.bootstrap-switch input[type=radio],.bootstrap-switch input[type=checkbox]{position:absolute!important;top:0;left:0;margin:0;z-index:-1;opacity:0;filter:alpha(opacity=0)}.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label{padding:1px 5px;font-size:12px;line-height:1.5}.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label{padding:5px 10px;font-size:12px;line-height:1.5}.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label{padding:6px 16px;font-size:18px;line-height:1.3333333}.bootstrap-switch.bootstrap-switch-disabled,.bootstrap-switch.bootstrap-switch-indeterminate,.bootstrap-switch.bootstrap-switch-readonly{cursor:default!important}.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label{opacity:.5;filter:alpha(opacity=50);cursor:default!important}.bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container{-webkit-transition:margin-left .5s;-o-transition:margin-left .5s;transition:margin-left .5s}.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on{border-radius:0 3px 3px 0}.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off{border-radius:3px 0 0 3px}.bootstrap-switch.bootstrap-switch-focused{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label{border-bottom-right-radius:3px;border-top-right-radius:3px}.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label{border-bottom-left-radius:3px;border-top-left-radius:3px} \ No newline at end of file diff --git a/monkey_island/cc/admin/ui/css/img/objects/computer-linux.png b/monkey_island/cc/admin/ui/css/img/objects/computer-linux.png new file mode 100644 index 000000000..9c5dc728e Binary files /dev/null and b/monkey_island/cc/admin/ui/css/img/objects/computer-linux.png differ diff --git a/monkey_island/cc/admin/ui/css/img/objects/computer-windows.png b/monkey_island/cc/admin/ui/css/img/objects/computer-windows.png new file mode 100644 index 000000000..f9a2f83a6 Binary files /dev/null and b/monkey_island/cc/admin/ui/css/img/objects/computer-windows.png differ diff --git a/monkey_island/cc/admin/ui/index.html b/monkey_island/cc/admin/ui/index.html index 9cb253316..d96ae3536 100644 --- a/monkey_island/cc/admin/ui/index.html +++ b/monkey_island/cc/admin/ui/index.html @@ -10,6 +10,7 @@ + @@ -23,6 +24,7 @@ + @@ -71,11 +73,33 @@ + +
+
+ +
+
+ Num of Monkeys: ( by exploiting)
+ Num of Hosts Detected:
+ Num of Tunnels Used:
+
+
+ Display Scanned Hosts: +
+
+
+
+ + + +
- - - - - - +
+
+ + + + +
diff --git a/monkey_island/cc/admin/ui/js/bootstrap-switch.min.js b/monkey_island/cc/admin/ui/js/bootstrap-switch.min.js new file mode 100644 index 000000000..9849658bc --- /dev/null +++ b/monkey_island/cc/admin/ui/js/bootstrap-switch.min.js @@ -0,0 +1,22 @@ +/* ======================================================================== + * bootstrap-switch - v3.3.2 + * http://www.bootstrap-switch.org + * ======================================================================== + * Copyright 2012-2013 Mattia Larentis + * + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== + */ + +(function(){var t=[].slice;!function(e,i){"use strict";var n;return n=function(){function t(t,i){null==i&&(i={}),this.$element=e(t),this.options=e.extend({},e.fn.bootstrapSwitch.defaults,{state:this.$element.is(":checked"),size:this.$element.data("size"),animate:this.$element.data("animate"),disabled:this.$element.is(":disabled"),readonly:this.$element.is("[readonly]"),indeterminate:this.$element.data("indeterminate"),inverse:this.$element.data("inverse"),radioAllOff:this.$element.data("radio-all-off"),onColor:this.$element.data("on-color"),offColor:this.$element.data("off-color"),onText:this.$element.data("on-text"),offText:this.$element.data("off-text"),labelText:this.$element.data("label-text"),handleWidth:this.$element.data("handle-width"),labelWidth:this.$element.data("label-width"),baseClass:this.$element.data("base-class"),wrapperClass:this.$element.data("wrapper-class")},i),this.prevOptions={},this.$wrapper=e("
",{"class":function(t){return function(){var e;return e=[""+t.options.baseClass].concat(t._getClasses(t.options.wrapperClass)),e.push(t.options.state?t.options.baseClass+"-on":t.options.baseClass+"-off"),null!=t.options.size&&e.push(t.options.baseClass+"-"+t.options.size),t.options.disabled&&e.push(t.options.baseClass+"-disabled"),t.options.readonly&&e.push(t.options.baseClass+"-readonly"),t.options.indeterminate&&e.push(t.options.baseClass+"-indeterminate"),t.options.inverse&&e.push(t.options.baseClass+"-inverse"),t.$element.attr("id")&&e.push(t.options.baseClass+"-id-"+t.$element.attr("id")),e.join(" ")}}(this)()}),this.$container=e("
",{"class":this.options.baseClass+"-container"}),this.$on=e("",{html:this.options.onText,"class":this.options.baseClass+"-handle-on "+this.options.baseClass+"-"+this.options.onColor}),this.$off=e("",{html:this.options.offText,"class":this.options.baseClass+"-handle-off "+this.options.baseClass+"-"+this.options.offColor}),this.$label=e("",{html:this.options.labelText,"class":this.options.baseClass+"-label"}),this.$element.on("init.bootstrapSwitch",function(e){return function(){return e.options.onInit.apply(t,arguments)}}(this)),this.$element.on("switchChange.bootstrapSwitch",function(i){return function(n){return!1===i.options.onSwitchChange.apply(t,arguments)?i.$element.is(":radio")?e("[name='"+i.$element.attr("name")+"']").trigger("previousState.bootstrapSwitch",!0):i.$element.trigger("previousState.bootstrapSwitch",!0):void 0}}(this)),this.$container=this.$element.wrap(this.$container).parent(),this.$wrapper=this.$container.wrap(this.$wrapper).parent(),this.$element.before(this.options.inverse?this.$off:this.$on).before(this.$label).before(this.options.inverse?this.$on:this.$off),this.options.indeterminate&&this.$element.prop("indeterminate",!0),this._init(),this._elementHandlers(),this._handleHandlers(),this._labelHandlers(),this._formHandler(),this._externalLabelHandler(),this.$element.trigger("init.bootstrapSwitch",this.options.state)}return t.prototype._constructor=t,t.prototype.setPrevOptions=function(){return this.prevOptions=e.extend(!0,{},this.options)},t.prototype.state=function(t,i){return"undefined"==typeof t?this.options.state:this.options.disabled||this.options.readonly?this.$element:this.options.state&&!this.options.radioAllOff&&this.$element.is(":radio")?this.$element:(this.$element.is(":radio")?e("[name='"+this.$element.attr("name")+"']").trigger("setPreviousOptions.bootstrapSwitch"):this.$element.trigger("setPreviousOptions.bootstrapSwitch"),this.options.indeterminate&&this.indeterminate(!1),t=!!t,this.$element.prop("checked",t).trigger("change.bootstrapSwitch",i),this.$element)},t.prototype.toggleState=function(t){return this.options.disabled||this.options.readonly?this.$element:this.options.indeterminate?(this.indeterminate(!1),this.state(!0)):this.$element.prop("checked",!this.options.state).trigger("change.bootstrapSwitch",t)},t.prototype.size=function(t){return"undefined"==typeof t?this.options.size:(null!=this.options.size&&this.$wrapper.removeClass(this.options.baseClass+"-"+this.options.size),t&&this.$wrapper.addClass(this.options.baseClass+"-"+t),this._width(),this._containerPosition(),this.options.size=t,this.$element)},t.prototype.animate=function(t){return"undefined"==typeof t?this.options.animate:(t=!!t,t===this.options.animate?this.$element:this.toggleAnimate())},t.prototype.toggleAnimate=function(){return this.options.animate=!this.options.animate,this.$wrapper.toggleClass(this.options.baseClass+"-animate"),this.$element},t.prototype.disabled=function(t){return"undefined"==typeof t?this.options.disabled:(t=!!t,t===this.options.disabled?this.$element:this.toggleDisabled())},t.prototype.toggleDisabled=function(){return this.options.disabled=!this.options.disabled,this.$element.prop("disabled",this.options.disabled),this.$wrapper.toggleClass(this.options.baseClass+"-disabled"),this.$element},t.prototype.readonly=function(t){return"undefined"==typeof t?this.options.readonly:(t=!!t,t===this.options.readonly?this.$element:this.toggleReadonly())},t.prototype.toggleReadonly=function(){return this.options.readonly=!this.options.readonly,this.$element.prop("readonly",this.options.readonly),this.$wrapper.toggleClass(this.options.baseClass+"-readonly"),this.$element},t.prototype.indeterminate=function(t){return"undefined"==typeof t?this.options.indeterminate:(t=!!t,t===this.options.indeterminate?this.$element:this.toggleIndeterminate())},t.prototype.toggleIndeterminate=function(){return this.options.indeterminate=!this.options.indeterminate,this.$element.prop("indeterminate",this.options.indeterminate),this.$wrapper.toggleClass(this.options.baseClass+"-indeterminate"),this._containerPosition(),this.$element},t.prototype.inverse=function(t){return"undefined"==typeof t?this.options.inverse:(t=!!t,t===this.options.inverse?this.$element:this.toggleInverse())},t.prototype.toggleInverse=function(){var t,e;return this.$wrapper.toggleClass(this.options.baseClass+"-inverse"),e=this.$on.clone(!0),t=this.$off.clone(!0),this.$on.replaceWith(t),this.$off.replaceWith(e),this.$on=t,this.$off=e,this.options.inverse=!this.options.inverse,this.$element},t.prototype.onColor=function(t){var e;return e=this.options.onColor,"undefined"==typeof t?e:(null!=e&&this.$on.removeClass(this.options.baseClass+"-"+e),this.$on.addClass(this.options.baseClass+"-"+t),this.options.onColor=t,this.$element)},t.prototype.offColor=function(t){var e;return e=this.options.offColor,"undefined"==typeof t?e:(null!=e&&this.$off.removeClass(this.options.baseClass+"-"+e),this.$off.addClass(this.options.baseClass+"-"+t),this.options.offColor=t,this.$element)},t.prototype.onText=function(t){return"undefined"==typeof t?this.options.onText:(this.$on.html(t),this._width(),this._containerPosition(),this.options.onText=t,this.$element)},t.prototype.offText=function(t){return"undefined"==typeof t?this.options.offText:(this.$off.html(t),this._width(),this._containerPosition(),this.options.offText=t,this.$element)},t.prototype.labelText=function(t){return"undefined"==typeof t?this.options.labelText:(this.$label.html(t),this._width(),this.options.labelText=t,this.$element)},t.prototype.handleWidth=function(t){return"undefined"==typeof t?this.options.handleWidth:(this.options.handleWidth=t,this._width(),this._containerPosition(),this.$element)},t.prototype.labelWidth=function(t){return"undefined"==typeof t?this.options.labelWidth:(this.options.labelWidth=t,this._width(),this._containerPosition(),this.$element)},t.prototype.baseClass=function(t){return this.options.baseClass},t.prototype.wrapperClass=function(t){return"undefined"==typeof t?this.options.wrapperClass:(t||(t=e.fn.bootstrapSwitch.defaults.wrapperClass),this.$wrapper.removeClass(this._getClasses(this.options.wrapperClass).join(" ")),this.$wrapper.addClass(this._getClasses(t).join(" ")),this.options.wrapperClass=t,this.$element)},t.prototype.radioAllOff=function(t){return"undefined"==typeof t?this.options.radioAllOff:(t=!!t,t===this.options.radioAllOff?this.$element:(this.options.radioAllOff=t,this.$element))},t.prototype.onInit=function(t){return"undefined"==typeof t?this.options.onInit:(t||(t=e.fn.bootstrapSwitch.defaults.onInit),this.options.onInit=t,this.$element)},t.prototype.onSwitchChange=function(t){return"undefined"==typeof t?this.options.onSwitchChange:(t||(t=e.fn.bootstrapSwitch.defaults.onSwitchChange),this.options.onSwitchChange=t,this.$element)},t.prototype.destroy=function(){var t;return t=this.$element.closest("form"),t.length&&t.off("reset.bootstrapSwitch").removeData("bootstrap-switch"),this.$container.children().not(this.$element).remove(),this.$element.unwrap().unwrap().off(".bootstrapSwitch").removeData("bootstrap-switch"),this.$element},t.prototype._width=function(){var t,e;return t=this.$on.add(this.$off),t.add(this.$label).css("width",""),e="auto"===this.options.handleWidth?Math.max(this.$on.width(),this.$off.width()):this.options.handleWidth,t.width(e),this.$label.width(function(t){return function(i,n){return"auto"!==t.options.labelWidth?t.options.labelWidth:e>n?e:n}}(this)),this._handleWidth=this.$on.outerWidth(),this._labelWidth=this.$label.outerWidth(),this.$container.width(2*this._handleWidth+this._labelWidth),this.$wrapper.width(this._handleWidth+this._labelWidth)},t.prototype._containerPosition=function(t,e){return null==t&&(t=this.options.state),this.$container.css("margin-left",function(e){return function(){var i;return i=[0,"-"+e._handleWidth+"px"],e.options.indeterminate?"-"+e._handleWidth/2+"px":t?e.options.inverse?i[1]:i[0]:e.options.inverse?i[0]:i[1]}}(this)),e?setTimeout(function(){return e()},50):void 0},t.prototype._init=function(){var t,e;return t=function(t){return function(){return t.setPrevOptions(),t._width(),t._containerPosition(null,function(){return t.options.animate?t.$wrapper.addClass(t.options.baseClass+"-animate"):void 0})}}(this),this.$wrapper.is(":visible")?t():e=i.setInterval(function(n){return function(){return n.$wrapper.is(":visible")?(t(),i.clearInterval(e)):void 0}}(this),50)},t.prototype._elementHandlers=function(){return this.$element.on({"setPreviousOptions.bootstrapSwitch":function(t){return function(e){return t.setPrevOptions()}}(this),"previousState.bootstrapSwitch":function(t){return function(e){return t.options=t.prevOptions,t.options.indeterminate&&t.$wrapper.addClass(t.options.baseClass+"-indeterminate"),t.$element.prop("checked",t.options.state).trigger("change.bootstrapSwitch",!0)}}(this),"change.bootstrapSwitch":function(t){return function(i,n){var o;return i.preventDefault(),i.stopImmediatePropagation(),o=t.$element.is(":checked"),t._containerPosition(o),o!==t.options.state?(t.options.state=o,t.$wrapper.toggleClass(t.options.baseClass+"-off").toggleClass(t.options.baseClass+"-on"),n?void 0:(t.$element.is(":radio")&&e("[name='"+t.$element.attr("name")+"']").not(t.$element).prop("checked",!1).trigger("change.bootstrapSwitch",!0),t.$element.trigger("switchChange.bootstrapSwitch",[o]))):void 0}}(this),"focus.bootstrapSwitch":function(t){return function(e){return e.preventDefault(),t.$wrapper.addClass(t.options.baseClass+"-focused")}}(this),"blur.bootstrapSwitch":function(t){return function(e){return e.preventDefault(),t.$wrapper.removeClass(t.options.baseClass+"-focused")}}(this),"keydown.bootstrapSwitch":function(t){return function(e){if(e.which&&!t.options.disabled&&!t.options.readonly)switch(e.which){case 37:return e.preventDefault(),e.stopImmediatePropagation(),t.state(!1);case 39:return e.preventDefault(),e.stopImmediatePropagation(),t.state(!0)}}}(this)})},t.prototype._handleHandlers=function(){return this.$on.on("click.bootstrapSwitch",function(t){return function(e){return e.preventDefault(),e.stopPropagation(),t.state(!1),t.$element.trigger("focus.bootstrapSwitch")}}(this)),this.$off.on("click.bootstrapSwitch",function(t){return function(e){return e.preventDefault(),e.stopPropagation(),t.state(!0),t.$element.trigger("focus.bootstrapSwitch")}}(this))},t.prototype._labelHandlers=function(){return this.$label.on({click:function(t){return t.stopPropagation()},"mousedown.bootstrapSwitch touchstart.bootstrapSwitch":function(t){return function(e){return t._dragStart||t.options.disabled||t.options.readonly?void 0:(e.preventDefault(),e.stopPropagation(),t._dragStart=(e.pageX||e.originalEvent.touches[0].pageX)-parseInt(t.$container.css("margin-left"),10),t.options.animate&&t.$wrapper.removeClass(t.options.baseClass+"-animate"),t.$element.trigger("focus.bootstrapSwitch"))}}(this),"mousemove.bootstrapSwitch touchmove.bootstrapSwitch":function(t){return function(e){var i;if(null!=t._dragStart&&(e.preventDefault(),i=(e.pageX||e.originalEvent.touches[0].pageX)-t._dragStart,!(i<-t._handleWidth||i>0)))return t._dragEnd=i,t.$container.css("margin-left",t._dragEnd+"px")}}(this),"mouseup.bootstrapSwitch touchend.bootstrapSwitch":function(t){return function(e){var i;if(t._dragStart)return e.preventDefault(),t.options.animate&&t.$wrapper.addClass(t.options.baseClass+"-animate"),t._dragEnd?(i=t._dragEnd>-(t._handleWidth/2),t._dragEnd=!1,t.state(t.options.inverse?!i:i)):t.state(!t.options.state),t._dragStart=!1}}(this),"mouseleave.bootstrapSwitch":function(t){return function(e){return t.$label.trigger("mouseup.bootstrapSwitch")}}(this)})},t.prototype._externalLabelHandler=function(){var t;return t=this.$element.closest("label"),t.on("click",function(e){return function(i){return i.preventDefault(),i.stopImmediatePropagation(),i.target===t[0]?e.toggleState():void 0}}(this))},t.prototype._formHandler=function(){var t;return t=this.$element.closest("form"),t.data("bootstrap-switch")?void 0:t.on("reset.bootstrapSwitch",function(){return i.setTimeout(function(){return t.find("input").filter(function(){return e(this).data("bootstrap-switch")}).each(function(){return e(this).bootstrapSwitch("state",this.checked)})},1)}).data("bootstrap-switch",!0)},t.prototype._getClasses=function(t){var i,n,o,s;if(!e.isArray(t))return[this.options.baseClass+"-"+t];for(n=[],o=0,s=t.length;s>o;o++)i=t[o],n.push(this.options.baseClass+"-"+i);return n},t}(),e.fn.bootstrapSwitch=function(){var i,o,s;return o=arguments[0],i=2<=arguments.length?t.call(arguments,1):[],s=this,this.each(function(){var t,a;return t=e(this),a=t.data("bootstrap-switch"),a||t.data("bootstrap-switch",a=new n(this,o)),"string"==typeof o?s=a[o].apply(a,i):void 0}),s},e.fn.bootstrapSwitch.Constructor=n,e.fn.bootstrapSwitch.defaults={state:!0,size:null,animate:!0,disabled:!1,readonly:!1,indeterminate:!1,inverse:!1,radioAllOff:!1,onColor:"primary",offColor:"default",onText:"ON",offText:"OFF",labelText:" ",handleWidth:"auto",labelWidth:"auto",baseClass:"bootstrap-switch",wrapperClass:"wrapper",onInit:function(){},onSwitchChange:function(){}}}(window.jQuery,window)}).call(this); \ No newline at end of file diff --git a/monkey_island/cc/admin/ui/js/monkeys-admin.js b/monkey_island/cc/admin/ui/js/monkeys-admin.js index 760a5e728..190542f7e 100644 --- a/monkey_island/cc/admin/ui/js/monkeys-admin.js +++ b/monkey_island/cc/admin/ui/js/monkeys-admin.js @@ -21,15 +21,27 @@ $.getJSON(jsonFile, function(json) { var network = null; var nodes = []; var edges = []; +var numOfParentLinks = 0; +var numOfTunnelLinks = 0; +var numOfScanLinks = 0; + +var showScannedHosts = true; // Images/icons constants const ICONS_DIR = "./css/img/objects/"; const ICONS_EXT = ".png"; +const HOST_TYPE_MONKEY = "monkey"; +const HOST_TYPE_SCAN = "scanned"; + const EDGE_TYPE_PARENT = "parent"; const EDGE_TYPE_TUNNEL = "tunnel"; const EDGE_TYPE_SCAN = "scan"; +const EDGE_COLOR_PARENT = "red"; +const EDGE_COLOR_TUNNEL = "blue"; +const EDGE_COLOR_SCAN = "gray"; + // General options // If variable from local storage != null, assign it, otherwise set it's default value. @@ -59,6 +71,8 @@ function initAdmin() { edges: edges }; + updateCounters(); + var options = { }; @@ -67,6 +81,9 @@ function initAdmin() { network = new vis.Network(container, data, options); + $("[name='chboxShowScanned']").bootstrapSwitch('onSwitchChange', toggleScannedHosts); + $("[name='chboxMonkeyEnabled']").bootstrapSwitch('onSwitchChange', toggleMonkeyEnabled); + prepareSearchEngine(); monkeyCfg = new JSONEditor(document.getElementById('monkey-config'),{ @@ -115,6 +132,55 @@ function initAdmin() { 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 0) { + refreshDrawing(); + updateCounters(); + } }); } } @@ -297,6 +375,13 @@ function buildMonkeyDescription(monkey) { 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 @@ -370,7 +455,8 @@ function onSelect(properties) { var content = "No selection" $("#selectionInfo").html(content); $('#monkey-config').hide() - $('#btnConfigLoad, #btnConfigUpdate, #btnKillMonkey, #btnReviveMonkey').hide(); + $('#btnConfigLoad, #btnConfigUpdate').hide(); + $('#monkey-enabled').hide(); telemTable.clear(); telemTable.draw(); } @@ -403,14 +489,12 @@ function onNodeSelect(nodeId) { loadMonkeyConfig(); if (monkey.config.alive) { - $('#btnKillMonkey').show(); - $('#btnReviveMonkey').hide(); + $("[name='chboxMonkeyEnabled']").bootstrapSwitch('state', true); } else { - $('#btnKillMonkey').hide(); - $('#btnReviveMonkey').show(); + $("[name='chboxMonkeyEnabled']").bootstrapSwitch('state', false); } - + $('#monkey-enabled').show(); $.getJSON('/api/telemetry/' + monkey.guid, function(json) { 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() { var curr_config = monkeyCfg.getValue(); curr_config.alive = false; diff --git a/monkey_island/readme.txt b/monkey_island/readme.txt index 1e9408e6c..edc101a13 100644 --- a/monkey_island/readme.txt +++ b/monkey_island/readme.txt @@ -11,27 +11,19 @@ How to set C&C server: python -m pip install Flask-Pymongo python -m pip install Flask-Restful python -m pip install python-dateutil - mkdir C:\MonkeyIsland\bin - mkdir C:\MonkeyIsland\db - mkdir C:\MonkeyIsland\cc\binaries -4. Put monkey binaries in C:\MonkeyIsland\cc\binaries: + mkdir MonkeyIsland\bin + mkdir MonkeyIsland\db + mkdir MonkeyIsland\cc\binaries +4. Put monkey binaries in MonkeyIsland\cc\binaries: monkey-linux-64 - monkey binary for linux 64bit monkey-linux-32 - monkey binary for linux 32bit monkey-windows-32.exe - monkey binary for windows 32bit 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 5. Install OpenSSL https://slproweb.com/download/Win64OpenSSL_Light-1_0_2d.exe -6. Generate SSL Certificate, Run create_certificate.bat - -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 +6. Generate SSL Certificate, run create_certificate.bat when your current working directory is MonkeyIsland How to run: 1. start run_mongodb.bat