def run(self):
        """Run evented signatures."""
        # This will contain all the matched signatures.
        matched = []

        stats = { } 

        complete_list = list_plugins(group="signatures")
        evented_list = [sig(self.results)
                        for sig in complete_list
                        if sig.enabled and sig.evented and
                        self._check_signature_version(sig) and (not sig.filter_analysistypes or self.results["target"]["category"] in sig.filter_analysistypes)]

        overlay = self._load_overlay()
        log.debug("Applying signature overlays for signatures: %s", ", ".join(overlay.keys()))
        for signature in complete_list + evented_list:
            self._apply_overlay(signature, overlay)

        if evented_list and "behavior" in self.results:
            log.debug("Running %u evented signatures", len(evented_list))
            for sig in evented_list:
                stats[sig.name] = timedelta()
                if sig == evented_list[-1]:
                    log.debug("\t `-- %s", sig.name)
                else:
                    log.debug("\t |-- %s", sig.name)

            # Iterate calls and tell interested signatures about them.
            for proc in self.results["behavior"]["processes"]:
                for call in proc["calls"]:
                    # Loop through active evented signatures.
                    for sig in evented_list:
                        # Skip current call if it doesn't match the filters (if any).
                        if sig.filter_processnames and not proc["process_name"] in sig.filter_processnames:
                            continue
                        if sig.filter_apinames and not call["api"] in sig.filter_apinames:
                            continue
                        if sig.filter_categories and not call["category"] in sig.filter_categories:
                            continue

                        result = None
                        try:
                            pretime = datetime.now()
                            result = sig.on_call(call, proc)
                            posttime = datetime.now()
                            timediff = posttime - pretime
                            stats[sig.name] += timediff
                        except NotImplementedError:
                            result = False
                        except:
                            log.exception("Failed to run signature \"%s\":", sig.name)
                            result = False

                        # If the signature returns None we can carry on, the
                        # condition was not matched.
                        if result is None:
                            continue

                        # On True, the signature is matched.
                        if result is True:
                            log.debug("Analysis matched signature \"%s\"", sig.name)
                            matched.append(sig.as_result())
                            if sig in complete_list:
                                complete_list.remove(sig)

                        # Either True or False, we don't need to check this sig anymore.
                        evented_list.remove(sig)
                        del sig

            # Call the stop method on all remaining instances.
            for sig in evented_list:
                try:
                    pretime = datetime.now()
                    result = sig.on_complete()
                    posttime = datetime.now()
                    timediff = posttime - pretime
                    stats[sig.name] += timediff
                except NotImplementedError:
                    continue
                except:
                    log.exception("Failed run on_complete() method for signature \"%s\":", sig.name)
                    continue
                else:
                    if result is True:
                        log.debug("Analysis matched signature \"%s\"", sig.name)
                        matched.append(sig.as_result())
                        if sig in complete_list:
                            complete_list.remove(sig)

        # Link this into the results already at this point, so non-evented signatures can use it
        self.results["signatures"] = matched

        # Add in statistics for evented signatures that took at least some time
        for key, value in stats.iteritems():
            if value:
                self.results["statistics"]["signatures"].append({
                    "name": key,
                    "time": float("%d.%03d" % (value.seconds,
                                             value.microseconds / 1000)),
                    })

        # Compat loop for old-style (non evented) signatures.
        if complete_list:
            complete_list.sort(key=lambda sig: sig.order)
            log.debug("Running non-evented signatures")

            for signature in complete_list:
                if not signature.filter_analysistypes or self.results["target"]["category"] in signature.filter_analysistypes:
                    match = self.process(signature)
                    # If the signature is matched, add it to the list.
                    if match:
                        matched.append(match)

                    # Reset the ParseProcessLog instances after each signature
                    if "behavior" in self.results:
                        for process in self.results["behavior"]["processes"]:
                            process["calls"].reset()

        # Sort the matched signatures by their severity level.
        matched.sort(key=lambda key: key["severity"])

        # Tweak later as needed
        malscore = 0.0
        for match in matched:
            if match["severity"] == 1:
                malscore += match["weight"] * 0.5 * (match["confidence"] / 100.0)
            else:
                malscore += match["weight"] * (match["severity"] - 1) * (match["confidence"] / 100.0)
        if malscore > 10.0:
            malscore = 10.0
        if malscore < 0.0:
            malscore = 0.0
        self.results["malscore"] = malscore

        family = ""
        # Make a best effort detection of malware family name (can be updated later by re-processing the analysis)
        for match in matched:
            if "families" in match and match["families"]:
                family = match["families"][0].title()
                break
        if not family and self.results["info"]["category"] == "file" and "virustotal" in self.results and "results" in self.results["virustotal"] and self.results["virustotal"]["results"]:
            detectnames = []
            for res in self.results["virustotal"]["results"]:
                if res["sig"]:
                    # weight Microsoft's detection, they seem to be more accurate than the rest
                    if res["vendor"] == "Microsoft":
                        detectnames.append(res["sig"])
                    detectnames.append(res["sig"])
            family = get_vt_consensus(detectnames)
        
        # add detection based on suricata here
        if not family and "suricata" in self.results and "alerts" in self.results["suricata"] and self.results["suricata"]["alerts"]:
            for alert in self.results["suricata"]["alerts"]:
                if "signature" in alert and alert["signature"]:
                    if alert["signature"].startswith("ET TROJAN") or alert["signature"].startswith("ETPRO TROJAN"):
                        words = re.findall(r"[A-Za-z0-9]+", alert["signature"])
                        famcheck = words[2]
                        famchecklower = famcheck.lower()
                        if famchecklower == "win32" or famchecklower == "w32":
                            famcheck = words[3]
                            famchecklower = famcheck.lower()

                        blacklist = [
                            "upx",
                            "executable",
                            "potential",
                            "likely",
                            "rogue",
                            "supicious",
                            "generic",
                            "possible",
                            "known",
                            "common",
                            "troj",
                            "trojan",
                            "team",
                            "probably",
                            "w2km",
                            "http",
                            "abuse.ch",
                            "win32",
                            "unknown",
                            "single",
                            "exe",
                            "filename",
                            "js",
                        ]
                        isgood = True
                        for black in blacklist:
                            if black == famchecklower:
                                isgood = False
                                break
                        if isgood:
                            famcheck = famcheck.split(".")[0]
                            family = famcheck.title()

        # fall back to ClamAV detection
        if not family and self.results["info"]["category"] == "file" and "clamav" in self.results["target"]["file"] and self.results["target"]["file"]["clamav"] and self.results["target"]["file"]["clamav"].startswith("Win.Trojan."):
            words = re.findall(r"[A-Za-z0-9]+", self.results["target"]["file"]["clamav"])
            family = words[2]

        self.results["malfamily"] = family
