Esempio n. 1
0
    def parse_alerts(self, alerts):
        res = Result()
        line_count = 0
        newline_count = 0
        content = ""
        yml_indicator = ""
        xml_hits = ResultSection(title_text='xml Malware Indicator Match')

        if os.stat("/opt/al/pkg/al_services/alsvc_beach/alerts_generated.txt"
                   ).st_size == 0:
            # Result file is empty, nothing to report
            return res

        for line in alerts:
            # Otherwise we iterate through each line to read the required information
            if line != "\n":
                line_count += 1
                if line_count == 1:
                    yml_indicator = line
                else:
                    content += line + "\n"
            elif line_count == 0:
                newline_count += 1
            else:
                newline_count = 0
                xml_hits.add_section(
                    XmlResultObject(yml_indicator, content, SCORE.VHIGH))
                content = ""
                line_count = 0

        res.add_result(xml_hits)
        return res
Esempio n. 2
0
    def parse_results(self, response):
        res = Result()
        response = response.get('results', response)

        if response is not None and response.get('response_code') == 1:
            av_hits = ResultSection(title_text='Anti-Virus Detections')
            url_section = ResultSection(
                SCORE.NULL,
                'Virus total report permalink',
                self.SERVICE_CLASSIFICATION,
                body_format=TEXT_FORMAT.URL,
                body=json.dumps({"url": response.get('permalink')}))
            res.add_section(url_section)

            scans = response.get('scans', response)
            av_hits.add_line(
                'Found %d AV hit(s) from %d scans.' %
                (response.get('positives'), response.get('total')))
            for majorkey, subdict in sorted(scans.iteritems()):
                if subdict['detected']:
                    virus_name = subdict['result']
                    res.append_tag(
                        VirusHitTag(virus_name,
                                    context="scanner:%s" % majorkey))
                    av_hits.add_section(
                        AvHitSection(majorkey, virus_name, SCORE.SURE))
            res.add_result(av_hits)

        return res
Esempio n. 3
0
    def parse_results(self, response):
        res = Result()
        response = response.get('results', response)

        if response is not None and response.get('response_code') == 204:
            message = "You exceeded the public API request rate limit (4 requests of any nature per minute)"
            raise VTException(message)
        elif response is not None and response.get('response_code') == 203:
            message = "You tried to perform calls to functions for which you require a Private API key."
            raise VTException(message)
        elif response is not None and response.get('response_code') == 1:
            av_hits = ResultSection(title_text='Anti-Virus Detections')
            url_section = ResultSection(
                SCORE.NULL,
                'Virus total report permalink',
                self.SERVICE_CLASSIFICATION,
                body_format=TEXT_FORMAT.URL,
                body=json.dumps({"url": response.get('permalink')}))
            res.add_section(url_section)

            scans = response.get('scans', response)
            av_hits.add_line('Found %d AV hit(s) from %d scans.' % (response.get('positives'), response.get('total')))
            for majorkey, subdict in sorted(scans.iteritems()):
                if subdict['detected']:
                    virus_name = subdict['result']
                    res.append_tag(VirusHitTag(virus_name, context="scanner:%s" % majorkey))
                    av_hits.add_section(AvHitSection(majorkey, virus_name, SCORE.SURE))
            res.add_result(av_hits)

        return res
Esempio n. 4
0
    def execute(self, request):
        if not self.rules:
            return

        self.task = request.task
        local_filename = request.download()

        yara_externals = {}
        for k, i in self.get_yara_externals.iteritems():
            # Check default request.task fields
            try:
                sval = self.task.get(i)
            except:
                sval = None
            if not sval:
                # Check metadata dictionary
                smeta = self.task.metadata
                if not smeta:
                    sval = smeta.get(i, None)
            if not sval:
                # Check params dictionary
                smeta = self.task.params
                if not smeta:
                    sval = smeta.get(i, None)
            # Create dummy value if item not found
            if not sval:
                sval = i

            yara_externals[k] = sval

        with self.initialization_lock:
            try:
                matches = self.rules.match(local_filename, externals=yara_externals)
                self.counters[RULE_HITS] += len(matches)
                request.result = self._extract_result_from_matches(matches)
            except Exception as e:
                if e.message != "internal error: 30":
                    raise
                else:
                    self.log.warning("Yara internal error 30 detected on submission {}" .format(self.task.sid))
                    section = ResultSection(title_text="Yara scan not completed.")
                    section.add_line("File returned too many matches with current rule set and Yara exited.")
                    result = Result()
                    request.result = result
                    result.add_result(section)
Esempio n. 5
0
    def parse_results(self, response):
        res = Result()
        response = response.get('scan_results', response)
        virus_name = ""

        if response is not None and response.get('progress_percentage') == 100:
            hit = False
            av_hits = ResultSection(title_text='Anti-Virus Detections')

            scans = response.get('scan_details', response)
            for majorkey, subdict in sorted(scans.iteritems()):
                score = SCORE.NULL
                if subdict['scan_result_i'] == 1:
                    virus_name = subdict['threat_found']
                    if virus_name:
                        score = SCORE.SURE
                elif subdict['scan_result_i'] == 2:
                    virus_name = subdict['threat_found']
                    if virus_name:
                        score = SCORE.VHIGH

                if score:
                    virus_name = virus_name.replace("a variant of ", "")
                    engine = self.engine_map[self._format_engine_name(
                        majorkey)]
                    res.append_tag(
                        VirusHitTag(virus_name,
                                    context="scanner:%s" % majorkey))
                    av_hits.add_section(
                        AvHitSection(majorkey, virus_name, engine, score))
                    hit = True

            if hit:
                res.add_result(av_hits)

        return res
