Example #1
0
def contains_peekabooyar(config, s):
    """
    Checks the given sample for the PeekabooYar (EICAR like) malicious string.

    :param s: sample to check
    :return: RueleResult
    """
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    rules = yara.compile(source='''
        rule peekabooyar
        {
             strings:
                  $peekabooyar1 = "X5O!P%@AP-/_(:)_/-X22x8cz2$PeekabooAV-STD-ANTIVIRUS-TEST-FILE!$H+H*"
        
             condition:
                  $peekabooyar1
        }''')

    with open(s.get_file_path(), 'rb') as f:
        matches = rules.match(data=f.read())

    if matches != []:
        return RuleResult(position,
                          result=Result.bad,
                          reason="Die Datei beinhaltet Peekabooyar.",
                          further_analysis=False)

    return RuleResult(
        position,
        result=Result.unknown,
        reason="Die Datei beinhaltet kein erkennbares Peekabooyar.",
        further_analysis=True)
Example #2
0
    def fetch_rule_result(self, sample):
        """
        Gets the sample information from the database as a RuleResult object.

        :param sample: The Sample object to get the rule result from.
        :return: Returns a RuleResult object containing the sample information.
        """
        with self.__lock:
            session = self.__Session()
            sample_info = PeekabooDatabase.__get(
                session,
                SampleInfo,
                sha256sum=sample.sha256sum,
                file_extension=sample.file_extension)
            if sample_info:
                result = RuleResult('db',
                                    result=Result.from_string(
                                        sample_info.result.name),
                                    reason=sample_info.reason,
                                    further_analysis=True)
            else:
                result = RuleResult(
                    'db',
                    result=Result.unknown,
                    reason="Datei ist dem System noch nicht bekannt",
                    further_analysis=True)
            session.close()
        return result
Example #3
0
    def __exec_rule(self, config, sample, rule_function):
        """
        rule wrapper for in/out logging and reporting
        """
        rule_name = rule_function.func_name
        logger.debug("Processing rule '%s' for %s" % (rule_name, sample))

        try:
            # skip disabled rules.
            if rule_name in config.keys() and \
               'enabled' in config[rule_name].keys() and \
               config[rule_name]['enabled'] == 'no':
                logger.debug("Rule '%s' is disabled." % rule_name)
                result = RuleResult(rule_name, result=Result.unchecked,
                                    reason="Regel '%s' ist deaktiviert." % rule_name,
                                    further_analysis=True)
            else:
                result = rule_function(config, sample)
            sample.add_rule_result(result)
        except CuckooReportPendingException as e:
            # in case the Sample is requesting the Cuckoo report
            raise
        # catch all other exceptions for this rule
        except Exception as e:
            logger.warning("Unexpected error in '%s' for %s" % (rule_name,
                                                                sample))
            logger.exception(e)
            # create "fake" RuleResult
            result = RuleResult("RulesetEngine", result=Result.unknown,
                                reason="Regel mit Fehler abgebrochen",
                                further_analysis=True)
            sample.add_rule_result(result)

        logger.info("Rule '%s' processed for %s" % (rule_name, sample))
        return result