示例#2
0
    def run(self):
        """Run all processing modules and all signatures.
        @return: processing results.
        """

        # Order modules using the user-defined sequence number.
        # If none is specified for the modules, they are selected in
        # alphabetical order.
        processing_list = list_plugins(group="processing")

        # If no modules are loaded, return an empty dictionary.
        if processing_list:
            processing_list.sort(key=lambda module: module.order)

            # Run every loaded processing module.
            for module in processing_list:
                result = self.process(module)
                # If it provided some results, append it to the big results
                # container.
                if result:
                    self.results.update(result)
        else:
            log.info("No processing modules loaded")

        # For correct error log on webgui
        logs = os.path.join(self.analysis_path, "logs")
        if os.path.exists(logs):
            for file_name in os.listdir(logs):
                file_path = os.path.join(logs, file_name)

                if os.path.isdir(file_path):
                    continue
                # Skipping the current log file if it's too big.
                if os.stat(
                        file_path
                ).st_size > self.cuckoo_cfg.processing.analysis_size_limit:
                    if not hasattr(self.results, "debug"):
                        self.results.setdefault("debug", dict()).setdefault(
                            "errors", list())
                    self.results["debug"]["errors"].append(
                        "Behavioral log {0} too big to be processed, skipped. Increase analysis_size_limit in cuckoo.conf"
                        .format(file_name))
                    continue
        else:
            log.info(
                "Logs folder doesn't exist, maybe something with with analyzer folder, any change?"
            )

        family = ""
        self.results["malfamily_tag"] = ""
        # add detection based on suricata here
        if not family and "suricata" in self.results and "alerts" in self.results[
                "suricata"] and self.results["suricata"]["alerts"]:
            for alert in self.results["suricata"]["alerts"]:
                if "signature" in alert and alert["signature"]:
                    if alert["signature"].startswith("ET TROJAN") or alert[
                            "signature"].startswith("ETPRO TROJAN"):
                        words = re.findall(r"[A-Za-z0-9]+", alert["signature"])
                        famcheck = words[2]
                        famchecklower = famcheck.lower()
                        if famchecklower == "win32" or famchecklower == "w32" or famchecklower == "ransomware":
                            famcheck = words[3]
                            famchecklower = famcheck.lower()

                        blacklist = [
                            "executable",
                            "potential",
                            "likely",
                            "rogue",
                            "supicious",
                            "generic",
                            "possible",
                            "known",
                            "common",
                            "troj",
                            "trojan",
                            "team",
                            "probably",
                            "w2km",
                            "http",
                            "abuse",
                            "win32",
                            "unknown",
                            "single",
                            "filename",
                            "worm",
                            "fake",
                            "malicious",
                        ]
                        isgood = True
                        for black in blacklist:
                            if black == famchecklower:
                                isgood = False
                                break
                        if len(famcheck) < 4:
                            isgood = False
                        if isgood:
                            family = famcheck.title()
                            self.results["malfamily_tag"] = "Suricata"

        if not family and self.results["info"][
                "category"] == "file" and "virustotal" in self.results and "results" in self.results[
                    "virustotal"] and self.results["virustotal"]["results"]:
            detectnames = []
            for res in self.results["virustotal"]["results"]:
                if res["sig"] and "Trojan.Heur." not in res["sig"]:
                    # weight Microsoft's detection, they seem to be more accurate than the rest
                    if res["vendor"] == "Microsoft":
                        detectnames.append(res["sig"])
                    detectnames.append(res["sig"])
            family = get_vt_consensus(detectnames)
            self.results["malfamily_tag"] = "VirusTotal"

        # fall back to ClamAV detection
        if not family and self.results["info"][
                "category"] == "file" and "clamav" in self.results["target"][
                    "file"] and self.results["target"]["file"][
                        "clamav"] and self.results["target"]["file"][
                            "clamav"].startswith("Win.Trojan."):
            words = re.findall(r"[A-Za-z0-9]+",
                               self.results["target"]["file"]["clamav"])
            family = words[2]
            self.results["malfamily_tag"] = "ClamAV"

        if self.results.get("cape", False):
            self.results["malfamily"] = self.results["cape"]
            self.results["malfamily_tag"] = "CAPE"
        else:
            self.results["malfamily"] = family

        return self.results
