Esempio n. 1
0
    def find_scouts(self):
        """ Find all 'Scout' level implants using their distinctive watermarks - these index the configuration files, allowing us to obtain AES key information """
        scouts = []
        # Dynamically generate Yara rules from watermark
        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        rules = self.gen_yara_rules()

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():
                hitdata = scanner.address_space.zread(address, 8)
                # Second hit from Yara rule is the 'FIRST_WI' string that we use to differentiate from Elite implants
                # This is a wide string, so the second character is a '\x00' - the first hit is on the watermark that we want to use.
                if hitdata[1] != "\x00":
                    scouts.append({
                        "watermark": hitdata,
                        "confidence": 4,
                        "pid": str(task.UniqueProcessId),
                        "task": task,
                        "process_name": str(task.ImageFileName),
                        "address_space": scanner.address_space,
                        "address": address,
                        "implant_type": "Scout",
                        "threat_actor": hit.rule.split('__')[2]
                    })

        return scouts
Esempio n. 2
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        if not has_crypto:
            debug.error("pycrypto must be installed for this plugin")

        if not has_pbkdf2:
            debug.error("pbkdf2 must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=quasar_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr,
                                             end - vad_base_addr)

                config_data = []

                offset = 0
                for pattern in CONFIG_PATTERNS:
                    mc = re.search(pattern, data)
                    if mc:
                        offset = mc.end()

                configs = []
                if offset > 0:
                    while 1:
                        strings = []
                        string_len = ord(data[offset])
                        if ord(data[offset]) == 0x80 or ord(
                                data[offset]) == 0x81:
                            string_len = ord(data[offset + 1]) + (
                                (ord(data[offset]) - 0x80) * 256)
                            offset += 1
                        offset += 1
                        for i in range(string_len):
                            if data[offset + i] != "\x00":
                                strings.append(data[offset + i])
                        configs.append("".join(strings))
                        offset = offset + string_len
                        if len(configs) > 10:
                            break

                config_data.append(self.parse_config(configs))

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 3
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        if not has_yara:
            debug.error("You must install yara to use this plugin")

        if not self._config.DUMP_DIR:
            debug.error("You must supply a --dump-dir parameter")

        if self._config.PHYSICAL:
            # Find the FileAddressSpace
            while addr_space.__class__.__name__ != "FileAddressSpace":
                addr_space = addr_space.base
            scanner = malfind.DiscontigYaraScanner(address_space=addr_space,
                                                   rules=DumpCerts.rules)
            for hit, address in scanner.scan():
                cert = obj.Object(
                    DumpCerts.type_map.get(hit.rule),
                    vm=scanner.address_space,
                    offset=address,
                )
                if cert.is_valid():
                    yield None, cert
        else:
            for process in self.filter_tasks(tasks.pslist(addr_space)):
                scanner = malfind.VadYaraScanner(task=process,
                                                 rules=DumpCerts.rules)
                for hit, address in scanner.scan():
                    cert = obj.Object(
                        DumpCerts.type_map.get(hit.rule),
                        vm=scanner.address_space,
                        offset=address,
                    )
                    if cert.is_valid():
                        yield process, cert