Esempio n. 6
0
    def parse_api(data):
        result = Result()

        # Info block
        hash_info = data.get('hash_info')
        if not hash_info:
            return result
        r_info = ResultSection(title_text='File Info')
        r_info.score = SCORE.NULL
        r_info.add_line('Received Data: %s-%s-%s' %
                        (data['received_date'][:4], data['received_date'][4:6],
                         data['received_date'][6:]))
        r_info.add_line('Size: %s' % hash_info.get('filesize', ""))
        r_info.add_line('MD5: %s' % hash_info.get('md5', ""))
        r_info.add_line('SHA1: %s' % hash_info.get('sha1', ""))
        r_info.add_line('SHA256: %s' % hash_info.get('sha256', ""))
        r_info.add_line('SSDeep Blocksize: %s' %
                        hash_info.get('ssdeep_blocksize', ""))
        r_info.add_line('SSDeep Hash1: %s' % hash_info.get('ssdeep_hash1', ""))
        r_info.add_line('SSDeep Hash2: %s' % hash_info.get('ssdeep_hash1', ""))
        result.add_result(r_info)

        callouts = data.get('callouts', [])
        if len(callouts) > 0:
            max_callouts = 10
            r_callouts = ResultSection(title_text='Sandbox Call-Outs')
            r_callouts.score = SCORE.VHIGH
            analyser = ''
            r_call_sub_section = None

            reported_count = 0
            for callout in callouts:
                reported_count += 1
                if reported_count <= max_callouts:
                    if analyser != callout['ip']:
                        title = '%s (Analysed on %s)' % (callout['ip'],
                                                         callout['addedDate'])
                        r_call_sub_section = ResultSection(title_text=title,
                                                           parent=r_callouts)
                        analyser = callout['ip']

                    channel = callout['channel']
                    if channel is not None:
                        channel = "(%s)" % channel.split('~~')[0]
                    else:
                        channel = ""

                    r_call_sub_section.add_line("{0:s}:{1:d}{2:s}".format(
                        callout['callout'], callout['port'], channel))

                try:
                    p1, p2, p3, p4 = callout['callout'].split(".")
                    if int(p1) <= 255 and int(p2) <= 255 and int(
                            p3) <= 255 and int(p4) <= 255:
                        result.append_tag(
                            Tag(TAG_TYPE.NET_IP,
                                callout['callout'],
                                TAG_WEIGHT.MED,
                                context=Context.BEACONS))
                except ValueError:
                    result.append_tag(
                        Tag(TAG_TYPE.NET_DOMAIN_NAME,
                            callout['callout'],
                            TAG_WEIGHT.MED,
                            context=Context.BEACONS))

                if callout['port'] != 0:
                    result.append_tag(
                        Tag(TAG_TYPE.NET_PORT,
                            str(callout['port']),
                            TAG_WEIGHT.MED,
                            context=Context.BEACONS))

            if len(callouts) > max_callouts:
                r_callouts.add_line("And %s more..." % str(len(callouts) - 10))
            result.add_result(r_callouts)

        spamcount = data.get('spamCount', {})
        if spamcount:
            r_spam = ResultSection(title_text='SPAM feed')
            r_spam.score = SCORE.VHIGH
            r_spam.add_line('Found %d related spam emails' %
                            spamcount['count'])
            email_sample = spamcount.get("email_sample", {})
            r_spam.add_line('\tFirst Seen: %s' % email_sample['firstSeen'])
            r_spam.add_line('\tLast Seen: %s' % email_sample['lastSeen'])
            r_sub_section = ResultSection(title_text='Attachments',
                                          parent=r_spam)
            if email_sample['filename']:
                r_sub_section.add_line(
                    '%s - md5: %s' %
                    (email_sample['filename'], email_sample['filenameMD5']))
            if email_sample['attachment']:
                r_sub_section.add_line('%s - md5: %s' %
                                       (email_sample['attachment'],
                                        email_sample['attachmentMD5']))
            result.add_result(r_spam)

        av_results = data.get('av_results', [])
        if len(av_results) > 0:
            r_av_sec = ResultSection(title_text='Anti-Virus Detections')
            r_av_sec.add_line('Found %d AV hit(s).' % len(av_results))
            for av_result in av_results:
                r_av_sec.add_section(
                    AvHitSection(av_result['scannerID'], av_result['name'],
                                 SCORE.SURE))
                result.append_tag(
                    VirusHitTag(av_result['name'],
                                context="scanner:%s" % av_result['scannerID']))
            result.add_result(r_av_sec)

        return result
