Exemplo n.º 1
0
    def handle(self):
        ip, port = self.client_address
        self.connect_time = datetime.datetime.now()

        self.storagepath = self.server.build_storage_path(ip)
        if not self.storagepath:
            return

        task, _ = self.server.get_ctx_for_ip(ip)
        task_log_start(task.id)

        # Create all missing folders for this analysis.
        self.create_folders()

        try:
            # Initialize the protocol handler class for this connection.
            self.negotiate_protocol()

            for event in self.protocol:
                if isinstance(self.protocol, BsonParser) and event["type"] == "process":
                    self.open_process_log(event)

        except CuckooResultError as e:
            log.warning(
                "ResultServer connection stopping because of "
                "CuckooResultError: %s.", e
            )
        except (Disconnect, socket.error):
            pass
        except:
            log.exception("FIXME - exception in resultserver connection %s",
                          self.client_address)

        task_log_stop(task.id)
Exemplo n.º 2
0
    def handle(self):
        ip, port = self.client_address
        self.connect_time = datetime.datetime.now()

        self.storagepath = self.server.build_storage_path(ip)
        if not self.storagepath:
            return

        task, _ = self.server.get_ctx_for_ip(ip)
        task_log_start(task.id)

        # Create all missing folders for this analysis.
        self.create_folders()

        try:
            # Initialize the protocol handler class for this connection.
            self.negotiate_protocol()

            for event in self.protocol:
                if isinstance(self.protocol,
                              BsonParser) and event["type"] == "process":
                    self.open_process_log(event)

        except CuckooResultError as e:
            log.warning(
                "ResultServer connection stopping because of "
                "CuckooResultError: %s.", e)
        except (Disconnect, socket.error):
            pass
        except:
            log.exception("FIXME - exception in resultserver connection %s",
                          self.client_address)

        task_log_stop(task.id)
Exemplo n.º 3
0
    def handle(self, sock, addr):
        """Handle the incoming connection.
        Gevent will close the socket when the function returns."""
        ipaddr = addr[0]

        with self.task_mgmt_lock:
            task_id = self.tasks.get(ipaddr)
            if not task_id:
                log.warning("ResultServer did not have a task for IP %s",
                            ipaddr)
                return

        self.storagepath = os.path.join(CUCKOO_ROOT, "storage", "analyses",
                                        str(task_id))

        # Create all missing folders for this analysis.
        self.create_folders()

        ctx = HandlerContext(task_id, self.storagepath, sock)
        task_log_start(task_id)
        try:
            try:
                protocol = self.negotiate_protocol(task_id, ctx)
            except EOFError:
                return

            # Registering the context allows us to abort the handler by
            # shutting down its socket when the task is deleted; this should
            # prevent lingering sockets
            with self.task_mgmt_lock:
                # NOTE: the task may have been cancelled during the negotation
                # protocol and a different task for that IP address may have
                # been registered
                if self.tasks.get(ipaddr) != task_id:
                    log.warning(
                        "Task #%s for IP %s was cancelled during "
                        "negotiation", task_id, ipaddr)
                    return
                s = self.handlers.setdefault(task_id, set())
                s.add(ctx)

            try:
                with protocol:
                    protocol.handle()
            except CuckooOperationalError as e:
                log.error(e)
            finally:
                with self.task_mgmt_lock:
                    s.discard(ctx)
                ctx.cancel()
                if ctx.buf:
                    # This is usually not a good sign
                    log.warning(
                        "Task #%s with protocol %s has unprocessed "
                        "data before getting disconnected", task_id, protocol)
        finally:
            task_log_stop(task_id)