Esempio n. 4
0
    def calculate(self):

        if not has_yara:
            debug.error('Yara must be installed for this plugin.')

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error('This command does not support the selected profile.')

        rules = yara.compile(sources=xxmm_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)
            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                memdata = proc_addr_space.get_available_addresses()

                config_data = []

                for m in memdata:
                    if 0x2000 < m[1]:
                        continue
                    p_data = {}

                    data = proc_addr_space.zread(m[0], m[1])
                    offset = 0
                    p_data['param'] = []
                    while (True):
                        param = {}
                        l, param['id'], param['data'] = self.extract_param(
                            data, offset)
                        if l == None:
                            if len(
                                    p_data['param']
                            ) == 1 and p_data['param'][0]['type'] == 'Unknown':
                                offset = 0
                                break
                            for c in data[offset:]:
                                if ord(c) != 0x00:
                                    offset = 0
                                    break
                            break
                        offset += l
                        if param['id'] in DATA_TYPE.keys():
                            param['type'] = DATA_TYPE[param['id']]
                        else:
                            param['type'] = 'Unknown'
                        p_data['param'].append(param)
                    if offset == 0:
                        continue
                    p_data['offset'] = m[0]
                    p_data['length'] = offset
                    config_data.append(p_data)
                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 5
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=emotet_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr,
                                             end - vad_base_addr)

                config_data = []

                p_data = OrderedDict()
                for pattern in CONFIG_PATTERNS:
                    mc = re.search(pattern, data)
                    if mc:
                        try:
                            d = 4
                            i = 0
                            while 1:
                                ip = data[mc.start() + d +
                                          3] + data[mc.start() + d + 2] + data[
                                              mc.start() + d +
                                              1] + data[mc.start() + d]
                                port = unpack(
                                    "=H", data[mc.start() + d + 4:mc.start() +
                                               d + 6])[0]
                                d += 8
                                if ip == "\x00\x00\x00\x00" and port == 0:
                                    break
                                else:
                                    p_data["IP " + str(i)] = str(
                                        inet_ntoa(ip)) + ":" + str(port)
                                    i += 1
                        except:
                            outfd.write("[!] Not found config data.\n")

                config_data.append(
                    {"RSA Public Key": self.extract_rsakey(data)})
                config_data.append(p_data)

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 6
0
 def get_ghost_process(self, magic, mal_process, add_space):
     rule = "rule Gh0strat_process {strings: $any_variant = " + '"' + magic + '"' + " condition: $any_variant}"
     ghost_proc_sig = {'ghostrat_process': rule}
     rules = yara.compile(sources=ghost_proc_sig)
     for task in self.filter_tasks(tasks.pslist(add_space)):
         scanner = malfind.VadYaraScanner(task=task, rules=rules)
         for hit, address in scanner.scan():
             if task.obj_name == "_EPROCESS":
                 process = str(task.ImageFileName)
                 pid = task.UniqueProcessId
                 mal_process[process] = pid
Esempio n. 7
0
    def calculate(self):  ### Not used here but kept if needed for improvements
        """ Required: Runs YARA search to find hits """
        if not HAS_YARA:
            debug.error('Yara must be installed for this plugin')

        addr_space = utils.load_as(self._config)
        rules = yara.compile(sources=YARA_SIGS)
        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)
            for hit, address in scanner.scan():
                vad_base_addr = self.get_vad_base(task, address)
                yield task, address
Esempio n. 8
0
    def calculate(self):

        if not has_yara:
            debug.error('Yara must be installed for this plugin.')

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error('This command does not support the selected profile.')

        rules = yara.compile(sources=azorult_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)
            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                memdata = proc_addr_space.get_available_addresses()

                config_data = []

                for m in memdata:
                    if m[1] < 0x100000:
                        continue
                    p_data = {}

                    data = proc_addr_space.zread(m[0], m[1])

                    for pattern in CONFIG_PATTERNS:
                        m = re.search(pattern, data)

                    if m:
                        offset = m.start() - 0x1c
                    else:
                        continue

                    i = 0
                    while (True):
                        _, _, param_len = unpack_from("<III", data, offset)
                        if param_len > 0x100:
                            break
                        offset = offset + 0xc
                        param_data = data[offset:offset + param_len]
                        p_data[i] = param_data
                        rest_len = 4 - (param_len % 4)
                        offset += param_len + rest_len
                        i += 1

                    config_data.append(p_data)
                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 9
0
    def calculate(self):
        addr_space = utils.load_as(self._config)
        if not is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=SIGNATURES)
        for task in tasks.pslist(addr_space):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)
            for hit, address in scanner.scan(maxlen=MAX_SCAN_SIZE):
                vad_base_addr = get_vad_base(task, address)
                yield task, vad_base_addr
                break