示例#3
0
    def run(self):
        """Run all processing modules and all signatures.
        @return: processing results.
        """

        # Order modules using the user-defined sequence number.
        # If none is specified for the modules, they are selected in
        # alphabetical order.
        processing_list = list_plugins(group="processing")

        # If no modules are loaded, return an empty dictionary.
        if processing_list:
            processing_list.sort(key=lambda module: module.order)

            # Run every loaded processing module.
            for module in processing_list:
                result = self.process(module)
                # If it provided some results, append it to the big results
                # container.
                if result:
                    self.results.update(result)
        else:
            log.info("No processing modules loaded")

        # For correct error log on webgui
        logs = os.path.join(self.analysis_path, "logs")
        if os.path.exists(logs):
            for file_name in os.listdir(logs):
                file_path = os.path.join(logs, file_name)

                if os.path.isdir(file_path):
                    continue
                # Skipping the current log file if it's too big.
                if os.stat(
                        file_path
                ).st_size > self.cuckoo_cfg.processing.analysis_size_limit:
                    if not hasattr(self.results, "debug"):
                        self.results.setdefault("debug", dict()).setdefault(
                            "errors", list())
                    self.results["debug"]["errors"].append(
                        "Behavioral log {0} too big to be processed, skipped. Increase analysis_size_limit in cuckoo.conf"
                        .format(file_name))
                    continue
        else:
            log.info(
                "Logs folder doesn't exist, maybe something with with analyzer folder, any change?"
            )

        family = ""
        self.results["malfamily_tag"] = ""
        if self.results.get("detections", False):
            family = self.results["detections"]
            self.results["malfamily_tag"] = "CAPE"
        # add detection based on suricata here
        elif not family and "suricata" in self.results and "alerts" in self.results[
                "suricata"] and self.results["suricata"]["alerts"]:
            for alert in self.results["suricata"]["alerts"]:
                if alert.get("signature",
                             "") and alert["signature"].startswith(
                                 ("ET TROJAN", "ETPRO TROJAN", "ET MALWARE",
                                  "ET CNC")):
                    family = get_suricata_family(alert["signature"])
                    if family:
                        self.results["malfamily_tag"] = "Suricata"
                        self.results["detections"] = family

        elif not family and self.results["info"][
                "category"] == "file" and "virustotal" in self.results and "results" in self.results[
                    "virustotal"] and self.results["virustotal"]["results"]:
            detectnames = []
            for res in self.results["virustotal"]["results"]:
                if res["sig"] and "Trojan.Heur." not in res["sig"]:
                    # weight Microsoft's detection, they seem to be more accurate than the rest
                    if res["vendor"] == "Microsoft":
                        detectnames.append(res["sig"])
                    detectnames.append(res["sig"])
            family = get_vt_consensus(detectnames)
            self.results["malfamily_tag"] = "VirusTotal"

        # fall back to ClamAV detection
        elif not family and self.results["info"][
                "category"] == "file" and "clamav" in self.results.get(
                    "target",
                    {}).get("file",
                            {}) and self.results["target"]["file"]["clamav"]:
            for detection in self.results["target"]["file"]["clamav"]:
                if detection.startswith("Win.Trojan."):
                    words = re.findall(r"[A-Za-z0-9]+", detection)
                    family = words[2]
                    self.results["malfamily_tag"] = "ClamAV"

        if family:
            self.results["malfamily"] = family

        return self.results