Exemplo n.º 4
0
    def launch_analysis(self):
        """Start analysis."""
        succeeded = False

        target = self.task.target
        if self.task.category == "file":
            target = os.path.basename(target)

        log.info("Starting analysis of %s \"%s\" (task #%d, options \"%s\")",
                 self.task.category.upper(), target, self.task.id,
                 emit_options(self.task.options))

        # Initialize the analysis folders.
        if not self.init_storage():
            return False

        # Initiates per-task logging.
        task_log_start(self.task.id)

        self.store_task_info()

        if self.task.category == "file":
            # Check if we have permissions to access the file.
            # And fail this analysis if we don't have access to the file.
            if not self.check_permissions():
                return False
                
            # Check whether the file has been changed for some unknown reason.
            # And fail this analysis if it has been modified.
            if not self.check_file():
                return False

            # Store a copy of the original file.
            if not self.store_file():
                return False

        # Acquire analysis machine.
        try:
            self.acquire_machine()
        except CuckooOperationalError as e:
            machine_lock.release()
            log.error("Cannot acquire machine: {0}".format(e))
            return False

        # At this point we can tell the ResultServer about it.
        try:
            ResultServer().add_task(self.task, self.machine)
        except Exception as e:
            machinery.release(self.machine.label)
            self.errors.put(e)

        # Initialize the guest manager.
        self.guest_manager = GuestManager(
            self.machine.name, self.machine.ip,
            self.machine.platform, self.task.id, self
        )

        self.aux = RunAuxiliary(self.task, self.machine, self.guest_manager)
        self.aux.start()

        # Generate the analysis configuration file.
        options = self.build_options()

        try:
            unlocked = False
            self.interface = None

            # Mark the selected analysis machine in the database as started.
            guest_log = self.db.guest_start(self.task.id,
                                            self.machine.name,
                                            self.machine.label,
                                            machinery.__class__.__name__)
            # Start the machine.
            machinery.start(self.machine.label, self.task)

            # Enable network routing.
            self.route_network()

            # By the time start returns it will have fully started the Virtual
            # Machine. We can now safely release the machine lock.
            machine_lock.release()
            unlocked = True

            # Run and manage the components inside the guest unless this
            # machine has the "noagent" option specified (please refer to the
            # wait_finish() function for more details on this function).
            if "noagent" not in self.machine.options:
                self.guest_manage(options)
            else:
                self.wait_finish()

            succeeded = True
        except CuckooMachineError as e:
            if not unlocked:
                machine_lock.release()
            log.error(
                "Machinery error: %s",
                e, extra={"task_id": self.task.id}
            )
            log.critical(
                "A critical error has occurred trying to use the machine "
                "with name %s during an analysis due to which it is no "
                "longer in a working state, please report this issue and all "
                "of the related environment details to the developers so we "
                "can improve this situation. (Note that before we would "
                "simply remove this VM from doing any more analyses, but as "
                "all the VMs will eventually be depleted that way, hopefully "
                "we'll find a better solution now).", self.machine.name,
            )
        except CuckooGuestError as e:
            if not unlocked:
                machine_lock.release()
            log.error(
                "Error from the Cuckoo Guest: %s",
                e, extra={"task_id": self.task.id}
            )
        finally:
            # Stop Auxiliary modules.
            self.aux.stop()

            # Take a memory dump of the machine before shutting it off.
            if self.cfg.cuckoo.memory_dump or self.task.memory:
                try:
                    dump_path = os.path.join(self.storage, "memory.dmp")
                    machinery.dump_memory(self.machine.label, dump_path)
                except NotImplementedError:
                    log.error("The memory dump functionality is not available "
                              "for the current machine manager.")
                except CuckooMachineError as e:
                    log.error("Machinery error: %s", e)

            try:
                # Stop the analysis machine.
                machinery.stop(self.machine.label)
            except CuckooMachineError as e:
                log.warning("Unable to stop machine %s: %s",
                            self.machine.label, e)

            # Mark the machine in the database as stopped. Unless this machine
            # has been marked as dead, we just keep it as "started" in the
            # database so it'll not be used later on in this session.
            self.db.guest_stop(guest_log)

            # After all this, we can make the ResultServer forget about the
            # internal state for this analysis task.
            ResultServer().del_task(self.task, self.machine)

            # Drop the network routing rules if any.
            self.unroute_network()

            try:
                # Release the analysis machine. But only if the machine has
                # not turned dead yet.
                machinery.release(self.machine.label)
            except CuckooMachineError as e:
                log.error("Unable to release machine %s, reason %s. "
                          "You might need to restore it manually.",
                          self.machine.label, e)

        return succeeded