Esempio n. 10
0
    def calculate(self):

        if not has_yara:
            debug.error('Yara must be installed for this plugin.')

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error('This command does not support the selected profile.')

        rules = yara.compile(sources=trickbot_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)
            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                memdata = proc_addr_space.get_available_addresses()

                config_data = []

                for m in memdata:

                    if m[1] <= 0x1000:
                        continue

                    data = proc_addr_space.zread(m[0], m[1])

                    for pattern in CONFIG_PATTERNS:
                        m = re.search(pattern, data)

                        if m:
                            offset = m.start()
                        else:
                            continue

                        p_data = OrderedDict()
                        xml_data = data[offset:m.end()]
                        root = ET.fromstring(xml_data)
                        i = 0
                        for e in root.getiterator():
                            if e.text is None:
                                if len(e.attrib) != 0:
                                    p_data[i] = e.tag + ": " + str(e.attrib)
                            else:
                                p_data[i] = e.tag + ": " + str(e.text)
                            i += 1
                        config_data.append(p_data)

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
    def calculate(self):
        """ Required: Runs YARA search to find hits """
        if not has_yara:
            debug.error('Yara must be installed for this plugin')

        addr_space = utils.load_as(self._config)
        rules = yara.compile(sources = signatures)
        for task in self.filter_tasks(tasks.pslist(addr_space)):
            if not task.ImageFileName.lower() in ['chrome.exe', 'firefox.exe', 'iexplore.exe']:
                continue
            scanner = malfind.VadYaraScanner(task=task, rules=rules)
            for hit, address in scanner.scan():
                yield task, address
Esempio n. 12
0
 def calculate(self):
     if not has_yara:
         debug.error("Yara must be installed for this plugin")
     addr_space = utils.load_as(self._config)
     tasks = win32.tasks.pslist(addr_space)
     for proc in tasks:
         if str(proc.ImageFileName) == "explorer.exe":
             rules = yara.compile(sources = {
                 'n':'rule toast {strings: $a=/<toast.*\/toast>/ condition: $a}'
                 })
             scanner = malfind.VadYaraScanner(task=proc, rules=rules)
             for hit,address in scanner.scan(maxlen=0x40000000):
                 yield (proc, address, hit, scanner.address_space.zread(address, 0x4000))
Esempio n. 13
0
    def calculate(self):
        if not can_run:
            debug.error(
                "Yara, Capstone and PyCrypto must be installed for this plugin"
            )

        addr_space = utils.load_as(self._config)

        rules = yara.compile(sources=signatures)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)
            for hit, addr in scanner.scan():
                yield task, addr
Esempio n. 14
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        if not has_yara:
            debug.error("You must install yara to use this plugin")

        if not self._config.DUMP_DIR:
            debug.error("You must supply a --dump-dir parameter")

        # Wildcard signatures to scan for
        rules = yara.compile(
            sources={
                'x509':
                'rule x509 {strings: $a = {30 82 ?? ?? 30 82 ?? ??} condition: $a}',
                'pkcs':
                'rule pkcs {strings: $a = {30 82 ?? ?? 02 01 00} condition: $a}',
            })

        # These signature names map to these data structures
        type_map = {
            'x509': '_X509_PUBLIC_CERT',
            'pkcs': '_PKCS_PRIVATE_CERT',
        }

        if self._config.PHYSICAL:
            # Find the FileAddressSpace
            while addr_space.__class__.__name__ != "FileAddressSpace":
                addr_space = addr_space.base
            scanner = malfind.DiscontigYaraScanner(address_space=addr_space,
                                                   rules=rules)
            for hit, address in scanner.scan():
                cert = obj.Object(
                    type_map.get(hit.rule),
                    vm=scanner.address_space,
                    offset=address,
                )
                if cert.is_valid():
                    yield None, cert
        else:
            for process in self.filter_tasks(tasks.pslist(addr_space)):
                scanner = malfind.VadYaraScanner(task=process, rules=rules)
                for hit, address in scanner.scan():
                    cert = obj.Object(
                        type_map.get(hit.rule),
                        vm=scanner.address_space,
                        offset=address,
                    )
                    if cert.is_valid():
                        yield process, cert
Esempio n. 15
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        osversion, memory_model = self.is_valid_profile(addr_space.profile)
        base = os.path.dirname(os.path.abspath(__file__))
        rules = yara.compile(base + "/yara/rule.yara")
        if osversion == "windows":

            for task in self.filter_tasks(tasks.pslist(addr_space)):
                scanner = malfind.VadYaraScanner(task=task, rules=rules)

                for hit, address in scanner.scan():

                    vad_base_addr, end = self.get_vad_base(task, address)

                    malname = str(hit).lower()
                    if str(hit) in [
                            "Himawari", "Lavender", "Armadill", "zark20rk"
                    ]:
                        malname = "redleaves"
                    if str(hit) in "TSC_Loader":
                        malname = "tscookie"
                    if "Agenttesla" in str(hit):
                        malname = "agenttesla"

                    try:
                        module = import_module(
                            "volatility.plugins.malware.utils.{name}scan".
                            format(name=malname))
                        module_cls = getattr(module, malname + "Config")
                        instance = module_cls(self._config)
                    except:
                        debug.error(
                            "Can't loading module volatility.plugins.malware.utils.{name}scan"
                            .format(name=malname))

                    for task, vad_base_addr, end, hit, memory_model, config_data in instance.calculate(
                    ):
                        yield task, vad_base_addr, end, hit, memory_model, config_data
                    break
        elif osversion == "linux":
            debug.error("Please use linux_malconfscan.")
        else:
            debug.error("This command does not support the selected profile.")