示例#4
0
    def run(self):
        """Run evented signatures."""
        # This will contain all the matched signatures.
        matched = []

        stats = {}

        complete_list = list_plugins(group="signatures")
        evented_list = [
            sig(self.results) for sig in complete_list if sig.enabled
            and sig.evented and self._check_signature_version(sig) and
            (not sig.filter_analysistypes
             or self.results["target"]["category"] in sig.filter_analysistypes)
        ]

        overlay = self._load_overlay()
        log.debug("Applying signature overlays for signatures: %s",
                  ", ".join(overlay.keys()))
        for signature in complete_list + evented_list:
            self._apply_overlay(signature, overlay)

        if evented_list and "behavior" in self.results:
            log.debug("Running %u evented signatures", len(evented_list))
            for sig in evented_list:
                stats[sig.name] = timedelta()
                if sig == evented_list[-1]:
                    log.debug("\t `-- %s", sig.name)
                else:
                    log.debug("\t |-- %s", sig.name)

            # Iterate calls and tell interested signatures about them.
            for proc in self.results["behavior"]["processes"]:
                for call in proc["calls"]:
                    # Loop through active evented signatures.
                    for sig in evented_list:
                        # Skip current call if it doesn't match the filters (if any).
                        if sig.filter_processnames and not proc[
                                "process_name"] in sig.filter_processnames:
                            continue
                        if sig.filter_apinames and not call[
                                "api"] in sig.filter_apinames:
                            continue
                        if sig.filter_categories and not call[
                                "category"] in sig.filter_categories:
                            continue

                        result = None
                        try:
                            pretime = datetime.now()
                            result = sig.on_call(call, proc)
                            posttime = datetime.now()
                            timediff = posttime - pretime
                            stats[sig.name] += timediff
                        except NotImplementedError:
                            result = False
                        except:
                            log.exception("Failed to run signature \"%s\":",
                                          sig.name)
                            result = False

                        # If the signature returns None we can carry on, the
                        # condition was not matched.
                        if result is None:
                            continue

                        # On True, the signature is matched.
                        if result is True:
                            log.debug("Analysis matched signature \"%s\"",
                                      sig.name)
                            matched.append(sig.as_result())
                            if sig in complete_list:
                                complete_list.remove(sig)

                        # Either True or False, we don't need to check this sig anymore.
                        evented_list.remove(sig)
                        del sig

            # Call the stop method on all remaining instances.
            for sig in evented_list:
                try:
                    pretime = datetime.now()
                    result = sig.on_complete()
                    posttime = datetime.now()
                    timediff = posttime - pretime
                    stats[sig.name] += timediff
                except NotImplementedError:
                    continue
                except:
                    log.exception(
                        "Failed run on_complete() method for signature \"%s\":",
                        sig.name)
                    continue
                else:
                    if result is True:
                        log.debug("Analysis matched signature \"%s\"",
                                  sig.name)
                        matched.append(sig.as_result())
                        if sig in complete_list:
                            complete_list.remove(sig)

        # Link this into the results already at this point, so non-evented signatures can use it
        self.results["signatures"] = matched

        # Add in statistics for evented signatures that took at least some time
        for key, value in stats.iteritems():
            if value:
                self.results["statistics"]["signatures"].append({
                    "name":
                    key,
                    "time":
                    float("%d.%03d" %
                          (value.seconds, value.microseconds / 1000)),
                })

        # Compat loop for old-style (non evented) signatures.
        if complete_list:
            complete_list.sort(key=lambda sig: sig.order)
            log.debug("Running non-evented signatures")

            for signature in complete_list:
                if not signature.filter_analysistypes or self.results[
                        "target"]["category"] in signature.filter_analysistypes:
                    match = self.process(signature)
                    # If the signature is matched, add it to the list.
                    if match:
                        matched.append(match)

                    # Reset the ParseProcessLog instances after each signature
                    if "behavior" in self.results:
                        for process in self.results["behavior"]["processes"]:
                            process["calls"].reset()

        # Sort the matched signatures by their severity level.
        matched.sort(key=lambda key: key["severity"])

        # Tweak later as needed
        malscore = 0.0
        for match in matched:
            if match["severity"] == 1:
                malscore += match["weight"] * 0.5 * (match["confidence"] /
                                                     100.0)
            else:
                malscore += match["weight"] * (match["severity"] - 1) * (
                    match["confidence"] / 100.0)
        if malscore > 10.0:
            malscore = 10.0
        if malscore < 0.0:
            malscore = 0.0
        self.results["malscore"] = malscore

        family = ""
        # Make a best effort detection of malware family name (can be updated later by re-processing the analysis)
        for match in matched:
            if "families" in match and match["families"]:
                family = match["families"][0].title()
                break
        if not family and self.results["info"][
                "category"] == "file" and "virustotal" in self.results and "results" in self.results[
                    "virustotal"] and self.results["virustotal"]["results"]:
            detectnames = []
            for res in self.results["virustotal"]["results"]:
                if res["sig"]:
                    # weight Microsoft's detection, they seem to be more accurate than the rest
                    if res["vendor"] == "Microsoft":
                        detectnames.append(res["sig"])
                    detectnames.append(res["sig"])
            family = get_vt_consensus(detectnames)

        # add detection based on suricata here
        if not family and "suricata" in self.results and "alerts" in self.results[
                "suricata"] and self.results["suricata"]["alerts"]:
            for alert in self.results["suricata"]["alerts"]:
                if "signature" in alert and alert["signature"]:
                    if alert["signature"].startswith("ET TROJAN") or alert[
                            "signature"].startswith("ETPRO TROJAN"):
                        words = re.findall(r"[A-Za-z0-9\.]+",
                                           alert["signature"])
                        famcheck = words[2]
                        famchecklower = famcheck.lower()
                        if famchecklower == "win32":
                            famcheck = words[3]
                            famchecklower = famcheck.lower()

                        blacklist = [
                            "upx",
                            "executable",
                            "potential",
                            "likely",
                            "rogue",
                            "supicious",
                            "generic",
                            "possible",
                            "known",
                            "common",
                            "troj",
                            "team",
                            "probably",
                            "w2km",
                            "http",
                        ]
                        isgood = True
                        for black in blacklist:
                            if black == famchecklower:
                                isgood = False
                                break
                        if isgood:
                            famcheck = famcheck.split(".")[0]
                            family = famcheck.title()

        self.results["malfamily"] = family