Example #4
0
def cuckoo_evil_sig(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    # signatures that if matched mark a sample as bad
    # list all installed signatures
    # grep -o "description.*" -R . ~/cuckoo2.0/modules/signatures/
    bad_sigs = config['cuckoo_evil_sig']['signature']

    sigs = []

    # look through matched signatures
    for descr in s.cuckoo_report.signatures:
        logger.debug(descr['description'])
        sigs.append(descr['description'])

    # check if there is a "bad" signatures and return bad
    matched_bad_sigs = []
    for sig in bad_sigs:
        match = re.search(sig, str(sigs))
        if match:
            matched_bad_sigs.append(sig)

    if len(matched_bad_sigs) == 0:
        return RuleResult(position,
                          result=Result.unknown,
                          reason="Keine Signatur erkannt die auf Schadcode hindeutet",
                          further_analysis=True)

    return RuleResult(position,
                      result=Result.bad,
                      reason="Folgende Signaturen wurden erkannt: %s"
                      % ''.ljust(8).join(["%s\n" % s for s in matched_bad_sigs]),
                      further_analysis=False)
Example #5
0
def office_macro(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    if s.office_macros:
        return RuleResult(position,
                          result=Result.bad,
                          reason="Die Datei beinhaltet ein Office-Makro",
                          further_analysis=False)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Die Datei beinhaltet kein erkennbares Office-Makro",
                      further_analysis=True)
Example #6
0
def cuckoo_analysis_failed(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    if s.cuckoo_analysis_failed:
        return RuleResult(position,
                          result=Result.bad,
                          reason="Die Verhaltensanalyse durch Cuckoo hat einen Fehler Produziert und konnte nicht erfolgreich abgeschlossen werden",
                          further_analysis=False)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Die Verhaltensanalyse durch Cuckoo wurde erfolgreich abgeschlossen",
                      further_analysis=True)
Example #7
0
def known(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    if s.known_to_db:
        sample_info = s.info_from_db
        return RuleResult(position,
                          result=sample_info.get_result(),
                          reason=sample_info.reason,
                          further_analysis=False)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Datei ist dem System noch nicht bekannt",
                      further_analysis=True)
Example #8
0
    def run(self, sample):
        """ Run all the rules in the ruleset against a given sample

        @param sample: sample to evaluate ruleset against
        @returns: Nothing, all state is recorded in the sample """
        for rule in self.rules:
            rule_name = rule.rule_name
            logger.debug("%d: Processing rule '%s'", sample.id, rule_name)

            try:
                result = rule.evaluate(sample)
                sample.add_rule_result(result)
            except PeekabooAnalysisDeferred:
                # in case the Sample is requesting the Cuckoo report
                raise
            # catch all other exceptions for this rule
            except Exception as error:
                logger.warning(
                    "%d: Unexpected error in '%s'", sample.id, rule_name)
                logger.exception(error)
                # create "fake" RuleResult
                result = RuleResult("RulesetEngine", result=Result.failed,
                                    reason=_("Rule aborted with error"),
                                    further_analysis=False)
                sample.add_rule_result(result)

            logger.info("%d: Rule '%s' processed", sample.id, rule_name)
            if not result.further_analysis:
                return

        logger.info("%d: Rules evaluated", sample.id)
Example #9
0
def file_larger_than(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    size = int(config['file_larger_than']['bytes'])
    if s.file_size > size:
        return RuleResult(position,
                          result=Result.unknown,
                          reason="Datei hat mehr als %d bytes" % size,
                          further_analysis=True)

    return RuleResult(position,
                      result=Result.ignored,
                      reason="Datei ist nur %d bytes lang" % s.file_size,
                      further_analysis=False)
Example #10
0
    def __exec_rule(self, sample, rule_class):
        """
        rule wrapper for in/out logging and reporting
        """
        rule_name = rule_class.rule_name
        logger.debug("Processing rule '%s' for %s", rule_name, sample)

        try:
            rule = rule_class(config=self.config, db_con=self.db_con)
            result = rule.evaluate(sample)
            sample.add_rule_result(result)
        except PeekabooAnalysisDeferred:
            # in case the Sample is requesting the Cuckoo report
            raise
        # catch all other exceptions for this rule
        except Exception as e:
            logger.warning("Unexpected error in '%s' for %s", rule_name,
                           sample)
            logger.exception(e)
            # create "fake" RuleResult
            result = RuleResult("RulesetEngine",
                                result=Result.failed,
                                reason=_("Rule aborted with error"),
                                further_analysis=False)
            sample.add_rule_result(result)

        logger.info("Rule '%s' processed for %s", rule_name, sample)
        return result
Example #11
0
    def run(self):
        while not self.shutdown_requested.is_set():
            logger.debug('Worker %d: Ready', self.worker_id)

            try:
                # wait blocking for next job (thread safe) with timeout
                sample = self.job_queue.dequeue()
            except queue.Empty:
                continue

            if sample is None:
                # we just got pinged
                continue

            logger.info('Worker %d: Processing sample %s', self.worker_id,
                        sample)

            # The following used to be one big try/except block catching any
            # exception. This got complicated because in the case of
            # CuckooReportPending we use exceptions for control flow as well
            # (which might be questionable in itself). Instead of catching,
            # logging and ignoring errors here if workers start to die again
            # because of uncaught exceptions we should improve error handling
            # in the subroutines causing it.

            if not sample.init():
                logger.error('Sample initialization failed')
                sample.add_rule_result(
                    RuleResult("Worker",
                               result=Result.failed,
                               reason=_("Sample initialization failed"),
                               further_analysis=False))
                self.job_queue.done(sample.sha256sum)
                continue

            try:
                self.ruleset_engine.run(sample)
            except PeekabooAnalysisDeferred:
                logger.debug("Report for sample %s still pending", sample)
                continue

            if sample.result >= Result.failed:
                sample.dump_processing_info()

            if sample.result != Result.failed:
                logger.debug('Saving results to database')
                try:
                    self.db_con.analysis_save(sample)
                except PeekabooDatabaseError as dberr:
                    logger.error(
                        'Failed to save analysis result to '
                        'database: %s', dberr)
                    # no showstopper, we can limp on without caching in DB
            else:
                logger.debug('Not saving results of failed analysis')

            sample.cleanup()
            self.job_queue.done(sample)

        logger.info('Worker %d: Stopped', self.worker_id)
Example #12
0
def file_type_on_whitelist(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    whitelist = config['file_type_on_whitelist']['whitelist']

    if set(s.mimetypes).issubset(set(whitelist)):
        return RuleResult(position,
                          result=Result.ignored,
                          reason="Dateityp ist auf Whitelist",
                          further_analysis=False)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Dateityp ist nicht auf Whitelist",
                      further_analysis=True)
Example #13
0
def known(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    db = get_config().get_db_con()
    if db.known(s):
        sample_info = db.sample_info_fetch(s)
        return RuleResult(position,
                          result=sample_info.get_result(),
                          reason=sample_info.reason,
                          further_analysis=False)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Datei ist dem System noch nicht bekannt",
                      further_analysis=True)
Example #14
0
def requests_evil_domain(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    evil_domains = config['requests_evil_domain']['domain']

    for d in s.requested_domains:
        if d in evil_domains:
            return RuleResult(position,
                              result=Result.bad,
                              reason="Die Datei versucht mindestens eine Domain aus der Blacklist zu kontaktieren (%s)" % d,
                              further_analysis=False)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Datei scheint keine Domains aus der Blacklist kontaktieren zu wollen",
                      further_analysis=True)
Example #15
0
def final_rule(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Datei scheint keine erkennbaren Schadroutinen zu starten",
                      further_analysis=True)
Example #16
0
def cuckoo_score(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    threshold = float(config['cuckoo_score']['higher_than'])
    if s.cuckoo_report.score >= threshold:
        return RuleResult(position,
                          result=Result.bad,
                          reason="Cuckoo score >= %s: %s"
                          % (threshold, s.cuckoo_report.score),
                          further_analysis=False)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Cuckoo score < %s: %s"
                      % (threshold, s.cuckoo_report.score),
                      further_analysis=True)
Example #17
0
def file_type_on_greylist(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    greylist = config['file_type_on_greylist']['greylist']

    if set(s.mimetypes).issubset(set(greylist)):
        return RuleResult(position,
                          result=Result.unknown,
                          reason="Dateityp ist auf der Liste der zu analysiserenden Typen",
                          further_analysis=True)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Dateityp ist nicht auf der Liste der zu analysierenden Typen (%s)"
                      % (str(s.mimetypes)),
                      further_analysis=False)
Example #18
0
 def test_6_add_rule_result(self):
     """ Test the adding of a rule result. """
     reason = 'This is just a test case.'
     result = RuleResult('Unittest',
                         Result.failed,
                         reason,
                         further_analysis=False)
     self.sample.add_rule_result(result)
     self.assertEqual(self.sample.result, Result.failed)
     self.assertEqual(self.sample.reason, reason)
Example #19
0
def requests_evil_domain(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    evil_domains = config.get('domain', ())
    if len(evil_domains) == 0:
        logger.warn("Empty evil domain list, check ruleset config.")

    for d in s.cuckoo_report.requested_domains:
        if d in evil_domains:
            return RuleResult(position,
                              result=Result.bad,
                              reason="Die Datei versucht mindestens eine Domain aus der Blacklist zu kontaktieren (%s)" % d,
                              further_analysis=False)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Datei scheint keine Domains aus der Blacklist kontaktieren zu wollen",
                      further_analysis=True)
Example #20
0
 def test_3_sample_info_update(self):
     result = RuleResult('Unittest',
                         Result.checked,
                         'This is another test case.',
                         further_analysis=False)
     self.sample.add_rule_result(result)
     self.sample.determine_result()
     self.conf.db_con.sample_info_update(self.sample)
     rule_result = self.conf.db_con.fetch_rule_result(self.sample)
     self.assertEqual(rule_result.result, Result.checked)
     self.assertEqual(rule_result.reason, 'This is another test case.')
Example #21
0
def file_type_on_whitelist(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    whitelist = config.get('whitelist', ())
    if len(whitelist) == 0:
        logger.warn("Empty whitelist, check ruleset config.")

    # ignore the file only if *all* of its mime types are on the whitelist
    if s.mimetypes.issubset(set(whitelist)):
        return RuleResult(position,
                          result=Result.ignored,
                          reason="Dateityp ist auf Whitelist",
                          further_analysis=False)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Dateityp ist nicht auf Whitelist",
                      further_analysis=True)
Example #22
0
def file_type_on_greylist(config, s):
    tb = traceback.extract_stack()
    tb = tb[-1]
    position = "%s:%s" % (tb[2], tb[1])

    greylist = config.get('greylist', ())
    if len(greylist) == 0:
        logger.warn("Empty greylist, check ruleset config.")

    # continue analysis if any of the sample's mime types are on the greylist
    if len(s.mimetypes.intersection(set(greylist))) > 0:
        return RuleResult(position,
                          result=Result.unknown,
                          reason="Dateityp ist auf der Liste der zu analysiserenden Typen",
                          further_analysis=True)

    return RuleResult(position,
                      result=Result.unknown,
                      reason="Dateityp ist nicht auf der Liste der zu analysierenden Typen (%s)"
                      % (str(s.mimetypes)),
                      further_analysis=False)
Example #23
0
 def setUpClass(cls):
     cls.test_db = os.path.abspath('./test.db')
     cls.conf = PeekabooDummyConfig()
     db_con = PeekabooDatabase('sqlite:///' + cls.test_db)
     cls.conf.set_db_con(db_con)
     _set_config(cls.conf)
     cls.sample = Sample(os.path.realpath(__file__))
     result = RuleResult('Unittest',
                         Result.unknown,
                         'This is just a test case.',
                         further_analysis=True)
     cls.sample.add_rule_result(result)
     cls.sample.determine_result()
Example #24
0
    def already_in_progress(self, config, s):
        with self.__in_use:
            logger.debug("enter already_in_progress")
            tb = traceback.extract_stack()
            tb = tb[-1]
            position = "%s:%s" % (tb[2], tb[1])

            if s.has_attr('pending'):
                s.set_attr('pending', False)
                return RuleResult(position,
                                  result=s.get_result(),
                                  reason='Datei wird jetzt Analysiert',
                                  further_analysis=True)

            l = []
            for sample in ConnectionMap.get_samples_by_sha256(s.sha256sum):
                if sample != s:
                    if not sample.has_attr('pending') or not sample.get_attr(
                            'pending') is True:
                        l.append(sample)

            if len(l) == 0:
                s.set_attr("pending", False)
                logger.debug("no second analysis present")
                return RuleResult(position,
                                  result=s.get_result(),
                                  reason='Datei wird jetzt Analysiert',
                                  further_analysis=True)

            logger.debug("there is another same sample")
            logger.debug("I'll be off until needed")
            s.set_attr("pending", True)
            # stop worker
            sys.stdout.flush()
            logger.debug("leave already_in_progress")
            raise CuckooReportPendingException()
Example #25
0
 def setUpClass(cls):
     cls.test_db = os.path.abspath('./test.db')
     cls.conf = PeekabooDummyConfig()
     cls.db_con = PeekabooDatabase('sqlite:///' + cls.test_db)
     cls.factory = SampleFactory(cuckoo = None,
             db_con = cls.db_con,
             connection_map = None,
             base_dir = cls.conf.sample_base_dir,
             job_hash_regex = cls.conf.job_hash_regex,
             keep_mail_data = False)
     cls.sample = cls.factory.make_sample(os.path.realpath(__file__))
     result = RuleResult('Unittest',
                         Result.unknown,
                         'This is just a test case.',
                         further_analysis=True)
     cls.sample.add_rule_result(result)
     cls.sample.determine_result()
Example #26
0
 def setUpClass(cls):
     """ Set up common test case resources. """
     cls.test_db = os.path.abspath('./test.db')
     cls.conf = CreatingPeekabooConfig()
     cls.db_con = PeekabooDatabase('sqlite:///' + cls.test_db,
                                   instance_id=1,
                                   stale_in_flight_threshold=10)
     cls.no_cluster_db = PeekabooDatabase('sqlite:///' + cls.test_db,
                                          instance_id=0)
     cls.factory = CreatingSampleFactory(
         cuckoo=None,
         base_dir=cls.conf.sample_base_dir,
         job_hash_regex=cls.conf.job_hash_regex,
         keep_mail_data=False,
         processing_info_dir=None)
     cls.sample = cls.factory.create_sample('test.py', 'test')
     result = RuleResult('Unittest',
                         Result.failed,
                         'This is just a test case.',
                         further_analysis=False)
     cls.sample.add_rule_result(result)
Example #27
0
 def result(self, result, reason, further_analysis):
     """ Construct a RuleResult for returning to the engine. """
     return RuleResult(self.rule_name,
                       result=result,
                       reason=reason,
                       further_analysis=further_analysis)
Example #28
0
 def fetch_rule_result(self, sha256):
     return RuleResult('fake_db',
                       result=Result.checked,
                       reason='Test Case',
                       further_analysis=True)