Esempio n. 16
0
    def calculate(self):
        """ Required: Runs YARA search to find hits """ 
        if not has_yara:
            debug.error('Yara must be installed for this plugin')

        addr_space = utils.load_as(self._config)
        rules = yara.compile(sources = signatures)
        for task in self.filter_tasks(tasks.pslist(addr_space)):
            if 'vmwareuser.exe' == task.ImageFileName.lower():
                continue
            if not 'java' in task.ImageFileName.lower():
                continue
            scanner = malfind.VadYaraScanner(task = task, rules = rules)
            for hit, address in scanner.scan():
                vad_base_addr = self.get_vad_base(task, address)
                yield task, address
Esempio n. 17
0
    def calculate(self):
        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=signatures)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)
            for hit, address in scanner.scan():
                if self.get_vad_perms(task, address) == 6:  # RWX vad
                    vad_base_addr = self.get_vad_base(task, address)
                    yield task, vad_base_addr
Esempio n. 18
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        if not has_crypto:
            debug.error("pycrypto must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=agenttesla_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr,
                                             end - vad_base_addr)

                config_data = []
                dlist = {}
                for word in self.strings(data):
                    try:
                        dec = self.stringdecrypt(word)
                        dec = re.sub(
                            "([\x00,\x01,\x02,\x03,\x04,\x05,\x06,\x07,\x08,\x09,\x0a,\x0b,\x0c,\x0d,\x0e,\x0f,\x10]{1})",
                            "\x00", dec)
                        dlist[word.strip().replace('\0',
                                                   '')] = dec.strip().replace(
                                                       "\n",
                                                       "").replace("\r", "")
                    except:
                        pass

                config_data.append(dlist)

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 19
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=signatures)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr, end - vad_base_addr)

                config_data = []

                if len(data) < 0x10000 or len(data) > 0x200000:
                    continue

                for nw in NETWIRE_INFO:
                    m = re.search(nw["pattern"], data)
                    if m:
                        offset = m.start()
                        break
                else:
                    continue

                cfg_addr = unpack("=I", data[offset + nw["cfg_offset"]:offset + nw["cfg_offset"] + 4])[0]
                if cfg_addr < vad_base_addr:
                    continue

                cfg_addr -= vad_base_addr
                cfg_blob = data[cfg_addr:cfg_addr + nw["cfg_size"]]
                config_data.append(self.parse_config(cfg_blob, nw))

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 20
0
    def calculate(self):

        if not has_yara:
            debug.error('Yara must be installed for this plugin.')

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error('This command does not support the selected profile.')

        rules = yara.compile(sources=noderat_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)
            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                memdata = proc_addr_space.get_available_addresses()

                config_data = []

                for m in memdata:
                    if m[1] < 0x100000:
                        continue
                    p_data = {}

                    data = proc_addr_space.zread(m[0], m[1])

                    for pattern in CONFIG_PATTERNS:
                        m = re.search(pattern, data)

                    if m:
                        offset = m.start()
                    else:
                        continue

                    json_data = data[offset:m.end()]
                    d = json.loads(json_data)

                    config_data.append(d)
                    break
                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 21
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        if not has_crypto:
            debug.error("pycrypto must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=agenttesla_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr,
                                             end - vad_base_addr)

                config_data = []
                dlist = OrderedDict()
                if "type1" in str(hit):
                    for word in self.base64strings(data):
                        try:
                            dec = self.stringdecrypt_type1(word)
                            dec = self.remove_unascii(dec).rstrip()
                            dlist[word.strip().replace('\0', '')] = dec
                        except:
                            pass

                if "type2" in str(hit):
                    dlist = self.stringdecrypt_type2(data)

                config_data.append(dlist)

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 22
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=bebloh_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr,
                                             end - vad_base_addr)

                config_data = []

                rsa_key_index = data.find(RSA_HEADER)
                rsa_key = data[rsa_key_index:rsa_key_index + 0x94]

                dga_key = self.crc32(rsa_key, 0xCA0B56EE)

                for pattern in CONFIG_PATTERNS:
                    offset = re.search(pattern, data).start()

                while not (data[offset] == "\xBA" or data[offset] == "\xB8"):
                    offset += 1

                (config_addr, ) = unpack("=I", data[offset + 1:offset + 5])
                config_addr -= vad_base_addr

                config_data.append(
                    self.parse_config(data, config_addr, rsa_key, dga_key))

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 23
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        if not has_crypto:
            debug.error("pycrypto must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=asyncrat_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():
                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr,
                                             end - vad_base_addr)

                config_data = []
                dlist = OrderedDict()

                for pattern in CONFIG_PATTERNS:
                    m = data.find(pattern)
                    if m > 0:
                        unicode_strings = self.storage_stream_us_parser(
                            data[m + 3:])
                        dlist = self.parse_config(unicode_strings)
                        break
                    else:
                        debug.info(
                            "Asyncrat configuration signature not found.")

                config_data.append(dlist)

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 24
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=ramnit_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr, end - vad_base_addr)

                config_data = []

                # resource PE search
                dll_index = data.rfind(MZ_HEADER)
                dll_data = data[dll_index:]

                try:
                    pe = pefile.PE(data=dll_data)
                except:
                    outfd.write("[!] Can't mapped PE.\n")
                    continue

                for section in pe.sections:
                    if ".data" in section.Name:
                        data_address = section.PointerToRawData

                config_data.append(self.parse_config(pe, dll_data, data_address))

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 25
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=poisonivy_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr,
                                             end - vad_base_addr)

                config_data = []

                for pattern in CONFIG_PATTERNS:
                    mc = re.search(pattern, data)
                    if mc:
                        offset = mc.start()
                        while data[offset] != "\xC3":
                            offset -= 1

                        while data[offset:offset + 2] != "\x00\x00":
                            (idx, size) = unpack_from("<HH", data, offset + 1)
                            if size > 0:
                                enc = data[offset + 5:offset + 5 + size]
                                config_data.append(self.parse_config(idx, enc))
                            offset = offset + size + 4

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 26
0
    def calculate(self):
        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)
        rules = yara.compile(sources=sigs)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)
            config = False
            start_add = False
            stop_add = False
            for hit, address in scanner.scan():
                if str(hit) == 'darkcomet_config':
                    config = hit
                    start_add = address
                    stop_add = address + 0x190

                if config and start_add and stop_add:
                    yield task, config, start_add, stop_add
                else:
                    pass
