예제 #1
0
    def wakeup(parent=None, has_internet_access=None):
        if parent:
            LOG.debug("parent: %s" % (parent, ))

        hostname = gethostname()
        if not parent:
            parent = GUID

        if has_internet_access is None:
            has_internet_access = check_internet_access(
                WormConfiguration.internet_services)

        monkey = {
            'guid': GUID,
            'hostname': hostname,
            'ip_addresses': local_ips(),
            'description': " ".join(platform.uname()),
            'internet_access': has_internet_access,
            'config': WormConfiguration.as_dict(),
            'parent': parent
        }

        if ControlClient.proxies:
            monkey['tunnel'] = ControlClient.proxies.get('https')

        requests.post(
            "https://%s/api/monkey" %
            (WormConfiguration.current_server, ),  # noqa: DUO123
            data=json.dumps(monkey),
            headers={'content-type': 'application/json'},
            verify=False,
            proxies=ControlClient.proxies,
            timeout=20)
예제 #2
0
파일: control.py 프로젝트: vanyell/monkey
    def wakeup(parent=None, has_internet_access=None):
        if parent:
            LOG.debug("parent: %s" % (parent,))

        hostname = gethostname()
        if not parent:
            parent = GUID

        if has_internet_access is None:
            has_internet_access = check_internet_access(WormConfiguration.internet_services)

        monkey = {
            "guid": GUID,
            "hostname": hostname,
            "ip_addresses": local_ips(),
            "description": " ".join(platform.uname()),
            "internet_access": has_internet_access,
            "config": WormConfiguration.as_dict(),
            "parent": parent,
            "launch_time": str(datetime.now().strftime(DEFAULT_TIME_FORMAT)),
        }

        if ControlClient.proxies:
            monkey["tunnel"] = ControlClient.proxies.get("https")

        requests.post(  # noqa: DUO123
            "https://%s/api/monkey" % (WormConfiguration.current_server,),
            data=json.dumps(monkey),
            headers={"content-type": "application/json"},
            verify=False,
            proxies=ControlClient.proxies,
            timeout=20,
        )
예제 #3
0
파일: tunnel.py 프로젝트: zecchino1/monkey
    def set_tunnel_for_host(self, host):
        assert isinstance(host, VictimHost)

        if not self.local_port:
            return

        ip_match = get_close_matches(host.ip_addr, local_ips()) or self.l_ips
        host.default_tunnel = '%s:%d' % (ip_match[0], self.local_port)
예제 #4
0
파일: tunnel.py 프로젝트: zecchino1/monkey
    def run(self):
        self._broad_sock = _set_multicast_socket(self._timeout)
        self.l_ips = local_ips()
        self.local_port = get_free_tcp_port()

        if not self.local_port:
            return

        if not firewall.listen_allowed(localport=self.local_port):
            LOG.info("Machine firewalled, listen not allowed, not running tunnel.")
            return

        proxy = self._proxy_class(local_port=self.local_port, dest_host=self._target_addr, dest_port=self._target_port)
        LOG.info("Running tunnel using proxy class: %s, listening on port %s, routing to: %s:%s",
                 proxy.__class__.__name__,
                 self.local_port,
                 self._target_addr,
                 self._target_port)
        proxy.start()

        while not self._stopped:
            try:
                search, address = self._broad_sock.recvfrom(BUFFER_READ)
                if '?' == search:
                    ip_match = get_close_matches(address[0], self.l_ips) or self.l_ips
                    if ip_match:
                        answer = '%s:%d' % (ip_match[0], self.local_port)
                        LOG.debug("Got tunnel request from %s, answering with %s", address[0], answer)
                        self._broad_sock.sendto(answer, (address[0], MCAST_PORT))
                elif '+' == search:
                    if not address[0] in self._clients:
                        LOG.debug("Tunnel control: Added %s to watchlist", address[0])
                        self._clients.append(address[0])
                elif '-' == search:
                    LOG.debug("Tunnel control: Removed %s from watchlist", address[0])
                    self._clients = [client for client in self._clients if client != address[0]]

            except socket.timeout:
                continue

        LOG.info("Stopping tunnel, waiting for clients: %s" % repr(self._clients))

        # wait till all of the tunnel clients has been disconnected, or no one used the tunnel in QUIT_TIMEOUT seconds
        while self._clients and (time.time() - get_last_serve_time() < QUIT_TIMEOUT):
            try:
                search, address = self._broad_sock.recvfrom(BUFFER_READ)
                if '-' == search:
                    LOG.debug("Tunnel control: Removed %s from watchlist", address[0])
                    self._clients = [client for client in self._clients if client != address[0]]
            except socket.timeout:
                continue

        LOG.info("Closing tunnel")
        self._broad_sock.close()
        proxy.stop()
        proxy.join()
