forked from p15670423/monkey
Added auto-scan subnets option
Monkey is now able to auto scan the local host subnets, removing the need to preconfigure it to scan the network subnets (option is on by default)
This commit is contained in:
parent
1449f1ef93
commit
3da0c1a57c
|
@ -141,12 +141,15 @@ class Configuration(object):
|
|||
|
||||
retry_failed_explotation = True
|
||||
|
||||
internet_services = ["www.guardicore.com", "www.google.com"]
|
||||
internet_services = ["monkey.guardicore.com", "www.google.com"]
|
||||
|
||||
###########################
|
||||
# scanners config
|
||||
###########################
|
||||
|
||||
# Auto detect and scan local subnets
|
||||
local_network_scan = True
|
||||
|
||||
range_class = FixedRange
|
||||
range_size = 1
|
||||
range_fixed = ["", ]
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -4,46 +4,74 @@ import socket
|
|||
import struct
|
||||
import array
|
||||
import psutil
|
||||
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):
|
||||
|
@ -60,9 +88,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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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 "<FixedRange %s>" % (",".join(self._fixed_addresses))
|
||||
|
|
|
@ -22,6 +22,7 @@ Windows:
|
|||
python -m pip install odict
|
||||
python -m pip install paramiko
|
||||
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:
|
||||
|
|
Loading…
Reference in New Issue