Esempio n. 27
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=cobaltstrike_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr,
                                             end - vad_base_addr)

                config_data = []

                for nw in CONF_PATTERNS:
                    cfg_addr = data.find(nw['pattern'])
                    if cfg_addr != -1:
                        break
                    else:
                        continue

                cfg_blob = data[cfg_addr:cfg_addr + nw['cfg_size']]
                config_data.append(
                    self.parse_config(self.decode_config(cfg_blob), nw))

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 28
0
    def calculate(self):
        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")
# For each process in the list
        for task in self.filter_tasks(tasks.pslist(addr_space)):
            # print task.ImageFileName
            for vad, address_space in task.get_vads(
                    vad_filter=task._injection_filter):
                # Injected code detected if there's values returned
                rules = yara.compile(sources=signatures)
                scanner = malfind.VadYaraScanner(task=task, rules=rules)
                # print 'before'
                for hit, address in scanner.scan():
                    vad_base_addr = self.get_vad_base(task, address)

                    # Get a chuck of memory of size 2048 next to where the string was detected
                    content = address_space.zread(address, 2048)
                    yield task, address, vad_base_addr, content
                    break
Esempio n. 29
0
    def calculate(self):

        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        if not has_yara:
            debug.error("Aplib must be installed for this plugin")

        addr_space = utils.load_as(self._config)

        os, memory_model = self.is_valid_profile(addr_space.profile)
        if not os:
            debug.error("This command does not support the selected profile.")

        rules = yara.compile(sources=ursnif_sig)

        for task in self.filter_tasks(tasks.pslist(addr_space)):
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():

                vad_base_addr, end = self.get_vad_base(task, address)
                proc_addr_space = task.get_process_address_space()
                data = proc_addr_space.zread(vad_base_addr,
                                             end - vad_base_addr)

                config_data = []

                # Parse standard Ursnif
                config_data = self.parse_joinned_data(data)

                # Parse static configuration type Ursnif
                if not config_data:
                    p_data = OrderedDict()
                    data = self.pe_magic_check(data)
                    try:
                        pe = pefile.PE(data=data)
                    except:
                        continue
                    imagebase = pe.NT_HEADERS.OPTIONAL_HEADER.ImageBase
                    for pattern in CONFIG_PATTERNS:
                        m = re.search(pattern, data)
                        if m:
                            if pe.FILE_HEADER.Machine in (
                                    pefile.
                                    MACHINE_TYPE['IMAGE_FILE_MACHINE_IA64'],
                                    pefile.
                                    MACHINE_TYPE['IMAGE_FILE_MACHINE_AMD64']):
                                c2_num = unpack("b", data[m.start(7) + 19])[0]
                            else:
                                c2_num = unpack("b", data[m.start(6)])[0]
                            if c2_num >= 16:
                                c2_num = 1
                            for i in range(c2_num):
                                if pe.FILE_HEADER.Machine in (
                                        pefile.MACHINE_TYPE[
                                            'IMAGE_FILE_MACHINE_IA64'],
                                        pefile.MACHINE_TYPE[
                                            'IMAGE_FILE_MACHINE_AMD64']):
                                    c2_addr = m.start(4) + unpack(
                                        "=I",
                                        data[m.start(3):m.start(3) + 4])[0]
                                    c2_table_offset = unpack(
                                        "=Q", data[c2_addr +
                                                   (8 * i):c2_addr + 8 +
                                                   (8 * i)])[0] - imagebase
                                else:
                                    c2_addr = unpack(
                                        "=I", data[m.start(4):m.start(4) +
                                                   4])[0] - imagebase
                                    c2_table_offset = unpack(
                                        "=I", data[c2_addr +
                                                   (4 * i):c2_addr + 4 +
                                                   (4 * i)])[0] - imagebase

                                try:
                                    c2 = self.decode_data(
                                        data, pe, c2_table_offset)
                                except:
                                    c2 = "Decode fail"

                                p_data["Server " + str(i)] = c2

                            if pe.FILE_HEADER.Machine in (
                                    pefile.
                                    MACHINE_TYPE['IMAGE_FILE_MACHINE_IA64'],
                                    pefile.
                                    MACHINE_TYPE['IMAGE_FILE_MACHINE_AMD64']):
                                serpent_key_offset = m.start(8) + unpack(
                                    "=I", data[m.start(7):m.start(7) + 4])[0]
                            else:
                                serpent_key_offset = unpack(
                                    "=I", data[m.start(8):m.start(8) +
                                               4])[0] - imagebase
                            try:
                                serpent_key = self.decode_data(
                                    data, pe, serpent_key_offset)
                            except:
                                serpent_key = "Decode fail"
                            p_data["Serpent key"] = serpent_key

                    for pattern in RSA_PATTERNS:
                        m = re.search(pattern, data)
                        if m:
                            if pe.FILE_HEADER.Machine in (
                                    pefile.
                                    MACHINE_TYPE['IMAGE_FILE_MACHINE_IA64'],
                                    pefile.
                                    MACHINE_TYPE['IMAGE_FILE_MACHINE_AMD64']):
                                rsa_key_offset = m.start(2) + unpack(
                                    "=I", data[m.start(1):m.start(1) + 4])[0]
                                rsa_key = data[rsa_key_offset +
                                               4:rsa_key_offset + 0x44]

                                rsa_mod = data[rsa_key_offset +
                                               0x44:rsa_key_offset + 0x84]
                            else:
                                rsa_key_offset = unpack(
                                    "=I", data[m.start(1):m.start(1) +
                                               4])[0] - imagebase
                                rsa_key = data[rsa_key_offset:rsa_key_offset +
                                               0x40]

                                mod_offset = unpack(
                                    "=I", data[m.start(4):m.start(4) +
                                               4])[0] - imagebase
                                rsa_mod = data[mod_offset:mod_offset + 0x40]
                            p_data["RSA key"] = rsa_key.encode("hex")
                            p_data["RSA modulus"] = rsa_mod.encode("hex")

                    config_data.append(p_data)

                yield task, vad_base_addr, end, hit, memory_model, config_data
                break