示例#5
0
    def run(self):
        """Run evented signatures."""
        # This will contain all the matched signatures.
        matched = []

        Database().set_statistics_time(self.task_id, SIGNATURES_STARTED)
        complete_list = list_plugins(group="signatures")
        evented_list = [sig(self.results)
                        for sig in complete_list
                        if sig.enabled and sig.evented and
                        self._check_signature_version(sig) and (not sig.filter_analysistypes or self.results["target"]["category"] in sig.filter_analysistypes)]

        overlay = self._load_overlay()
        log.debug("Applying signature overlays for signatures: %s", ", ".join(overlay.keys()))
        for signature in complete_list + evented_list:
            self._apply_overlay(signature, overlay)

        if evented_list:
            log.debug("Running %u evented signatures", len(evented_list))
            for sig in evented_list:
                if sig == evented_list[-1]:
                    log.debug("\t `-- %s", sig.name)
                else:
                    log.debug("\t |-- %s", sig.name)

            # Iterate calls and tell interested signatures about them.
            for proc in self.results["behavior"]["processes"]:
                for call in proc["calls"]:
                    # Loop through active evented signatures.
                    for sig in evented_list:
                        # Skip current call if it doesn't match the filters (if any).
                        if sig.filter_processnames and not proc["process_name"] in sig.filter_processnames:
                            continue
                        if sig.filter_apinames and not call["api"] in sig.filter_apinames:
                            continue
                        if sig.filter_categories and not call["category"] in sig.filter_categories:
                            continue

                        result = None
                        try:
                            result = sig.on_call(call, proc)
                        except NotImplementedError:
                            result = False
                        except:
                            log.exception("Failed to run signature \"%s\":", sig.name)
                            result = False

                        # If the signature returns None we can carry on, the
                        # condition was not matched.
                        if result is None:
                            continue

                        # On True, the signature is matched.
                        if result is True:
                            log.debug("Analysis matched signature \"%s\"", sig.name)
                            matched.append(sig.as_result())
                            if sig in complete_list:
                                complete_list.remove(sig)

                        # Either True or False, we don't need to check this sig anymore.
                        evented_list.remove(sig)
                        del sig

            # Call the stop method on all remaining instances.
            for sig in evented_list:
                try:
                    result = sig.on_complete()
                except NotImplementedError:
                    continue
                except:
                    log.exception("Failed run on_complete() method for signature \"%s\":", sig.name)
                    continue
                else:
                    if result is True:
                        log.debug("Analysis matched signature \"%s\"", sig.name)
                        matched.append(sig.as_result())
                        if sig in complete_list:
                            complete_list.remove(sig)

        # Link this into the results already at this point, so non-evented signatures can use it
        self.results["signatures"] = matched

        # Compat loop for old-style (non evented) signatures.
        if complete_list:
            complete_list.sort(key=lambda sig: sig.order)
            log.debug("Running non-evented signatures")

            for signature in complete_list:
                if not signature.filter_analysistypes or self.results["target"]["category"] in signature.filter_analysistypes:
                    match = self.process(signature)
                    # If the signature is matched, add it to the list.
                    if match:
                        matched.append(match)

                    # Reset the ParseProcessLog instances after each signature
                    if "behavior" in self.results:
                        for process in self.results["behavior"]["processes"]:
                            process["calls"].reset()

        # Sort the matched signatures by their severity level.
        matched.sort(key=lambda key: key["severity"])

        # Tweak later as needed
        malscore = 0.0
        for match in matched:
            if match["severity"] == 1:
                malscore += match["weight"] * 0.5 * (match["confidence"] / 100.0)
            else:
                malscore += match["weight"] * (match["severity"] - 1) * (match["confidence"] / 100.0)
        if malscore > 10.0:
            malscore = 10.0
        if malscore < 0.0:
            malscore = 0.0
        self.results["malscore"] = malscore

        family = ""
        # Make a best effort detection of malware family name (can be updated later by re-processing the analysis)
        for match in matched:
            if "families" in match and match["families"]:
                family = match["families"][0].title()
                break
        if not family and "virustotal" in self.results and "results" in self.results["virustotal"] and self.results["virustotal"]["results"]:
            detectnames = []
            for res in self.results["virustotal"]["results"]:
                if res["sig"]:
                    # weight Microsoft's detection, they seem to be more accurate than the rest
                    if res["vendor"] == "Microsoft":
                        detectnames.append(res["sig"])
                    detectnames.append(res["sig"])
            family = get_vt_consensus(detectnames)
        
        # add detection based on suricata here
        if not family and "suricata" in self.results and "alerts" in self.results["suricata"] and self.results["suricata"]["alerts"]:
            for alert in self.results["suricata"]["alerts"]:
                if "signature" in alert and alert["signature"]:
                    if alert["signature"].startswith("ET TROJAN") or alert["signature"].startswith("ETPRO TROJAN"):
                        words = re.findall(r"[A-Za-z0-9\./]+", alert["signature"])
                        famcheck = words[2]
                        famchecklower = words[2].lower()
                        blacklist = [
                            "upx",
                            "executable",
                            "potential",
                            "likely",
                            "rogue",
                            "supicious",
                            "generic",
                            "possible",
                            "known",
                            "common",
                            "troj",
                            "team",
                            "probably",
                        ]
                        isgood = True
                        for black in blacklist:
                            if black == famchecklower:
                                isgood = False
                                break
                        if isgood:
                            if famchecklower.startswith("win32"):
                                famcheck = famcheck[6:]
                            famcheck = famcheck.split(".")[0]
                            family = famcheck.title()

        self.results["malfamily"] = family

        # Doing signature statistics
        alert = 0
        normal = 0
        crash = 0
        anti = 0
        for sig in self.results["signatures"]:
            if sig["alert"]:
                alert += 1
            if sig["name"] in ["exec_crash"]:
                crash += 1
            if sig["name"] in ["antidbg_devices", "antidbg_windows", "antiemu_wine", "antisandbox_mouse_hook",
                               "antivm_generic_bios", "antivm_generic_disk", "antivm_generic_ide",
                               "antivm_generic_scsi", "antivm_vbox_acpi", "antivm_vbox_devices", "antivm_vbox_files",
                               "antivm_vbox_keys", "antivm_vbox_libs"]:
                anti += 1
            normal += 1
        Database().set_statistics_counter(self.task_id, SIGNATURES_TOTAL, normal)
        Database().set_statistics_counter(self.task_id, SIGNATURES_ALERT, alert)
        Database().set_statistics_counter(self.task_id, TASK_ISSUE_CRASH, crash)
        Database().set_statistics_counter(self.task_id, TASK_ISSUE_ANTI, anti)
        if "info" in self.results and "timeout" in self.results["info"]:
            Database().set_statistics_counter(self.task_id, TASK_TIMEDOUT, self.results["info"]["timeout"])
        Database().set_statistics_time(self.task_id, SIGNATURES_FINISHED)
