Beispiel #1
0
    def upload_support_files(self, options):
        """ Upload supporting files from zip temp directory if they exist
        :param options: options
        :return:
        """
        log.info("Uploading support files to guest (id=%s, ip=%s)", self.id,
                 self.ip)
        basedir = os.path.dirname(options["target"])

        for dirpath, _, files in os.walk(basedir):
            for xf in files:
                target = os.path.join(dirpath, xf)
                # Copy all files except for the original target
                if not target == options["target"]:
                    try:
                        file_data = open(target, "rb").read()
                    except (IOError, OSError) as e:
                        raise CuckooGuestError(
                            "Unable to read {}, error: {}".format(target, e))

                    data = xmlrpclib.Binary(file_data)

                    try:
                        self.server.add_malware(data, xf)
                    except Exception as e:
                        raise CuckooGuestError(
                            "{}: unable to upload support file to "
                            "analysis machine: {}".format(self.id, e))
        return
Beispiel #2
0
    def start_analysis(self, options):
        """Start analysis.
        @param options: options.
        @return: operation status.
        """
        log.info("Starting analysis on guest (id=%s, ip=%s)", self.id, self.ip)

        # TODO: deal with unicode URLs.
        if options["category"] == "file":
            options["file_name"] = sanitize_filename(options["file_name"])

        # If the analysis timeout is higher than the critical timeout,
        # automatically increase the critical timeout by one minute.
        if options["timeout"] > self.timeout:
            log.debug("Automatically increased critical timeout to %s",
                      self.timeout)
            self.timeout = options["timeout"] + 60

        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)
            # Invoke the upload of the analyzer to the guest.
            self.upload_analyzer()
            # 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("{0}: unable to upload config to "
                                       "analysis machine".format(self.id))

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

                data = xmlrpclib.Binary(file_data)

                try:
                    self.server.add_malware(data, options["file_name"])
                except Exception as e:
                    raise CuckooGuestError("{0}: unable to upload malware to "
                                           "analysis machine: {1}".format(
                                               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("{0}: guest communication timeout, check "
                                   "networking or try to increase "
                                   "timeout".format(self.id))
Beispiel #3
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"] + self.cfg.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)

            # 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("{0}: unable to upload config to "
                                       "analysis machine".format(self.id))

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

                data = xmlrpclib.Binary(file_data)

                try:
                    self.server.add_malware(data, options["file_name"])
                except Exception as e:
                    raise CuckooGuestError("{0}: unable to upload malware to "
                                           "analysis machine: {1}".format(
                                               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("{0}: guest communication timeout, check "
                                   "networking or try to increase "
                                   "timeout".format(self.id))
Beispiel #4
0
    def wait_for_completion(self):
        """Wait for analysis completion.
        @return: operation status.
        """
        log.debug("%s: waiting for completion", self.id)

        # Same procedure as in self.wait(). Just look at the comments there.
        abort = Event()
        abort.clear()

        def die():
            abort.set()

        timer = Timer(self.timeout, die)
        timer.start()
        self.server._set_timeout(self.timeout)

        while True:
            time.sleep(1)

            # If the analysis hits the critical timeout, just return straight
            # straight away and try to recover the analysis results from the
            # guest.
            if abort.is_set():
                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()
                if not error:
                    error = "unknown error"

                raise CuckooGuestError("Analysis failed: {0}".format(error))
            else:
                log.debug("%s: analysis not completed yet (status=%s)",
                          self.id, status)

        self.server._set_timeout(None)
Beispiel #5
0
    def wait(self, status):
        """Waiting for status.
        @param status: status.
        @return: always True.
        """
        log.info("%s: waiting for status 0x%.04x", self.id, status)

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

        while True:
            # Check if we've passed the timeout.
            if time.time() > end:
                raise CuckooGuestError("{0}: the guest initialization hit the "
                                       "critical timeout, analysis "
                                       "aborted.".format(self.id))

            try:
                # If the server returns the given status, break the loop
                # and return.
                if self.server.get_status() == status:
                    log.info("%s: status ready", self.id)
                    break
            except:
                pass

            log.info("%s: not ready yet", self.id)
            time.sleep(1)

        self.server._set_timeout(None)
        return True
Beispiel #6
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.info("%s: analysis caught an exception\n%s", self.vmid,
                         status["description"])
                return
Beispiel #7
0
    def wait_for_completion(self):
        if self.is_old:
            self.old.wait_for_completion()
            return

        end = time.time() + self.timeout

        while True:
            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:
                log.info("Virtual Machine stopped abruptly")
                break

            if status["status"] == "complete":
                log.info("%s: analysis completed successfully", self.vmid)
                return
            elif status["status"] == "exception":
                log.info("%s: analysis caught an exception\n%s", self.vmid,
                         status["description"])
                return

            log.debug("%s: analysis still processing", self.vmid)
Beispiel #8
0
    def start_analysis(self, options):
        """Start analysis.
        @param options: options.
        @return: operation status.
        """
        if not os.path.exists(options["file_path"]):
            return False

        log.info("Starting analysis on guest (id=%s, ip=%s)" %
                 (self.id, self.ip))

        socket.setdefaulttimeout(180)

        try:
            self.wait(CUCKOO_GUEST_INIT)
            self.upload_analyzer()
            self.server.add_config(options)

            file_data = open(options["file_path"], "rb").read()
            data = xmlrpclib.Binary(file_data)

            self.server.add_malware(data, options["file_name"])
            self.server.execute()
        except socket.timeout:
            raise CuckooGuestError(
                "%s: guest communication timeout, check networking or try to increase timeout"
                % self.id)
Beispiel #9
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 True:
            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:
                self._fm.turn_off()
                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:
                self._fm.turn_off()
                log.info("%s: analysis completed successfully", self.id)
                break
            elif status == CUCKOO_GUEST_FAILED:
                error = self.server.get_error()
                if not error:
                    error = "unknown error"
                self._fm.turn_off()
                raise CuckooGuestError("Analysis failed: {0}".format(error))
            elif self._fm.check_frida_status():
                raise CuckooGuestError(
                    "Analysis failed: {0}".format("Frida is not working"))
            else:
                log.debug("%s: analysis not completed yet (status=%s)",
                          self.id, status)

        self.server._set_timeout(None)
Beispiel #10
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 True:
            time.sleep(0.2)

            # 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()
                if not error:
                    error = "unknown error"

                raise CuckooGuestError("Analysis failed: {0}".format(error))
            elif status == CUCKOO_GUEST_INIT:
                # means the system must have bluescreened or restarted and now we're getting the initial agent.py request again
                raise CuckooGuestError(
                    "Analysis failed: system restarted unexpectedly")
            else:
                log.debug("%s: analysis not completed yet (status=%s)",
                          self.id, status)

        self.server._set_timeout(None)
Beispiel #11
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(zip_data, "w", ZIP_STORED)

    # Select the proper analyzer's folder according to the operating
    # system associated with the current machine.
    root = os.path.join(CUCKOO_ROOT, "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 = os.path.join(CUCKOO_ROOT, "data", "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 = os.path.join(CUCKOO_ROOT, "data", "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)

    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
Beispiel #12
0
    def wait_for_completion(self):
        if self.is_old:
            self.old.wait_for_completion()
            return

        end = time.time() + self.timeout
        s = 0
        burn = False  # custom
        child = os.popen('python ~/cuckoo/child.py')  # custom
        log.debug('[MADE Child FLAG] python ~/cuckoo/child.py')
        FIN_flag = False

        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.get("/status", timeout=5).json()
            except:
                log.info("Virtual Machine stopped abruptly")
                break

            if status["status"] == "complete" or FIN_flag == True:  #custom
                log.info("%s: analysis completed successfully", self.vmid)
                return
            elif status["status"] == "exception":
                log.info("%s: analysis caught an exception\n%s", self.vmid,
                         status["description"])
                return

            log.debug(
                "%s: analysis not completed yet (status=%s) (spent=%ds/%s)",
                self.vmid, status, s, self.timeout)  # custom
            ############### custom from here #################
            if burn == False:
                s, FIN_flag = internet_control.check(self.hv, self.timeout,
                                                     log, int(self.burn_limit))
                if FIN_flag != True:
                    burn = True
                    log.debug("[return odoriba] internet control out.. %ds" %
                              s)
            if subprocess.check_output(['ps']).find('child.py') == -1:
                FIN_flag = True
                log.debug('[Analysis Finished] FIN_flag set in guest.py')
Beispiel #13
0
    def upload_analyzer(self, monitor):
        """Upload analyzer to guest.
        @return: operation status.
        """
        zip_data = StringIO()
        zip_file = ZipFile(zip_data, "w", ZIP_STORED)

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

        if not os.path.exists(root):
            log.error("No valid analyzer found at path: %s", root)
            return False

        # 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 self.platform == "windows":
            dirpath = os.path.join(CUCKOO_ROOT, "data", "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)

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

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

        # Send the zip containing the analyzer to the agent running inside
        # the guest.
        try:
            self.server.add_analyzer(data)
        except socket.timeout:
            raise CuckooGuestError("{0}: guest communication timeout: unable "
                                   "to upload agent, check networking or try "
                                   "to increase timeout".format(self.id))
Beispiel #14
0
def analyzer_zipfile(platform):
    """Create the zip file that is sent to the Guest."""
    t = time.time()

    zip_data = BytesIO()
    zip_file = ZipFile(zip_data, "w", ZIP_STORED)

    # Select the proper analyzer's folder according to the operating
    # system associated with the current machine.
    root = os.path.join(CUCKOO_ROOT, "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)
        #ToDo remove
        """
        for name in os.listdir(dirpath):
            zip_file.write(
                os.path.join(dirpath, name), os.path.join("bin", name)
            )
        """

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

    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
Beispiel #15
0
    def wait_available(self):
        """Wait until the Virtual Machine is available for usage."""
        end = time.time() + self.timeout
        while True:
            try:
                socket.create_connection((self.ipaddr, self.port), 1).close()
                break
            except socket.timeout:
                log.debug("%s: not ready yet", self.vmid)
            except socket.error:
                log.debug("%s: not ready yet", self.vmid)
                time.sleep(1)

            if time.time() > end:
                raise CuckooGuestError("{0}: the guest initialization hit the "
                                       "critical timeout, analysis "
                                       "aborted.".format(self.vmid))
Beispiel #16
0
    def wait(self, status):
        """Waiting for status.
        @param status: status.
        @return: always True.
        """
        log.debug("%s: waiting for status 0x%.04x", self.id, status)

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

        while True:
            # Check if we've passed the timeout.
            if time.time() > end:
                raise CuckooGuestError("{0}: the guest initialization hit the "
                                       "critical timeout, analysis "
                                       "aborted.".format(self.id))

            try:
                # If the server returns the given status, break the loop
                # and return.
                if self.server.get_status() == status:
                    log.debug("%s: status ready", self.id)
                    break
            except:
                if self.id == "aosx" and self._fm and check_ping(self.ip):
                    if not self._fm.process_on:
                        run_cmd_with_timeout("killall adb", 4)
                        run_cmd_with_timeout("adb root", 4)
                        run_cmd_with_timeout("adb connect {}".format(self.ip),
                                             4)
                        run_cmd_with_timeout(
                            "adb shell am start -n com.cuckoo.agent/com.cuckoo.agent.MainActivity -a android.intent.action.MAIN,android.intent.action.BOOT_COMPLETED -c android.intent.category.LAUNCHER",
                            4)
                        time.sleep(2)
                        self._fm.set_frida_server()
                        time.sleep(2)
                        run_cmd_with_timeout("adb shell am restart", 4)
                        self._fm.process_on = True
                        time.sleep(10)
                pass

            log.debug("%s: not ready yet", self.id)
            time.sleep(1)

        self.server._set_timeout(None)
        return True
Beispiel #17
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(
                "CAPE 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
Beispiel #18
0
    def get(self, method, *args, **kwargs):
        """Simple wrapper around requests.get()."""
        do_raise = kwargs.pop("do_raise", True)
        url = f"http://{self.ipaddr}:{self.port}{method}"
        with requests.Session() as session:
            session.trust_env = False
            session.proxies = None

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

        do_raise and r.raise_for_status()
        return r
Beispiel #19
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))
Beispiel #20
0
    def wait_available(self):
        """Wait until the Virtual Machine is available for usage."""
        end = time.time() + self.timeout

        while db.guest_get_status(self.task_id) == "starting":
            try:
                socket.create_connection((self.ipaddr, self.port), 1).close()
                break
            except socket.timeout:
                log.debug("%s: not ready yet", self.vmid)
            except socket.error:
                log.debug("%s: not ready yet", self.vmid)
                time.sleep(1)

            if time.time() > end:
                raise CuckooGuestError(
                    "%s: the guest initialization hit the critical timeout, "
                    "analysis aborted." % self.vmid)
Beispiel #21
0
    def wait(self, status):
        """Waiting for status.
        @param status: status.
        @return: always True.
        """
        log.debug("%s: waiting for status 0x%.04x", self.id, status)

        # Create an event that will invoke a function to stop the loop when
        # the critical timeout is h it.
        abort = Event()
        abort.clear()

        def die():
            abort.set()

        # Initialize the timer.
        timer = Timer(self.timeout, die)
        timer.start()
        self.server._set_timeout(self.timeout)

        while True:
            # Check if the timer was hit and the abort event was set.
            if abort.is_set():
                raise CuckooGuestError("{0}: the guest initialization hit the "
                                       "critical timeout, analysis "
                                       "aborted".format(self.id))

            try:
                # If the server returns the given status, break the loop
                # and return.
                if self.server.get_status() == status:
                    log.debug("%s: status ready", self.id)
                    break
            except:
                pass

            log.debug("%s: not ready yet", self.id)
            time.sleep(1)

        self.server._set_timeout(None)
        return True
Beispiel #22
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":
            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:
                log.info("Virtual Machine stopped abruptly")
                break

            if status["status"] == "complete":
                log.info("%s: analysis completed successfully", self.vmid)
                # TODO: dirty-hack for non-rooter system
                import subprocess
                subprocess.Popen(
                    "vboxmanage hostonlyif ipconfig vboxnet0 --ip 10.31.37.1 --netmask 255.255.255.0"
                    .split())
                return
            elif status["status"] == "exception":
                log.info("%s: analysis caught an exception\n%s", self.vmid,
                         status["description"])
                return

            log.debug("%s: analysis still processing", self.vmid)
Beispiel #23
0
    def start_analysis(self, options):
        """Start analysis.
        @param options: options.
        @return: operation status.
        """
        log.info("Starting analysis on guest (id=%s, ip=%s)", self.id, self.ip)

        # TODO: deal with unicode URLs.
        if options["category"] == "file":
            options["file_name"] = "'" + sanitize_filename(
                options["file_name"]) + "'"

        self.timeout = options["timeout"] + self.cfg.timeouts.critical
        # Get and set dynamically generated resultserver port.
        options["port"] = str(ResultServer().port)

        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)

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

            # 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("{0}: unable to upload config to "
                                       "analysis machine".format(self.id))

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

                data = xmlrpclib.Binary(file_data)

                try:
                    # strip off the added surrounding quotes
                    self.server.add_malware(data, options["file_name"][1:-1])
                except Exception as e:
                    raise CuckooGuestError("{0}: unable to upload malware to "
                                           "analysis machine: {1}".format(
                                               self.id, e))

                # check for support files and upload them to guest.
                self.upload_support_files(options)

            # Debug analyzer.py in vm
            if "CUCKOO_DBG" in os.environ:
                while True:
                    pass
            # 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("{0}: guest communication timeout, check "
                                   "networking or try to increase "
                                   "timeout".format(self.id))
    def wait_for_completion(self, machine, storage, machinery):
        """Wait for analysis completion.
        @return: operation status.
        """
        log.debug("%s: waiting for completion", self.id)

        # Same procedure as in self.wait(). Just look at the comments there.
        abort = Event()
        abort.clear()

        def die():
            abort.set()

# CHANGED: Added time-based dumps here.

        resumableTimer = ResumableTimer(self.timeout, die)
        resumableTimer.start()
        sec_counter = 0
        mem_analysis_conf = Config(
            os.path.join(CUCKOO_ROOT, "conf", "memoryanalysis.conf"))
        time_to_sleep = int(
            mem_analysis_conf.time_based.time_to_sleep_before_dump_in_seconds)
        number_of_dumps = int(mem_analysis_conf.basic.max_number_of_dumps)
        memory_results_dir = os.path.join(storage, "memory")
        dumps_dir = os.path.join(memory_results_dir, "dumps")
        create_dir_safe(memory_results_dir)
        create_dir_safe(dumps_dir)
        while True:
            if abort.is_set():
                info_dict = {
                    "trigger": {
                        "name": "End",
                        "args": {}
                    },
                    "time": str(sec_counter)
                }
                log.info("Taking dump before termination...")
                self.take_mem_dump(dumps_dir, machine, machinery, info_dict)
                raise CuckooGuestError(
                    "The analysis hit the critical timeout, terminating")
            while Event(STOP_EVENT).is_set():
                time.sleep(0.005)
            time.sleep(1)
            sec_counter += 1
            if mem_analysis_conf.basic.time_based and sec_counter % time_to_sleep == 0:
                resumableTimer.stop()
                info_dict = {
                    "trigger": {
                        "name": "Time",
                        "args": {
                            "interval": time_to_sleep
                        }
                    }
                }
                self.take_mem_dump(dumps_dir, machine, machinery, info_dict)
                resumableTimer.resume()
            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()
                if not error:
                    error = "unknown error"
                info_dict = {"trigger": {"name": "End", "args": {}}}
                log.info("Taking dump before termination...")
                self.take_mem_dump(dumps_dir, machine, machinery, info_dict)
                raise CuckooGuestError("Analysis failed: {0}".format(error))
# TODO: suspend machine and take dump
            else:
                log.debug("%s: analysis not completed yet (status=%s)",
                          self.id, status)
        self.server._set_timeout(None)
        log.info("Taking dump before termination...")
        info_dict = {"trigger": {"name": "End", "args": {}}}
        self.take_mem_dump(dumps_dir, machine, machinery, info_dict)
Beispiel #25
0
    def start_analysis(self, options):
        """Start analysis.
        @param options: options.
        @return: operation status.
        """
        log.info("Starting analysis on guest (id=%s, ip=%s)", self.id, self.ip)

        if misc_config.ENABLE_CUCKOO_EXTRA_INFO:
            time.sleep(10)
            subprocess.call([misc_config.ADB_PATH, "connect", "192.168.56.10"])
            log.info("Starting to collect information")

            # Custom: Get process information
            try:
                self.getProcessList()
                # Get listening Ports
                self.getListeningPorts()
                self.generateFileList()
            except:
                log.info("ADB Error occured! Try again...")
                try:
                    subprocess.Popen([misc_config.ADB_PATH, "kill-server"])
                    subprocess.Popen(["killall adb"])
                    time.sleep(2)
                    subprocess.call(
                        [misc_config.ADB_PATH, "connect", "192.168.56.10"])
                    time.sleep(5)
                    self.getProcessList()
                    # Get listening Ports
                    self.getListeningPorts()
                    self.generateFileList()
                except:
                    log.info("ADB Error for the second time!")

        # TODO: deal with unicode URLs.
        if options["category"] == "file":
            options["file_name"] = sanitize_filename(options["file_name"])

        # If the analysis timeout is higher than the critical timeout,
        # automatically increase the critical timeout by one minute.
        if options["timeout"] > self.timeout:
            log.debug("Automatically increased critical timeout to %s",
                      self.timeout)
            self.timeout = options["timeout"] + 60

        # Get and set dynamically generated resultserver port.
        options["port"] = str(ResultServer().port)

        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)

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

            # 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("{0}: unable to upload config to "
                                       "analysis machine".format(self.id))

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

                data = xmlrpclib.Binary(file_data)

                try:
                    self.server.add_malware(data, options["file_name"])
                except Exception as e:
                    raise CuckooGuestError("{0}: unable to upload malware to "
                                           "analysis machine: {1}".format(
                                               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("{0}: guest communication timeout, check "
                                   "networking or try to increase "
                                   "timeout".format(self.id))

        # Custom
        # Give the app some time to start up
        log.debug("Starting to simulate user interaction")
        time.sleep(10)
        self.simulateUserInteraction()
Beispiel #26
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)

        s = 0
        burn = False  # custom
        home = os.path.expanduser('~')
        child = os.popen('python %s/odoriba/child.py' % home)  # custom
        print "A" * 100
        log.debug('[MADE Child FLAG] python ~/odoriba/child.py')
        FIN_flag = False

        while db.guest_get_status(self.task_id) == "running":
            time.sleep(1)
            s += 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 or FIN_flag == True:  #custom
                log.info("%s: analysis completed successfully", self.id)
                status = CUCKOO_GUEST_COMPLETED  #custom
                break
            elif status == CUCKOO_GUEST_FAILED:
                error = self.server.get_error()
                if not error:
                    error = "unknown error"

                raise CuckooGuestError("Analysis failed: {0}".format(error))
            else:
                log.debug(
                    "%s: analysis not completed yet (status=%s) (spent=%ds/%s)",
                    self.id, status, s, self.timeout)  # custom
                ############### custom from here #################
                if burn == False:
                    s, FIN_flag = internet_control.check(
                        self.hv, self.timeout, log, int(self.burn_limit))
                    if FIN_flag != True:
                        burn = True
                        log.debug(
                            "[return odoriba] internet control out.. %ds" % s)
                if subprocess.check_output(['ps']).find('child.py') == -1:
                    FIN_flag = True
                    log.debug('[Analysis Finished] FIN_flag set in guest.py')
                ############### custom until here #################

        self.server._set_timeout(None)
def analyzer_zipfile(platform, monitor, options):
    """Creates the Zip file that is sent to the Guest."""
    t = time.time()

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

    # Select the proper analyzer's folder according to the operating
    # system associated with the current machine.
    root = os.path.join(CUCKOO_ROOT, "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)

    user_options = {}
    try:
        # Split the options by comma.
        fields = options["options"].split(",")
    except ValueError as e:
        log.error("Khaled: error while split options")
        pass
    else:
        for field in fields:
            # Split the name and the value of the option.
            try:
                key, value = field.split("=", 1)
                #log.debug("Key: " + key + " value: " + value)
            except ValueError as e:
                #log.debug("Error while split in loop" + e)
                pass
            else:
                # If the parsing went well we add the option to the
                # dictionary.
                user_options[key.strip()] = value.strip()

    submit_file = None
    pass_check = True
    pass_type = "cuckoo"

    if "request_file" in user_options:
        submit_file = user_options["request_file"]
        log.debug("Submit file: " + submit_file)
    elif "formatted_request_file" in user_options:
        submit_file = user_options["formatted_request_file"]
        log.debug("Submit file: " + submit_file)
        pass_type = "lwr"
        pass_check = False

    #If a "pass type" option is present in the request, then simply use that pass type
    #Else, check the request file (if present) to see what type of pass this is

    if pass_check:
        if "pass_type" in user_options:
            pass_type = user_options["pass_type"]
        elif submit_file:
            if "LWR.txt" in submit_file:
                pass_type = "lwr"
            elif "EMP_Request.bin" in submit_file:
                pass_type = "dynamorio"

    #Eventually we may be able to make this in the configuration file:
    copy_dict = {
        "dynamorio": "dynamorio",
        "dvasion_vm.dll": "dynamorio",
        "dvasion_vm1.dll": "dynamorio",
        "dvasion_vm2.dll": "dynamorio",
        "dvasion_exp.exe": "lwr",
        "dvasion_exp.dll": "lwr"
    }

    # 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)

            #Kapil:Transfer whole dynamo rio only if this is first pass
            if name in copy_dict and not copy_dict[name] == pass_type:
                log.debug("Not Writing to zip: " + archive_name)
                continue

            zip_file.write(path, archive_name)

    if submit_file:
        dest_path = os.path.join("processing_files",
                                 submit_file.split("/")[-1])
        submit_file_path = os.path.join(CUCKOO_ROOT, "leader", submit_file)
        if (not os.path.isfile(submit_file_path)):
            log.critical("File does not exist at " + submit_file_path)
            raise CuckooGuestError("Submit_File was not found on disk")
        zip_file.write(os.path.join(CUCKOO_ROOT, "leader", submit_file),
                       dest_path)
        log.debug("Added submit file to zip at: " + dest_path)

    # Include the chosen monitoring component.
    if platform == "windows":
        dirpath = os.path.join(CUCKOO_ROOT, "data", "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 = os.path.join(CUCKOO_ROOT, "data", "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)

    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
Beispiel #28
0
    def start_analysis(self, options):
        """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.

        # If the analysis timeout is higher than the critical timeout,
        # automatically increase the critical timeout by one minute.
        if options["timeout"] > self.timeout:
            log.debug("Automatically increased critical timeout to %s",
                      self.timeout)
            self.timeout = options["timeout"] + 60

        opt = {}
        for row in options["options"].split(","):
            if "=" not in row:
                continue

            key, value = row.split("=", 1)
            opt[key.strip()] = value.strip()

        # Check whether the hashes file exists if it was provided.
        if "hashes-path" in opt:
            if not os.path.isfile(opt["hashes-path"]):
                raise CuckooGuestError("Non-existing hashing file provided!")

        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)

            # Invoke the upload of the analyzer to the guest.
            self.upload_analyzer(opt.get("hashes-path"))

            # 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("{0}: unable to upload config to "
                                       "analysis machine".format(self.id))

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

                data = xmlrpclib.Binary(file_data)

                try:
                    self.server.add_malware(data, options["file_name"])
                except Exception as e:
                    raise CuckooGuestError("{0}: unable to upload malware to "
                                           "analysis machine: {1}".format(
                                               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("{0}: guest communication timeout, check "
                                   "networking or try to increase "
                                   "timeout".format(self.id))