Esempio n. 30
0
    def extract_elite_config(self, pid_list):
        configurations = {}

        target_pids = [
            t["pid"] for t in pid_list if t["implant_type"] != "Scout"
        ]
        addr_space = utils.load_as(self._config)

        # Check all the things that could be wrong...
        if not has_yara:
            debug.error("Yara must be installed for this plugin")

        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")
        if self._config.DUMP_DIR == None:
            debug.error("Please specify a dump directory (--dump-dir)")
        if not os.path.isdir(self._config.DUMP_DIR):
            debug.error(self._config.DUMP_DIR + " is not a directory")

        sources = {
            'namespace1':
            'rule HT_ELITE {strings: $a = {22 53 59 4e 43 22} condition: $a}'
        }  # Search for "SYNC"

        rules = yara.compile(sources=sources)

        tasklist = [
            t for t in tasks.pslist(addr_space)
            if str(t.UniqueProcessId) in target_pids
        ]  # Only target Elite implants we've discovered - saves work and false positives
        for task in tasklist:
            scanner = malfind.VadYaraScanner(task=task, rules=rules)

            for hit, address in scanner.scan():
                hitdata = scanner.address_space.zread(address - 768, 1024)

                # Now go backwards until we get to a binary character (i.e. the start of the ascii configuration file)
                binary_found = False
                start = address
                character = scanner.address_space.zread(start, 1)
                while character in string.printable:
                    start = start - 1
                    character = scanner.address_space.zread(start, 1)

                start = start + 1  # Avoids \x00 at beginning

                # Search forwards until we find the end of the ascii configuration file
                end = address
                character = scanner.address_space.zread(end, 1)
                while character in string.printable:
                    end = end + 1
                    character = scanner.address_space.zread(end, 1)

                config_file = scanner.address_space.zread(start, end - start)

                # Now try to parse the config file
                data = config_file
                try:
                    config = json.loads(data)
                except:
                    # Our config isn't entirely intact - try to repair - this is not exact
                    # Count quotes
                    quotes = [i for i in data if i == "\""]

                    if len(quotes) % 2 != 0:
                        data = "\"" + data

                    # Count Braces
                    right_braces = [i for i in data if i == "}"]
                    left_braces = [i for i in data if i == "{"]
                    if left_braces < right_braces:
                        data = "{" + data
                    elif left_braces > right_braces:
                        data = data + "}"

                    # Now try to decode again
                    try:
                        config = json.loads(data)
                        dump_file = "configuration_elite_" + str(
                            task.UniqueProcessId) + "_" + hex(start) + ".json"
                        config_file = json.dumps(config, indent=4)
                        config_json = True

                    except:
                        dump_file = "configuration_elite_" + str(
                            task.UniqueProcessId) + "_" + hex(start) + ".text"
                        config_json = False

                # Write config file out to directory
                with open(os.path.join(self._config.DUMP_DIR, dump_file),
                          'w') as f:
                    f.write(config_file)

                pid_dict = [
                    i for i in pid_list
                    if i["pid"] == str(task.UniqueProcessId)
                ][0]
                index = pid_list.index(pid_dict)
                pid_list[index]["config_file"] = os.path.join(
                    self._config.DUMP_DIR, dump_file)

                if config_json:
                    # Try to parse the json to extract the C2 server
                    try:
                        for action in config["actions"]:
                            if action["desc"] == "SYNC":
                                pid_list[index]["c2_server"] = action[
                                    "subactions"][0]["host"]
                    except:
                        pid_list[index]["c2_server"] = None
                else:
                    pid_list[index]["c2_server"] = None

        # Now for the other pids that don't have a configuration file:
        for pid in pid_list:
            if "config_file" not in pid.keys():
                pid["config_file"] = None
                pid["c2_server"] = None

        return pid_list