示例#6
0
    def run(self):
        """Run all processing modules and all signatures.
        @return: processing results.
        """

        # Order modules using the user-defined sequence number.
        # If none is specified for the modules, they are selected in
        # alphabetical order.
        processing_list = list_plugins(group="processing")

        # If no modules are loaded, return an empty dictionary.
        if processing_list:
            processing_list.sort(key=lambda module: module.order)

            # Run every loaded processing module.
            for module in processing_list:
                result = self.process(module)
                # If it provided some results, append it to the big results
                # container.
                if result:
                    self.results.update(result)
        else:
            log.info("No processing modules loaded")

        family = ""
        # add detection based on suricata here
        if not family and "suricata" in self.results and "alerts" in self.results[
                "suricata"] and self.results["suricata"]["alerts"]:
            for alert in self.results["suricata"]["alerts"]:
                if "signature" in alert and alert["signature"]:
                    if alert["signature"].startswith("ET TROJAN") or alert[
                            "signature"].startswith("ETPRO TROJAN"):
                        words = re.findall(r"[A-Za-z0-9]+", alert["signature"])
                        famcheck = words[2]
                        famchecklower = famcheck.lower()
                        if famchecklower == "win32" or famchecklower == "w32" or famchecklower == "ransomware":
                            famcheck = words[3]
                            famchecklower = famcheck.lower()

                        blacklist = [
                            "executable",
                            "potential",
                            "likely",
                            "rogue",
                            "supicious",
                            "generic",
                            "possible",
                            "known",
                            "common",
                            "troj",
                            "trojan",
                            "team",
                            "probably",
                            "w2km",
                            "http",
                            "abuse",
                            "win32",
                            "unknown",
                            "single",
                            "filename",
                            "worm",
                            "fake",
                            "malicious",
                        ]
                        isgood = True
                        for black in blacklist:
                            if black == famchecklower:
                                isgood = False
                                break
                        if len(famcheck) < 4:
                            isgood = False
                        if isgood:
                            family = famcheck.title()

        if not family and self.results["info"][
                "category"] == "file" and "virustotal" in self.results and "results" in self.results[
                    "virustotal"] and self.results["virustotal"]["results"]:
            detectnames = []
            for res in self.results["virustotal"]["results"]:
                if res["sig"] and "Trojan.Heur." not in res["sig"]:
                    # weight Microsoft's detection, they seem to be more accurate than the rest
                    if res["vendor"] == "Microsoft":
                        detectnames.append(res["sig"])
                    detectnames.append(res["sig"])
            family = get_vt_consensus(detectnames)

        # fall back to ClamAV detection
        if not family and self.results["info"][
                "category"] == "file" and "clamav" in self.results["target"][
                    "file"] and self.results["target"]["file"][
                        "clamav"] and self.results["target"]["file"][
                            "clamav"].startswith("Win.Trojan."):
            words = re.findall(r"[A-Za-z0-9]+",
                               self.results["target"]["file"]["clamav"])
            family = words[2]

        if self.results.get("cape", False):
            self.results["malfamily"] = self.results["cape"]
        else:
            self.results["malfamily"] = family

        return self.results