Exemplo n.º 5
0
    def launch_analysis(self):
        """Start analysis."""
        succeeded = False

        target = self.task.target
        if self.task.category == "file":
            target = os.path.basename(target)

        log.info("Starting analysis of %s \"%s\" (task #%d, options \"%s\")",
                 self.task.category.upper(), target, self.task.id,
                 emit_options(self.task.options))

        # Initialize the analysis folders.
        if not self.init_storage():
            return False

        # Initiates per-task logging.
        task_log_start(self.task.id)

        self.store_task_info()

        if self.task.category == "file":
            # Check if we have permissions to access the file.
            # And fail this analysis if we don't have access to the file.
            if not self.check_permissions():
                return False

            # Check whether the file has been changed for some unknown reason.
            # And fail this analysis if it has been modified.
            if not self.check_file():
                return False

            # Store a copy of the original file.
            if not self.store_file():
                return False

        # Acquire analysis machine.
        try:
            self.acquire_machine()
        except CuckooOperationalError as e:
            machine_lock.release()
            log.error("Cannot acquire machine: {0}".format(e))
            return False

        # At this point we can tell the ResultServer about it.
        try:
            ResultServer().add_task(self.task, self.machine)
        except Exception as e:
            machinery.release(self.machine.label)
            self.errors.put(e)

        # Initialize the guest manager.
        self.guest_manager = GuestManager(self.machine.name, self.machine.ip,
                                          self.machine.platform, self.task.id,
                                          self)

        self.aux = RunAuxiliary(self.task, self.machine, self.guest_manager)
        self.aux.start()

        # Generate the analysis configuration file.
        options = self.build_options()

        try:
            unlocked = False
            self.interface = None

            # Mark the selected analysis machine in the database as started.
            guest_log = self.db.guest_start(self.task.id, self.machine.name,
                                            self.machine.label,
                                            machinery.__class__.__name__)
            # Start the machine.
            machinery.start(self.machine.label, self.task)

            # Enable network routing.
            self.route_network()

            # By the time start returns it will have fully started the Virtual
            # Machine. We can now safely release the machine lock.
            machine_lock.release()
            unlocked = True

            # Run and manage the components inside the guest unless this
            # machine has the "noagent" option specified (please refer to the
            # wait_finish() function for more details on this function).
            if "noagent" not in self.machine.options:
                self.guest_manage(options)
            else:
                self.wait_finish()

            succeeded = True
        except CuckooMachineError as e:
            if not unlocked:
                machine_lock.release()
            log.error("Machinery error: %s",
                      e,
                      extra={"task_id": self.task.id})
            log.critical(
                "A critical error has occurred trying to use the machine "
                "with name %s during an analysis due to which it is no "
                "longer in a working state, please report this issue and all "
                "of the related environment details to the developers so we "
                "can improve this situation. (Note that before we would "
                "simply remove this VM from doing any more analyses, but as "
                "all the VMs will eventually be depleted that way, hopefully "
                "we'll find a better solution now).",
                self.machine.name,
            )
        except CuckooGuestError as e:
            if not unlocked:
                machine_lock.release()
            log.error("Error from the Cuckoo Guest: %s",
                      e,
                      extra={"task_id": self.task.id})
        finally:
            # Stop Auxiliary modules.
            self.aux.stop()

            # Take a memory dump of the machine before shutting it off.
            if self.cfg.cuckoo.memory_dump or self.task.memory:
                try:
                    dump_path = os.path.join(self.storage, "memory.dmp")
                    machinery.dump_memory(self.machine.label, dump_path)
                except NotImplementedError:
                    log.error("The memory dump functionality is not available "
                              "for the current machine manager.")
                except CuckooMachineError as e:
                    log.error("Machinery error: %s", e)

            try:
                # Stop the analysis machine.
                machinery.stop(self.machine.label)
            except CuckooMachineError as e:
                log.warning("Unable to stop machine %s: %s",
                            self.machine.label, e)

            # Mark the machine in the database as stopped. Unless this machine
            # has been marked as dead, we just keep it as "started" in the
            # database so it'll not be used later on in this session.
            self.db.guest_stop(guest_log)

            # After all this, we can make the ResultServer forget about the
            # internal state for this analysis task.
            ResultServer().del_task(self.task, self.machine)

            # Drop the network routing rules if any.
            self.unroute_network()

            try:
                # Release the analysis machine. But only if the machine has
                # not turned dead yet.
                machinery.release(self.machine.label)
            except CuckooMachineError as e:
                log.error(
                    "Unable to release machine %s, reason %s. "
                    "You might need to restore it manually.",
                    self.machine.label, e)

        return succeeded