예제 #5
0
    def initialize(self):
        """
        Set up scanning.
        based on configuration: scans local network and/or scans fixed list of IPs/subnets.
        """
        # get local ip addresses
        self._ip_addresses = local_ips()

        if not self._ip_addresses:
            raise Exception("Cannot find local IP address for the machine")

        LOG.info("Found local IP addresses of the machine: %r", self._ip_addresses)
        # for fixed range, only scan once.
        self._ranges = [NetworkRange.get_range_obj(address_str=x) for x in WormConfiguration.subnet_scan_list]
        if WormConfiguration.local_network_scan:
            self._ranges += get_interfaces_ranges()
        self._ranges += self._get_inaccessible_subnets_ips()
        LOG.info("Base local networks to scan are: %r", self._ranges)
예제 #6
0
    def get_victim_machines(self, max_find=5, stop_callback=None):
        """
        Finds machines according to the ranges specified in the object
        :param max_find: Max number of victims to find regardless of ranges
        :param stop_callback: A callback to check at any point if we should stop scanning
        :return: yields a sequence of VictimHost instances
        """
        # We currently use the ITERATION_BLOCK_SIZE as the pool size, however, this may not be the best decision
        # However, the decision what ITERATION_BLOCK_SIZE also requires balancing network usage (pps and bw)
        # Because we are using this to spread out IO heavy tasks, we can probably go a lot higher than CPU core size
        # But again, balance
        pool = Pool(ITERATION_BLOCK_SIZE)
        victim_generator = VictimHostGenerator(self._ranges,
                                               WormConfiguration.blocked_ips,
                                               local_ips())

        victims_count = 0
        for victim_chunk in victim_generator.generate_victims(
                ITERATION_BLOCK_SIZE):
            LOG.debug("Scanning for potential victims in chunk %r",
                      victim_chunk)

            # check before running scans
            if stop_callback and stop_callback():
                LOG.debug("Got stop signal")
                return

            results = pool.map(self.scan_machine, victim_chunk)
            resulting_victims = filter(lambda x: x is not None, results)
            for victim in resulting_victims:
                LOG.debug("Found potential victim: %r", victim)
                victims_count += 1
                yield victim

                if victims_count >= max_find:
                    LOG.debug("Found max needed victims (%d), stopping scan",
                              max_find)
                    return
            if WormConfiguration.tcp_scan_interval:
                # time.sleep uses seconds, while config is in milliseconds
                time.sleep(WormConfiguration.tcp_scan_interval / float(1000))
예제 #7
0
파일: tunnel.py 프로젝트: zkbupt/monkey
def find_tunnel(default=None, attempts=3, timeout=DEFAULT_TIMEOUT):
    l_ips = local_ips()

    if default:
        if default.find(':') != -1:
            address, port = default.split(':', 1)
            if _check_tunnel(address, port):
                return address, port

    for adapter in l_ips:
        for attempt in range(0, attempts):
            try:
                LOG.info("Trying to find using adapter %s", adapter)
                sock = _set_multicast_socket(timeout, adapter)
                sock.sendto(b"?", (MCAST_GROUP, MCAST_PORT))
                tunnels = []

                while True:
                    try:
                        answer, address = sock.recvfrom(BUFFER_READ)
                        if answer not in [b'?', b'+', b'-']:
                            tunnels.append(answer)
                    except socket.timeout:
                        break

                for tunnel in tunnels:
                    if tunnel.find(':') != -1:
                        address, port = tunnel.split(':', 1)
                        if address in l_ips:
                            continue

                        if _check_tunnel(address, port, sock):
                            sock.close()
                            return address, port

            except Exception as exc:
                LOG.debug("Caught exception in tunnel lookup: %s", exc)
                continue

    return None
예제 #8
0
def is_running_on_server(ip: str) -> bool:
    return ip in local_ips()