示例#7
0
def vt_lookup(category, target, on_demand=False):
    if processing_conf.virustotal.enabled and (processing_conf.virustotal.get(
            "on_demand", False) is False or on_demand is True):

        if category not in ("file", "url"):
            return {"error": True, "msg": "VT category isn't supported"}

        if category == "file":
            if not do_file_lookup:
                return {
                    "error": True,
                    "msg": "VT File lookup disabled in processing.conf"
                }
            if not os.path.exists(target):
                return {"error": True, "msg": "File doesn't exist"}

            sha256 = File(target).get_sha256()
            url = VIRUSTOTAL_FILE_URL.format(id=sha256)

        elif category == "url":
            if not do_url_lookup:
                return {
                    "error": True,
                    "msg": "VT URL lookup disabled in processing.conf"
                }
            if urlscrub:
                urlscrub_compiled_re = None
                try:
                    urlscrub_compiled_re = re.compile(urlscrub)
                except Exception as e:
                    raise CuckooProcessingError(
                        "Failed to compile urlscrub regex" % (e))
                try:
                    target = re.sub(urlscrub_compiled_re, "", target)
                except Exception as e:
                    return {"error": True, "msg": "Failed to scrub url" % (e)}

            # normalize the URL the way VT appears to
            if not target.lower().startswith(
                    "http://") and not target.lower().startswith("https://"):
                target = "http://" + target
            slashsplit = target.split("/")
            slashsplit[0] = slashsplit[0].lower()
            slashsplit[2] = slashsplit[2].lower()
            if len(slashsplit) == 3:
                slashsplit.append("")
            target = "/".join(slashsplit)

            sha256 = hashlib.sha256(target.encode("utf-8")).hexdigest()
            url = VIRUSTOTAL_URL_URL.format(id=target)

        try:
            r = requests.get(url,
                             headers=headers,
                             verify=True,
                             timeout=timeout)
            if r.ok:
                vt_response = r.json()
                engines = vt_response.get("data",
                                          {}).get("attributes", {}).get(
                                              "last_analysis_results", {})
                if engines:
                    virustotal = {}
                    virustotal["names"] = vt_response.get("data", {}).get(
                        "attributes", {}).get("names")
                    virustotal["scan_id"] = vt_response.get("data",
                                                            {}).get("id")
                    virustotal["md5"] = vt_response.get("data", {}).get(
                        "attributes", {}).get("md5")
                    virustotal["sha1"] = vt_response.get("data", {}).get(
                        "attributes", {}).get("sha1")
                    virustotal["sha256"] = vt_response.get("data", {}).get(
                        "attributes", {}).get("sha256")
                    virustotal["tlsh"] = vt_response.get("data", {}).get(
                        "attributes", {}).get("tlsh")
                    virustotal["positive"] = (vt_response.get("data", {}).get(
                        "attributes", {}).get("last_analysis_stats",
                                              {}).get("malicious"))
                    virustotal["total"] = len(engines.keys())
                    virustotal["permalink"] = vt_response.get("data", {}).get(
                        "links", {}).get("self")
                    virustotal["scans"] = dict(
                        (engine.replace(".", "_"), block)
                        for engine, block in engines.items()
                        if remove_empty and block["result"])
                    virustotal["resource"] = sha256

                    virustotal["results"] = list()
                    detectnames = list()
                    for engine, block in engines.items():
                        virustotal["results"] += [{
                            "vendor":
                            engine.replace(".", "_"),
                            "sig":
                            block["result"]
                        }]
                        if block["result"] and "Trojan.Heur." not in block[
                                "result"]:
                            # weight Microsoft's detection, they seem to be more accurate than the rest
                            if engine == "Microsoft":
                                detectnames.append(block["result"])
                            detectnames.append(block["result"])

                    virustotal["detection"] = get_vt_consensus(detectnames)
                    return virustotal
                else:
                    return dict()
            else:
                return {
                    "error":
                    True,
                    "msg":
                    "Unable to complete connection to VirusTotal. Status code: {}"
                    .format(r.status_code)
                }
        except requests.exceptions.RequestException as e:
            return {
                "error": True,
                "msg":
                "Unable to complete connection to VirusTotal: {0}".format(e)
            }
    else:
        return dict()