Exemple #1
0
    def start_analysis(self, options, monitor):
        """Start analysis.
        @param options: options.
        @return: operation status.
        """
        # TODO Deal with unicode URLs, should probably try URL encoding.
        # Unicode files are being taken care of.

        self.timeout = options["timeout"] + config("cuckoo:timeouts:critical")

        url = "http://{0}:{1}".format(self.ip, CUCKOO_GUEST_PORT)
        self.server = TimeoutServer(url, allow_none=True, timeout=self.timeout)

        try:
            # Wait for the agent to respond. This is done to check the
            # availability of the agent and verify that it's ready to receive
            # data.
            self.wait(CUCKOO_GUEST_INIT)
            if not self.do_run:
                return

            # Invoke the upload of the analyzer to the guest.
            self.upload_analyzer(monitor)

            # Give the analysis options to the guest, so it can generate the
            # analysis.conf inside the guest.
            try:
                self.server.add_config(options)
            except:
                raise CuckooGuestError(
                    "%s: unable to upload config to analysis machine" %
                    self.id)

            # If the target of the analysis is a file, upload it to the guest.
            if options["category"] in ("file", "archive"):
                try:
                    file_data = open(options["target"], "rb").read()
                except (IOError, OSError) as e:
                    raise CuckooGuestError("Unable to read %s, error: %s" %
                                           (options["target"], e))

                data = xmlrpclib.Binary(file_data)

                try:
                    self.server.add_malware(data, options["file_name"])
                except Exception as e:
                    raise CuckooGuestError(
                        "#%s: unable to upload malware to analysis "
                        "machine: %s" % (self.id, e))

            # Launch the analyzer.
            pid = self.server.execute()
            log.debug("%s: analyzer started with PID %d", self.id, pid)
        # If something goes wrong when establishing the connection, raise an
        # exception and abort the analysis.
        except (socket.timeout, socket.error):
            raise CuckooGuestError(
                "%s: guest communication timeout, check networking or try "
                "to increase timeout" % self.id)
Exemple #2
0
    def wait_for_completion(self):
        if self.is_old:
            self.old.wait_for_completion()
            return

        end = time.time() + self.timeout

        while db.guest_get_status(self.task_id) == "running":
            log.debug("%s: analysis still processing", self.vmid)

            time.sleep(1)

            # If the analysis hits the critical timeout, just return straight
            # away and try to recover the analysis results from the guest.
            if time.time() > end:
                raise CuckooGuestError("The analysis hit the critical timeout, terminating.")

            try:
                status = self.get("/status", timeout=5).json()
            except Exception as e:
                log.info("Virtual Machine /status failed (%r)", e)
                # this might fail due to timeouts or just temporary network issues
                # thus we don't want to abort the analysis just yet and wait for things to
                # recover
                continue

            if status["status"] == "complete":
                log.info("%s: analysis completed successfully", self.vmid)
                return
            elif status["status"] == "exception":
                log.warning(
                    "%s: analysis caught an exception\n%s",
                    self.vmid, status["description"]
                )
                return
Exemple #3
0
def analyzer_zipfile(platform, monitor):
    """Creates the Zip file that is sent to the Guest."""
    t = time.time()

    zip_data = io.BytesIO()
    zip_file = zipfile.ZipFile(zip_data, "w", zipfile.ZIP_STORED)

    # Select the proper analyzer's folder according to the operating
    # system associated with the current machine.
    root = cwd("analyzer", platform)
    root_len = len(os.path.abspath(root))

    if not os.path.exists(root):
        log.error("No valid analyzer found at path: %s", root)
        raise CuckooGuestError(
            "No valid analyzer found for %s platform!" % platform
        )

    # Walk through everything inside the analyzer's folder and write
    # them to the zip archive.
    for root, dirs, files in os.walk(root):
        archive_root = os.path.abspath(root)[root_len:]
        for name in files:
            path = os.path.join(root, name)
            archive_name = os.path.join(archive_root, name)
            zip_file.write(path, archive_name)

    # Include the chosen monitoring component.
    if platform == "windows":
        dirpath = cwd("monitor", monitor)

        # Sometimes we might get a file instead of a symbolic link, in that
        # case we follow the semi-"symbolic link" manually.
        if os.path.isfile(dirpath):
            monitor = os.path.basename(open(dirpath, "rb").read().strip())
            dirpath = cwd("monitor", monitor)

        for name in os.listdir(dirpath):
            path = os.path.join(dirpath, name)
            archive_name = os.path.join("/bin", name)
            zip_file.write(path, archive_name)
    elif platform == "linux":
        pass
        #modify by xuyuu
        #stpdir = cwd("monitor_linux")
        #stpfile = os.path.join(stpdir, "strace.stp")
        #zip_file.write(stpfile)

    zip_file.close()
    data = zip_data.getvalue()

    if time.time() - t > 10:
        log.warning(
            "It took more than 10 seconds to build the Analyzer Zip for the "
            "Guest. This might be a serious performance penalty. Is your "
            "analyzer/windows/ directory bloated with unnecessary files?"
        )

    return data