Esempio n. 7
0
    def execute(self, request):
        """
        Main Module.
        """
        result = Result()
        request.result = result

        if (request.task.size or 0) < 50000 and (
                request.tag.startswith('code') or
            (request.tag == "unknown" and (request.task.size or 0) < 5000)):
            patterns = PatternMatch()

            alfile = request.download()
            with open(alfile, "rb") as f:
                raw = f.read()

            # Get all IOCs that originally hit in file (to filter later- service FrankenStrings SHOULD catch it anyways)
            pat_values = patterns.ioc_match(raw,
                                            bogon_ip=True,
                                            just_network=False)
            before = []
            for k, val in pat_values.iteritems():
                if val == "":
                    asc_asc = unicodedata.normalize('NFKC', val).encode(
                        'ascii', 'ignore')
                    before.append(asc_asc)
                else:
                    for v in val:
                        before.append(v)

            # --- Stage 1 ----------------------------------------------------------------------------------------------
            # Get script(s) that we want
            code_extracts = [('^unknown$', self.convert_wide_unicode),
                             ('.*html.*', self.extract_htmlscript)]

            extracted_parts = None
            for tu in code_extracts:
                if re.match(re.compile(tu[0]), request.tag):
                    extracted_parts = tu[1](raw)
                    break
            if extracted_parts:
                parsed = [x for x in extracted_parts]
            else:
                parsed = [raw]

            # --- Stage 2 ----------------------------------------------------------------------------------------------
            # Hack time!
            for script in parsed:
                extract_file = False
                layer = script
                layers_list = []

                if request.deep_scan:
                    self.max_attempts = 50

                techniques = [
                    ('VBE Decode', self.vbe_decode, True),
                    ('MSWord macro vars', self.mswordmacro_vars, False),
                    ('Powershell vars', self.powershell_vars, False),
                    ('Concat strings', self.concat_strings, False),
                    ('String replace', self.string_replace, False),
                    ('Powershell carets', self.powershell_carets, False),
                    ('Array of strings', self.array_of_strings, False),
                    ('Fake array vars', self.vars_of_fake_arrays, False),
                    ('Simple XOR function', self.simple_xor_function, False),
                    ('Charcode', self.charcode, False),
                    ('Charcode hex', self.charcode_hex, False),
                    ('B64 Decode', self.b64decode_str, False)
                ]

                done = False
                idx = 0
                while not done:
                    if idx > self.max_attempts:
                        break
                    done = True
                    for name, technique, extract in techniques:
                        final, res = technique(layer)
                        if res:
                            layers_list.append((name, res))
                            if extract:
                                extract_file = True
                            # Looks like it worked, restart with new layer
                            layer = res
                            done = final
                            if done:
                                break
                    idx += 1

                if len(layers_list) > 0:
                    final_score = len(layers_list) * 10
                    clean = self.clean_up_final_layer(layers_list[-1][1])
                    if clean != raw:
                        pat_values = patterns.ioc_match(clean,
                                                        bogon_ip=True,
                                                        just_network=False)
                        after = []
                        for k, val in pat_values.iteritems():
                            if val == "":
                                asc_asc = unicodedata.normalize(
                                    'NFKC', val).encode('ascii', 'ignore')
                                after.append(asc_asc)
                            else:
                                for v in val:
                                    after.append(v)
                        diff_tags = list(
                            set(before).symmetric_difference(set(after)))
                        # Add additional checks to see if the file should be extracted. 1500 is an arbitrary score...
                        if (len(clean) > 1000 and final_score > 500) or (
                                len(before) < len(after)):
                            extract_file = True
                        res = (ResultSection(
                            SCORE.NULL,
                            "CrowBar detected possible obfuscated script:"))
                        mres = (ResultSection(
                            SCORE.NULL,
                            "The following CrowBar modules made deofuscation attempts:",
                            parent=res))
                        mres.score = final_score
                        lcount = Counter([x[0] for x in layers_list])
                        for l, c in lcount.iteritems():
                            mres.add_line("{0}, {1} time(s).".format(l, c))
                        if extract_file:
                            self.submit_extracted(clean, res, request)
                        # Display final layer
                        lres = (ResultSection(
                            SCORE.NULL,
                            "Final layer:",
                            body_format=TEXT_FORMAT.MEMORY_DUMP,
                            parent=res))
                        if extract_file:
                            lres.add_line("First 500 bytes of file:")
                            lres.add_line(clean[:500])
                        else:
                            lres.add_line("First 5000 bytes of file:")
                            lres.add_line(clean[:5000])
                        # Look for all IOCs in final layer
                        if len(pat_values) > 0 and len(diff_tags) > 0:
                            for ty, val in pat_values.iteritems():
                                if val == "":
                                    asc_asc = unicodedata.normalize(
                                        'NFKC', val).encode('ascii', 'ignore')
                                    if asc_asc in diff_tags:
                                        res.add_tag(TAG_TYPE[ty], asc_asc,
                                                    TAG_WEIGHT.LOW)
                                else:
                                    for v in val:
                                        if v in diff_tags:
                                            res.add_tag(
                                                TAG_TYPE[ty], v,
                                                TAG_WEIGHT.LOW)
                        result.add_result(res)