Exemple #4
0
def analyzer_zipfile(platform, monitor):
    """Creates the Zip file that is sent to the Guest."""
    t = time.time()

    zip_data = io.BytesIO()
    zip_file = zipfile.ZipFile(zip_data, "w", zipfile.ZIP_STORED)

    # Select the proper analyzer's folder according to the operating
    # system associated with the current machine.
    root = cwd("analyzer", platform)
    root_len = len(os.path.abspath(root))

    if not os.path.exists(root):
        log.error("No valid analyzer found at path: %s", root)
        raise CuckooGuestError(
            "No valid analyzer found for %s platform!" % platform
        )

    # Walk through everything inside the analyzer's folder and write
    # them to the zip archive.
    for root, dirs, files in os.walk(root):
        archive_root = os.path.abspath(root)[root_len:]
        for name in files:
            path = os.path.join(root, name)
            archive_name = os.path.join(archive_root, name)
            zip_file.write(path, archive_name)

    # Include the chosen monitoring component and any additional files.
    if platform == "windows":
        dirpath = cwd("monitor", monitor)

        # Generally speaking we should no longer be getting symbolic links for
        # "latest" anymore, so in the case of a file; follow it.
        if os.path.isfile(dirpath):
            monitor = os.path.basename(open(dirpath, "rb").read().strip())
            dirpath = cwd("monitor", monitor)

        for name in os.listdir(dirpath):
            zip_file.write(
                os.path.join(dirpath, name), os.path.join("bin", name)
            )

        # Dump compiled "dumpmem" Yara rules for zer0m0n usage.
        zip_file.write(cwd("stuff", "dumpmem.yarac"), "bin/rules.yarac")

    zip_file.close()
    data = zip_data.getvalue()

    if time.time() - t > 10:
        log.warning(
            "It took more than 10 seconds to build the Analyzer Zip for the "
            "Guest. This might be a serious performance penalty. Is your "
            "analyzer/windows/ directory bloated with unnecessary files?"
        )

    return data
Exemple #5
0
    def wait_for_completion(self):
        """Wait for analysis completion.
        @return: operation status.
        """
        log.debug("%s: waiting for completion", self.id)

        end = time.time() + self.timeout
        self.server._set_timeout(self.timeout)

        while db.guest_get_status(self.task_id) == "running":
            time.sleep(1)

            # If the analysis hits the critical timeout, just return straight
            # away and try to recover the analysis results from the guest.
            if time.time() > end:
                raise CuckooGuestError(
                    "The analysis hit the critical timeout, terminating."
                )

            try:
                status = self.server.get_status()
            except Exception as e:
                log.debug("%s: error retrieving status: %s", self.id, e)
                continue

            # React according to the returned status.
            if status == CUCKOO_GUEST_COMPLETED:
                log.info("%s: analysis completed successfully", self.id)
                break
            elif status == CUCKOO_GUEST_FAILED:
                error = self.server.get_error()
                raise CuckooGuestError(
                    "Analysis failed: %s" % (error or "unknown error")
                )
            else:
                log.debug("%s: analysis not completed yet (status=%s)",
                          self.id, status)

        self.server._set_timeout(None)
Exemple #6
0
    def post(self, method, *args, **kwargs):
        """Simple wrapper around requests.post()."""
        url = "http://%s:%s%s" % (self.ipaddr, self.port, method)
        session = requests.Session()
        session.trust_env = False
        session.proxies = None

        try:
            r = session.post(url, *args, **kwargs)
        except requests.ConnectionError:
            raise CuckooGuestError(
                "Cuckoo Agent failed without error status, please try "
                "upgrading to the latest version of agent.py (>= 0.10) and "
                "notify us if the issue persists.")

        r.raise_for_status()
        return r
Exemple #7
0
    def upload_analyzer(self, monitor):
        """Upload analyzer to guest.
        @return: operation status.
        """
        zip_data = analyzer_zipfile(self.platform, monitor)

        log.debug(
            "Uploading analyzer to guest (id=%s, ip=%s, monitor=%s, size=%d)",
            self.id, self.ip, monitor, len(zip_data))

        # Send the zip containing the analyzer to the agent running inside
        # the guest.
        try:
            self.server.add_analyzer(xmlrpclib.Binary(zip_data))
        except socket.timeout:
            raise CuckooGuestError("{0}: guest communication timeout: unable "
                                   "to upload agent, check networking or try "
                                   "to increase timeout".format(self.id))